X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstm32lx.c;h=ce41f9421ff18670a405c68f6d7dd0c65fab8944;hp=3bc825acdff051ff68896044a94993d2fc2d864f;hb=9b045f62f4bac2411a7662d8b312637347aac73d;hpb=38dc2530013a992b98e7926447378dae4f33ed59;ds=sidebyside diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 3bc825acdf..ce41f9421f 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -119,7 +119,6 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector); static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank); struct stm32lx_flash_bank { - struct working_area *write_algorithm; int probed; }; @@ -142,7 +141,6 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command) bank->driver_priv = stm32lx_info; - stm32lx_info->write_algorithm = NULL; stm32lx_info->probed = 0; return ERROR_OK; @@ -213,9 +211,9 @@ static int stm32lx_protect(struct flash_bank *bank, int set, int first, static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count) { - struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; struct target *target = bank->target; uint32_t buffer_size = 4096 * 4; + struct working_area *write_algorithm; struct working_area *source; uint32_t address = bank->base + offset; @@ -264,17 +262,17 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, /* Add bytes to make 4byte aligned */ reg32 += (4 - (reg32 % 4)) % 4; retval = target_alloc_working_area(target, reg32, - &stm32lx_info->write_algorithm); + &write_algorithm); if (retval != ERROR_OK) return retval; /* Write the flashing code */ retval = target_write_buffer(target, - stm32lx_info->write_algorithm->address, + write_algorithm->address, sizeof(stm32lx_flash_write_code), (uint8_t *)stm32lx_flash_write_code); if (retval != ERROR_OK) { - target_free_working_area(target, stm32lx_info->write_algorithm); + target_free_working_area(target, write_algorithm); return retval; } @@ -287,10 +285,9 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, buffer_size /= 2; if (buffer_size <= 256) { - /* if we already allocated the writing code, but failed to get a + /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ - if (stm32lx_info->write_algorithm) - target_free_working_area(target, stm32lx_info->write_algorithm); + target_free_working_area(target, write_algorithm); LOG_WARNING("no large enough working area available, can't do block memory writes"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -310,7 +307,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, retval = stm32lx_enable_write_half_page(bank); if (retval != ERROR_OK) { target_free_working_area(target, source); - target_free_working_area(target, stm32lx_info->write_algorithm); + target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); @@ -341,7 +338,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, /* 5: Execute the bunch of code */ retval = target_run_algorithm(target, 0, NULL, sizeof(reg_params) / sizeof(*reg_params), reg_params, - stm32lx_info->write_algorithm->address, 0, 20000, &armv7m_info); + write_algorithm->address, 0, 20000, &armv7m_info); if (retval != ERROR_OK) break; @@ -359,7 +356,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, uint8_t *buffer, retval = stm32lx_lock_program_memory(bank); target_free_working_area(target, source); - target_free_working_area(target, stm32lx_info->write_algorithm); + target_free_working_area(target, write_algorithm); destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); @@ -402,13 +399,20 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer, } if (halfpages_number) { - retval = stm32lx_write_half_pages(bank, buffer, offset, 128 - * halfpages_number); - if (retval != ERROR_OK) - return ERROR_FAIL; + retval = stm32lx_write_half_pages(bank, buffer, offset, 128 * halfpages_number); + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) { + /* attempt slow memory writes */ + LOG_WARNING("couldn't use block writes, falling back to single memory accesses"); + halfpages_number = 0; + words_remaining = (count / 4); + } else { + if (retval != ERROR_OK) + return ERROR_FAIL; + } } bytes_written = 128 * halfpages_number; + address += bytes_written; retval = stm32lx_unlock_program_memory(bank); if (retval != ERROR_OK) @@ -461,7 +465,8 @@ static int stm32lx_probe(struct flash_bank *bank) struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; int i; - uint16_t flash_size; + uint16_t flash_size_in_kb; + uint16_t max_flash_size_in_kb; uint32_t device_id; stm32lx_info->probed = 0; @@ -473,29 +478,36 @@ static int stm32lx_probe(struct flash_bank *bank) LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id); - if ((device_id & 0xfff) != 0x416) { + /* set max flash size depending on family */ + switch (device_id & 0xfff) { + case 0x416: + max_flash_size_in_kb = 128; + break; + case 0x436: + max_flash_size_in_kb = 384; + break; + default: LOG_WARNING("Cannot identify target as a STM32L family."); return ERROR_FAIL; } /* get flash size from target. */ - retval = target_read_u16(target, F_SIZE, &flash_size); - if (retval != ERROR_OK) - return retval; + retval = target_read_u16(target, F_SIZE, &flash_size_in_kb); - /* check for valid flash size */ - if (flash_size == 0xffff) { - /* number of sectors incorrect on revA */ - LOG_ERROR("STM32 flash size failed, probe inaccurate"); - return ERROR_FAIL; + /* failed reading flash size or flash size invalid (early silicon), + * default to max target family */ + if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { + LOG_WARNING("STM32 flash size failed, probe inaccurate - assuming %dk flash", + max_flash_size_in_kb); + flash_size_in_kb = max_flash_size_in_kb; } /* STM32L - we have 32 sectors, 16 pages per sector -> 512 pages * 16 pages for a protection area */ /* calculate numbers of sectors (4kB per sector) */ - int num_sectors = (flash_size * 1024) / FLASH_SECTOR_SIZE; - LOG_INFO("flash size = %dkbytes", flash_size); + int num_sectors = (flash_size_in_kb * 1024) / FLASH_SECTOR_SIZE; + LOG_INFO("flash size = %dkbytes", flash_size_in_kb); if (bank->sectors) { free(bank->sectors); @@ -503,7 +515,7 @@ static int stm32lx_probe(struct flash_bank *bank) } bank->base = FLASH_BANK0_ADDRESS; - bank->size = flash_size * 1024; + bank->size = flash_size_in_kb * 1024; bank->num_sectors = num_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); if (bank->sectors == NULL) { @@ -609,6 +621,41 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) case 0x1008: snprintf(buf, buf_size, "Y"); break; + + case 0x1018: + snprintf(buf, buf_size, "X"); + break; + + case 0x1038: + snprintf(buf, buf_size, "W"); + break; + + case 0x1078: + snprintf(buf, buf_size, "V"); + break; + + default: + snprintf(buf, buf_size, "unknown"); + break; + } + } else if ((device_id & 0xfff) == 0x436) { + printed = snprintf(buf, buf_size, "stm32lx (HD) - Rev: "); + buf += printed; + buf_size -= printed; + + switch (device_id >> 16) { + case 0x1000: + snprintf(buf, buf_size, "A"); + break; + + case 0x1008: + snprintf(buf, buf_size, "Z"); + break; + + case 0x1018: + snprintf(buf, buf_size, "Y"); + break; + default: snprintf(buf, buf_size, "unknown"); break;