Monthly Archives: September 2021

STM32 Flash Option Bytes Programming


Utilities

dfu-util – Device Firmware Upgrade Utilities


Forum

ST

How to program FLASH_OPTR register to survive system reset?
Programming STM32 in bootloader mode under Linux
Unlock readout protection
STM32F0 read out protection problem

Mikrocontroller.net

STM32 Option Bytes beim Flashen gleich mit verändern


Register Access

STM32F3 Anleitung (ohne HAL, SET_BIT, etc.)

Schauen wir uns den modify Befehl genauer an:

MODIFY_REG(GPIOA->MODER, GPIO_MODER_MODER5, GPIO_MODER_MODER5_0);

Dies bedeutet: Modifiziere im Register GPIOA->MODER das Feld MODER5. Schalte dort nur das
untere Bit 0 an. Alle anderen Felder bleiben unverändert.
Falls du schon mit bitweisen Operationen vertraut bist, kannst du stattdessen auch schreiben:

GPIOA->MODER = (GPIOA->MODER & ~GPIO_MODER_MODER5) | GPIO_MODER_MODER5_0;
  • RM0440: STM32G4 Reference manual
  • ST production value: 0xFFEF F8AA

Drivers/CMSIS/Device/ST/STM32G4xx/Include/stm32g4xx.h

  • SET_BIT
  • CLEAR_BIT
  • READ_BIT
  • CLEAR_REG
  • MODIFY_REG
  • WRITE_REG
  • READ_reg


FLASH Register: Option Bytes

typedef struct
{
  __IO uint32_t ACR;              /*!< FLASH access control register,            Address offset: 0x00 */
  __IO uint32_t PDKEYR;           /*!< FLASH power down key register,            Address offset: 0x04 */
  __IO uint32_t KEYR;             /*!< FLASH key register,                       Address offset: 0x08 */
  __IO uint32_t OPTKEYR;          /*!< FLASH option key register,                Address offset: 0x0C */
  __IO uint32_t SR;               /*!< FLASH status register,                    Address offset: 0x10 */
  __IO uint32_t CR;               /*!< FLASH control register,                   Address offset: 0x14 */
  __IO uint32_t ECCR;             /*!< FLASH ECC register,                       Address offset: 0x18 */
       uint32_t RESERVED1;        /*!< Reserved1,                                Address offset: 0x1C */
  __IO uint32_t OPTR;             /*!< FLASH option register,                    Address offset: 0x20 */
  __IO uint32_t PCROP1SR;         /*!< FLASH bank1 PCROP start address register, Address offset: 0x24 */
  __IO uint32_t PCROP1ER;         /*!< FLASH bank1 PCROP end address register,   Address offset: 0x28 */
  __IO uint32_t WRP1AR;           /*!< FLASH bank1 WRP area A address register,  Address offset: 0x2C */
  __IO uint32_t WRP1BR;           /*!< FLASH bank1 WRP area B address register,  Address offset: 0x30 */
       uint32_t RESERVED2[4];     /*!< Reserved2,                                Address offset: 0x34 */
  __IO uint32_t PCROP2SR;         /*!< FLASH bank2 PCROP start address register, Address offset: 0x44 */
  __IO uint32_t PCROP2ER;         /*!< FLASH bank2 PCROP end address register,   Address offset: 0x48 */
  __IO uint32_t WRP2AR;           /*!< FLASH bank2 WRP area A address register,  Address offset: 0x4C */
  __IO uint32_t WRP2BR;           /*!< FLASH bank2 WRP area B address register,  Address offset: 0x50 */
       uint32_t RESERVED3[7];     /*!< Reserved3,                                Address offset: 0x54 */
  __IO uint32_t SEC1R;            /*!< FLASH Securable memory register bank1,    Address offset: 0x70 */
  __IO uint32_t SEC2R;            /*!< FLASH Securable memory register bank2,    Address offset: 0x74 */
} FLASH_TypeDef;
printf("FLASH->OPTR = %" PRIx32 "\n", FLASH->OPTR);
printf("  RDP         = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_RDP_Msk)         >> FLASH_OPTR_RDP_Pos);
printf("  BOR_LEV     = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_BOR_LEV_Msk)     >> FLASH_OPTR_BOR_LEV_Pos);
printf("  nRST_STOP   = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_nRST_STOP_Msk)   >> FLASH_OPTR_nRST_STOP_Pos);
printf("  nRST_STDBY  = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_nRST_STDBY_Msk)  >> FLASH_OPTR_nRST_STDBY_Pos);
printf("  nRST_SHDW   = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_nRST_SHDW_Msk)   >> FLASH_OPTR_nRST_SHDW_Pos);
printf("  IWDG_SW     = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_IWDG_SW_Msk)     >> FLASH_OPTR_IWDG_SW_Pos);
printf("  IWDG_STOP   = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_IWDG_STOP_Msk)   >> FLASH_OPTR_IWDG_STOP_Pos);
printf("  IWDG_STDBY  = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_IWDG_STDBY_Msk)  >> FLASH_OPTR_IWDG_STDBY_Pos);
printf("  WWDG_SW     = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_WWDG_SW_Msk)     >> FLASH_OPTR_WWDG_SW_Pos);
printf("  BFB2        = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_BFB2_Msk)        >> FLASH_OPTR_BFB2_Pos);
printf("  DBANK       = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_DBANK_Msk)       >> FLASH_OPTR_DBANK_Pos);
printf("  nBOOT1      = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_nBOOT1_Msk)      >> FLASH_OPTR_nBOOT1_Pos);
printf("  SRAM_PE     = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_SRAM_PE_Msk)     >> FLASH_OPTR_SRAM_PE_Pos);
printf("  CCMSRAM_RST = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_CCMSRAM_RST_Msk) >> FLASH_OPTR_CCMSRAM_RST_Pos);
printf("  nSWBOOT0    = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_nSWBOOT0_Msk)    >> FLASH_OPTR_nSWBOOT0_Pos);
printf("  nBOOT0      = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_nBOOT0_Msk)      >> FLASH_OPTR_nBOOT0_Pos);
printf("  NRST_MODE   = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_NRST_MODE_Msk)   >> FLASH_OPTR_NRST_MODE_Pos);
printf("  IRHEN       = %" PRIx32 "\n", READ_BIT(FLASH->OPTR, FLASH_OPTR_IRHEN_Msk)       >> FLASH_OPTR_IRHEN_Pos);
FLASH->OPTR = fbeff8aa
  RDP         = aa
  BOR_LEV     = 0
  nRST_STOP   = 1
  nRST_STDBY  = 1
  nRST_SHDW   = 1
  IWDG_SW     = 1
  IWDG_STOP   = 1
  IWDG_STDBY  = 1
  WWDG_SW     = 1
  BFB2        = 0
  DBANK       = 1
  nBOOT1      = 1
  SRAM_PE     = 1
  CCMSRAM_RST = 1
  nSWBOOT0    = 0
  nBOOT0      = 1
  NRST_MODE   = 3
  IRHEN       = 1
HAL_FLASHEx_OBGetConfig(&FLASH_OBInitStruct);

/* Get BOR Option Bytes */
if((FLASH_OBInitStruct.BORLevel & 0x0C) != BOR_LEVEL) 
{
  /* Unlock the option bytes block access */
  HAL_FLASH_OB_Unlock();
  
  /* Select the desired V(BOR) Level */
  FLASH_OBInitStruct.OptionType = OPTIONBYTE_BOR;
  FLASH_OBInitStruct.BORLevel = BOR_LEVEL;
  HAL_FLASHEx_OBProgram(&FLASH_OBInitStruct);
  
  /* Launch the option byte loading */
  HAL_FLASH_OB_Launch();
  
  /* Locks the option bytes block access */
  HAL_FLASH_OB_Lock();
}
/* Program operation functions  ***********************************************/
HAL_StatusTypeDef  HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
HAL_StatusTypeDef  HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data);

/* FLASH IRQ handler method */
void               HAL_FLASH_IRQHandler(void);

/* Callbacks in non blocking modes */
void               HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue);
void               HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue);


/* Peripheral Control functions  **********************************************/
HAL_StatusTypeDef  HAL_FLASH_Unlock(void);
HAL_StatusTypeDef  HAL_FLASH_Lock(void);

/* Option bytes control */
HAL_StatusTypeDef  HAL_FLASH_OB_Unlock(void);
HAL_StatusTypeDef  HAL_FLASH_OB_Lock(void);
HAL_StatusTypeDef  HAL_FLASH_OB_Launch(void);
/* Extended Program operation functions  *************************************/
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError);
HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit);
HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit);
void              HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit);
HAL_StatusTypeDef HAL_FLASHEx_EnableSecMemProtection(uint32_t Bank);
void              HAL_FLASHEx_EnableDebugger(void);
void              HAL_FLASHEx_DisableDebugger(void);
/* Private function prototypes -----------------------------------------------*/
static void              FLASH_MassErase(uint32_t Banks);
static HAL_StatusTypeDef FLASH_OB_WRPConfig(uint32_t WRPArea, uint32_t WRPStartOffset, uint32_t WRDPEndOffset);
static HAL_StatusTypeDef FLASH_OB_RDPConfig(uint32_t RDPLevel);
static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig);
static HAL_StatusTypeDef FLASH_OB_PCROPConfig(uint32_t PCROPConfig, uint32_t PCROPStartAddr, uint32_t PCROPEndAddr);
static void              FLASH_OB_GetWRP(uint32_t WRPArea, uint32_t *WRPStartOffset, uint32_t *WRDPEndOffset);
static uint32_t          FLASH_OB_GetRDP(void);
static uint32_t          FLASH_OB_GetUser(void);
static void              FLASH_OB_GetPCROP(uint32_t *PCROPConfig, uint32_t *PCROPStartAddr, uint32_t *PCROPEndAddr);
static HAL_StatusTypeDef FLASH_OB_SecMemConfig(uint32_t SecMemBank, uint32_t SecMemSize);
static void              FLASH_OB_GetSecMem(uint32_t SecMemBank, uint32_t *SecMemSize);
static HAL_StatusTypeDef FLASH_OB_BootLockConfig(uint32_t BootLockConfig);
static uint32_t          FLASH_OB_GetBootLock(void);
/** @defgroup FLASH_OB_Type FLASH Option Bytes Type */
#define OPTIONBYTE_WRP            0x01U                    /*!< WRP option byte configuration */
#define OPTIONBYTE_RDP            0x02U                    /*!< RDP option byte configuration */
#define OPTIONBYTE_USER           0x04U                    /*!< USER option byte configuration */
#define OPTIONBYTE_PCROP          0x08U                    /*!< PCROP option byte configuration */
#define OPTIONBYTE_BOOT_LOCK      0x10U                    /*!< Boot lock option byte configuration */
#define OPTIONBYTE_SEC            0x20U                    /*!< Securable memory option byte configuration */

#define OB_USER_BOR_LEV           0x00000001U              /*!< BOR reset Level */
#define OB_USER_nRST_STOP         0x00000002U              /*!< Reset generated when entering the stop mode */
#define OB_USER_nRST_STDBY        0x00000004U              /*!< Reset generated when entering the standby mode */
#define OB_USER_IWDG_SW           0x00000008U              /*!< Independent watchdog selection */
#define OB_USER_IWDG_STOP         0x00000010U              /*!< Independent watchdog counter freeze in stop mode */
#define OB_USER_IWDG_STDBY        0x00000020U              /*!< Independent watchdog counter freeze in standby mode */
#define OB_USER_WWDG_SW           0x00000040U              /*!< Window watchdog selection */
#define OB_USER_BFB2              0x00000080U              /*!< Dual-bank boot */
#define OB_USER_DBANK             0x00000100U              /*!< Single bank with 128-bits data or two banks with 64-bits data */
#define OB_USER_nBOOT1            0x00000200U              /*!< Boot configuration */
#define OB_USER_SRAM_PE           0x00000400U              /*!< SRAM parity check enable (first 32kB of SRAM1 + CCM SRAM) */
#define OB_USER_CCMSRAM_RST       0x00000800U              /*!< CCMSRAM Erase when system reset */
#define OB_USER_nRST_SHDW         0x00001000U              /*!< Reset generated when entering the shutdown mode */
#define OB_USER_nSWBOOT0          0x00002000U              /*!< Software BOOT0 */
#define OB_USER_nBOOT0            0x00004000U              /*!< nBOOT0 option bit */
#define OB_USER_NRST_MODE         0x00008000U              /*!< Reset pin configuration */
#define OB_USER_IRHEN             0x00010000U              /*!< Internal Reset Holder enable */

/**
  * @brief  FLASH Option Bytes Program structure definition
  */
typedef struct
{
  uint32_t OptionType;     /*!< Option byte to be configured. */
  [...]
  uint32_t USERType;       /*!< User option byte(s) to be configured (used for OPTIONBYTE_USER). */
  uint32_t USERConfig;     /*!< Value of the user option byte (used for OPTIONBYTE_USER). */
  [...]
} FLASH_OBProgramInitTypeDef;
/* Load */
void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
{
  pOBInit->OptionType = (OPTIONBYTE_RDP | OPTIONBYTE_USER);

  [...]

  /* Get Read protection level */
  pOBInit->RDPLevel = FLASH_OB_GetRDP();

  /* Get the user option bytes */
  pOBInit->USERConfig = FLASH_OB_GetUser();

  [...]

  pOBInit->OptionType |= OPTIONBYTE_BOOT_LOCK;

  /* Get the boot entry point */
  pOBInit->BootEntryPoint = FLASH_OB_GetBootLock();

  [...]
}

/* Save */
HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
{
  [...]

  /* User Configuration */
  if ((pOBInit->OptionType & OPTIONBYTE_USER) != 0U)
  {
    /* Configure the user option bytes */
    if (FLASH_OB_UserConfig(pOBInit->USERType, pOBInit->USERConfig) != HAL_OK)
    {
      status = HAL_ERROR;
    }
  }

  [...]
}

/* Private */
static HAL_StatusTypeDef FLASH_OB_UserConfig(uint32_t UserType, uint32_t UserConfig)
{
    [...]

    if ((UserType & OB_USER_nBOOT0) != 0U)
    {
      /* nBOOT0 option byte should be modified */
      assert_param(IS_OB_USER_BOOT0(UserConfig & FLASH_OPTR_nBOOT0));

      /* Set value and mask for nBOOT0 option byte */
      optr_reg_val |= (UserConfig & FLASH_OPTR_nBOOT0);
      optr_reg_mask |= FLASH_OPTR_nBOOT0;
    }

    [...]

    /* Configure the option bytes register */
    MODIFY_REG(FLASH->OPTR, optr_reg_mask, optr_reg_val);

    /* Set OPTSTRT Bit */
    SET_BIT(FLASH->CR, FLASH_CR_OPTSTRT);

    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
  }

  return status;
}