changing any of option bytes leads to increase of read protection level in stm32f407
I am new to ST forums. actually, this is my first post here.
I am facing a kind of strange problem with no explanation. actually, I have been digging through the reference manual for 5 hours now.
currently, I am implementing my own version of bare-metal for the embedded flash memory in stm32f407, the problem is that whenever I try to modify options bytes of the flash memory, it behaves as expected but when I power off and then power on my board, the read protection level is always set 1 even if I set it to 0 in the code.
not only that but even if the board
is still connected and I end the debug session after modifying boot options leaving RDP to level 0, when I start a new debugging session, I can't. simply because RDP is set to level 1 by itself.
I actually read in the reference manual page 93 this line:
• Level 1: read protection enabled
It is the default read protection level after option byte erase.
but still don't know what it has to do with RDP level.
here is my code:
HAL_FLASH_ErrStates_t HAL_FLASH_Init()
{
// local used variables
uint16_t local_u16TempVal = 0;
uint8_t local_u32Counter = 0;
uint8_t local_u8TempBitPos = 0;
uint8_t local_u8SectorsLength = sizeof globalConstArr_SectorsConfig_t / sizeof globalConstArr_SectorsConfig_t[0];
HAL_FLASH_ErrStates_t local_errState_t = HAL_FLASH_OK;
// check for errors
for (local_u32Counter = 0; local_u32Counter < local_u8SectorsLength; local_u32Counter++) // if you want to improve code, unroll this for loop for 11 lines of code
{
if (globalConstArr_SectorsConfig_t[local_u32Counter].WriteProtection >= LIB_CONSTANTS_MAX_DRIVER_STATE || globalConstArr_SectorsConfig_t[local_u32Counter].SectorNumber >= HAL_FLASH_MAX_MAIN_MEM_SECTOR)
{
local_errState_t = HAL_FLASH_ERR_INVALID_CONFIG;
break;
}
else
{
// do nothing
}
}
if (globalConstArr_FlashConfig_t[0].DataCacheEnabled >= LIB_CONSTANTS_MAX_DRIVER_STATE || globalConstArr_FlashConfig_t[0].InstructionCacheEnabled >= LIB_CONSTANTS_MAX_DRIVER_STATE || globalConstArr_FlashConfig_t[0].PrefetchEnabled >= LIB_CONSTANTS_MAX_DRIVER_STATE || globalConstArr_FlashConfig_t[0].WaitStates >= HAL_FLASH_MAX_WAIT_STATE || globalConstArr_FlashConfig_t[0].LockConfiguration >= LIB_CONSTANTS_MAX_LOCK_STATE || globalConstArr_FlashConfig_t[0].InterruptsEnabled >= LIB_CONSTANTS_MAX_DRIVER_STATE || globalConstArr_FlashConfig_t[0].ProgramSize >= HAL_FLASH_MAX_PROGRAM_SIZE || globalConstArr_FlashConfig_t[0].ReadProtectionLevel >= HAL_FLASH_MAX_READ_PROTECT_LVL || globalConstArr_MiscellaneousConfig_t[0].ResetOnStandBy >= LIB_CONSTANTS_MAX_DRIVER_STATE || globalConstArr_MiscellaneousConfig_t[0].ResetOnStop >= LIB_CONSTANTS_MAX_DRIVER_STATE || globalConstArr_MiscellaneousConfig_t[0].IndependentWatchDogType >= HAL_FLASH_MAX_INDPEND_WATCH_DOG_TYPE || globalConstArr_MiscellaneousConfig_t[0].BrownoutResetLevel >= HAL_FLASH_MAX_BROWN_RESET_LVL)
{
local_errState_t = HAL_FLASH_ERR_INVALID_CONFIG;
}
else
{
// do nothing
}
// check for busy wait or not
local_errState_t = HAL_FLASH_GetHardwareErrors();
if (local_errState_t == HAL_FLASH_ERR_FLASH_BUSY && globalConstArr_FlashConfig_t[0].InterruptsEnabled == LIB_CONSTANTS_DISABLED)
{
// busy wait
while (LIB_MATH_BTT_GET_BIT(global_pFlashReg_t->FLASH_SR, HAL_FLASH_SR_BSY) == 1)
{
};
local_errState_t = HAL_FLASH_OK;
}
// main function
if (local_errState_t == HAL_FLASH_OK)
{
// unlock all configuration registers
global_pFlashReg_t->FLASH_KEYR = HAL_FLASH_CR_KEY1;
global_pFlashReg_t->FLASH_KEYR = HAL_FLASH_CR_KEY2;
global_pFlashReg_t->FLASH_OPTKEYR = HAL_FLASH_OPTCR_OPTKEY1;
global_pFlashReg_t->FLASH_OPTKEYR = HAL_FLASH_OPTCR_OPTKEY2;
// assign global configuration variables
global_u8BehaviorType = globalConstArr_FlashConfig_t[0].InterruptsEnabled == LIB_CONSTANTS_ENABLED ? HAL_FLASH_CONFIG_VAL_OPERATION_TYPE_INTERRUPT : HAL_FLASH_CONFIG_VAL_OPERATION_TYPE_BLOCKING;
// configure flash & sectors
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_ACR, HAL_FLASH_ACR_DCEN, globalConstArr_FlashConfig_t[0].DataCacheEnabled);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_ACR, HAL_FLASH_ACR_ICEN, globalConstArr_FlashConfig_t[0].InstructionCacheEnabled);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_ACR, HAL_FLASH_ACR_PRFTEN, globalConstArr_FlashConfig_t[0].PrefetchEnabled);
LIB_MATH_BTT_ASSIGN_BITS(global_pFlashReg_t->FLASH_ACR, HAL_FLASH_ACR_LATENCY, globalConstArr_FlashConfig_t[0].WaitStates, 3);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_CR, HAL_FLASH_CR_ERRIE, globalConstArr_FlashConfig_t[0].InterruptsEnabled);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_CR, HAL_FLASH_CR_EOPIE, globalConstArr_FlashConfig_t[0].InterruptsEnabled);
LIB_MATH_BTT_ASSIGN_BITS(global_pFlashReg_t->FLASH_CR, HAL_FLASH_CR_PSIZE, globalConstArr_FlashConfig_t[0].ProgramSize, 2);
for (local_u32Counter = 0; local_u32Counter < local_u8SectorsLength; local_u32Counter++) // if you want to improve code, unroll this for loop for 11 lines of code
{
local_u8TempBitPos = LIB_MATH_BTT_u8GetMSBSetPos(globalConstArr_SectorsConfig_t[local_u32Counter].SectorNumber);
local_u16TempVal |= (!globalConstArr_SectorsConfig_t[local_u32Counter].WriteProtection << local_u8TempBitPos);
}
LIB_MATH_BTT_ASSIGN_BITS(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_nWRP, local_u16TempVal, 12);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_nRST_STDBY, !globalConstArr_MiscellaneousConfig_t[0].ResetOnStandBy);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_nRST_STOP, !globalConstArr_MiscellaneousConfig_t[0].ResetOnStop);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_WDG_SW, globalConstArr_MiscellaneousConfig_t[0].IndependentWatchDogType);
LIB_MATH_BTT_ASSIGN_BITS(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_BOR_LEV, globalConstArr_MiscellaneousConfig_t[0].BrownoutResetLevel, 2);
LIB_MATH_BTT_ASSIGN_BITS(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_RDP, globalConstArr_FlashConfig_t[0].ReadProtectionLevel, 8);
// lock configuration if configured
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_CR, HAL_FLASH_CR_LOCK, globalConstArr_FlashConfig_t[0].LockConfiguration);
LIB_MATH_BTT_ASSIGN_BIT(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_OPTLOCK, globalConstArr_FlashConfig_t[0].LockConfiguration);
// save the values
LIB_MATH_BTT_SET_BIT(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_OPTSTRT);
while (LIB_MATH_BTT_GET_BIT(global_pFlashReg_t->FLASH_SR, HAL_FLASH_SR_BSY) == 1)
{
};
// check for errors
local_errState_t = HAL_FLASH_GetHardwareErrors();
if (local_errState_t == HAL_FLASH_ERR_FLASH_BUSY && globalConstArr_FlashConfig_t[0].InterruptsEnabled == LIB_CONSTANTS_DISABLED)
{
// busy wait
while (LIB_MATH_BTT_GET_BIT(global_pFlashReg_t->FLASH_SR, HAL_FLASH_SR_BSY) == 1)
{
};
local_errState_t = HAL_FLASH_OK;
}
local_errState_t = HAL_FLASH_ERR_FLASH_BUSY ? HAL_FLASH_OK : local_errState_t;
}
return local_errState_t;
}
PS: the problem is solved when I comment below these lines which are responsible for saving option values:
// save the values
LIB_MATH_BTT_SET_BIT(global_pFlashReg_t->FLASH_OPTCR, HAL_FLASH_OPTCR_OPTSTRT);
while (LIB_MATH_BTT_GET_BIT(global_pFlashReg_t->FLASH_SR, HAL_FLASH_SR_BSY) == 1)
{
};
