* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
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);
.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,
},
stm32lx_info->user_bank_size = bank->size;
/* the stm32l erased value is 0x00 */
- bank->default_padded_value = 0x00;
+ bank->default_padded_value = bank->erased_value = 0x00;
return ERROR_OK;
}
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;
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;
return stm32lx_probe(bank);
}
-static int stm32lx_erase_check(struct flash_bank *bank)
-{
- struct target *target = bank->target;
- const int buffer_size = 4096;
- int i;
- uint32_t nBytes;
- int retval = ERROR_OK;
-
- if (bank->target->state != TARGET_HALTED) {
- LOG_ERROR("Target not halted");
- return ERROR_TARGET_NOT_HALTED;
- }
-
- uint8_t *buffer = malloc(buffer_size);
- if (buffer == NULL) {
- LOG_ERROR("failed to allocate read buffer");
- return ERROR_FAIL;
- }
-
- for (i = 0; i < bank->num_sectors; i++) {
- uint32_t j;
- bank->sectors[i].is_erased = 1;
-
- /* Loop chunk by chunk over the sector */
- for (j = 0; j < bank->sectors[i].size; j += buffer_size) {
- uint32_t chunk;
- chunk = buffer_size;
- if (chunk > (j - bank->sectors[i].size))
- chunk = (j - bank->sectors[i].size);
-
- retval = target_read_memory(target, bank->base
- + bank->sectors[i].offset + j, 4, chunk / 4, buffer);
- if (retval != ERROR_OK)
- break;
-
- for (nBytes = 0; nBytes < chunk; nBytes++) {
- if (buffer[nBytes] != 0x00) {
- bank->sectors[i].is_erased = 0;
- break;
- }
- }
- }
- if (retval != ERROR_OK)
- break;
- }
- free(buffer);
-
- return retval;
-}
-
/* This method must return a string displaying information about the bank */
static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size)
{
.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
};
.read = default_flash_read,
.probe = stm32lx_probe,
.auto_probe = stm32lx_auto_probe,
- .erase_check = stm32lx_erase_check,
+ .erase_check = default_flash_blank_check,
.protect_check = stm32lx_protect_check,
.info = stm32lx_get_info,
};
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)
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;