2
\$\begingroup\$

I am working on an application on the STM32L4 microcontroller. The idea is when I press the user button, the bootloader jumps from the main application (0x08000000) to the second one (0x08080000).

The second firmware is just a blinking LED application. The jumping is fine and the LED starts blinking, but my problem is that when I want to go back from the second application to the first one (0x08000000) the exti won't work!

Here's my code:

First firmware:

if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
    /* Jump to user application */
    JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
    JumpToApplication = (pFunction) JumpAddress;

    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

    __disable_irq;
    SCB->VTOR = FLASH_BASE | 0x80000;

    HAL_RCC_DeInit();
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;
    __set_PRIMASK(1);

    printf("Starting Firmware 2 . . .  \r\n");
    HAL_DeInit();
    JumpToApplication();
}

The beginning of the second firmware:

  SCB->VTOR = FLASH_BASE | 0x80000;
  __set_PRIMASK(0);
  HAL_Init();

  SystemClock_Config();

  HAL_InitTick(1);

...

This is the exti callback from the second firmware:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    HAL_NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
    HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);

    if (GPIO_Pin == GPIO_PIN_13)
    {
        if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
        {
            JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
            JumpToApplication = (pFunction) JumpAddress;

            __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

             HAL_NVIC_DisableIRQ(EXTI15_10_IRQn);
            __disable_irq;
             SCB->VTOR = FLASH_BASE;
            JumpToApplication();
        }
    }
}

Why is this not working?

\$\endgroup\$
  • \$\begingroup\$ How do you intend to "go back" from the second application to the first? Is it your intention that the second application will simply return to the first application as if it was a subroutine? Is the second application compiled separately, with it's own startup code? If so then the second application's startup code will reset the stack and prevent you from returning to the first application so simply. \$\endgroup\$ – kkrambo Mar 31 '17 at 15:29
  • \$\begingroup\$ thnx for the reply , going back to the first application is the same way as going from the first one to the second , by clicking the user button. I've tested the second application separatly, so when I press the button it goes to the first one but when I press again it never goes back \$\endgroup\$ – Raed Bouchaa Mar 31 '17 at 16:26
  • \$\begingroup\$ It looks like you are jumping to the same application address, so just restarting your application. \$\endgroup\$ – stark Mar 31 '17 at 18:31
  • \$\begingroup\$ no I've declared "APPLICATION_ADDRESS=0x08080000" in the first firmware and "APPLICATION_ADDRESS=0x08000000" in the second. As I sad the jumping works fine but it stop working after the first jump , so no going back . It's like the interruption stop working after the jump . \$\endgroup\$ – Raed Bouchaa Mar 31 '17 at 18:34
  • \$\begingroup\$ can any one help ??? \$\endgroup\$ – Raed Bouchaa Apr 1 '17 at 11:23
5
\$\begingroup\$

You are starting the other application from within the interrupt serice routine, never returning from the interrupt handler. The system won't execute the same interrupt handler (or any other handler with the same or lower priority) until a proper exception return sequence is executed. You should somehow exit all active handlers before jumping to the other firmware.

Simplest method is to set a global volatile flag in the interrupt handler, and check it periodically in your main applocation loop.

You can also reset the system using NVIC_SystemReset(). You'd need a way to check and communicate where did the reset request come from, as it always goes to the first application.

Also note that __disable_irq; does nothing, you'd need () to actually call a function. It's always a good idea to enable and check compiler warnings.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ thank you alot , then if I jump to the second application from the main , that can solve the problem , and the exti will work from the second application ? \$\endgroup\$ – Raed Bouchaa Apr 4 '17 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.