X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fstm32lx.c;h=11d853228440131bb2818ca6884810d307cb0543;hb=c0f0d622982fc8dec89501064c0d7d779e21c1d2;hp=bac2c4c727942675f319e0c0574420fa9701b3b4;hpb=6581bf5f15f404a9a219cfed8eebced76b4414a5;p=openocd.git
diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c
index bac2c4c727..11d8532284 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);
@@ -139,7 +141,10 @@ static const struct stm32lx_rev stm32_416_revs[] = {
{ 0x1000, "A" }, { 0x1008, "Y" }, { 0x1038, "W" }, { 0x1078, "V" },
};
static const struct stm32lx_rev stm32_417_revs[] = {
- { 0x1000, "A" }, { 0x1008, "Z" },
+ { 0x1000, "A" }, { 0x1008, "Z" }, { 0x1018, "Y" }, { 0x1038, "X" }
+};
+static const struct stm32lx_rev stm32_425_revs[] = {
+ { 0x1000, "A" }, { 0x2000, "B" }, { 0x2008, "Y" },
};
static const struct stm32lx_rev stm32_427_revs[] = {
{ 0x1000, "A" }, { 0x1018, "Y" }, { 0x1038, "X" },
@@ -153,6 +158,12 @@ static const struct stm32lx_rev stm32_436_revs[] = {
static const struct stm32lx_rev stm32_437_revs[] = {
{ 0x1000, "A" },
};
+static const struct stm32lx_rev stm32_447_revs[] = {
+ { 0x1000, "A" }, { 0x2000, "B" }, { 0x2008, "Z" },
+};
+static const struct stm32lx_rev stm32_457_revs[] = {
+ { 0x1000, "A" }, { 0x1008, "Z" },
+};
static const struct stm32lx_part_info stm32lx_parts[] = {
{
@@ -171,7 +182,7 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.id = 0x417,
.revs = stm32_417_revs,
.num_revs = ARRAY_SIZE(stm32_417_revs),
- .device_str = "STM32L0xx",
+ .device_str = "STM32L0xx (Cat. 3)",
.page_size = 128,
.pages_per_sector = 32,
.max_flash_size_kb = 64,
@@ -179,6 +190,18 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.flash_base = 0x40022000,
.fsize_base = 0x1FF8007C,
},
+ {
+ .id = 0x425,
+ .revs = stm32_425_revs,
+ .num_revs = ARRAY_SIZE(stm32_425_revs),
+ .device_str = "STM32L0xx (Cat. 2)",
+ .page_size = 128,
+ .pages_per_sector = 32,
+ .max_flash_size_kb = 32,
+ .has_dual_banks = false,
+ .flash_base = 0x40022000,
+ .fsize_base = 0x1FF8007C,
+ },
{
.id = 0x427,
.revs = stm32_427_revs,
@@ -187,8 +210,7 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.page_size = 256,
.pages_per_sector = 16,
.max_flash_size_kb = 256,
- .first_bank_size_kb = 192,
- .has_dual_banks = true,
+ .has_dual_banks = false,
.flash_base = 0x40023C00,
.fsize_base = 0x1FF800CC,
},
@@ -230,6 +252,31 @@ static const struct stm32lx_part_info stm32lx_parts[] = {
.flash_base = 0x40023C00,
.fsize_base = 0x1FF800CC,
},
+ {
+ .id = 0x447,
+ .revs = stm32_447_revs,
+ .num_revs = ARRAY_SIZE(stm32_447_revs),
+ .device_str = "STM32L0xx (Cat.5)",
+ .page_size = 128,
+ .pages_per_sector = 32,
+ .max_flash_size_kb = 192,
+ .first_bank_size_kb = 128,
+ .has_dual_banks = true,
+ .flash_base = 0x40022000,
+ .fsize_base = 0x1FF8007C,
+ },
+ {
+ .id = 0x457,
+ .revs = stm32_457_revs,
+ .num_revs = ARRAY_SIZE(stm32_457_revs),
+ .device_str = "STM32L0xx (Cat.1)",
+ .page_size = 128,
+ .pages_per_sector = 32,
+ .max_flash_size_kb = 16,
+ .has_dual_banks = false,
+ .flash_base = 0x40022000,
+ .fsize_base = 0x1FF8007C,
+ },
};
/* flash bank stm32lx 0 0
@@ -286,6 +333,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;
@@ -694,6 +781,8 @@ static int stm32lx_probe(struct flash_bank *bank)
if (!stm32lx_info->part_info) {
LOG_WARNING("Cannot identify target as a STM32L family.");
return ERROR_FAIL;
+ } else {
+ LOG_INFO("Device: %s", stm32lx_info->part_info->device_str);
}
stm32lx_info->flash_base = stm32lx_info->part_info->flash_base;
@@ -897,6 +986,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
};
@@ -1230,33 +1333,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)
@@ -1271,6 +1378,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;