From 2d21188cdce20cfdcf9126044a2368a6ccc8dfc0 Mon Sep 17 00:00:00 2001 From: Mirko Date: Wed, 8 Nov 2023 14:51:19 +0000 Subject: [PATCH 1/5] first commit --- config/chips/L45x_L46x.chip | 2 ++ config/chips/L496x_L4A6x.chip | 2 ++ src/st-flash/flash.c | 24 +++++++++++++++ src/st-flash/flash_opts.c | 18 +++++------- src/stlink-lib/chipid.c | 16 ++++++++-- src/stlink-lib/chipid.h | 2 ++ src/stlink-lib/common.c | 3 ++ src/stlink-lib/common_flash.c | 55 ++++++++++++++++++++++++++++++++++- src/stlink-lib/common_flash.h | 2 ++ 9 files changed, 111 insertions(+), 13 deletions(-) diff --git a/config/chips/L45x_L46x.chip b/config/chips/L45x_L46x.chip index cbe948c1f..1c8fc2e1f 100644 --- a/config/chips/L45x_L46x.chip +++ b/config/chips/L45x_L46x.chip @@ -12,3 +12,5 @@ bootrom_size 0x7000 // 28 KB option_base 0x0 option_size 0x0 flags swo +otp_base 0x1fff7000 +otp_size 0x400 // 1 KB \ No newline at end of file diff --git a/config/chips/L496x_L4A6x.chip b/config/chips/L496x_L4A6x.chip index 24788c092..8a4a93b1c 100644 --- a/config/chips/L496x_L4A6x.chip +++ b/config/chips/L496x_L4A6x.chip @@ -12,3 +12,5 @@ bootrom_size 0x7000 // 28 KB option_base 0x1fff7800 // STM32_L4_OPTION_BYTES_BASE option_size 0x4 // 4 B flags swo +otp_base 0x1fff7000 +otp_size 0x400 // 1 KB \ No newline at end of file diff --git a/src/st-flash/flash.c b/src/st-flash/flash.c index 0577ee179..6553298c3 100644 --- a/src/st-flash/flash.c +++ b/src/st-flash/flash.c @@ -61,6 +61,7 @@ static void usage(void) { puts("example write option control register1 byte: ./st-flash --area=optcr write 0xXXXXXXXX"); puts("example read option control register1 byte: ./st-flash --area=optcr1 read"); puts("example write option control register1 byte: ./st-flash --area=optcr1 write 0xXXXXXXXX"); + puts("example read OTP area: ./st-flash --area=otp read [path]"); } int32_t main(int32_t ac, char** av) { @@ -180,6 +181,18 @@ int32_t main(int32_t ac, char** av) { DLOG("@@@@ Write %d (%0#10x) to option bytes boot address\n", o.val, o.val); err = stlink_write_option_bytes_boot_add32(sl, o.val); + } else if (o.area == FLASH_OTP) { + if(sl->otp_base == 0) { + err = -1; + printf("OTP Write Not implimented\n"); + goto on_error; + } + err = stlink_fwrite_flash(sl, o.filename, o.addr); + + if (err == -1) { + printf("stlink_fwrite_flash() == -1\n"); + goto on_error; + } } else { err = -1; printf("Unknown memory region\n"); @@ -284,6 +297,17 @@ int32_t main(int32_t ac, char** av) { } else { printf("%08x\n",option_byte); } + } else if (o.area == FLASH_OTP) { + if(sl->otp_base == 0) { + err = -1; + printf("OTP Read not implimented\n"); + goto on_error; + } + err = stlink_fread(sl, o.filename, 0, sl->otp_base, sl->otp_size); + if (err == -1) { + printf("could not read OTP area (%d)\n", err); + goto on_error; + } } } diff --git a/src/st-flash/flash_opts.c b/src/st-flash/flash_opts.c index 300203a3f..cf80407d1 100644 --- a/src/st-flash/flash_opts.c +++ b/src/st-flash/flash_opts.c @@ -86,7 +86,6 @@ static int32_t bad_arg(const char *arg) { } int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) { - // defaults memset(o, 0, sizeof(*o)); o->log_level = STND_LOG_LEVEL; @@ -270,13 +269,13 @@ int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) { if (ac != 3) { return invalid_args("read "); } o->filename = av[0]; - uint32_t address; - result = get_integer_from_char_array(av[1], &address); - if (result != 0) { - return bad_arg ("addr"); - } else { - o->addr = (stm32_addr_t) address; - } + uint32_t address; + result = get_integer_from_char_array(av[1], &address); + if (result != 0) { + return bad_arg ("addr"); + } else { + o->addr = (stm32_addr_t) address; + } uint32_t size; result = get_integer_from_char_array(av[2], &size); @@ -288,8 +287,7 @@ int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) { break; } else if (o->area == FLASH_OTP) { - return bad_arg("TODO: otp not implemented yet"); - if (ac > 1) { return invalid_args("otp read: [path]"); } + if (ac > 1 || ac ==0 ) { return invalid_args("otp read: [path]"); } if (ac > 0) { o->filename = av[0]; } break; } else if (o->area == FLASH_OPTION_BYTES) { diff --git a/src/stlink-lib/chipid.c b/src/stlink-lib/chipid.c index 06edb26f3..1b6fc13f7 100644 --- a/src/stlink-lib/chipid.c +++ b/src/stlink-lib/chipid.c @@ -34,6 +34,7 @@ void dump_a_chip(struct stlink_chipid_params *dev) { DLOG("option_base 0x%x\n", dev->option_base); DLOG("option_size 0x%x\n", dev->option_size); DLOG("flags %d\n\n", dev->flags); + DLOG("otp_base %d\n\n", dev->otp_base); } struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chip_id) { @@ -57,7 +58,6 @@ void process_chipfile(char *fname) { // fprintf (stderr, "processing chip-id file %s.\n", fname); fp = fopen(fname, "r"); - if (!fp) { perror(fname); return; @@ -180,8 +180,19 @@ void process_chipfile(char *fname) { fprintf(stderr, "Unknown flags word in %s: '%s'\n", fname, p); } } - sscanf(value, "%x", &ts->flags); + } else if (strcmp(word, "otp_base") == 0) { + buf[strlen(buf) - 1] = 0; // chomp newline + sscanf(buf, "%*s %n", &nc); + if (sscanf(value, "%i", &ts->otp_base) < 1) { + fprintf(stderr, "Failed to parse option size\n"); + } + } else if (strcmp(word, "otp_size") == 0) { + buf[strlen(buf) - 1] = 0; // chomp newline + sscanf(buf, "%*s %n", &nc); + if (sscanf(value, "%i", &ts->otp_size) < 1) { + fprintf(stderr, "Failed to parse option size\n"); + } } else { fprintf(stderr, "Unknown keyword in %s: %s\n", fname, word); } @@ -191,6 +202,7 @@ void process_chipfile(char *fname) { devicelist = ts; } + #if defined(STLINK_HAVE_DIRENT_H) #include diff --git a/src/stlink-lib/chipid.h b/src/stlink-lib/chipid.h index 6726a7420..cf97e6609 100644 --- a/src/stlink-lib/chipid.h +++ b/src/stlink-lib/chipid.h @@ -21,6 +21,8 @@ struct stlink_chipid_params { uint32_t option_base; uint32_t option_size; uint32_t flags; + uint32_t otp_base; + uint32_t otp_size; struct stlink_chipid_params *next; }; diff --git a/src/stlink-lib/common.c b/src/stlink-lib/common.c index dbfcc8b9e..c470f9095 100644 --- a/src/stlink-lib/common.c +++ b/src/stlink-lib/common.c @@ -290,6 +290,9 @@ int32_t stlink_load_device_params(stlink_t *sl) { sl->option_base = params->option_base; sl->option_size = params->option_size; sl->chip_flags = params->flags; + sl->otp_base = params->otp_base; + sl->otp_size = params->otp_size; + // medium and low devices have the same chipid. ram size depends on flash // size. STM32F100xx datasheet Doc ID 16455 Table 2 diff --git a/src/stlink-lib/common_flash.c b/src/stlink-lib/common_flash.c index 3038b53e7..60d8f42fb 100644 --- a/src/stlink-lib/common_flash.c +++ b/src/stlink-lib/common_flash.c @@ -1310,9 +1310,17 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { * If the file is identified to be all-empty and four-bytes aligned, * still flash the whole file even if ignoring message is printed. */ - err = stlink_write_flash(sl, addr, mf.base, + + /* In case the address is within the OTP area we use a different flash method */ + if(addr >= sl->otp_base && addr <= sl->otp_base + sl->otp_size) { + err = stlink_write_otp(sl, addr, mf.base, + (num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty); + } else { + err = stlink_write_flash(sl, addr, mf.base, (num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty, num_empty == mf.len); + } + stlink_fwrite_finalize(sl, addr); unmap_file(&mf); return (err); @@ -1389,6 +1397,22 @@ int32_t stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, uin return 0; } +// Check if an address and size are within the flash (otp area) +int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, uint32_t size) { + uint32_t logvar; + if (addr < sl->otp_base || addr >= (sl->otp_base + sl->otp_size)) { + logvar = sl->otp_base + sl->otp_size - 1; + ELOG("Invalid address, it should be within 0x%08x - 0x%08x\n", sl->otp_base, logvar); + return (-1); + } + if ((addr + size) > (sl->otp_base + sl->otp_size)) { + logvar = sl->otp_base + sl->otp_size - addr; + ELOG("The size exceeds the size of the OTP Area (0x%08x bytes available)\n", logvar); + return (-1); + } + return 0; +} + // Check if an address is aligned with the beginning of a page int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr) { stm32_addr_t page = sl->flash_base; @@ -1408,6 +1432,9 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3 int32_t ret; flash_loader_t fl; ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr); + + (void)eraseonly; + // check addr range is inside the flash stlink_calculate_pagesize(sl, addr); @@ -1437,7 +1464,33 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3 if (eraseonly) { return (0); } + + ret = stlink_flashloader_start(sl, &fl); + if (ret) + return ret; + ret = stlink_flashloader_write(sl, &fl, addr, base, len); + if (ret) + return ret; + ret = stlink_flashloader_stop(sl, &fl); + if (ret) + return ret; + + return (stlink_verify_write_flash(sl, addr, base, len)); +} + +int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len) { + int32_t ret; + flash_loader_t fl; + ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr); + + // Check the address and size validity + if (stlink_check_address_range_validity_otp(sl, addr, len) < 0) { + return (-1); + } + // make sure we've loaded the context with the chip details + stlink_core_id(sl); + ret = stlink_flashloader_start(sl, &fl); if (ret) return ret; diff --git a/src/stlink-lib/common_flash.h b/src/stlink-lib/common_flash.h index 9b2b84057..238f0403e 100644 --- a/src/stlink-lib/common_flash.h +++ b/src/stlink-lib/common_flash.h @@ -44,8 +44,10 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr); int32_t stlink_fcheck_flash(stlink_t *sl, const char *path, stm32_addr_t addr); int32_t stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, uint32_t length); int32_t stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, uint32_t size); +int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, uint32_t size); int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr); int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len, uint8_t eraseonly); +int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len); void stlink_fwrite_finalize(stlink_t *, stm32_addr_t); #endif // COMMON_FLASH_H From b1d99a2fc22af6935f714525641a01483c076b3c Mon Sep 17 00:00:00 2001 From: Mirko Date: Wed, 8 Nov 2023 15:04:10 +0000 Subject: [PATCH 2/5] cleaning ident --- config/chips/L45x_L46x.chip | 2 +- config/chips/L496x_L4A6x.chip | 2 +- src/st-flash/flash.c | 4 ++-- src/st-flash/flash_opts.c | 15 ++++++++------- src/stlink-lib/chipid.c | 2 +- src/stlink-lib/common.c | 1 - 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/config/chips/L45x_L46x.chip b/config/chips/L45x_L46x.chip index 1c8fc2e1f..c32030be9 100644 --- a/config/chips/L45x_L46x.chip +++ b/config/chips/L45x_L46x.chip @@ -13,4 +13,4 @@ option_base 0x0 option_size 0x0 flags swo otp_base 0x1fff7000 -otp_size 0x400 // 1 KB \ No newline at end of file +otp_size 0x400 // 1 KB diff --git a/config/chips/L496x_L4A6x.chip b/config/chips/L496x_L4A6x.chip index 8a4a93b1c..65fa3dcbc 100644 --- a/config/chips/L496x_L4A6x.chip +++ b/config/chips/L496x_L4A6x.chip @@ -13,4 +13,4 @@ option_base 0x1fff7800 // STM32_L4_OPTION_BYTES_BASE option_size 0x4 // 4 B flags swo otp_base 0x1fff7000 -otp_size 0x400 // 1 KB \ No newline at end of file +otp_size 0x400 // 1 KB diff --git a/src/st-flash/flash.c b/src/st-flash/flash.c index 6553298c3..c2cd77a47 100644 --- a/src/st-flash/flash.c +++ b/src/st-flash/flash.c @@ -184,7 +184,7 @@ int32_t main(int32_t ac, char** av) { } else if (o.area == FLASH_OTP) { if(sl->otp_base == 0) { err = -1; - printf("OTP Write Not implimented\n"); + printf("OTP Write NOT implemented\n"); goto on_error; } err = stlink_fwrite_flash(sl, o.filename, o.addr); @@ -300,7 +300,7 @@ int32_t main(int32_t ac, char** av) { } else if (o.area == FLASH_OTP) { if(sl->otp_base == 0) { err = -1; - printf("OTP Read not implimented\n"); + printf("OTP Read NOT implemented\n"); goto on_error; } err = stlink_fread(sl, o.filename, 0, sl->otp_base, sl->otp_size); diff --git a/src/st-flash/flash_opts.c b/src/st-flash/flash_opts.c index cf80407d1..8f88f6ea7 100644 --- a/src/st-flash/flash_opts.c +++ b/src/st-flash/flash_opts.c @@ -86,6 +86,7 @@ static int32_t bad_arg(const char *arg) { } int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) { + // defaults memset(o, 0, sizeof(*o)); o->log_level = STND_LOG_LEVEL; @@ -269,13 +270,13 @@ int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) { if (ac != 3) { return invalid_args("read "); } o->filename = av[0]; - uint32_t address; - result = get_integer_from_char_array(av[1], &address); - if (result != 0) { - return bad_arg ("addr"); - } else { - o->addr = (stm32_addr_t) address; - } + uint32_t address; + result = get_integer_from_char_array(av[1], &address); + if (result != 0) { + return bad_arg ("addr"); + } else { + o->addr = (stm32_addr_t) address; + } uint32_t size; result = get_integer_from_char_array(av[2], &size); diff --git a/src/stlink-lib/chipid.c b/src/stlink-lib/chipid.c index 1b6fc13f7..77cbfb15d 100644 --- a/src/stlink-lib/chipid.c +++ b/src/stlink-lib/chipid.c @@ -58,6 +58,7 @@ void process_chipfile(char *fname) { // fprintf (stderr, "processing chip-id file %s.\n", fname); fp = fopen(fname, "r"); + if (!fp) { perror(fname); return; @@ -202,7 +203,6 @@ void process_chipfile(char *fname) { devicelist = ts; } - #if defined(STLINK_HAVE_DIRENT_H) #include diff --git a/src/stlink-lib/common.c b/src/stlink-lib/common.c index c470f9095..337fe6efa 100644 --- a/src/stlink-lib/common.c +++ b/src/stlink-lib/common.c @@ -293,7 +293,6 @@ int32_t stlink_load_device_params(stlink_t *sl) { sl->otp_base = params->otp_base; sl->otp_size = params->otp_size; - // medium and low devices have the same chipid. ram size depends on flash // size. STM32F100xx datasheet Doc ID 16455 Table 2 if (sl->chip_id == STM32_CHIPID_F1_VL_MD_LD && sl->flash_size < 64 * 1024) { From 3cb15d7da2deb69a38940d1fa82570771252951b Mon Sep 17 00:00:00 2001 From: Mirko Date: Wed, 8 Nov 2023 15:14:19 +0000 Subject: [PATCH 3/5] final --- src/st-flash/flash.c | 1 + src/st-flash/flash_opts.c | 2 +- src/stlink-lib/chipid.c | 2 ++ src/stlink-lib/common_flash.c | 3 --- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/st-flash/flash.c b/src/st-flash/flash.c index c2cd77a47..0b7c0cfca 100644 --- a/src/st-flash/flash.c +++ b/src/st-flash/flash.c @@ -62,6 +62,7 @@ static void usage(void) { puts("example read option control register1 byte: ./st-flash --area=optcr1 read"); puts("example write option control register1 byte: ./st-flash --area=optcr1 write 0xXXXXXXXX"); puts("example read OTP area: ./st-flash --area=otp read [path]"); + puts("example write OTP area: ./st-flash --area=otp write [path] 0xXXXXXXXX"); } int32_t main(int32_t ac, char** av) { diff --git a/src/st-flash/flash_opts.c b/src/st-flash/flash_opts.c index 8f88f6ea7..e2d4154fe 100644 --- a/src/st-flash/flash_opts.c +++ b/src/st-flash/flash_opts.c @@ -86,7 +86,7 @@ static int32_t bad_arg(const char *arg) { } int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) { - + // defaults memset(o, 0, sizeof(*o)); o->log_level = STND_LOG_LEVEL; diff --git a/src/stlink-lib/chipid.c b/src/stlink-lib/chipid.c index 77cbfb15d..ceeed3114 100644 --- a/src/stlink-lib/chipid.c +++ b/src/stlink-lib/chipid.c @@ -35,6 +35,7 @@ void dump_a_chip(struct stlink_chipid_params *dev) { DLOG("option_size 0x%x\n", dev->option_size); DLOG("flags %d\n\n", dev->flags); DLOG("otp_base %d\n\n", dev->otp_base); + DLOG("otp_size %d\n\n", dev->otp_size); } struct stlink_chipid_params *stlink_chipid_get_params(uint32_t chip_id) { @@ -181,6 +182,7 @@ void process_chipfile(char *fname) { fprintf(stderr, "Unknown flags word in %s: '%s'\n", fname, p); } } + sscanf(value, "%x", &ts->flags); } else if (strcmp(word, "otp_base") == 0) { buf[strlen(buf) - 1] = 0; // chomp newline diff --git a/src/stlink-lib/common_flash.c b/src/stlink-lib/common_flash.c index 60d8f42fb..5005a632f 100644 --- a/src/stlink-lib/common_flash.c +++ b/src/stlink-lib/common_flash.c @@ -1320,7 +1320,6 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { (num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty, num_empty == mf.len); } - stlink_fwrite_finalize(sl, addr); unmap_file(&mf); return (err); @@ -1433,8 +1432,6 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3 flash_loader_t fl; ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr); - (void)eraseonly; - // check addr range is inside the flash stlink_calculate_pagesize(sl, addr); From e122764f214fb9821b173a63f7ae18690611dc0a Mon Sep 17 00:00:00 2001 From: Mirko Date: Wed, 8 Nov 2023 22:58:05 +0000 Subject: [PATCH 4/5] forgot to include this --- inc/stlink.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/inc/stlink.h b/inc/stlink.h index dec608e97..557a9eeaa 100644 --- a/inc/stlink.h +++ b/inc/stlink.h @@ -232,6 +232,9 @@ struct _stlink { uint32_t chip_flags; // stlink_chipid_params.flags, set by stlink_load_device_params(), values: CHIP_F_xxx uint32_t max_trace_freq; // set by stlink_open_usb() + + uint32_t otp_base; + uint32_t otp_size; }; /* Functions defined in common.c */ From 033007fd2713aba630d28c706499959dc8792277 Mon Sep 17 00:00:00 2001 From: Mirko Matonti Date: Thu, 23 Nov 2023 17:46:09 +0000 Subject: [PATCH 5/5] pr adjustment --- src/stlink-lib/common_flash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stlink-lib/common_flash.c b/src/stlink-lib/common_flash.c index 5005a632f..7172352ee 100644 --- a/src/stlink-lib/common_flash.c +++ b/src/stlink-lib/common_flash.c @@ -1312,7 +1312,7 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { */ /* In case the address is within the OTP area we use a different flash method */ - if(addr >= sl->otp_base && addr <= sl->otp_base + sl->otp_size) { + if(addr >= sl->otp_base && addr < sl->otp_base + sl->otp_size) { err = stlink_write_otp(sl, addr, mf.base, (num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty); } else { @@ -1404,7 +1404,7 @@ int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, ELOG("Invalid address, it should be within 0x%08x - 0x%08x\n", sl->otp_base, logvar); return (-1); } - if ((addr + size) > (sl->otp_base + sl->otp_size)) { + if ((addr + size) >= (sl->otp_base + sl->otp_size)) { logvar = sl->otp_base + sl->otp_size - addr; ELOG("The size exceeds the size of the OTP Area (0x%08x bytes available)\n", logvar); return (-1); @@ -1431,7 +1431,7 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3 int32_t ret; flash_loader_t fl; ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr); - + // check addr range is inside the flash stlink_calculate_pagesize(sl, addr);