X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fstm32x.c;h=e151fc573811ffd0bb6f6d4710eabeaa76c92865;hb=0643263d68bcddc56eaa7e3678b7502798410711;hp=1b821059c6fa038b80d9903f4a31189db586e748;hpb=ab28153685f44a5fab9a0d346239f116fd996a7a;p=openocd.git diff --git a/src/flash/stm32x.c b/src/flash/stm32x.c index 1b821059c6..e151fc5738 100644 --- a/src/flash/stm32x.c +++ b/src/flash/stm32x.c @@ -37,23 +37,23 @@ #include #include -int stm32x_register_commands(struct command_context_s *cmd_ctx); -int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); -int stm32x_erase(struct flash_bank_s *bank, int first, int last); -int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last); -int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); -int stm32x_probe(struct flash_bank_s *bank); -int stm32x_auto_probe(struct flash_bank_s *bank); -int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int stm32x_protect_check(struct flash_bank_s *bank); -int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size); +static int stm32x_register_commands(struct command_context_s *cmd_ctx); +static int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); +static int stm32x_erase(struct flash_bank_s *bank, int first, int last); +static int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last); +static int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); +static int stm32x_probe(struct flash_bank_s *bank); +static int stm32x_auto_probe(struct flash_bank_s *bank); +//static int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int stm32x_protect_check(struct flash_bank_s *bank); +static int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size); -int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); -int stm32x_mass_erase(struct flash_bank_s *bank); +static int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +static int stm32x_mass_erase(struct flash_bank_s *bank); flash_driver_t stm32x_flash = { @@ -70,7 +70,7 @@ flash_driver_t stm32x_flash = .info = stm32x_info }; -int stm32x_register_commands(struct command_context_s *cmd_ctx) +static int stm32x_register_commands(struct command_context_s *cmd_ctx) { command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stm32x", NULL, COMMAND_ANY, "stm32x flash specific commands"); @@ -89,7 +89,7 @@ int stm32x_register_commands(struct command_context_s *cmd_ctx) /* flash bank stm32x 0 0 */ -int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) +static int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) { stm32x_flash_bank_t *stm32x_info; @@ -108,7 +108,7 @@ int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char return ERROR_OK; } -u32 stm32x_get_flash_status(flash_bank_t *bank) +static u32 stm32x_get_flash_status(flash_bank_t *bank) { target_t *target = bank->target; u32 status; @@ -118,8 +118,9 @@ u32 stm32x_get_flash_status(flash_bank_t *bank) return status; } -u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout) +static u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout) { + target_t *target = bank->target; u32 status; /* wait for busy to clear */ @@ -128,11 +129,15 @@ u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout) LOG_DEBUG("status: 0x%x", status); alive_sleep(1); } - + /* Clear but report errors */ + if (status & (FLASH_WRPRTERR|FLASH_PGERR)) + { + target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR|FLASH_PGERR); + } return status; } -int stm32x_read_options(struct flash_bank_s *bank) +static int stm32x_read_options(struct flash_bank_s *bank) { u32 optiondata; stm32x_flash_bank_t *stm32x_info = NULL; @@ -160,7 +165,7 @@ int stm32x_read_options(struct flash_bank_s *bank) return ERROR_OK; } -int stm32x_erase_options(struct flash_bank_s *bank) +static int stm32x_erase_options(struct flash_bank_s *bank) { stm32x_flash_bank_t *stm32x_info = NULL; target_t *target = bank->target; @@ -197,7 +202,7 @@ int stm32x_erase_options(struct flash_bank_s *bank) return ERROR_OK; } -int stm32x_write_options(struct flash_bank_s *bank) +static int stm32x_write_options(struct flash_bank_s *bank) { stm32x_flash_bank_t *stm32x_info = NULL; target_t *target = bank->target; @@ -281,7 +286,7 @@ int stm32x_write_options(struct flash_bank_s *bank) return ERROR_OK; } -int stm32x_protect_check(struct flash_bank_s *bank) +static int stm32x_protect_check(struct flash_bank_s *bank) { target_t *target = bank->target; stm32x_flash_bank_t *stm32x_info = bank->driver_priv; @@ -352,7 +357,7 @@ int stm32x_protect_check(struct flash_bank_s *bank) return ERROR_OK; } -int stm32x_erase(struct flash_bank_s *bank, int first, int last) +static int stm32x_erase(struct flash_bank_s *bank, int first, int last) { target_t *target = bank->target; int i; @@ -393,7 +398,7 @@ int stm32x_erase(struct flash_bank_s *bank, int first, int last) return ERROR_OK; } -int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last) +static int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last) { stm32x_flash_bank_t *stm32x_info = NULL; target_t *target = bank->target; @@ -480,11 +485,11 @@ int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last) return stm32x_write_options(bank); } -int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +static int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { stm32x_flash_bank_t *stm32x_info = bank->driver_priv; target_t *target = bank->target; - u32 buffer_size = 8192; + u32 buffer_size = 16384; working_area_t *source; u32 address = bank->base + offset; reg_param_t reg_params[4]; @@ -508,7 +513,7 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co 0x01, 0x3A, /* subs r2, r2, #1 */ 0xED, 0xD1, /* bne write */ /* exit: */ - 0xFE, 0xE7, /* b exit */ + 0xFE, 0xE7, /* b exit */ 0x10, 0x20, 0x02, 0x40, /* STM32_FLASH_CR: .word 0x40022010 */ 0x0C, 0x20, 0x02, 0x40 /* STM32_FLASH_SR: .word 0x4002200C */ }; @@ -565,8 +570,20 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co break; } - if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14) + if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_PGERR) { + LOG_ERROR("flash memory not erased before writing"); + /* Clear but report errors */ + target_write_u32(target, STM32_FLASH_SR, FLASH_PGERR); + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + if (buf_get_u32(reg_params[3].value, 0, 32) & FLASH_WRPRTERR) + { + LOG_ERROR("flash memory write protected"); + /* Clear but report errors */ + target_write_u32(target, STM32_FLASH_SR, FLASH_WRPRTERR); retval = ERROR_FLASH_OPERATION_FAILED; break; } @@ -587,7 +604,7 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co return retval; } -int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +static int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { target_t *target = bank->target; u32 words_remaining = (count / 2); @@ -595,7 +612,7 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) u32 address = bank->base + offset; u32 bytes_written = 0; u8 status; - u32 retval; + int retval; if (bank->target->state != TARGET_HALTED) { @@ -641,15 +658,24 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) while (words_remaining > 0) { + u16 value; + memcpy(&value, buffer + bytes_written, sizeof(u16)); + target_write_u32(target, STM32_FLASH_CR, FLASH_PG); - target_write_u16(target, address, *(u16*)(buffer + bytes_written)); + target_write_u16(target, address, value); status = stm32x_wait_status_busy(bank, 5); if( status & FLASH_WRPRTERR ) + { + LOG_ERROR("flash memory not erased before writing"); return ERROR_FLASH_OPERATION_FAILED; + } if( status & FLASH_PGERR ) + { + LOG_ERROR("flash memory write protected"); return ERROR_FLASH_OPERATION_FAILED; + } bytes_written += 2; words_remaining--; @@ -658,25 +684,24 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) if (bytes_remaining) { - u8 last_halfword[2] = {0xff, 0xff}; - int i = 0; - - while(bytes_remaining > 0) - { - last_halfword[i++] = *(buffer + bytes_written); - bytes_remaining--; - bytes_written++; - } - + u16 value = 0xffff; + memcpy(&value, buffer + bytes_written, bytes_remaining); + target_write_u32(target, STM32_FLASH_CR, FLASH_PG); - target_write_u16(target, address, *(u16*)last_halfword); + target_write_u16(target, address, value); status = stm32x_wait_status_busy(bank, 5); if( status & FLASH_WRPRTERR ) + { + LOG_ERROR("flash memory not erased before writing"); return ERROR_FLASH_OPERATION_FAILED; + } if( status & FLASH_PGERR ) + { + LOG_ERROR("flash memory write protected"); return ERROR_FLASH_OPERATION_FAILED; + } } target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); @@ -684,7 +709,7 @@ int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) return ERROR_OK; } -int stm32x_probe(struct flash_bank_s *bank) +static int stm32x_probe(struct flash_bank_s *bank) { target_t *target = bank->target; stm32x_flash_bank_t *stm32x_info = bank->driver_priv; @@ -757,6 +782,21 @@ int stm32x_probe(struct flash_bank_s *bank) num_pages = 512; } } + else if ((device_id & 0x7ff) == 0x418) + { + /* connectivity line density - we have 1k pages + * 4 pages for a protection area */ + page_size = 1024; + stm32x_info->ppage_size = 4; + + /* check for early silicon */ + if (num_pages == 0xffff) + { + /* number of sectors incorrect on revZ */ + LOG_WARNING( "STM32 flash size failed, probe inaccurate - assuming 256k flash" ); + num_pages = 256; + } + } else { LOG_WARNING( "Cannot identify target as a STM32 family." ); @@ -786,7 +826,7 @@ int stm32x_probe(struct flash_bank_s *bank) return ERROR_OK; } -int stm32x_auto_probe(struct flash_bank_s *bank) +static int stm32x_auto_probe(struct flash_bank_s *bank) { stm32x_flash_bank_t *stm32x_info = bank->driver_priv; if (stm32x_info->probed) @@ -794,12 +834,14 @@ int stm32x_auto_probe(struct flash_bank_s *bank) return stm32x_probe(bank); } -int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +#if 0 +static int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { return ERROR_OK; } +#endif -int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size) +static int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size) { target_t *target = bank->target; u32 device_id; @@ -875,6 +917,23 @@ int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size) break; } } + else if ((device_id & 0x7ff) == 0x418) + { + printed = snprintf(buf, buf_size, "stm32x (Connectivity) - Rev: "); + buf += printed; + buf_size -= printed; + + switch(device_id >> 16) + { + case 0x1000: + snprintf(buf, buf_size, "A"); + break; + + default: + snprintf(buf, buf_size, "unknown"); + break; + } + } else { snprintf(buf, buf_size, "Cannot identify target as a stm32x\n"); @@ -884,7 +943,7 @@ int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size) return ERROR_OK; } -int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { flash_bank_t *bank; target_t *target = NULL; @@ -933,7 +992,7 @@ int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, cha return ERROR_OK; } -int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { flash_bank_t *bank; target_t *target = NULL; @@ -979,7 +1038,7 @@ int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, c return ERROR_OK; } -int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { flash_bank_t *bank; u32 optionbyte; @@ -1038,7 +1097,7 @@ int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char * return ERROR_OK; } -int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { flash_bank_t *bank; target_t *target = NULL; @@ -1114,7 +1173,7 @@ int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char return ERROR_OK; } -int stm32x_mass_erase(struct flash_bank_s *bank) +static int stm32x_mass_erase(struct flash_bank_s *bank) { target_t *target = bank->target; u32 status; @@ -1152,7 +1211,7 @@ int stm32x_mass_erase(struct flash_bank_s *bank) return ERROR_OK; } -int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { flash_bank_t *bank; int i;