cancel
Showing results for 
Search instead for 
Did you mean: 

Problem to Jump from bootloader to application on STM32F412

SDall.11
Associate III

Good morning everyone,
I am trying to modify a bootloader that is already in production and working.
My problem is that if I call the JumpToApplication() function right after peripheral initialization (as the production bootloader does), everything works perfectly.
However, if I call it from within the infinite loop or even after exiting the loop, as you can see from the attached code, the jump does not work.
I can't explain why.
Additionally, I wanted to ask two more things:

  1. Is it necessary to define the array volatile uint32_t stack_arr[30]? I have never seen it in any bootloader.

  2. In the statement pmain_app = (void (*)(void)) * (APPLICATION_START_ADDRESS + 1); I see that there is a +1 at the end, but in various examples, I always see +4. Yet it still works!!!

Can you give me some advice?
Thank you.

 

 

 

 

#include "main.h"
#include "dma.h"
#include "fatfs.h"
#include "spi.h"
#include "usb_host.h"
#include "gpio.h"
#include "crc.h"

extern HCD_HandleTypeDef hhcd_USB_OTG_FS;
extern TIM_HandleTypeDef htim11;

static uint16_t           tim_boot_x1ms = 0;
volatile static uint8_t   timRefreshDisplay_x1ms = 0;

void SystemClock_Config(void);
void MX_USB_HOST_Process(void);

void JumpToApplication(void);

int main(void)
{
    volatile uint32_t stack_arr[30] = {0}; // Allocate some stack
                                           // just to show that
                                           // the SP should be reset
                                           // before the jump - or the
                                           // stack won't be configured
                                           // correctly.

    HAL_Init();
    SystemClock_Config();

    static void JumpToApplication(void)
    MX_GPIO_Init();
    __enable_irq();
    MX_DMA_Init();
    MX_SPI1_Init();
	MX_USB_HOST_Init();
    MX_FATFS_Init();
	MX_CRC_Init();

    //JumpToApplication(); //JumpToApplication called here works fine

    static bool endLoop = false;

    while(!endLoop)
    {
        MX_USB_HOST_Process();

		retStatus_t ret = USB_FW_Update_Process();
        
		switch(ret)
		{
			case retNothing:
			break;

			case retJump:
				__disable_irq();
				endLoop = true;
			break;

			case retReset:
				NVIC_SystemReset();
			break;
		}
    }

	JumpToApplication();
}


void JumpToApplication(void)
{
    //Deinit all peripherals
	HAL_SPI_MspDeInit(&hspi1);
    HAL_TIM_Base_DeInit(&htim11);
	HAL_CRC_MspDeInit(&hcrc);
	__HAL_RCC_USB_OTG_FS_CLK_DISABLE();
	__HAL_RCC_DMA2_CLK_DISABLE();
    __HAL_RCC_SPI1_CLK_DISABLE();
    __HAL_RCC_TIM1_CLK_DISABLE();
    __HAL_RCC_GPIOA_CLK_DISABLE();
	__HAL_RCC_GPIOB_CLK_DISABLE();
	__HAL_RCC_GPIOC_CLK_DISABLE();
	__HAL_RCC_GPIOD_CLK_DISABLE();

    void (*pmain_app)(void);

    __disable_irq();

    SCB->VTOR = (uint32_t)APPLICATION_START_ADDRESS;
    __set_MSP((uint32_t)*APPLICATION_START_ADDRESS);
    pmain_app = (void (*)(void)) * (APPLICATION_START_ADDRESS + 1);

    // JUMP TO APP!
    pmain_app();
}

 

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

Hi, I rearranged the function as you can see below and it works fine:

void jumpToApplication(void)
{
    void (*pmain_app)(void);

    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_All);
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_All);
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_All);
    HAL_GPIO_DeInit(GPIOD, GPIO_PIN_All);

    HAL_SPI_MspDeInit(&hspi1);
    HAL_CRC_MspDeInit(&hcrc);

    HAL_TIM_Base_DeInit(&htim11);
    HAL_DeInit();                

    __disable_irq();

    __DSB();
    __ISB();

    SCB->VTOR = (uint32_t)APPLICATION_START_ADDRESS;
    __set_MSP((uint32_t)*APPLICATION_START_ADDRESS);

    pmain_app = (void (*)(void)) * (APPLICATION_START_ADDRESS + 1);
    pmain_app();
}

 

View solution in original post

5 REPLIES 5

Hi,

Can you please elaborate more? How it is not working? Does it show hard fault? 

What does this function do USB_FW_Update_Process?

 

 

 

pmain_app = (void (*)(void)) * (APPLICATION_START_ADDRESS + 1);

That line works only if APPLICATION_START_ADDRESS is defined something like this:

#define APPLICATION_START_ADDRESS ((void *)(0x08010000))

Since it is defined as a "pointer to void", pointers are 32-bit values (aka 4 bytes).  So incrementing a pointer increments the actual value by 4.

The stack_arr[] variable is not used anywhere, not sure why it is there.

As to why your application fails when you call JumpToApplication() in or after that loop - just a wild guess but you do not de-initialize the USB interface, you only turn off the clock.  Presuming your application uses the USB interface, as soon as it enables the clock it MAY get an interrupt, and the USB data structures have not yet been fully enabled and the registers have not be reset - so who knows what the interrupt handler will do.  Most likely hit a memory fault.

Good morning everyone and thank you for your responses.
First of all, I apologize for omitting in the previous post the define concerning the assignment of  APPLICATION_START_ADDRESS.
I have conducted further tests to understand more and to provide you with a more complete picture.
As already mentioned previously, I confirm that if I place JumpToApplication() right before the while(true) loop, everything works correctly.
I have also noticed that if I do not initialize any peripherals, the JumpToApplication() also works within the while loop.
So, I started to perform selective initializations, but even with the first initialization, MX_GPIO_Init(), the JumpToApplication() works outside the while loop but not inside.
And yet, I think I am deinitializing everything correctly, what am I doing wrong?
Thank you.

#include "main.h"
#include "dma.h"
#include "fatfs.h"
#include "spi.h"
#include "usb_host.h"
#include "gpio.h"
#include "crc.h"

extern TIM_HandleTypeDef htim11;
extern const uint32_t   app_vector; 

#define APPLICATION_START_ADDRESS       (uint32_t *)&app_vector


void SystemClock_Config(void);
void MX_USB_HOST_Process(void);
void JumpToApplication(void);


int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    __enable_irq();

    volatile static int xxx;

    //JumpToApplication() //Here works

    while(true)
    {
		retStatus_t ret = retNothing;

        if(xxx++ >= 10000) ret = retJump;

		switch(ret)
		{
			case retNothing:
			break;

			case retJump:
				__disable_irq();
				JumpToApplication();
			break;

			case retReset:
				NVIC_SystemReset();
			break;
		}
    }
}

void JumpToApplication(void)
{
    __HAL_RCC_GPIOA_CLK_DISABLE();
	__HAL_RCC_GPIOB_CLK_DISABLE();
	__HAL_RCC_GPIOC_CLK_DISABLE();
	__HAL_RCC_GPIOD_CLK_DISABLE();

    HAL_TIM_Base_DeInit(&htim11);

    void (*pmain_app)(void);

    __disable_irq();

    __HAL_RCC_CRC_CLK_DISABLE();

    SCB->VTOR = (uint32_t)APPLICATION_START_ADDRESS;
    __set_MSP((uint32_t)*APPLICATION_START_ADDRESS);
    pmain_app = (void (*)(void)) * (APPLICATION_START_ADDRESS + 4);

    __DSB();
    __ISB();

    pmain_app();
}

Disabling the clock to the GPIO blocks does NOT un-configure the GPIO.  Do you have any GPIO configured as EXTI?  If so, as soon as the main app re-starts the clock to that GPIO block it will respond to rising/falling edges on the EXTI line.

And you de-init TIM11 but never initialize it - was that just left over code or did the init call get missed when you copy/pasted into the forum?

The bottom line is you should use your debugger to see where the main app is "hung".  It is possible to load two sets of symbol tables into the debugger, one for your bootloader and one for the application.  I think ST even has an example:

https://github.com/ethanhuanginst/STM32CubeIDE-Workshop-2019/tree/master/hands-on/09_BOOT-APP

 

Hi, I rearranged the function as you can see below and it works fine:

void jumpToApplication(void)
{
    void (*pmain_app)(void);

    HAL_GPIO_DeInit(GPIOA, GPIO_PIN_All);
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_All);
    HAL_GPIO_DeInit(GPIOC, GPIO_PIN_All);
    HAL_GPIO_DeInit(GPIOD, GPIO_PIN_All);

    HAL_SPI_MspDeInit(&hspi1);
    HAL_CRC_MspDeInit(&hcrc);

    HAL_TIM_Base_DeInit(&htim11);
    HAL_DeInit();                

    __disable_irq();

    __DSB();
    __ISB();

    SCB->VTOR = (uint32_t)APPLICATION_START_ADDRESS;
    __set_MSP((uint32_t)*APPLICATION_START_ADDRESS);

    pmain_app = (void (*)(void)) * (APPLICATION_START_ADDRESS + 1);
    pmain_app();
}