AnsweredAssumed Answered

RDP and PCROP spurious activation

Question asked by fahmi on Oct 22, 2014
Latest reply on Oct 22, 2014 by fahmi
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:

001.#ifdef BOOT
002.#define OPTCR_DEFAULT_VALUE             ((uint32_t)0x4FFFAAE1)
003.#define OPTCR_RESERVED_BITS             ((uint32_t)0x30000000)
004.#define OPTCR1_DEFAULT_VALUE            ((uint32_t)0x0FFF0000)
005.#define OPTCR1_RESERVED_BITS            ((uint32_t)0xF000FFFF)
006.#endif /* BOOT */
007. 
008.void Flash_Init(void)
009.{
010.#ifndef _UNITARY_TESTS
011.     
012.    /* Set the Latency value */
013.    FLASH->ACR |= FLASH_Latency_5;
014.     
015.    /* Enable the Prefetch Buffer */
016.    FLASH->ACR |= FLASH_ACR_PRFTEN;   
017.     
018.    /* Enables the Instruction Cache feature */
019.    FLASH->ACR |= FLASH_ACR_ICEN;
020.     
021.    /* Enables the Data Cache feature */   
022.    FLASH->ACR |= FLASH_ACR_DCEN;
023. 
024.#ifdef BOOT
025.     
026.    /* Unlock the CR register */
027.    if ((uint32_t)RESET != (FLASH->CR & FLASH_CR_LOCK))
028.    {
029.        /* Unlock the FLASH control register access */
030.        FLASH->KEYR = FLASH_KEY1;
031.        FLASH->KEYR = FLASH_KEY2;
032.    }
033.    else
034.    {
035.        /* CR register is already unlocked */
036.    }
037. 
038.    /* If OPTCR or OPTCR1 values are NOT the preconfigured ones, reprogram them */
039.    if ((OPTCR_DEFAULT_VALUE  != (FLASH->OPTCR  & ~OPTCR_RESERVED_BITS)) ||
040.        (OPTCR1_DEFAULT_VALUE != (FLASH->OPTCR1 & ~OPTCR1_RESERVED_BITS)))
041.    {
042.        if ((uint32_t)RESET != (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK))
043.        {
044.            /* Unlock the FLASH Option Control Register access */
045.            FLASH->OPTKEYR = FLASH_OPT_KEY1;
046.            FLASH->OPTKEYR = FLASH_OPT_KEY2;
047.        }
048.        else
049.        {
050.            /* OPTCR register is already unlocked */
051.        }
052. 
053.        /* Set BOR Level 3: reset threshold level for 2.70 to 3.60 V voltage range */
054.        FLASH->OPTCR &= ~FLASH_OPTCR_BOR_LEV;
055. 
056.        /* Reset BFB2 */
057.        FLASH->OPTCR &= ~FLASH_OPTCR_BFB2;
058. 
059.        /* Set nRST_STOP and nRST_STDBY */
060.        FLASH->OPTCR |= FLASH_OPTCR_nRST_STOP | FLASH_OPTCR_nRST_STDBY;
061. 
062.        /* Reset SPRMOD */
063.        FLASH->OPTCR &= ~FLASH_OPTCR_SPRMOD;
064. 
065.        /* Set the read protection level 0 */
066.        // TODO: set level 1 for release
067.        *(uint8_t volatile*)OPTCR_BYTE1_ADDRESS = OB_RDP_Level_0;
068. 
069.        /* Deactivate the write protection for all flash sectors (2 banks) */
070.        *(uint16_t volatile*)OPTCR_BYTE2_ADDRESS  |= (uint16_t)OB_WRP_Sector_All;
071.        *(uint16_t volatile*)OPTCR1_BYTE2_ADDRESS |= (uint16_t)OB_WRP_Sector_All;
072. 
073.        /* Set OPTSTRT bit to program the user option bytes in flash */
074.        FLASH->OPTCR |= FLASH_OPTCR_OPTSTRT;
075. 
076.        /* Wait for the last operation to finish */
077.        while ( (uint32_t)RESET != (FLASH->SR & FLASH_FLAG_BSY) )
078.        {
079.        }
080. 
081.        /* Lock the FLASH Option Control Register access */
082.        FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
083.    }
084.    else
085.    {
086.        /* Nothing to do: OPTCR and OPTCR1 have the preconfigured values */
087.    }
088. 
089.#else
090.    #ifdef APPLI
091. 
092.    /* Lock the FLASH control register access */
093.    FLASH->CR |= FLASH_CR_LOCK;
094. 
095.    if ((uint32_t)RESET != (FLASH->OPTCR & FLASH_OPTCR_OPTLOCK))
096.    {
097.        /* Unlock the FLASH Option Control Register access */
098.        FLASH->OPTKEYR = FLASH_OPT_KEY1;
099.        FLASH->OPTKEYR = FLASH_OPT_KEY2;
100.    }
101.    else
102.    {
103.        /* OPTCR register is already unlocked */
104.    }
105. 
106.    /* Activate the write protection for all flash sectors (2 banks) */
107.    *(uint16_t volatile*)OPTCR_BYTE2_ADDRESS  &= (uint16_t)~OB_WRP_Sector_All;
108.    *(uint16_t volatile*)OPTCR1_BYTE2_ADDRESS &= (uint16_t)~OB_WRP_Sector_All;
109. 
110.    /* Lock the FLASH Option Control Register access */
111.    FLASH->OPTCR |= FLASH_OPTCR_OPTLOCK;
112. 
113.    #endif /* APPLI */
114.#endif /* BOOT */
115.     
116.#else
117.    FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS;
118.#endif /* !_UNITARY_TESTS */
119.}

Any help would be highly appreciated.

Regards,
Fahmi

Outcomes