2014-10-22 12:52 AM
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
2014-10-22 01:24 AM
Hi
''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.'' Why would they change? I am not seeing any evidence of them changing on the project here. ''I can't reproduce that bug systematically which makes debugging hard.'' ''Any help would be highly appreciated.'' We did a similar thing, updated option bytes on boot up, and got the same problems you are encountering. You get particular problems if the board is powered off during the option byte update! We stopped doing the change on boot and the problems stopped. Also, we started off by re-configuring ALL the IO pins to inputs (including the pins used for SWD/JTAG). This also caused problems. The problems seemed to improve (got less instances) when we stopped re-configuring the debug IO pins. To sum up - do not change the Option bytes during boot. There should be no reason for them to change. Only update them when it is 'safe' eg during a firmware upgrade.2014-10-22 02:39 AM
Hi sung.chen_chung,
Thanks for the reply.>>Why would they change?
>>I am not seeing any evidence of them changing on the project here.
We need for example to activate BOR level 3 and deactivate BFB2. And if we do that every boot, we've found that the occurence of the problem increases: every time the PC is restarted with our device plugged in USB the option bytes will be corrupted. The solution was to just update the option bytes if their values changes (using ST-Link for example).What is intriguing now is that the same problem occurs while apparently there has been no update in OB.Regards,Fahmi2014-10-22 03:00 AM
''What is intriguing now is that the same problem occurs while apparently there has been no update in OB.''
What happens if you use the ST-Link to 'update' the option bytes? We have been told by ST reps that the Options Bytes are effectively Flash memory. So they MUST be locked again after programming. If they remain unlocked, they can be corrupted. The ST-Link should unlock, program and then re-lock them.2014-10-22 03:05 AM
>>
What happens if you use the ST-Link to 'update' the option bytes?
Indeed, ST-Link unlock, program, then lock the OB.