How to access the System Bootloader on Nucleo F411RE using software RESET?
Hello all,
My aim is to utilize the User Push button (configured as an EXTI gpio) on Nucelo-F411RE board along with a software reset to enter the System Bootloader located @0x1FFF0000 (ref: AN2606).
With the software reset implementation, I face the bellow issues:
A.) The SFTRSTF flag is always set by the hardware while the user application is running. Shouldn't this flag be set only when the software reset line is executed? This should only occur when the User Push button is pressed.
B.) Because the SFTRSTF flag is set, the program always enters the check flag function (See Step 2.) and tries executing the bootloader code without even reaching the user application code (See Step 4.). The program always remains in this function an keeps on continuously executing the bootloader function and never goes to the user application.
C.) Sometimes, the program correctly enters the 'check flag' function (See Step 2.) upon pressing the user button, the function 'check flag' (See Step 2) clears the software reset flag bit and then executes the system bootloader, but then the program gets stuck in this loop and never exits the bootloader code.
D.) The VTOR is never loaded with the System Bootloader address and is always 0x00000000 while testing software reset.
NOTE:
SFTRSTF flag in the RCC_CSR register is set by the Hardware upon software reset. This flag can be used to check if the software reset condition is met and must be cleared by setting the RMVF flag in the RCC_CSR register.
Implementation Steps for Software RESET:
Step 1.) User Push button is configured as an EXTI gpio, so the callback function would get called upon pressing this button. Once pressed, I perform the Software Reset using the HAL_API.
<bootloader.c>
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == User_PB_Pin)
{
//Perform software reset
HAL_NVIC_SystemReset();
}
}
Step 2.) Upon Software reset, the board initiates its execution by initializing everything. So, in the register (RCC_CSR), I check for software reset flag condition(SFTRSTF) which is automatically set by the hardware when a software reset occurs. If SFTRSTF is set, I clear this flag by setting the RMVF (Remove Flag) bit from the same register (RCC_CSR) and implement the call the function "jumpTo_STBootloader()'.
<main.c>
int main (void) {
// HAL initialization here
// CODE HERE
if(__HAL_RCC_GET_FLAG(RCC_FLAG_SFTRST))
{
//Clr reset flag
RCC->CSR |= RCC_CSR_RMVF;
jumpTo_STBootloader();
}
//CODE HERE
while (1) {
}
return 0;
}
Step 3.) The function 'jumpTo_STBootloader' handles the jump from the user application to the system memory bootloader. This function is implemented as below:
<bootloader.c>
void jumpTo_STBootloader()
{
void(*SysMemBootJump)(void);
volatile uint32_t addr = 0x01FFF0000; // System memory address
__disable_irq();
// Diaable RCC peripherals
HAL_RCC_DeInit();
HAL_DeInit();
// Re-map memory address
SYSCFG->MEMRMP = 0x01;
// Reset SYSTICK
SysTick->CTRL = 0;
SysTick->VAL = 0;
SysTick->LOAD = 0;
SysMemBootJump = (void (*) (void))(*((uint32_t *)(addr+4)));
__set_MSP(*(uint32_t *)addr);
SysMemBootJump();
//should never return here
while(1);
}
Step 4.) User application is Toggling led in the super loop as below,
<main.c>
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
TOGG_LED();
HAL_Delay(250);
}
/* USER CODE END 3 */
Previous Implementation using Hardware RESET button:
I had previously tested using a hardware reset button and I was able to access the System Bootloader without any issues. While testing the hardware reset, instead of using the interrupt callback function for the User Push button, I was simply using an if condition to check if the button was pressed and execute the jumpTo-STBootloader() function.
The way it was achieved was, I would press the hardware RESET button while pressing the User Push button, so that the moment my Nucleo board would reset, the first thing that it would check was the user push button is pressed and immediately it would execute the bootloader code. Also the VTOR register would correctly hold the System Bootloader Address (0x1FFF0000).
But with the software reset implementation, I am facing issues which I am not able to understand. I would appreciate any guidance on this. Also is my implementation correct?
Thank you
