From 8d8c6df557ab1976c6df39cf712b6ef23ce8a27e Mon Sep 17 00:00:00 2001 From: Tarek BOCHKATI Date: Thu, 29 Aug 2019 15:58:39 +0200 Subject: [PATCH] flash/nor/stm32h7x: fix option bytes handling to work with both banks To achieve that we need to avoid using FLASH_REG_BASE_B0, and use bank registers instead: For dual bank devices, each option register is mapped in 2 addresses at the same offset from flash_bank_reg_base. This is true for OPTCR, OPTKEYR, OPTSR_CUR/PRG, OPTCCR according to RM0433 Rev6 (refer to section 3.9: FLASH registers) In stm32x_write_options, according to RM0433 Rev6, after OBL launch we should wait for OPTSR_CUR.BSY bit instead of FLASH_SR.QW Change-Id: Ie24a91f069d03c9233797390fc2e925c737dad90 Signed-off-by: Tarek BOCHKATI Reviewed-on: http://openocd.zylin.com/5291 Tested-by: jenkins Reviewed-by: Christopher Head Reviewed-by: Tomas Vanek --- src/flash/nor/stm32h7x.c | 48 ++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index 1d128f3be1..feb7acafda 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -79,6 +79,9 @@ #define OPT_LOCK (1 << 0) #define OPT_START (1 << 1) +/* FLASH_OPTSR register bits */ +#define OPT_BSY (1 << 0) + /* register unlock keys */ #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -263,7 +266,7 @@ static int stm32x_unlock_option_reg(struct flash_bank *bank) uint32_t ctrl; struct target *target = bank->target; - int retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, &ctrl); + int retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), &ctrl); if (retval != ERROR_OK) return retval; @@ -271,15 +274,15 @@ static int stm32x_unlock_option_reg(struct flash_bank *bank) return ERROR_OK; /* unlock option registers */ - retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTKEYR, OPTKEY1); + retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTKEYR), OPTKEY1); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTKEYR, OPTKEY2); + retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTKEYR), OPTKEY2); if (retval != ERROR_OK) return retval; - retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, &ctrl); + retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), &ctrl); if (retval != ERROR_OK) return retval; @@ -310,7 +313,7 @@ static int stm32x_read_options(struct flash_bank *bank) struct target *target = bank->target; /* read current option bytes */ - int retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTSR_CUR, &optiondata); + int retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTSR_CUR), &optiondata); if (retval != ERROR_OK) return retval; @@ -349,7 +352,7 @@ static int stm32x_write_options(struct flash_bank *bank) optiondata |= (stm32x_info->option_bytes.user3_options & 0xa3) << 24; /* program options */ - retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTSR_PRG, optiondata); + retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTSR_PRG), optiondata); if (retval != ERROR_OK) return retval; @@ -361,12 +364,12 @@ static int stm32x_write_options(struct flash_bank *bank) optiondata = 0x40000000; /* Remove OPT error flag before programming */ - retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCCR, optiondata); + retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCCR), optiondata); if (retval != ERROR_OK) return retval; /* start programming cycle */ - retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, OPT_START); + retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), OPT_START); if (retval != ERROR_OK) return retval; @@ -374,23 +377,23 @@ static int stm32x_write_options(struct flash_bank *bank) int timeout = FLASH_ERASE_TIMEOUT; for (;;) { uint32_t status; - retval = target_read_u32(target, FLASH_REG_BASE_B0 + FLASH_SR, &status); + retval = target_read_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTSR_CUR), &status); if (retval != ERROR_OK) { - LOG_INFO("stm32x_write_options: wait_flash_op_queue : error"); + LOG_INFO("stm32x_write_options: failed to read FLASH_OPTSR_CUR"); return retval; } - if ((status & FLASH_QW) == 0) + if ((status & OPT_BSY) == 0) break; if (timeout-- <= 0) { - LOG_INFO("wait_flash_op_queue, time out expired, status: 0x%" PRIx32 "", status); + LOG_INFO("waiting for OBL launch, time out expired, OPTSR: 0x%" PRIx32 "", status); return ERROR_FAIL; } alive_sleep(1); } /* relock option registers */ - retval = target_write_u32(target, FLASH_REG_BASE_B0 + FLASH_OPTCR, OPT_LOCK); + retval = target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_OPTCR), OPT_LOCK); if (retval != ERROR_OK) return retval; @@ -904,13 +907,6 @@ COMMAND_HANDLER(stm32x_handle_lock_command) stm32x_info = bank->driver_priv; target = bank->target; - /* if we have a dual flash bank device then - * we need to perform option byte lock on bank0 only */ - if (stm32x_info->flash_base != FLASH_REG_BASE_B0) { - LOG_ERROR("Option Byte Lock Operation must use bank0"); - return ERROR_FLASH_OPERATION_FAILED; - } - if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -921,6 +917,9 @@ COMMAND_HANDLER(stm32x_handle_lock_command) bank->driver->name); return ERROR_OK; } + + LOG_WARNING("locking the entire flash device"); + /* set readout protection */ stm32x_info->option_bytes.RDP = 0; @@ -950,13 +949,6 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) stm32x_info = bank->driver_priv; target = bank->target; - /* if we have a dual flash bank device then - * we need to perform option byte unlock on bank0 only */ - if (stm32x_info->flash_base != FLASH_REG_BASE_B0) { - LOG_ERROR("Option Byte Unlock Operation must use bank0"); - return ERROR_FLASH_OPERATION_FAILED; - } - if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -967,6 +959,8 @@ COMMAND_HANDLER(stm32x_handle_unlock_command) return ERROR_OK; } + LOG_WARNING("unlocking the entire flash device"); + /* clear readout protection option byte * this will also force a device unlock if set */ stm32x_info->option_bytes.RDP = 0xAA; -- 2.30.2