cancel
Showing results for 
Search instead for 
Did you mean: 

Option Bytes programing (NBOOT_SEL & WRP) problem

rengl
Associate II

Hi,

programing NBOOT_SEL and WRP in the firmware leads to strange behavior of the MCU. After running the code below and reseting the MCU, I can still debug with CubeIDE to some extent by connecting without downloading the firmware, but I can only see that the MCU is stuck in a hard fault. CubeProgrammer cannot read either flash or option bytes. If I try to reset the option bytes anyway, I lose the connection to the MCU completely and it is no longer recognized by CubeProgrammer.

The behavior is not always the same either. On my first attempt, I was able to debug the code several times and see that it works correctly in principle. Resetting the WRP with CubeProgrammer also worked. However, I have now lost my second MCU.

I develop a minimal bootstub for STM32C011J6 and therefore do not use the HAL. Is there an error in the code, that can lead to such a behaviour? 

 

Thank you in advance for any hints or guidance.

 

typedef struct
{
  volatile uint32_t ACR;
           uint32_t RESERVED1;
  volatile uint32_t KEYR;
  volatile uint32_t OPTKEYR;
  volatile uint32_t SR;
  volatile uint32_t CR;
           uint32_t RESERVED2[2];
  volatile uint32_t OPTR;
  volatile uint32_t PCROP1ASR;
  volatile uint32_t PCROP1AER;
  volatile uint32_t WRP1AR;
  volatile uint32_t WRP1BR;
  volatile uint32_t PCROP1BSR;
  volatile uint32_t PCROP1BER;
           uint32_t RESERVED3[17];
  volatile uint32_t SECR;
} FLASH_TypeDef;


#define FLASH_BASE           0x40022000U

#define FLASH_KEY1           0x45670123U
#define FLASH_KEY2           0xCDEF89ABU
#define FLASH_OPT_KEY1       0x08192A3BU
#define FLASH_OPT_KEY2       0x4C5D6E7FU

#define FLASH                ((FLASH_TypeDef*)FLASH_BASE)

#define FLASH_CR_OPTSTRT     (1U << 17)
#define FLASH_CR_OPTLOCK     (1U << 30)
#define FLASH_CR_LOCK        (1U << 31)
#define FLASH_SR_BSY1        (1U << 16)
#define FLASH_OPTR_NBOOT_SEL (1U << 24)

#define FLASH_WRP_A_END      (0xFFU << 16)
#define FLASH_WRP_A_STRT     (0xFFU << 0)

#define GET_FLASH_OPTR_NBOOT_SEL() ((FLASH->OPTR & FLASH_OPTR_NBOOT_SEL) >> 24)
#define GET_FLASH_WRP_A_END()      ((FLASH->WRP1AR & FLASH_WRP_A_END) >> 16)
#define GET_FLASH_WRP_A_STRT()     ((FLASH->WRP1AR & FLASH_WRP_A_STRT) >> 0)

/**
 * Clears nBOOT_SEL and activates write protection (WRP)
 * for the first page (0x8000000 - 0x8000800) where this
 * bootstub resides.
 */
static void configure_option_bytes(void)
{
    if (GET_FLASH_OPTR_NBOOT_SEL() == 0 &&
        GET_FLASH_WRP_A_STRT() == 0 &&
        GET_FLASH_WRP_A_END() == 0)
        return; // Already configured

    // Unlock FLASH
    FLASH->KEYR = FLASH_KEY1;
    FLASH->KEYR = FLASH_KEY2;

    // Halt here if FLASH is not unlocked
    while (FLASH->CR & FLASH_CR_LOCK);

    // Unlock Option Bytes
    FLASH->OPTKEYR = FLASH_OPT_KEY1;
    FLASH->OPTKEYR = FLASH_OPT_KEY2;

    // Halt here if Option Bytes are not unlocked
    while (FLASH->CR & FLASH_CR_OPTLOCK);

    // Clear nBOOT_SEL bit
    FLASH->OPTR &= ~FLASH_OPTR_NBOOT_SEL;

    // Write protect first page (WRP1A_END = WRP1A_STRT = 0)
    FLASH->WRP1AR = 0;

    // Wait until FLASH not busy
    while (FLASH->SR & FLASH_SR_BSY1);

    // Start Option Bytes programming
    FLASH->CR |= FLASH_CR_OPTSTRT;

    while (FLASH->SR & FLASH_SR_BSY1);

    // Clear OPTSTRT bit after programming
    FLASH->CR &= ~FLASH_CR_OPTSTRT;

    // Lock Option Bytes and FLASH
    FLASH->CR |= FLASH_CR_OPTLOCK;
    FLASH->CR |= FLASH_CR_LOCK;
}

 

0 REPLIES 0