diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 88e16a0..7a438da 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -290,7 +290,6 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->opt_targetid = strtol(optarg, NULL, 0); break; case 'M': - opt->opt_mode = BMP_MODE_MONITOR; if (optarg) opt->opt_monitor = optarg; break; @@ -321,7 +320,11 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) if (opt->opt_mode == BMP_MODE_DEBUG) opt->opt_mode = BMP_MODE_FLASH_WRITE; opt->opt_flash_file = argv[optind]; + } else if ((opt->opt_mode == BMP_MODE_DEBUG) && + (opt->opt_monitor)) { + opt->opt_mode = BMP_MODE_MONITOR; // To avoid DEBUG mode } + /* Checks */ if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) || (opt->opt_mode == BMP_MODE_SWJ_TEST) || @@ -448,10 +451,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) default: DEBUG_WARN("No test for this core type yet\n"); } - } else if (opt->opt_mode == BMP_MODE_MONITOR) { - res = command_process(t, opt->opt_monitor); - if (res) - DEBUG_WARN("Command \"%s\" failed\n", opt->opt_monitor); } if ((opt->opt_mode == BMP_MODE_TEST) || (opt->opt_mode == BMP_MODE_SWJ_TEST)) @@ -480,9 +479,14 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) if (opt->opt_flash_size < map.size) /* restrict to size given on command line */ map.size = opt->opt_flash_size; + if (opt->opt_monitor) { + res = command_process(t, opt->opt_monitor); + if (res) + DEBUG_WARN("Command \"%s\" failed\n", opt->opt_monitor); + } if (opt->opt_mode == BMP_MODE_RESET) { target_reset(t); - } else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) { + } else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) { DEBUG_INFO("Erase %zu bytes at 0x%08" PRIx32 "\n", opt->opt_flash_size, opt->opt_flash_start); unsigned int erased = target_flash_erase(t, opt->opt_flash_start, @@ -510,6 +514,8 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) unsigned int flashed = target_flash_write(t, opt->opt_flash_start, map.data, map.size); /* Buffered write cares for padding*/ + if (!flashed) + flashed = target_flash_done(t); if (flashed) { DEBUG_WARN("Flashing failed!\n"); res = -1; @@ -518,7 +524,6 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) DEBUG_INFO("Success!\n"); } } - target_flash_done(t); uint32_t end_time = platform_time_ms(); DEBUG_WARN("Flash Write succeeded for %d bytes, %8.3f kiB/s\n", (int)map.size, (((map.size * 1.0)/(end_time - start_time)))); diff --git a/src/target/stm32g0.c b/src/target/stm32g0.c index d563790..43c58c3 100644 --- a/src/target/stm32g0.c +++ b/src/target/stm32g0.c @@ -52,6 +52,9 @@ #define FLASH_MEMORY_SIZE 0x1FFF75E0 #define FLASH_PAGE_SIZE 0x800 #define FLASH_BANK2_START_PAGE_NB 256U +#define FLASH_OTP_START 0x1FFF7000 +#define FLASH_OTP_SIZE 0x400 +#define FLASH_OTP_BLOCKSIZE 0x8 #define FLASH_SIZE_MAX_G03_4 (64U * 1024U) // 64 kiB #define FLASH_SIZE_MAX_G05_6 (64U * 1024U) // 64 kiB #define FLASH_SIZE_MAX_G07_8 (128U * 1024U) // 128 kiB @@ -189,7 +192,7 @@ static void stm32g0_add_flash(target *t, uint32_t addr, size_t length, f->blocksize = blocksize; f->erase = stm32g0_flash_erase; f->write = stm32g0_flash_write; - f->buf_size = FLASH_PAGE_SIZE; + f->buf_size = blocksize; f->erased = 0xFF; target_add_flash(t, f); } @@ -249,6 +252,9 @@ bool stm32g0_probe(target *t) priv_storage->irreversible_enabled = false; t->target_storage = (void*)priv_storage; + /* OTP Flash area */ + stm32g0_add_flash(t, FLASH_OTP_START, FLASH_OTP_SIZE, FLASH_OTP_BLOCKSIZE); + return true; } @@ -311,6 +317,7 @@ static void stm32g0_flash_lock(target *t) /* * Flash erasure function. + * OTP case: this function clears any previous error and returns. */ static int stm32g0_flash_erase(struct target_flash *f, target_addr addr, size_t len) @@ -328,11 +335,6 @@ static int stm32g0_flash_erase(struct target_flash *f, target_addr addr, if (len == (size_t)0U) goto exit_cleanup; - nb_pages_to_erase = (uint16_t)((len - 1U) / f->blocksize) + 1U; - if (t->idcode == STM32G0B_C) // Dual-bank devices - bank1_end_page_nb = ((f->length / 2U) - 1U) / f->blocksize; - page_nb = (uint16_t)((addr - f->start) / f->blocksize); - /* Wait for Flash ready */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY_MASK) { if (target_check_error(t)) @@ -342,6 +344,14 @@ static int stm32g0_flash_erase(struct target_flash *f, target_addr addr, /* Clear any previous programming error */ target_mem_write32(t, FLASH_SR, target_mem_read32(t, FLASH_SR)); + if (addr >= (target_addr)FLASH_OTP_START) + goto exit_cleanup; + + nb_pages_to_erase = (uint16_t)((len - 1U) / f->blocksize) + 1U; + if (t->idcode == STM32G0B_C) // Dual-bank devices + bank1_end_page_nb = ((f->length / 2U) - 1U) / f->blocksize; + page_nb = (uint16_t)((addr - f->start) / f->blocksize); + stm32g0_flash_unlock(t); do { @@ -392,12 +402,20 @@ exit_cleanup: * The SR is supposed to be ready and free of any error. * After a successful programming, the EMPTY bit is cleared to allow rebooting * in Main Flash memory without power cycle. + * OTP area is programmed as the "program" area. It can be programmed 8-bytes + * by 8-bytes. */ static int stm32g0_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len) { target *t = f->t; int ret = 0; + struct stm32g0_priv_s *ps = (struct stm32g0_priv_s*)t->target_storage; + + if ((dest >= (target_addr)FLASH_OTP_START) && !ps->irreversible_enabled) { + tc_printf(t, "Irreversible operations disabled\n"); + goto exit_error; + } stm32g0_flash_unlock(t);