diff --git a/tools/icesprog.arm b/tools/icesprog.arm index 739c200..8050995 100755 Binary files a/tools/icesprog.arm and b/tools/icesprog.arm differ diff --git a/tools/src/README.md b/tools/src/README.md new file mode 100755 index 0000000..53b9734 --- /dev/null +++ b/tools/src/README.md @@ -0,0 +1,24 @@ +# iCELink Tips +## GPIO control +``` +$icesprog --gpio PB14 --mode out +$icesprog --gpio PB14 --write 0 +$icesprog --gpio PB14 --write 1 +$icesprog --gpio PB14 --read +``` + +## JTAG select (available on iCESugar-pro) +``` +$icesprog --jtag-sel ? +$icesprog --jtag-sel 1 +$icesprog --jtag-sel 2 +``` + +## MCO config (available on iCESugar-nano) +``` +$icesprog --clk-sel ? +$icesprog --clk-sel 1 +$icesprog --clk-sel 2 +$icesprog --clk-sel 3 +$icesprog --clk-sel 4 +``` diff --git a/tools/src/icesprog b/tools/src/icesprog index 739c200..8050995 100755 Binary files a/tools/src/icesprog and b/tools/src/icesprog differ diff --git a/tools/src/icesprog.c b/tools/src/icesprog.c index 268d7f1..2875125 100644 --- a/tools/src/icesprog.c +++ b/tools/src/icesprog.c @@ -48,6 +48,7 @@ #define PACKET_SIZE (64 + 1) /* 64 bytes plus report id */ #define USB_TIMEOUT_DEFAULT 1000 +#define ID_DAP_Vendor0 0x80U #define ID_DAP_Vendor13 0x8DU #define SPI_FLASH_SIZE flash_size @@ -55,6 +56,13 @@ #define SPI_FLASH_SECTOR_ALIGN_UP(x) ((x + SPI_FLASH_SECTOR_SIZE - 1) & (~(SPI_FLASH_SECTOR_SIZE - 1))) #define SPI_FLASH_SECTOR_ALIGN_DOWN(x) ((x) & (~(SPI_FLASH_SECTOR_SIZE - 1))) +enum BOARD_TYPE_E { + BT_iCESugar = 0, /* iCE40UP5K */ + BT_iCESugar_Pro = 0xa55a0001, /* ECP5 LFE5U-25F-BG256 */ + BT_iCESugar_Nano = 0xa55a0002, /* iCE40LP1K */ + BT_Unknown = 0xFFFFFFFF, +}; + enum ICELINK_CMD_E { CMD_FLASH_GET_INFO = 0, CMD_FLASH_TRANSACTION_START, @@ -64,6 +72,23 @@ enum ICELINK_CMD_E { CMD_FLASH_WRITE_SECTOR, CMD_FLASH_READ_SECTOR, CMD_FLASH_ERASE_CHIP, + + CMD_SYS_GET_INFO = 0x80, + CMD_SYS_GPIO_MODE, + CMD_SYS_GPIO_WRITE, + CMD_SYS_GPIO_READ, + CMD_SYS_JTAG_SEL, + CMD_SYS_JTAG_INFO, + CMD_SYS_MCO_SEL, + CMD_SYS_MCO_INFO, +}; + +enum MCO_SOURCE_E { + MCO_HSI = 1, /* 8MHz */ + MCO_HSE, /* 12MHz */ + MCO_PLLCLK, /* 36MHz */ /* actually is RCC_CFGR_MCO_PLLCLK_DIV2 */ + MCO_SYSCLK, /* 72MHz */ + MCO_MAX, }; struct icelink { @@ -80,6 +105,8 @@ struct icelink_packet_head { uint8_t data[0]; }; +int32_t board_type = BT_Unknown; + uint32_t flash_id = 0; uint32_t flash_size = 8 * 1024 * 1024; @@ -189,7 +216,7 @@ int icelink_usb_xfer_wait(int txlen) return 0; } -int icelink_flash_get_info() +int icelink_flash_get_info(int verbose) { struct icelink_packet_head *ph; @@ -198,33 +225,33 @@ int icelink_flash_get_info() ph->vendor_cmd = 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(); - - 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); + } 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_buf = malloc(SPI_FLASH_SECTOR_ALIGN_UP(len))) == NULL) { - perror("malloc"); + } 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); } - memset(flash_buf, 0, SPI_FLASH_SECTOR_ALIGN_UP(len)); + } 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(); - sector_num = SPI_FLASH_SECTOR_ALIGN_UP(len) / SPI_FLASH_SECTOR_SIZE; + 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); + } - icelink_flash_read_sectors(flash_offset, sector_num, flash_buf); + if ((flash_buf = malloc(SPI_FLASH_SECTOR_ALIGN_UP(len))) == NULL) { + perror("malloc"); + exit(-1); + } - if ((fd = open(ifile, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0664)) == -1) { - perror("open"); - exit(-1); - } + memset(flash_buf, 0, SPI_FLASH_SECTOR_ALIGN_UP(len)); - if (write(fd, flash_buf, len) != len) { - perror("write"); - exit(-1); - } + sector_num = SPI_FLASH_SECTOR_ALIGN_UP(len) / SPI_FLASH_SECTOR_SIZE; - close(fd); + icelink_flash_read_sectors(flash_offset, sector_num, flash_buf); - } 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 ((fd = open(ifile, O_CREAT | O_RDWR | O_TRUNC | O_BINARY, 0664)) == -1) { + perror("open"); + exit(-1); + } - if ((fstat(fd, &st)) == -1) { - perror("fstat"); - exit(-1); - } + if (write(fd, flash_buf, len) != len) { + perror("write"); + exit(-1); + } - fprintf(stdout, "write flash (%d (0x%x) Bytes)\r\n", (uint32_t)st.st_size, (uint32_t)st.st_size); + close(fd); - if ((flash_buf = malloc(SPI_FLASH_SECTOR_ALIGN_UP(st.st_size))) == NULL) { - perror("malloc"); - exit(-1); - } + } 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); + } - memset(flash_buf, 0, SPI_FLASH_SECTOR_ALIGN_UP(st.st_size)); + if ((fstat(fd, &st)) == -1) { + perror("fstat"); + exit(-1); + } - if (read(fd, flash_buf, st.st_size) != st.st_size) { - perror("read"); - exit(-1); - } + fprintf(stdout, "write flash (%d (0x%x) Bytes)\r\n", (uint32_t)st.st_size, (uint32_t)st.st_size); - /* FIXME: overflow check */ - sector_num = SPI_FLASH_SECTOR_ALIGN_UP(st.st_size) / SPI_FLASH_SECTOR_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); + } - icelink_flash_write_sectors(flash_offset, sector_num, flash_buf); + /* FIXME: overflow check */ + sector_num = SPI_FLASH_SECTOR_ALIGN_UP(st.st_size) / SPI_FLASH_SECTOR_SIZE; - close(fd); + 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); + + } - } 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;