From: Paul Fertser Date: Fri, 23 Jan 2015 09:33:50 +0000 (+0300) Subject: flash/nor/stm32l: fix mass erase X-Git-Tag: v0.9.0-rc1~161 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=cd72808889e426d15c07949c8fcea50dc40fe393;hp=c9639ae2acb5554c7b61cda2b4251b4e22223d8b flash/nor/stm32l: fix mass erase Topaz reports on http://sourceforge.net/p/openocd/tickets/87/ that protection level constants are mixed up. This leads to device ending up in protection level 1 after mass erase. Additional work is required to actually put the device in RDP Level 1 and then back to Level 0, as Option bootloader launch is a special kind of full target reset. To be able to flash properly after mass_erase a "reset init" is needed (it's anyway recommended to always perform it before any flash operation). Change-Id: I9a838909458039bb0114d3019723bf134fa4d7c9 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/2490 Tested-by: jenkins Reviewed-by: Spencer Oliver --- diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index e5b66cf7fd..13db7b924a 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -95,8 +95,8 @@ /* option bytes */ #define OPTION_BYTES_ADDRESS 0x1FF80000 -#define OPTION_BYTE_0_PR1 0x015500AA -#define OPTION_BYTE_0_PR0 0x01FF0011 +#define OPTION_BYTE_0_PR1 0xFFFF0000 +#define OPTION_BYTE_0_PR0 0xFF5500AA static int stm32lx_unlock_program_memory(struct flash_bank *bank); static int stm32lx_lock_program_memory(struct flash_bank *bank); @@ -1222,6 +1222,26 @@ static int stm32lx_wait_status_busy(struct flash_bank *bank, int timeout) return retval; } +static int stm32lx_obl_launch(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; + int retval; + + /* This will fail as the target gets immediately rebooted */ + target_write_u32(target, stm32lx_info->flash_base + FLASH_PECR, + FLASH_PECR__OBL_LAUNCH); + + size_t tries = 10; + do { + target_halt(target); + retval = target_poll(target); + } while (--tries > 0 && + (retval != ERROR_OK || target->state != TARGET_HALTED)); + + return tries ? ERROR_OK : ERROR_FAIL; +} + static int stm32lx_mass_erase(struct flash_bank *bank) { int retval; @@ -1240,18 +1260,33 @@ static int stm32lx_mass_erase(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - /* mass erase flash memory, write 0x015500AA option byte address 0*/ - /* pass the RDP privilege to 1 */ + /* mass erase flash memory */ + /* set the RDP protection level to 1 */ retval = target_write_u32(target, OPTION_BYTES_ADDRESS, OPTION_BYTE_0_PR1); + if (retval != ERROR_OK) + return retval; - /* restore the RDP privilege to 0 */ + retval = stm32lx_obl_launch(bank); + if (retval != ERROR_OK) + return retval; + + retval = stm32lx_unlock_options_bytes(bank); + if (retval != ERROR_OK) + return retval; + + /* set the RDP protection level to 0 */ retval = target_write_u32(target, OPTION_BYTES_ADDRESS, OPTION_BYTE_0_PR0); + if (retval != ERROR_OK) + return retval; - /* the mass erase occur when the privilege go back to 0 */ retval = stm32lx_wait_status_busy(bank, 30000); if (retval != ERROR_OK) return retval; + retval = stm32lx_obl_launch(bank); + if (retval != ERROR_OK) + return retval; + retval = target_read_u32(target, stm32lx_info->flash_base + FLASH_PECR, ®32); if (retval != ERROR_OK) return retval;