cancel
Showing results for 
Search instead for 
Did you mean: 

How can the nBOOT0 pin be modified via a UART connection. I am using the STM32G071 chip

VWied.1
Associate III

Hello,

I am looking to be able to do in-the-field firmware upgrades with the STM32G071 board. I have used the STMCubeProg tool to be able to modify the nBOOT0 user bit with the ST-Link built into the NUCLEO board.

What I am looking to do is

  • to modify nBOOT0 to 0 through the firmware on the device.
  • Then I am assuming that I can reset the device,
  • and then using a connected UART comms, I can update the firmware,
  • After that, I can set the nBOOT0 pin back to 0.

The issues are that I can't figure out how to modify the nBOOT0 bit in the firmware. Also, I am unsure if my STM32G071 will be able to flip its nBOOT0 pin back itself after the firmware update.

I have read through the AN2606 and AN3155 and cannot find an answer to my question. Everything points back to the STM32Prog tool which I don't want to have to rely on.

12 REPLIES 12
VWied.1
Associate III

Hello,

I understand the theory of setting the nBOOT0 user bit in software, but the examples I have found do not seem to work. I suspect I am missing a basic step here. From what I understand, I need to:

unlock the flash

unlock the Option Bytes flash

Program the Option Bytes

lock the Option Bytes flash

lock the flash

reset the system

Currently, this is what I have. I have confirmed that all of the HAL function calls are returning HAL_OK, I just removed the error checking to reduce the code size.

uint8_t startBootloader(){
    FLASH_OBProgramInitTypeDef ob_cfg;
    HAL_FLASHEx_OBGetConfig(&ob_cfg);
 
    /*
    From ST AN2606, pattern 11 Only nBOOT0 bit needs to change.
    nBOOT0(bit) == 0 for bootloader therefore OB_nBOOT0_RESET
    */
 
    ob_cfg.OptionType = OPTIONBYTE_USER;
    ob_cfg.USERType = OB_USER_nBOOT0;
    ob_cfg.USERConfig =  OB_nBOOT0_RESET;
 
    // of any ifs are true, throw error.
    HAL_FLASH_Unlock();
    HAL_FLASH_OB_Unlock();
    HAL_FLASHEx_OBProgram(&ob_cfg);
    HAL_FLASH_OB_Lock();
    HAL_FLASH_Lock();
    return 0;
}

If I do another function call of:

HAL_FLASHEx_OBGetConfig()

After the HAL_FLASH_Lock, I find that the option bytes has not changed.

When I try to do the function call HAL_FLASH_OB_Launch(void) To reset the device, it returns with HAL_ERROR.

Am I missing a step?

TDK
Guru

Sequence should be:

    HAL_FLASH_Unlock();
    HAL_FLASH_OB_Unlock();
    HAL_FLASHEx_OBProgram(&ob_cfg);
    HAL_FLASHEx_OB_Launch();

The last function causes a reset which makes the option bytes active. It doesn't matter what code you have after this because the mcu resets, but I would still monitor the return value.

The reference manual goes over the sequence needed to perform these steps. You can also look at the source to find out what HAL is doing. For example:

/**
  * @brief  Launch the option byte loading.
  * @retval HAL Status
  */
HAL_StatusTypeDef HAL_FLASH_OB_Launch(void)
{
  /* Set the bit to force the option byte reloading */
  SET_BIT(FLASH->CR, FLASH_CR_OBL_LAUNCH);
 
  /* We should not reach here : Option byte launch generates Option byte reset
     so return error */
  return HAL_ERROR;
}

It makes sense that this returns HAL_ERROR. The first statement, which would normally reset the chip, doesn't work because the option bytes are locked.

If you find checking for return values a pain, consider defining a macro:

#define RUN_HAL(x) if ((x) != HAL_OK) {while (1);}
 
...
 
RUN_HAL(HAL_FLASH_Unlock());

At least that way you have a chance of catching errors when they happen, instead of having to hunt them down afterwards.

If you feel a post has answered your question, please click "Accept as Solution".
VWied.1
Associate III

That was it, thank you.