cancel
Showing results for 
Search instead for 
Did you mean: 

Resetting option bytes of STM32U575xx with RAM application

Nick van IJzendoorn
Associate III

Currently I write locked the first few sectors of my STM32U575xx. However I would also like the unlock the write protection. Since both J-Link and the ST-Link cannot do this I thought about writing a small application and run it from RAM to reset the option bytes. This however does not work.

When I try to write the option bytes the status register returns `Option write error`. Does anyone has an idea on what I'm doing wrong? I previously locked pages 0 to 8, I thought I leave it unchanged. Changing this to the factory default however doesn't work.

The failure occurs on line 82.

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_ICACHE_Init();
  /* USER CODE BEGIN 2 */
 
  void disable_wr_protection(void);
  disable_wr_protection();
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
 
/** Enable write protection on the bootloader region if not yet enabled
 */
void disable_wr_protection(void)
{
	// Get FLASH_WRP_SECTORS write protection status
	FLASH_OBProgramInitTypeDef option_bytes_init = {0};
	option_bytes_init.WRPArea = OB_WRPAREA_BANK1_AREAA;
    HAL_FLASHEx_OBGetConfig(&option_bytes_init);
    uint32_t wrp_status = ((option_bytes_init.OptionType & OPTIONBYTE_WRP) == OPTIONBYTE_WRP)
    						&& (option_bytes_init.WRPLock == DISABLE);
 
    // check if write protection is already enabled
    if (wrp_status)
    {
    	printf("wrp: write protection disabled\r\n");
    	return;
    }
 
    printf("wrp: disabling write protection on the bootloader sections\r\n");
 
    // allow access to flash control registers and user flash
    if (HAL_FLASH_Unlock() != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // allow access to option bytes sector
    if (HAL_FLASH_OB_Unlock() != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // enable FLASH_WRP_SECTORS write protection
    option_bytes_init.OptionType = OPTIONBYTE_WRP;
    option_bytes_init.WRPStartOffset = 0;
    option_bytes_init.WRPEndOffset = 8;
    option_bytes_init.WRPLock = DISABLE;
    if (HAL_FLASHEx_OBProgram(&option_bytes_init) != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // start the option bytes programming process
    if (HAL_FLASH_OB_Launch() != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // prevent access to option bytes sector
    if (HAL_FLASH_OB_Lock() != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // disable the flash option control register access (recommended to protect the option bytes against possible unwanted operations)
    if (HAL_FLASH_Lock() != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // get FLASH_WRP_SECTORS write protection status
    HAL_FLASHEx_OBGetConfig(&option_bytes_init);
    wrp_status = ((option_bytes_init.OptionType & OPTIONBYTE_WRP) == OPTIONBYTE_WRP)
    				&& (option_bytes_init.WRPLock == DISABLE);
 
    // check if FLASH_WRP_SECTORS write protection is disabled
    if (wrp_status)
    	printf("wrp: write protection disabled\r\n");
    else
    	printf("wrp: failed to disable write protection\r\n");
}

Related: https://community.st.com/s/question/0D53W00001JVhsxSAD/howto-reset-option-bytes-on-stm32u575xx

3 REPLIES 3
Nick van IJzendoorn
Associate III

Oke although this might help someone else, I just found this:

Rules for modifying specific option bytes

Some of the option byte field must respect specific rules before being updated with new

values. These option bytes, as well as the associated constraints, are described below:

• UNLOCK option bits

– These bits can be set only when regressing from RDP level 1 to level 0.

So let's try it...

Nick van IJzendoorn
Associate III

Changing the code to do this however doesn't work. I see the RAM being erased while single stepping and it seems the flash is erased as well, since my bootloader no longer boots but when I program the SRAM application again it still says the section is write protected and the RDP is set to level 1. 

Nick van IJzendoorn
Associate III

Oke I got it working, I forgot to reset the actual write protection:

/** This function checks if the lock bit is set and handles unlocking it
 */
static void disable_wrp_1(void)
{
	FLASH_OBProgramInitTypeDef ob = {0};
	ob.WRPArea = OB_WRPAREA_BANK1_AREAA;
    HAL_FLASHEx_OBGetConfig(&ob);
    uint32_t wrp_locked = ((ob.OptionType & OPTIONBYTE_WRP) == OPTIONBYTE_WRP)
    						&& (ob.WRPLock == ENABLE);
 
    if (! wrp_locked)
    	return;
 
    uint32_t rdp_set = (ob.RDPLevel != OB_RDP_LEVEL_0);
 
    // allow access to flash control registers and user flash
    if (HAL_FLASH_Unlock() != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // allow access to option bytes sector
    if (HAL_FLASH_OB_Unlock() != HAL_OK)
    	// reset on failure, shouldn't happen
    	NVIC_SystemReset();
 
    // check if we must set the RDP level to 1
    if (! rdp_set)
    {
    	// switch to RDP level 1
    	ob.OptionType = OPTIONBYTE_RDP;
    	ob.RDPLevel = OB_RDP_LEVEL_1;
 
        // start the option bytes programming process
        if (HAL_FLASHEx_OBProgram(&ob) != HAL_OK)
        	// reset on failure, shouldn't happen
        	NVIC_SystemReset();
 
		// start the option bytes programming process
		if (HAL_FLASH_OB_Launch() != HAL_OK)
			// reset on failure, shouldn't happen
			NVIC_SystemReset();
    }
    else
    {
        // let's disable the lock bit by resetting the RDP to 0 and disabling the bit
        ob.OptionType = OPTIONBYTE_WRP | OPTIONBYTE_RDP;
        ob.RDPLevel = OB_RDP_LEVEL_0;
        ob.WRPLock = DISABLE;
        if (HAL_FLASHEx_OBProgram(&ob) != HAL_OK)
        	// reset on failure, shouldn't happen
        	NVIC_SystemReset();
 
		// start the option bytes programming process
		if (HAL_FLASH_OB_Launch() != HAL_OK)
			// reset on failure, shouldn't happen
			NVIC_SystemReset();
    }
}
 
/** This function checks if the write protection is in it's default state
 *  if not, resets to default
 */
static void disable_wrp_2(void)
{
	FLASH_OBProgramInitTypeDef ob = {0};
	ob.WRPArea = OB_WRPAREA_BANK1_AREAA;
    HAL_FLASHEx_OBGetConfig(&ob);
 
	if (ob.WRPStartOffset == 0x7f && ob.WRPEndOffset == 0x00)
		return;
 
	// allow access to flash control registers and user flash
	if (HAL_FLASH_Unlock() != HAL_OK)
		// reset on failure, shouldn't happen
		NVIC_SystemReset();
 
	// allow access to option bytes sector
	if (HAL_FLASH_OB_Unlock() != HAL_OK)
		// reset on failure, shouldn't happen
		NVIC_SystemReset();
 
	ob.OptionType = OPTIONBYTE_WRP;
	ob.WRPStartOffset = 0x7f;
	ob.WRPEndOffset = 0x00;
	if (HAL_FLASHEx_OBProgram(&ob) != HAL_OK)
		// reset on failure, shouldn't happen
		NVIC_SystemReset();
 
	// start the option bytes programming process
	if (HAL_FLASH_OB_Launch() != HAL_OK)
		// reset on failure, shouldn't happen
		NVIC_SystemReset();
 
	// prevent access to option bytes sector
	if (HAL_FLASH_OB_Lock() != HAL_OK)
		// reset on failure, shouldn't happen
		NVIC_SystemReset();
 
	// disable the flash option control register access (recommended to protect the option bytes against possible unwanted operations)
	if (HAL_FLASH_Lock() != HAL_OK)
		// reset on failure, shouldn't happen
		NVIC_SystemReset();
}
 
/** Enable write protection on the bootloader region if not yet enabled
 */
void disable_wr_protection(void)
{
	// disable write protection step 1, clearing the lock bit
	disable_wrp_1();
 
	// resetting the write protection
	disable_wrp_2();
}