From 79aa508078c4e2113c79389867fea30c6b5d5b61 Mon Sep 17 00:00:00 2001 From: wuxx Date: Sat, 2 Jan 2021 16:15:26 +0800 Subject: [PATCH] commit icesprog v1.1a --- tools/icesprog.arm | Bin 18784 -> 23788 bytes tools/src/README.md | 24 ++ tools/src/icesprog | Bin 18784 -> 23788 bytes tools/src/icesprog.c | 617 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 545 insertions(+), 96 deletions(-) create mode 100755 tools/src/README.md diff --git a/tools/icesprog.arm b/tools/icesprog.arm index 739c200028546fa444eedf0ac18a260e1493e871..8050995d5746f1478247c167d38a9c776f91af7a 100755 GIT binary patch literal 23788 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 literal 18784 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 literal 18784 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 = ID_DAP_Vendor13; ph->icelink_cmd = CMD_FLASH_GET_INFO; - if (icelink_usb_xfer(3) != 0) { + if (icelink_usb_xfer_wait(3) != 0) { fprintf(stderr, "iCELink CMD_FLASH_GET_INFO failed."); return -1; } flash_id = *((uint32_t *)(&(icelink_handle.packet_buffer[2]))); - fprintf(stdout, "flash id: 0x%x \n", flash_id); + if (verbose) { fprintf(stdout, "flash id: 0x%x ", flash_id); } switch (flash_id) { case (0xEF4015): - fprintf(stdout, "w25q16 (4MB)\n"); + if (verbose) { fprintf(stdout, "w25q16 (4MB)\n"); } flash_size = 4 * 1024 * 1024; break; case (0xEF4017): - fprintf(stdout, "w25q64 (8MB)\n"); + if (verbose) { fprintf(stdout, "w25q64 (8MB)\n"); } flash_size = 8 * 1024 * 1024; break; case (0xEF4018): - fprintf(stdout, "w25q128 (16MB)\n"); + if (verbose) { fprintf(stdout, "w25q128 (16MB)\n"); } flash_size = 16 * 1024 * 1024; break; default: - fprintf(stdout, "unknown (??MB)\n"); + if (verbose) { fprintf(stdout, "unknown (??MB)\n"); } break; } - return 0; + return flash_id; } int icelink_flash_transaction_start() @@ -479,6 +506,303 @@ int icelink_flash_erase_chip() return 0; } +int32_t icelink_sys_get_info() +{ + int32_t sys_info; + struct icelink_packet_head *ph; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_GET_INFO; + + if (icelink_usb_xfer_wait(3) != 0) { + fprintf(stderr, "iCELink CMD_SYS_GET_INFO failed.\n"); + return -1; + } + + sys_info = *((int32_t *)(&(icelink_handle.packet_buffer[2]))); + + return sys_info; + +} + +int32_t icelink_sys_get_id(char *id) +{ + int i; + struct icelink_packet_head *ph; + uint8_t *pb; + uint32_t size; + + pb = (uint8_t *)&icelink_handle.packet_buffer[1]; + + //pb[0] = ID_DAP_Vendor0; + + pb[0] = 0x00; /* ID_DAP_Info */ + pb[1] = 0x03; /* DAP_ID_SER_NUM */ + + if (icelink_usb_xfer(3) != 0) { + fprintf(stderr, "iCELink ID_DAP_Vendor0 failed.\n"); + return -1; + } + + pb = &(icelink_handle.packet_buffer[0]); + size = pb[1]; +#if 0 + for(i = 0; i < 8; i++) { + fprintf(stdout, "pb[%d]: 0x%x\n", i, pb[i]); + } +#endif + + memcpy(id, &pb[2], size); + + return 0; + +} + +int icelink_gpio_mode(uint32_t gpio_port, uint32_t gpio_index, uint32_t gpio_mode) +{ + struct icelink_packet_head *ph; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_GPIO_MODE; + + writel(&(ph->data[0]), gpio_port); + writel(&(ph->data[4]), gpio_index); + writel(&(ph->data[8]), gpio_mode); + + if (icelink_usb_xfer_wait(15) != 0) { + fprintf(stderr, "iCELink CMD_SYS_GPIO_MODE failed.\n"); + return -1; + } + + return 0; +} + + +int32_t icelink_gpio_read(uint32_t gpio_port, uint32_t gpio_index) +{ + struct icelink_packet_head *ph; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_GPIO_READ; + + writel(&(ph->data[0]), gpio_port); + writel(&(ph->data[4]), gpio_index); + + if (icelink_usb_xfer_wait(11) != 0) { + fprintf(stderr, "iCELink CMD_SYS_GPIO_MODE failed.\n"); + return -1; + } + + return readl(&(icelink_handle.packet_buffer[2])); + +} + +int32_t icelink_gpio_write(uint32_t gpio_port, uint32_t gpio_index, uint32_t gpio_value) +{ + struct icelink_packet_head *ph; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_GPIO_WRITE; + + writel(&(ph->data[0]), gpio_port); + writel(&(ph->data[4]), gpio_index); + writel(&(ph->data[8]), gpio_value); + + if (icelink_usb_xfer_wait(15) != 0) { + fprintf(stderr, "iCELink CMD_SYS_GPIO_WRITE failed.\n"); + return -1; + } + + return 0; + +} + +int32_t icelink_jtag_info() +{ + uint32_t jtag_num; + + struct icelink_packet_head *ph; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_JTAG_INFO; + + if (icelink_usb_xfer_wait(3) != 0) { + fprintf(stderr, "iCELink CMD_SYS_JTAG_INFO failed.\n"); + return -1; + } + + jtag_num = *((uint32_t *)(&(icelink_handle.packet_buffer[2]))); + + return jtag_num; +} + +int32_t icelink_jtag_select(int jtag_num) +{ + struct icelink_packet_head *ph; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + if (board_type == BT_iCESugar_Pro) { + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_JTAG_SEL; + + writel(&(ph->data[0]), jtag_num); + + if (icelink_usb_xfer_wait(7) != 0) { + fprintf(stderr, "iCELink CMD_SYS_JTAG_SEL failed.\n"); + return -1; + } + + jtag_num = icelink_jtag_info(); + fprintf(stdout, "JTAG --> [JTAG-%d]\n", jtag_num); + fputs (("\ + [JTAG-1] \n\ + TCK: iCELink-PB4 -- ECP5-JTAG-TCK (25F-BG256-T10) \n\ + TMS: iCELink-PA15 -- ECP5-JTAG-TMS (25F-BG256-T11) \n\ + TDI: iCELink-PB3 -- ECP5-JTAG-TDI (25F-BG256-R11) \n\ + TDO: iCELink-PB5 -- ECP5-JTAG-TDO (25F-BG256-M10) \n\ + \n\ + [JTAG-2] \n\ + TCK: iCELink-PB0 -- ECP5-IO-PL8D (25F-BG256-F5) \n\ + TMS: iCELink-PB1 -- ECP5-IO-PL17A (25F-BG256-H5) \n\ + TDI: iCELink-PB8 -- ECP5-IO-PL38A (25F-BG256-N4) \n\ + TDO: iCELink-PB9 -- ECP5-IO-PL17D (25F-BG256-J5) \n\n\ + "), stdout); + + } else { + fprintf(stdout, "only iCESugar-Pro support jtag select\r\n"); + } + + return 0; +} + +int32_t icelink_mco_info() +{ + int i; + uint32_t mco_source; + + struct icelink_packet_head *ph; + char *clk_desc[] = {"dummy", " 8MHz", "12MHz", "36MHz", "72MHz"}; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_MCO_INFO; + + if (icelink_usb_xfer_wait(3) != 0) { + fprintf(stderr, "iCELink CMD_SYS_JTAG_INFO failed.\n"); + return -1; + } + + mco_source = *((uint32_t *)(&(icelink_handle.packet_buffer[2]))); + + + fprintf(stdout, "CLK -> [%s]\n", clk_desc[mco_source]); + fprintf(stdout, "CLK-SELECT:\n"); + for(i = 1; i < MCO_MAX; i++) { + fprintf(stdout, "\t[%d]: %s\n", i, clk_desc[i]); + } + + + return mco_source; +} + +int32_t icelink_mco_select(int mco_source) +{ + struct icelink_packet_head *ph; + + ph = (struct icelink_packet_head *)&icelink_handle.packet_buffer[1]; + + if (board_type == BT_iCESugar_Nano) { + + ph->vendor_cmd = ID_DAP_Vendor13; + ph->icelink_cmd = CMD_SYS_MCO_SEL; + + writel(&(ph->data[0]), mco_source); + + if (icelink_usb_xfer_wait(7) != 0) { + fprintf(stderr, "iCELink CMD_SYS_MCO_SEL failed.\n"); + return -1; + } + + } else { + fprintf(stdout, "only iCESugar-Nano support mco select\r\n"); + } + + return 0; +} + +int32_t icelink_sys_get_board_type() +{ + char board_id[128] = {0}; + + icelink_sys_get_id(board_id); + + //fprintf(stdout, "board_id: %s\n", board_id); + + if (strncmp(board_id, "0700", 4) == 0) { + board_type = BT_iCESugar; + } else if (strncmp(board_id, "0710", 4) == 0) { + board_type = BT_iCESugar_Pro; + } else if (strncmp(board_id, "0720", 4) == 0) { + board_type = BT_iCESugar_Nano; + } else { + board_type = BT_Unknown; + } + + return board_type; +} + +int32_t icelink_dump_board_info(uint32_t board_type, uint32_t flash_id) +{ + + switch (board_type) { + case (BT_iCESugar): + fprintf(stdout, "board: [iCESugar]\n"); + break; + case (BT_iCESugar_Pro): + fprintf(stdout, "board: [iCESugar-Pro]\n"); + break; + case (BT_iCESugar_Nano): + fprintf(stdout, "board: [iCESugar-Nano]\n"); + break; + default: + fprintf(stdout, "board: [Unknown]\n"); + break; + } + + //fprintf(stdout, "flash id: 0x%x ", flash_id); + switch (flash_id) { + case (0xEF4015): + fprintf(stdout, "flash: [w25q16] (4MB)\n"); + flash_size = 4 * 1024 * 1024; + break; + case (0xEF4017): + fprintf(stdout, "flash: [w25q64] (8MB)\n"); + flash_size = 8 * 1024 * 1024; + break; + case (0xEF4018): + fprintf(stdout, "flash: [w25q128] (16MB)\n"); + flash_size = 16 * 1024 * 1024; + break; + default: + fprintf(stdout, "flash: unknown flash id 0x%x (??MB)\n", flash_id); + break; + } + +} + void icelink_close() { hid_close(icelink_handle.dev_handle); @@ -514,30 +838,58 @@ void usage(char *program_name) { printf("usage: %s [OPTION] [FILE]\n", program_name); fputs (("\ - -w | --write write spi-flash \n\ - -r | --read read spi-flash \n\ + -w | --write write spi-flash or gpio \n\ + -r | --read read spi-flash or gpio \n\ -e | --erase erase spi-flash \n\ -p | --probe probe spi-flash \n\ -o | --offset spi-flash offset \n\ -l | --len len of write/read \n\ + -g | --gpio icelink gpio write/read \n\ + -m | --mode icelink gpio mode \n\ + -j | --jtag-sel jtag interface select (1 or 2) \n\ + -c | --clk-sel clk source select (1 to 4) \n\ -h | --help display help info \n\n\ - -- version 1.0 --\n\ + -- version 1.1a --\n\ "), stdout); exit(0); } static struct option const long_options[] = { - {"write", no_argument, NULL, 'w'}, - {"read", no_argument, NULL, 'r'}, - {"erase", no_argument, NULL, 'e'}, - {"probe", no_argument, NULL, 'p'}, - {"offset", required_argument, NULL, 'o'}, - {"len", required_argument, NULL, 'l'}, - {"help", no_argument, NULL, 'h'}, - {NULL, 0, NULL, 0}, // avoid crashes due to unsupported options + {"write", no_argument, NULL, 'w'}, + {"read", no_argument, NULL, 'r'}, + {"erase", no_argument, NULL, 'e'}, + {"probe", no_argument, NULL, 'p'}, + {"offset", required_argument, NULL, 'o'}, + {"len", required_argument, NULL, 'l'}, + + /* gpio */ + {"gpio", required_argument, NULL, 'g'}, + {"mode", required_argument, NULL, 'm'}, + + /* jtag select */ + {"jtag-sel", required_argument, NULL, 'j'}, + + /* clk select */ + {"clk-sel", required_argument, NULL, 'c'}, + + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0 }, }; +/* stm32f1xx_hal_gpio.h */ +uint32_t gpio_mode_map(char *s) +{ + if (strcmp(s, "in") == 0) { + return 0; /* GPIO_MODE_INPUT */ + } else if (strcmp(s, "out") == 0) { + return 1; /* GPIO_MODE_OUTPUT_PP */ + } else { + fprintf(stderr, "invalid gpio mode %s\n", s); + exit(-1); + } +} + int main(int argc, char **argv) { char *ifile = NULL; @@ -553,27 +905,33 @@ int main(int argc, char **argv) uint32_t len = 0; uint32_t flash_offset = 0, sector_num = 0; - int mode = 1; /* read: 0; write: 1; erase all: 2 */ + uint32_t gpio_port = 0, gpio_index, gpio_value; + int32_t gpio_mode = -1; + + int jtag_sel = -1; + int mco_sel = -1; + + int op_mode = 1; /* read: 0; write: 1; erase all: 2 */ if (argc == 1) { usage(argv[0]); exit(-1); } - while ((c = getopt_long (argc, argv, "wrpel:o:h", + while ((c = getopt_long (argc, argv, "wrpel:o:g:m:j:c:h", long_options, &option_index)) != -1) { switch (c) { case ('r'): - mode = 0; + op_mode = 0; break; case ('w'): - mode = 1; + op_mode = 1; break; case ('e'): - mode = 2; + op_mode = 2; break; case ('p'): - mode = 3; + op_mode = 3; break; case ('l'): len = strtoul(optarg, NULL, 0); @@ -581,12 +939,26 @@ int main(int argc, char **argv) case ('o'): flash_offset = strtoul(optarg, NULL, 0); break; + case ('g'): + //gpio_num = strtoul(&optarg[1], NULL, 16); + gpio_port = 0xA + (optarg[1] - 'A'); + gpio_index = strtoul(&optarg[2], NULL, 0); + break; + case ('m'): + gpio_mode = gpio_mode_map(optarg); + break; + case ('j'): + jtag_sel = strtoul(optarg, NULL, 0); + break; + case ('c'): + mco_sel = strtoul(optarg, NULL, 0); + break; case ('h'): usage(argv[0]); - break; + exit(0); default: usage(argv[0]); - break; + exit(0); } } @@ -601,90 +973,143 @@ int main(int argc, char **argv) //icelink_flash_get_info(); //icelink_flash_dump_sector(0); - if (mode == 0) { /* read spi-flash */ - fprintf(stdout, "flash offset: 0x%08x\r\n", flash_offset); - fprintf(stdout, "read flash (%d (0x%x) Bytes)\r\n", len, len); - if (len == 0) { - fprintf(stderr, "use -l to set read len\r\n"); + if (jtag_sel != -1) { + /* jtag select */ + if (jtag_sel == 1 || jtag_sel == 2) { + icelink_sys_get_board_type(); + icelink_jtag_select(jtag_sel); + } else { + fprintf(stderr, "invalid jtag_num [%d] (should be 1 or 2)\r\n", jtag_sel); exit(-1); } - //icelink_flash_get_info(); + } else if (mco_sel != -1) { + icelink_sys_get_board_type(); + if (mco_sel == 0 || (mco_sel >= MCO_MAX)) { + //fprintf(stdout, "mco_info:\n"); + icelink_mco_info(); + } else { + icelink_mco_select(mco_sel); + icelink_mco_info(); + } - if ((flash_offset + len) > SPI_FLASH_SIZE) { - fprintf(stderr, "invalid read region [0x%08x, 0x%08x]\r\n", flash_offset, flash_offset + len); + } else if (gpio_port != 0) { + /* gpio control */ + //fprintf(stdout, "gpio_port P%X\r\n", gpio_port); + //fprintf(stdout, "gpio_index %d\r\n", gpio_index); + if ((gpio_port >= 0xA && gpio_port <=0xF) && (gpio_index >= 0 && gpio_index <= 15)) { + if (gpio_mode != -1) { /* gpio mode */ + fprintf(stdout, "gpio mode P%X%d 0x%x\r\n", gpio_port, gpio_index, gpio_mode); + icelink_gpio_mode(gpio_port, gpio_index, gpio_mode); + } else if (op_mode == 0) { /* gpio read */ + gpio_value = icelink_gpio_read(gpio_port, gpio_index); + fprintf(stdout, "gpio read P%X%d return %d\r\n", gpio_port, gpio_index, gpio_value); + } else if (op_mode == 1) { /* gpio write */ + gpio_value = strtoul(argv[argc - 1], NULL, 0); + fprintf(stdout, "gpio write P%X%d %d\r\n", gpio_port, gpio_index, gpio_value); + icelink_gpio_write(gpio_port, gpio_index, gpio_value); + } + + } else { + fprintf(stderr, "invalid gpio_num %X%d\r\n", gpio_port, gpio_index); exit(-1); } - if ((flash_buf = malloc(SPI_FLASH_SECTOR_ALIGN_UP(len))) == NULL) { - perror("malloc"); - exit(-1); + } else { + /* flash access */ + if (op_mode == 0) { /* read spi-flash */ + fprintf(stdout, "flash offset: 0x%08x\r\n", flash_offset); + fprintf(stdout, "read flash (%d (0x%x) Bytes)\r\n", len, len); + if (len == 0) { + fprintf(stderr, "use -l to set read len\r\n"); + exit(-1); + } + + //icelink_flash_get_info(); + + if ((flash_offset + len) > SPI_FLASH_SIZE) { + fprintf(stderr, "invalid read region [0x%08x, 0x%08x]\r\n", flash_offset, flash_offset + len); + exit(-1); + } + + if ((flash_buf = malloc(SPI_FLASH_SECTOR_ALIGN_UP(len))) == NULL) { + perror("malloc"); + exit(-1); + } + + memset(flash_buf, 0, SPI_FLASH_SECTOR_ALIGN_UP(len)); + + sector_num = SPI_FLASH_SECTOR_ALIGN_UP(len) / SPI_FLASH_SECTOR_SIZE; + + icelink_flash_read_sectors(flash_offset, sector_num, flash_buf); + + if ((fd = open(ifile, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0664)) == -1) { + perror("open"); + exit(-1); + } + + if (write(fd, flash_buf, len) != len) { + perror("write"); + exit(-1); + } + + close(fd); + + } else if (op_mode == 1) { /* write spi-flash */ + fprintf(stdout, "flash offset: 0x%08x\r\n", flash_offset); + if ((fd = open(ifile, O_RDONLY | O_BINARY)) == -1) { + perror("open"); + exit(-1); + } + + if ((fstat(fd, &st)) == -1) { + perror("fstat"); + exit(-1); + } + + fprintf(stdout, "write flash (%d (0x%x) Bytes)\r\n", (uint32_t)st.st_size, (uint32_t)st.st_size); + + if ((flash_buf = malloc(SPI_FLASH_SECTOR_ALIGN_UP(st.st_size))) == NULL) { + perror("malloc"); + exit(-1); + } + + memset(flash_buf, 0, SPI_FLASH_SECTOR_ALIGN_UP(st.st_size)); + + if (read(fd, flash_buf, st.st_size) != st.st_size) { + perror("read"); + exit(-1); + } + + /* FIXME: overflow check */ + sector_num = SPI_FLASH_SECTOR_ALIGN_UP(st.st_size) / SPI_FLASH_SECTOR_SIZE; + + icelink_flash_write_sectors(flash_offset, sector_num, flash_buf); + + close(fd); + + } else if (op_mode == 2) { /* erase chip */ + fprintf(stdout, "erase chip\n"); + icelink_flash_erase_chip(); + } else if (op_mode == 3) { /* probe chip */ + fprintf(stdout, "probe chip\n"); + + icelink_sys_get_board_type(); + icelink_flash_get_info(0); + + icelink_dump_board_info(board_type, flash_id); + } - memset(flash_buf, 0, SPI_FLASH_SECTOR_ALIGN_UP(len)); - - sector_num = SPI_FLASH_SECTOR_ALIGN_UP(len) / SPI_FLASH_SECTOR_SIZE; - - icelink_flash_read_sectors(flash_offset, sector_num, flash_buf); - - if ((fd = open(ifile, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0664)) == -1) { - perror("open"); - exit(-1); - } - - if (write(fd, flash_buf, len) != len) { - perror("write"); - exit(-1); - } - - close(fd); - - } else if (mode == 1) { /* write spi-flash */ - fprintf(stdout, "flash offset: 0x%08x\r\n", flash_offset); - if ((fd = open(ifile, O_RDONLY | O_BINARY)) == -1) { - perror("open"); - exit(-1); - } - - if ((fstat(fd, &st)) == -1) { - perror("fstat"); - exit(-1); - } - - fprintf(stdout, "write flash (%d (0x%x) Bytes)\r\n", (uint32_t)st.st_size, (uint32_t)st.st_size); - - if ((flash_buf = malloc(SPI_FLASH_SECTOR_ALIGN_UP(st.st_size))) == NULL) { - perror("malloc"); - exit(-1); - } - - memset(flash_buf, 0, SPI_FLASH_SECTOR_ALIGN_UP(st.st_size)); - - if (read(fd, flash_buf, st.st_size) != st.st_size) { - perror("read"); - exit(-1); - } - - /* FIXME: overflow check */ - sector_num = SPI_FLASH_SECTOR_ALIGN_UP(st.st_size) / SPI_FLASH_SECTOR_SIZE; - - icelink_flash_write_sectors(flash_offset, sector_num, flash_buf); - - close(fd); - - } else if (mode == 2) { /* erase chip */ - fprintf(stdout, "erase chip\n"); - icelink_flash_erase_chip(); - } else if (mode == 3) { /* probe chip */ - fprintf(stdout, "probe chip\n"); - icelink_flash_get_info(); } fprintf(stdout, "done\n"); //icelink_ram_dump(); icelink_close(); - free(flash_buf); + if (flash_buf) { + free(flash_buf); + } return 0;