Question
RDP and PCROP spurious activation
Posted on October 22, 2014 at 09:52
Hi,
I have a flash init routine that I call after enabling the main PLL in my boot loader and my main application. The routine will check in the bootloader if the OPTCR or OPTCR1 values have been changed for any reason and restore them in this case. But my board (STM32F4) powered by USB has been frozen multiple times at startup and has became unresponsive. Suspecting a change in option bytes, I've checked with ST-Link, I've found that: - ROP is set to level 1 while it should be level 0 - BOR Level is set to OFF while it should be Level 3 - BFB2 is set while it shouldn't - Flash protection mode is set to Read/Write protection while it should be set to Write protection - All sectors are checked for protection while they shouldn't be at boot I can't reproduce that bug systematically which makes debugging hard. Here after is my routine:
#ifdef BOOT
#define OPTCR_DEFAULT_VALUE ((uint32_t)0x4FFFAAE1)
#define OPTCR_RESERVED_BITS ((uint32_t)0x30000000)
#define OPTCR1_DEFAULT_VALUE ((uint32_t)0x0FFF0000)
#define OPTCR1_RESERVED_BITS ((uint32_t)0xF000FFFF)
#endif /* BOOT */
void
Flash_Init(
void
)
{
#ifndef _UNITARY_TESTS
/* Set the Latency value */
FLASH->ACR |= FLASH_Latency_5;
/* Enable the Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTEN;
/* Enables the Instruction Cache feature */
FLASH->ACR |= FLASH_ACR_ICEN;
/* Enables the Data Cache feature */
FLASH->ACR |= FLASH_ACR_DCEN;
#ifdef BOOT
/* Unlock the CR register */
if
((uint32_t)RESET != (FLASH->CR & FLASH_CR_LOCK))
{
/* Unlock the FLASH control register access */
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
else
{
/* CR register is already unlocked */
}
/* If OPTCR or OPTCR1 values are NOT the preconfigured ones, reprogram them */
if
((OPTCR_DEFAULT_VALUE != (FLASH->OPTCR & ~OPTCR_RESERVED_BITS)) ||
(OPTCR1_DEFAULT_VALUE != (FLASH->OPTCR1 & ~OPTCR1_RESERVED_BITS)))
{
if
((uint32_t)RESET != (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK))
{
/* Unlock the FLASH Option Control Register access */
FLASH->OPTKEYR = FLASH_OPT_KEY1;
FLASH->OPTKEYR = FLASH_OPT_KEY2;
}
else
{
/* OPTCR register is already unlocked */
}
/* Set BOR Level 3: reset threshold level for 2.70 to 3.60 V voltage range */
FLASH->OPTCR &= ~FLASH_OPTCR_BOR_LEV;
/* Reset BFB2 */
FLASH->OPTCR &= ~FLASH_OPTCR_BFB2;
/* Set nRST_STOP and nRST_STDBY */
FLASH->OPTCR |= FLASH_OPTCR_nRST_STOP | FLASH_OPTCR_nRST_STDBY;
/* Reset SPRMOD */
FLASH->OPTCR &= ~FLASH_OPTCR_SPRMOD;
/* Set the read protection level 0 */
// TODO: set level 1 for release
*(uint8_t
volatile
*)OPTCR_BYTE1_ADDRESS = OB_RDP_Level_0;
/* Deactivate the write protection for all flash sectors (2 banks) */
*(uint16_t
volatile
*)OPTCR_BYTE2_ADDRESS |= (uint16_t)OB_WRP_Sector_All;
*(uint16_t
volatile
*)OPTCR1_BYTE2_ADDRESS |= (uint16_t)OB_WRP_Sector_All;
/* Set OPTSTRT bit to program the user option bytes in flash */
FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;
/* Wait for the last operation to finish */
while
( (uint32_t)RESET != (FLASH->SR & FLASH_FLAG_BSY) )
{
}
/* Lock the FLASH Option Control Register access */
FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
}
else
{
/* Nothing to do: OPTCR and OPTCR1 have the preconfigured values */
}
#else
#ifdef APPLI
/* Lock the FLASH control register access */
FLASH->CR |= FLASH_CR_LOCK;
if
((uint32_t)RESET != (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK))
{
/* Unlock the FLASH Option Control Register access */
FLASH->OPTKEYR = FLASH_OPT_KEY1;
FLASH->OPTKEYR = FLASH_OPT_KEY2;
}
else
{
/* OPTCR register is already unlocked */
}
/* Activate the write protection for all flash sectors (2 banks) */
*(uint16_t
volatile
*)OPTCR_BYTE2_ADDRESS &= (uint16_t)~OB_WRP_Sector_All;
*(uint16_t
volatile
*)OPTCR1_BYTE2_ADDRESS &= (uint16_t)~OB_WRP_Sector_All;
/* Lock the FLASH Option Control Register access */
FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
#endif /* APPLI */
#endif /* BOOT */
#else
FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
#endif /* !_UNITARY_TESTS */
}
Any help would be highly appreciated.
Regards,
Fahmi