AnsweredAssumed Answered

Why does my interrupt stop working after I jump to a different area of execution?

Question asked by arnold_w on Jun 15, 2016
Latest reply on Jun 15, 2016 by Clive One
I am working with the Discovery Development Board (STM32F407) and I have 2 projects, a bootloader project and an application project. The application project can run by itself, but the bootloader cannot. If I run the application by itself, it works as expected, it resets when I press the blue button. However, when I run the bootloader and the application together, then my application does not generate any button events.

Bootloader code:
001        #define GOTO_APPLICATION()       __asm__("LDR R0,=0x08010004"); \
002                                         __asm__("LDR R0, [R0]");       \
003                                         __asm__("BX  R0")
004        int main(int argc, char* argv[])
005        {
006            __disable_irq();
007            __HAL_RCC_GPIOA_CLK_ENABLE();          // Enable clock for GPIO port A
008            __HAL_RCC_GPIOC_CLK_ENABLE();          // Enable clock for GPIO port C
009            __HAL_RCC_TIM3_CLK_ENABLE();           // Enable clock for Timer 3
010            HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
011       
012            UART_Init(115200);
013            UART_TransmitNullTerminatedString((uint8_t*) "\r\nHello in bootloader. SCB->VTOR is 0x");
014            UART_TransmitHexNumberAsASCII((uint32_t)SCB->VTOR);
015       
016            /***************************************************
017            *****************  PA0, BUTTON PIN  ****************
018            ***************************************************/
019            GPIO_InitTypeDef GPIO_InitStructure;
020            GPIO_InitStructure.Pin       = GPIO_PIN_0;
021            GPIO_InitStructure.Mode      = GPIO_MODE_IT_RISING;
022            GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
023            GPIO_InitStructure.Pull      = GPIO_NOPULL;
024            GPIO_InitStructure.Alternate = 0;
025            HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
026       
027            HAL_NVIC_EnableIRQ(EXTI0_IRQn);
028            __enable_irq();
029            while (1) {}
030            return 0;
031        }
032       
033       
034        void EXTI0_IRQHandler(void)
035        {
036            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
037        }
038       
039       
040        void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
041        {
042            UART_TransmitNullTerminatedString((uint8_t*) "\r\nHAL_GPIO_EXTI_Callback, pin 0x");
043            UART_TransmitHexNumberAsASCII((uint32_t)GPIO_Pin);
044            HAL_NVIC_DisableIRQ(EXTI0_IRQn);
045            __disable_irq();
046            GOTO_APPLICATION();
047        }

Bootloader linker scripts and vectors:
__attribute__ ((section(".startUpVector"),used)) pHandler __startUpVector[] =
{
  // Core Level - CM4
      (pHandler) &_estack,                      // The initial stack pointer
      (pHandler) 0x08000405,                    // The reset handler
};
 
 
SECTIONS
{
    .startUpVector : ALIGN(4)
    {
        KEEP(*(.startUpVector))
        *(.startUpVector .startUpVector.*)     
 
    } >STARTUP_VECTOR
 
 
MEMORY
{
  RAM (xrw)                : ORIGIN = 0x20000000, LENGTH = 127K
  CCMRAM (xrw)             : ORIGIN = 0x10000000, LENGTH = 64K
  STARTUP_VECTOR (rx)      : ORIGIN = 0x08000000, LENGTH = 1016
  EMPTY_SPACE (rx)         : ORIGIN = 0x080003F8, LENGTH = 8
  FLASH (rx)               : ORIGIN = 0x08000400, LENGTH = 31K
  ANOTHER_EMPTY_SPACE (rx) : ORIGIN = 0x08008000, LENGTH = 32K
  APPLICATION_FW (rx)      : ORIGIN = 0x08010000, LENGTH = 960K
  FLASHB1 (rx)             : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB0 (rx)            : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx)            : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx)            : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx)            : ORIGIN = 0x00000000, LENGTH = 0
  MEMORY_ARRAY (xrw)       : ORIGIN = 0x20002000, LENGTH = 32
}

Application code:
001        int main(int argc, char* argv[])
002        {
003            __disable_irq();
004            __HAL_RCC_GPIOA_CLK_ENABLE();              // Enable clock for GPIO port A
005            __HAL_RCC_GPIOC_CLK_ENABLE();              // Enable clock for GPIO port C
006            __HAL_RCC_TIM3_CLK_ENABLE();               // Enable clock for Timer 3       
007            HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
008       
009            UART_Init(115200);
010            UART_TransmitNullTerminatedString((uint8_t*) "\r\nHello in application. SCB->VTOR is 0x");
011            UART_TransmitHexNumberAsASCII((uint32_t)SCB->VTOR);
012       
013            /***************************************************
014            *****************  PA0, BUTTON PIN  ****************
015            ***************************************************/
016            GPIO_InitTypeDef GPIO_InitStructure;
017            GPIO_InitStructure.Pin       = GPIO_PIN_0;
018            GPIO_InitStructure.Mode      = GPIO_MODE_IT_RISING;
019            GPIO_InitStructure.Speed     = GPIO_SPEED_FAST;
020            GPIO_InitStructure.Pull      = GPIO_NOPULL;
021            GPIO_InitStructure.Alternate = 0;
022            HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
023       
024            HAL_NVIC_EnableIRQ(EXTI0_IRQn);
025            __enable_irq();
026            while (1) { }
027            return 0;
028        }
029       
030       
031        void EXTI0_IRQHandler(void)
032        {
033            HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0);
034        }
035       
036       
037        void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
038        {
039            UART_TransmitNullTerminatedString((uint8_t*) "\r\nHAL_GPIO_EXTI_Callback, pin 0x");
040            UART_TransmitHexNumberAsASCII((uint32_t)GPIO_Pin);
041            HAL_NVIC_DisableIRQ(EXTI0_IRQn);
042            __disable_irq();
043            NVIC_SystemReset();
044        }

Application linker scripts and vectors:
#define GOTO_APPLICATION()         __asm__("LDR R0,=0x08010004"); \
                     __asm__("LDR R0, [R0]");       \
                     __asm__("BX  R0")
 
 
__attribute__ ((section(".startUpVector"),used)) pHandler __startUpVector[] =
{
  // Core Level - CM4
      (pHandler) &_estack,                      // The initial stack pointer
      (pHandler) 0x08000401,                    // The reset handler
};
 
 
void __attribute__ ((section(".jumpToApplication"),used)) __jumpToApplication(void)
{
    GOTO_APPLICATION();
}
 
SECTIONS
{
    .startUpVector : ALIGN(4)
    {
        KEEP(*(.startUpVector))
        *(.startUpVector .startUpVector.*)     
 
    } >STARTUP_VECTOR
 
 
    .jumpToApplication : ALIGN(4)
    {
        KEEP(*(.jumpToApplication))
        *(.jumpToApplication .jumpToApplication.*)     
 
    } >BOOTLOADER_FW
 
 
    /*
     * For Cortex-M devices, the beginning of the startup code is stored in
     * the .isr_vector section, which goes to FLASH.
     */
    .isr_vector : ALIGN(4)
    {
        FILL(0xFF)
         
        __vectors_start = ABSOLUTE(.) ;
        __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
        KEEP(*(.isr_vector))        /* Interrupt vectors */
         
        KEEP(*(.cfmconfig))         /* Freescale configuration words */  
              
        /*
         * This section is here for convenience, to store the
         * startup code at the beginning of the flash area, hoping that
         * this will increase the readability of the listing.
         */
        *(.after_vectors .after_vectors.*)  /* Startup code and ISR */
 
    } >ISR_VECTORS
 
 
    .inits : ALIGN(4)
    {
        /*
         * Memory regions initialisation arrays.
         *
         * Thee are two kinds of arrays for each RAM region, one for
         * data and one for bss. Each is iterrated at startup and the  
         * region initialisation is performed.
         *
         * The data array includes:
         * - from (LOADADDR())
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * The bss array includes:
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * WARNING: It is mandatory that the regions are word aligned,
         * since the initialisation code works only on words.
         */
          
        __data_regions_array_start = .;
         
        LONG(LOADADDR(.data));
        LONG(ADDR(.data));
        LONG(ADDR(.data)+SIZEOF(.data));
         
        LONG(LOADADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM)+SIZEOF(.data_CCMRAM));
         
        __data_regions_array_end = .;
         
        __bss_regions_array_start = .;
         
        LONG(ADDR(.bss));
        LONG(ADDR(.bss)+SIZEOF(.bss));
         
        LONG(ADDR(.bss_CCMRAM));
        LONG(ADDR(.bss_CCMRAM)+SIZEOF(.bss_CCMRAM));
         
        __bss_regions_array_end = .;
 
        /* End of memory regions initialisation arrays. */
     
        /*
         * These are the old initialisation sections, intended to contain
         * naked code, with the prologue/epilogue added by crti.o/crtn.o
         * when linking with startup files. The standalone startup code
         * currently does not run these, better use the init arrays below.
         */
        KEEP(*(.init))
        KEEP(*(.fini))
 
        . = ALIGN(4);
 
        /*
         * The preinit code, i.e. an array of pointers to initialisation
         * functions to be performed before constructors.
         */
        PROVIDE_HIDDEN (__preinit_array_start = .);
         
        /*
         * Used to run the SystemInit() before anything else.
         */
        KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))
         
        /*
         * Used for other platform inits.
         */
        KEEP(*(.preinit_array_platform .preinit_array_platform.*))
         
        /*
         * The application inits. If you need to enforce some order in
         * execution, create new sections, as before.
         */
        KEEP(*(.preinit_array .preinit_array.*))
 
        PROVIDE_HIDDEN (__preinit_array_end = .);
 
        . = ALIGN(4);
 
        /*
         * The init code, i.e. an array of pointers to static constructors.
         */
        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP(*(SORT(.init_array.*)))
        KEEP(*(.init_array))
        PROVIDE_HIDDEN (__init_array_end = .);
 
        . = ALIGN(4);
 
        /*
         * The fini code, i.e. an array of pointers to static destructors.
         */
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP(*(SORT(.fini_array.*)))
        KEEP(*(.fini_array))
        PROVIDE_HIDDEN (__fini_array_end = .);
 
    } >FLASH
 
    /*
     * For some STRx devices, the beginning of the startup code
     * is stored in the .flashtext section, which goes to FLASH.
     */
    .flashtext : ALIGN(4)
    {
        *(.flashtext .flashtext.*)  /* Startup code */
    } >FLASH
 
 
MEMORY
{
  RAM (xrw)               : ORIGIN = 0x20000000, LENGTH = 127K
  CCMRAM (xrw)            : ORIGIN = 0x10000000, LENGTH = 64K
  STARTUP_VECTOR (rx)     : ORIGIN = 0x08000000, LENGTH = 1K
  BOOTLOADER_FW (rx)      : ORIGIN = 0x08000400, LENGTH = 31K
  EMPTY_SPACE (rx)        : ORIGIN = 0x08008000, LENGTH = 32K
  ISR_VECTORS (rx)        : ORIGIN = 0x08010000, LENGTH = 1K
  FLASH (rx)              : ORIGIN = 0x08010400, LENGTH = 982016
  FLASHB1 (rx)            : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB0 (rx)           : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx)           : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx)           : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx)           : ORIGIN = 0x00000000, LENGTH = 0
  MEMORY_ARRAY (xrw)      : ORIGIN = 0x20002000, LENGTH = 32
}

If I run the application by itself and press the button several times I get the following:

Hello in application. SCB->VTOR is 0x8010000
HAL_GPIO_EXTI_Callback, pin 0x1
Hello in application. SCB->VTOR is 0x8010000
HAL_GPIO_EXTI_Callback, pin 0x1
Hello in application. SCB->VTOR is 0x8010000
HAL_GPIO_EXTI_Callback, pin 0x1
Hello in application. SCB->VTOR is 0x8010000
HAL_GPIO_EXTI_Callback, pin 0x1
Hello in application. SCB->VTOR is 0x8010000
HAL_GPIO_EXTI_Callback, pin 0x1
Hello in application. SCB->VTOR is 0x8010000

If I run the bootloader together with the application and press the button several times I get the following:

Hello in bootloader. SCB->VTOR is 0x8000400
HAL_GPIO_EXTI_Callback, pin 0x1
Hello in application. SCB->VTOR is 0x8010000
<No more printouts; the development board seems dead>

Does anybody know why my button interrupt isn't working in the application in this case?

Outcomes