From: Alan Green Date: Mon, 14 Sep 2020 07:30:33 +0000 (+1000) Subject: clkdiv: added clkdiv X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=566812453a69f3185c1170ff5653075d581b2177;p=ecpprog.git clkdiv: added clkdiv This change allows arbitrary divider values to be used for the 6MHz FTDI SPI/JTAG clock. I find that, on the Lattice NX Evaluation Board, the FTDI clock divider needs to be set to a value of 3 or higher in order to program the flash rom. This may be because the board uses an ES (Early Silicon/Engineering Sample) CrossLink/NX-40. I see similar behavior with the Radiant programmer where a divisor of 2 or higher is needed. With a slower clock divider, ecpprog is also able to verify programmed flash rom content. --- diff --git a/ecpprog/ecpprog.c b/ecpprog/ecpprog.c index f366e9b..eba15e4 100644 --- a/ecpprog/ecpprog.c +++ b/ecpprog/ecpprog.c @@ -631,7 +631,10 @@ static void help(const char *progname) fprintf(stderr, " -o start address for read/write [default: 0]\n"); fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n"); fprintf(stderr, " or 'M' for size in megabytes)\n"); - fprintf(stderr, " -s slow SPI (50 kHz instead of 6 MHz)\n"); + fprintf(stderr, " -k divider for SPI clock [default: 1]\n"); + fprintf(stderr, " clock speed is 6MHz/divider"); + fprintf(stderr, " -s slow SPI. (50 kHz instead of 6 MHz)\n"); + fprintf(stderr, " Equivalent to -k 30\n"); fprintf(stderr, " -v verbose output\n"); fprintf(stderr, " -i [4,32,64] select erase block size [default: 64k]\n"); fprintf(stderr, "\n"); @@ -685,6 +688,7 @@ int main(int argc, char **argv) int erase_block_size = 64; int erase_size = 0; int rw_offset = 0; + int clkdiv = 1; bool read_mode = false; bool check_mode = false; @@ -693,7 +697,6 @@ int main(int argc, char **argv) bool dont_erase = false; bool prog_sram = false; bool test_mode = false; - bool slow_clock = false; bool disable_protect = false; bool disable_verify = false; const char *filename = NULL; @@ -713,7 +716,7 @@ int main(int argc, char **argv) /* Decode command line parameters */ int opt; char *endptr; - while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStvspX", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:k:scbnStvpX", long_options, NULL)) != -1) { switch (opt) { case 'd': /* device string */ devstr = optarg; @@ -788,6 +791,16 @@ int main(int argc, char **argv) return EXIT_FAILURE; } break; + case 'k': /* set clock div */ + clkdiv = strtol(optarg, &endptr, 0); + if (clkdiv < 1 || clkdiv > 65536) { + fprintf(stderr, "%s: clock divider must be in range 1-65536 `%s' is not a valid divider\n", my_name, optarg); + return EXIT_FAILURE; + } + break; + case 's': /* use slow SPI clock */ + clkdiv = 30; + break; case 'c': /* do not write just check */ check_mode = true; break; @@ -806,9 +819,6 @@ int main(int argc, char **argv) case 'v': /* provide verbose output */ verbose = true; break; - case 's': /* use slow SPI clock */ - slow_clock = true; - break; case 'p': /* disable flash protect before erase/write */ disable_protect = true; break; @@ -965,7 +975,7 @@ int main(int argc, char **argv) // --------------------------------------------------------- fprintf(stderr, "init..\n"); - jtag_init(ifnum, devstr, slow_clock); + jtag_init(ifnum, devstr, clkdiv); read_idcode(); read_status_register(); diff --git a/ecpprog/jtag.h b/ecpprog/jtag.h index 51caa9d..ce41925 100644 --- a/ecpprog/jtag.h +++ b/ecpprog/jtag.h @@ -34,7 +34,7 @@ typedef enum e_TAPState /** * Performs the start-of-day tasks necessary to talk JTAG to our FPGA. */ -void jtag_init(int ifnum, const char *devstr, bool slow_clock); +void jtag_init(int ifnum, const char *devstr, int clkdiv); /** diff --git a/ecpprog/jtag_tap.c b/ecpprog/jtag_tap.c index 43bb062..17f4bfd 100644 --- a/ecpprog/jtag_tap.c +++ b/ecpprog/jtag_tap.c @@ -130,9 +130,9 @@ void jtag_deinit(){ /** * Performs any start-of-day tasks necessary to talk JTAG to our FPGA. */ -void jtag_init(int ifnum, const char *devstr, bool slow_clock) +void jtag_init(int ifnum, const char *devstr, int clkdiv) { - mpsse_init(ifnum, devstr, slow_clock); + mpsse_init(ifnum, devstr, clkdiv); jtag_set_current_state(STATE_TEST_LOGIC_RESET); jtag_go_to_state(STATE_TEST_LOGIC_RESET); @@ -200,9 +200,6 @@ static void jtag_shift_bytes( } //printf("jtag_shift_bytes(0x%08x,0x%08x,%u,%s);\n",input_data, output_data, data_bits, must_end ? "true" : "false"); uint32_t byte_count = data_bits / 8; - - - data[0] = MC_DATA_OUT | MC_DATA_IN | MC_DATA_LSB | MC_DATA_OCN; data[1] = (byte_count - 1); data[2] = (byte_count - 1) >> 8; diff --git a/ecpprog/mpsse.c b/ecpprog/mpsse.c index df93e19..339df7e 100644 --- a/ecpprog/mpsse.c +++ b/ecpprog/mpsse.c @@ -140,7 +140,7 @@ void mpsse_xfer(uint8_t* data_buffer, uint16_t send_length, uint16_t receive_len } } -void mpsse_init(int ifnum, const char *devstr, bool slow_clock) +void mpsse_init(int ifnum, const char *devstr, int clkdiv) { enum ftdi_interface ftdi_ifnum = INTERFACE_A; @@ -216,17 +216,10 @@ void mpsse_init(int ifnum, const char *devstr, bool slow_clock) mpsse_send_byte(MC_TCK_X5); - if (slow_clock) { - // set 50 kHz clock - mpsse_send_byte(MC_SET_CLK_DIV); - mpsse_send_byte(29); - mpsse_send_byte(0x00); - } else { - // set 6 MHz clock - mpsse_send_byte(MC_SET_CLK_DIV); - mpsse_send_byte(1); - mpsse_send_byte(0x00); - } + // set clock - actual clock is 6MHz/(clkdiv) + mpsse_send_byte(MC_SET_CLK_DIV); + mpsse_send_byte((clkdiv-1) & 0xff); + mpsse_send_byte((clkdiv-1) >> 8); mpsse_send_byte(MC_SETB_LOW); mpsse_send_byte(0x08); /* Value */ @@ -239,4 +232,4 @@ void mpsse_close(void) ftdi_disable_bitbang(&mpsse_ftdic); ftdi_usb_close(&mpsse_ftdic); ftdi_deinit(&mpsse_ftdic); -} \ No newline at end of file +} diff --git a/ecpprog/mpsse.h b/ecpprog/mpsse.h index e10601a..2fa6f70 100644 --- a/ecpprog/mpsse.h +++ b/ecpprog/mpsse.h @@ -113,7 +113,7 @@ int mpsse_readb_low(void); int mpsse_readb_high(void); void mpsse_send_dummy_bytes(uint8_t n); void mpsse_send_dummy_bit(void); -void mpsse_init(int ifnum, const char *devstr, bool slow_clock); +void mpsse_init(int ifnum, const char *devstr, int clkdiv); void mpsse_close(void); #endif /* MPSSE_H */