flash/nor/stm32f1x: lock flash in case of error 10/6710/6
authorTomas Vanek <vanekt@fbl.cz>
Tue, 16 Nov 2021 19:12:53 +0000 (20:12 +0100)
committerTomas Vanek <vanekt@fbl.cz>
Wed, 13 Apr 2022 16:56:18 +0000 (16:56 +0000)
The current code locks the flash controller in case of error during
flash write only. An error in other flash operations may cause the
flash is left unlocked.

Implement locking also after error in erase, mass erase, options
write and erase.

Change-Id: I26c2ed7914e7847122306f29b777b9eefd1dc580
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/6710
Tested-by: jenkins
Reviewed-by: Tarek BOCHKATI <tarek.bouchkati@gmail.com>
src/flash/nor/stm32f1x.c

index 26231e9cbbab789cda33438cfc533e20b5759dee..8e66af368fa642138903d95fbb3459981e455f54 100644 (file)
@@ -261,36 +261,39 @@ static int stm32x_erase_options(struct flash_bank *bank)
        int retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY1);
        if (retval != ERROR_OK)
                return retval;
-
        retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        /* unlock option flash registers */
        retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
        retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        /* erase option bytes */
        retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_OPTWRE);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
        retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTER | FLASH_STRT | FLASH_OPTWRE);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        /* clear read protection option byte
         * this will also force a device unlock if set */
        stm32x_info->option_bytes.rdp = stm32x_info->default_rdp;
 
        return ERROR_OK;
+
+flash_lock:
+       target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK);
+       return retval;
 }
 
 static int stm32x_write_options(struct flash_bank *bank)
@@ -306,20 +309,20 @@ static int stm32x_write_options(struct flash_bank *bank)
                return retval;
        retval = target_write_u32(target, STM32_FLASH_KEYR_B0, KEY2);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        /* unlock option flash registers */
        retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY1);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
        retval = target_write_u32(target, STM32_FLASH_OPTKEYR_B0, KEY2);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        /* program option bytes */
        retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_OPTPG | FLASH_OPTWRE);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        uint8_t opt_bytes[16];
 
@@ -338,14 +341,14 @@ static int stm32x_write_options(struct flash_bank *bank)
         * https://review.openocd.org/c/openocd/+/480
         */
        retval = stm32x_write_block(bank, opt_bytes, STM32_OB_RDP, sizeof(opt_bytes) / 2);
-       if (retval != ERROR_OK)
-               return retval;
 
-       retval = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return ERROR_OK;
+flash_lock:
+       {
+               int retval2 = target_write_u32(target, STM32_FLASH_CR_B0, FLASH_LOCK);
+               if (retval == ERROR_OK)
+                       retval = retval2;
+       }
+       return retval;
 }
 
 static int stm32x_protect_check(struct flash_bank *bank)
@@ -389,31 +392,33 @@ static int stm32x_erase(struct flash_bank *bank, unsigned int first,
                return retval;
        retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        for (unsigned int i = first; i <= last; i++) {
                retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER);
                if (retval != ERROR_OK)
-                       return retval;
+                       goto flash_lock;
                retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_AR),
                                bank->base + bank->sectors[i].offset);
                if (retval != ERROR_OK)
-                       return retval;
+                       goto flash_lock;
                retval = target_write_u32(target,
                                stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_PER | FLASH_STRT);
                if (retval != ERROR_OK)
-                       return retval;
+                       goto flash_lock;
 
                retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
                if (retval != ERROR_OK)
-                       return retval;
+                       goto flash_lock;
        }
 
-       retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return ERROR_OK;
+flash_lock:
+       {
+               int retval2 = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
+               if (retval == ERROR_OK)
+                       retval = retval2;
+       }
+       return retval;
 }
 
 static int stm32x_protect(struct flash_bank *bank, int set, unsigned int first,
@@ -1483,8 +1488,10 @@ COMMAND_HANDLER(stm32x_handle_options_load_command)
        if (retval != ERROR_OK)
                return retval;
        retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
-       if (retval != ERROR_OK)
+       if (retval != ERROR_OK) {
+               (void)target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
                return retval;
+       }
 
        /* force re-load of option bytes - generates software reset */
        retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_OBL_LAUNCH);
@@ -1509,26 +1516,26 @@ static int stm32x_mass_erase(struct flash_bank *bank)
                return retval;
        retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_KEYR), KEY2);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        /* mass erase flash memory */
        retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_MER);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
        retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR),
                        FLASH_MER | FLASH_STRT);
        if (retval != ERROR_OK)
-               return retval;
+               goto flash_lock;
 
        retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT);
-       if (retval != ERROR_OK)
-               return retval;
 
-       retval = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
-       if (retval != ERROR_OK)
-               return retval;
-
-       return ERROR_OK;
+flash_lock:
+       {
+               int retval2 = target_write_u32(target, stm32x_get_flash_reg(bank, STM32_FLASH_CR), FLASH_LOCK);
+               if (retval == ERROR_OK)
+                       retval = retval2;
+       }
+       return retval;
 }
 
 COMMAND_HANDLER(stm32x_handle_mass_erase_command)

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)