X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstm32lx.c;h=17ac6f080093b0f5e6f6c36d90e4688c3da35928;hp=58a2a80b02edb8a1010ee21342b7a41e94ded778;hb=4da4e1cfb7d93dcedc333c11c787b83b8baf7dfa;hpb=9f0cba528a163645c8ecace413731c23310f2c26 diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 58a2a80b02..17ac6f0800 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]); @@ -409,6 +406,7 @@ static int stm32lx_write(struct flash_bank *bank, uint8_t *buffer, } bytes_written = 128 * halfpages_number; + address += bytes_written; retval = stm32lx_unlock_program_memory(bank); if (retval != ERROR_OK) @@ -461,9 +459,9 @@ 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; - uint32_t reg32; stm32lx_info->probed = 0; @@ -474,87 +472,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; } - /* Read the RDP byte and check if it is 0xAA */ - uint8_t rdp; - retval = target_read_u32(target, FLASH_OBR, ®32); - if (retval != ERROR_OK) - return retval; - rdp = reg32 & 0xFF; - if (rdp != 0xAA) { - /* - * Unlocking the option byte is done by unlocking the PECR, then - * by writing the 2 option byte keys to OPTKEYR - */ - - /* To unlock the PECR write the 2 PEKEY to the PEKEYR register */ - retval = target_write_u32(target, FLASH_PEKEYR, PEKEY1); - if (retval != ERROR_OK) - return retval; - - retval = target_write_u32(target, FLASH_PEKEYR, PEKEY2); - if (retval != ERROR_OK) - return retval; - - /* Make sure it worked */ - retval = target_read_u32(target, FLASH_PECR, ®32); - if (retval != ERROR_OK) - return retval; - - if (reg32 & FLASH_PECR__PELOCK) - return ERROR_FLASH_OPERATION_FAILED; - - retval = target_write_u32(target, FLASH_OPTKEYR, OPTKEY1); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, FLASH_OPTKEYR, OPTKEY2); - if (retval != ERROR_OK) - return retval; - - retval = target_read_u32(target, FLASH_PECR, ®32); - if (retval != ERROR_OK) - return retval; - - if (reg32 & FLASH_PECR__OPTLOCK) { - LOG_ERROR("OPTLOCK is not cleared"); - return ERROR_FLASH_OPERATION_FAILED; - } - - /* Then, write RDP to 0x00 to set level 1 */ - reg32 = ((~0xAA) << 16) | (0xAA); - retval = target_write_u32(target, OB_RDP, reg32); - if (retval != ERROR_OK) - return retval; - - /* Set Automatic update of the option byte, by setting OBL_LAUNCH in FLASH_PECR */ - reg32 = FLASH_PECR__OBL_LAUNCH; - retval = target_write_u32(target, FLASH_PECR, reg32); - if (retval != ERROR_OK) - return retval; - } - /* 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); @@ -562,7 +509,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) { @@ -668,6 +615,37 @@ 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; + default: snprintf(buf, buf_size, "unknown"); break;