How can I debug what is going wrong with a jump from one application to another in STM32G4?

441 Views Asked by At

I have a project with a FreeRTOS application running on custom hardware (STM32G483VETS). The project generates two versions of the binary. App1 loads at 0x08000000,App2 (future enhancements and bug fixes) at 0x08040000.

At power on, the MCU boots into App1 running in flash. When instructed over the CAN bus, it disables all interrupts, de-initialises all peripherals, sets up the new stack pointer and jumps to App2 with a call such as:

jump_to_app(EXTENDED_START); // EXTENDED_START is 0x08040000

Code for jump_to_app:

typedef struct {
    uint32_t stack_address;         // Stack Pointer
    application_t *function_ptr;    // Program Counter
} jump_structure_t;



void jumpToApp(const uint32_t address)
{
    const jump_structure_t *jump_vector_p = (jump_structure_t*) address;

    DeInit_all_modules();

    /* Jump, uses assembler to avoid stack optimisation */
    asm("msr msp, %0; bx %1;" : : "r"(jump_vector_p->stack_address), "r"(jump_vector_p->function_ptr));
}

Code for disabling interrupts and de-initialising modules:

void DeInitAllModules()
{
    /* Disable all interrupts */
    __disable_irq();

    /* De-initialise all modules in the opposite order they were
     * initialised in main.c
     */
    //  MX_OPAMP3_Init();
    HAL_OPAMP_DeInit(&hopamp3);

    //  MX_OPAMP1_Init();
    HAL_OPAMP_DeInit(&hopamp1);

    //  MX_TIM16_Init();
    HAL_TIM_PWM_DeInit(&htim16);

    //  MX_SPI4_Init();
    HAL_SPI_DeInit(&hspi4);

    //  MX_SPI3_Init();
    HAL_SPI_DeInit(&hspi3);

    //  MX_SPI2_Init();
    HAL_SPI_DeInit(&hspi2);

    //  MX_SPI1_Init();
    HAL_SPI_DeInit(&hspi1);

    //MX_DMA_Init();
    HAL_NVIC_DisableIRQ(DMA1_Channel5_IRQn);
    HAL_NVIC_DisableIRQ(DMA1_Channel4_IRQn);
    HAL_NVIC_DisableIRQ(DMA1_Channel3_IRQn);
    HAL_NVIC_DisableIRQ(DMA1_Channel2_IRQn);
    HAL_NVIC_DisableIRQ(DMA1_Channel1_IRQn);

    //  MX_DAC3_Init();
    HAL_DAC_DeInit(&hdac3);

    //  MX_COMP2_Init();
    HAL_COMP_DeInit(&hcomp2);

    //  MX_ADC5_Init();
    HAL_ADC_DeInit(&hadc5);

    //  MX_TIM8_Init();
    HAL_TIM_PWM_DeInit(&htim8);

    //  MX_TIM3_Init();
    HAL_TIM_Base_DeInit(&htim3);

    //  MX_TIM1_Init();
    HAL_TIM_Base_DeInit(&htim1);

    //  MX_RTC_Init();
    HAL_RTC_DeInit(&hrtc);

    //  MX_ADC1_Init();
    HAL_ADC_DeInit(&hadc1);

    //  MX_FDCAN1_Init();
    HAL_FDCAN_DeInit(&hfdcan1);

    //  MX_GPIO_Init();
    HAL_GPIO_DeInit(USR_LED_GPIO_Port, USR_LED_Pin);
    HAL_GPIO_DeInit(ERR_LED_GPIO_Port, ERR_LED_Pin);
    __HAL_RCC_GPIOG_CLK_DISABLE();
    __HAL_RCC_GPIOF_CLK_DISABLE();
    __HAL_RCC_GPIOE_CLK_DISABLE();
    __HAL_RCC_GPIOD_CLK_DISABLE();
    __HAL_RCC_GPIOC_CLK_DISABLE();
    __HAL_RCC_GPIOB_CLK_DISABLE();
    __HAL_RCC_GPIOA_CLK_DISABLE();

    HAL_DeInit();
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
}

Up until the point where the jump happens, the IDE is using the ELF to display the C code, variables etc. but App2 has a separate ELF.

How do I keep debugging after the jump? Can I 'combine' the ELF files?

I am developing in STM32CubeIDE v1.9.0 and debugging using a J-Link Ultra+.

Thanks

1

There are 1 best solutions below

1
On

Can I 'combine' the ELF files?

Go to the debugging configuration (you find this this by clicking the downwards arrow right of the green bug symbol and selecting "Debug configurations" in the drop-down menu) and select the debugging configuration that you use for debugging.

Select the "Start" tab.

In the "Start" tab you can specify which ELF files are used for debugging and you can specify if these ELF files are used for Flashing or only for the debugging information.

How do I keep debugging after the jump?

At least entering the new application (this is the asm part...) I would debug on machine code (disassembly) level.

To do this, you check the "black 'i' with a yellow arrow to the right" button.

... sets up the new stack pointer ...

I have not much experience with FreeRTOS, but are you sure that the CONTROL register (which specifies if msp or psp is the stack pointer and if the CPU runs in privileged mode) has the correct value?

If the CPU is in privileged mode, you even have to enter an exception handler to modify the CONTROL register...


There is a screenshot in the Eclipse Wiki: I'm talking about ...

  • the "down arrow" next to the leftmost icon in the icon bar and
  • the third icon from the right.