aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>2016-02-09 17:50:47 +0100
committerFreddie Chopin <freddie.chopin@gmail.com>2016-05-04 23:11:30 +0100
commit0534a5e0abf979072f6342f8adc691b81024b209 (patch)
treeea2a5b82ce620ae6eab3f252349cabb4edfc568f
parentb200dea3873d816fa2c58bdac4bbee249f08535a (diff)
stm32lx: Add support for lock/unlock (RDP Level 0<->1)
Change-Id: Iecc356373e084056d048d92820062483cac3c8ec Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com> Reviewed-on: http://openocd.zylin.com/3234 Tested-by: jenkins Reviewed-by: Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de> Reviewed-by: Freddie Chopin <freddie.chopin@gmail.com>
-rw-r--r--src/flash/nor/stm32lx.c107
1 files changed, 98 insertions, 9 deletions
diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c
index 22830e60..2ae58cc0 100644
--- a/src/flash/nor/stm32lx.c
+++ b/src/flash/nor/stm32lx.c
@@ -103,6 +103,8 @@ static int stm32lx_lock_program_memory(struct flash_bank *bank);
static int stm32lx_enable_write_half_page(struct flash_bank *bank);
static int stm32lx_erase_sector(struct flash_bank *bank, int sector);
static int stm32lx_wait_until_bsy_clear(struct flash_bank *bank);
+static int stm32lx_lock(struct flash_bank *bank);
+static int stm32lx_unlock(struct flash_bank *bank);
static int stm32lx_mass_erase(struct flash_bank *bank);
static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout);
@@ -332,6 +334,46 @@ COMMAND_HANDLER(stm32lx_handle_mass_erase_command)
return retval;
}
+COMMAND_HANDLER(stm32lx_handle_lock_command)
+{
+ if (CMD_ARGC < 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct flash_bank *bank;
+ int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+ if (ERROR_OK != retval)
+ return retval;
+
+ retval = stm32lx_lock(bank);
+
+ if (retval == ERROR_OK)
+ command_print(CMD_CTX, "STM32Lx locked, takes effect after power cycle.");
+ else
+ command_print(CMD_CTX, "STM32Lx lock failed");
+
+ return retval;
+}
+
+COMMAND_HANDLER(stm32lx_handle_unlock_command)
+{
+ if (CMD_ARGC < 1)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+
+ struct flash_bank *bank;
+ int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+ if (ERROR_OK != retval)
+ return retval;
+
+ retval = stm32lx_unlock(bank);
+
+ if (retval == ERROR_OK)
+ command_print(CMD_CTX, "STM32Lx unlocked, takes effect after power cycle.");
+ else
+ command_print(CMD_CTX, "STM32Lx unlock failed");
+
+ return retval;
+}
+
static int stm32lx_protect_check(struct flash_bank *bank)
{
int retval;
@@ -945,6 +987,20 @@ static const struct command_registration stm32lx_exec_command_handlers[] = {
.usage = "bank_id",
.help = "Erase entire flash device. including available EEPROM",
},
+ {
+ .name = "lock",
+ .handler = stm32lx_handle_lock_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id",
+ .help = "Increase the readout protection to Level 1.",
+ },
+ {
+ .name = "unlock",
+ .handler = stm32lx_handle_unlock_command,
+ .mode = COMMAND_EXEC,
+ .usage = "bank_id",
+ .help = "Lower the readout protection from Level 1 to 0.",
+ },
COMMAND_REGISTRATION_DONE
};
@@ -1278,33 +1334,37 @@ static int stm32lx_obl_launch(struct flash_bank *bank)
return tries ? ERROR_OK : ERROR_FAIL;
}
-static int stm32lx_mass_erase(struct flash_bank *bank)
+static int stm32lx_lock(struct flash_bank *bank)
{
int retval;
struct target *target = bank->target;
- struct stm32lx_flash_bank *stm32lx_info = NULL;
- uint32_t reg32;
if (target->state != TARGET_HALTED) {
LOG_ERROR("Target not halted");
return ERROR_TARGET_NOT_HALTED;
}
- stm32lx_info = bank->driver_priv;
-
retval = stm32lx_unlock_options_bytes(bank);
if (retval != ERROR_OK)
return retval;
- /* 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;
- retval = stm32lx_obl_launch(bank);
- if (retval != ERROR_OK)
- return retval;
+ return ERROR_OK;
+}
+
+static int stm32lx_unlock(struct flash_bank *bank)
+{
+ int retval;
+ struct target *target = bank->target;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
retval = stm32lx_unlock_options_bytes(bank);
if (retval != ERROR_OK)
@@ -1319,6 +1379,35 @@ static int stm32lx_mass_erase(struct flash_bank *bank)
if (retval != ERROR_OK)
return retval;
+ return ERROR_OK;
+}
+
+static int stm32lx_mass_erase(struct flash_bank *bank)
+{
+ int retval;
+ struct target *target = bank->target;
+ struct stm32lx_flash_bank *stm32lx_info = NULL;
+ uint32_t reg32;
+
+ if (target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ stm32lx_info = bank->driver_priv;
+
+ retval = stm32lx_lock(bank);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = stm32lx_obl_launch(bank);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = stm32lx_unlock(bank);
+ if (retval != ERROR_OK)
+ return retval;
+
retval = stm32lx_obl_launch(bank);
if (retval != ERROR_OK)
return retval;