2
\$\begingroup\$

I am trying to understand arm architecture and i got stuck with one concept, i.e, INTERRUPT SERVICE ROUTINE. I had gone NVIC structure for HARDWARE & SOFTWARE interrupts. But at some point i got confused how that particular function is called when an interrupt occurs. All those functions are already defined like for TIMER-6, TIM6_IRQHandler(). How can i update this particular function with user defined function (means any function).

Any reference document or link will be appreciated. Working IDE is EWARM. Testing Controller STM32L152RE.

asked Mar 2, 2019 at 9:28
\$\endgroup\$
2
  • \$\begingroup\$ This question is much too broad for this site. It sounds like you are not clear on the general concept of interrupts, much less how they are implemented on a Cortex-M. I recommend the books by Yiu about the Cortex-M processors. \$\endgroup\$ Commented Mar 2, 2019 at 13:52
  • \$\begingroup\$ I understand that i was not much clear with my query to all. But i researched more and found what i am looking. Now i am working on its implementation. Thanks for recommendation. \$\endgroup\$ Commented Mar 3, 2019 at 13:03

1 Answer 1

3
\$\begingroup\$

The default interrupt handlers are usually defined as weak symbols somewhere in the startup code.

This means that you can write your own function with exactly the same name and during link time it will "win" over a weak function (otherwise you would get a link error claiming duplicate symbol names).

Example for an STM32L432. This is a piece of the startup code you get from CubeMX (ST's project generation tool). Cut for clarity.

/**
 * @brief This is the code that gets called when the processor receives an
 * unexpected interrupt. This simply enters an infinite loop, preserving
 * the system state for examination by a debugger.
 *
 * @param None
 * @retval : None
*/
 .section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
 b Infinite_Loop
 .size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex-M4. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
 .section .isr_vector,"a",%progbits
 .type g_pfnVectors, %object
 .size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
 .word _estack
 .word Reset_Handler
 .word NMI_Handler
 .word HardFault_Handler
 .word MemManage_Handler
 .word BusFault_Handler
 .word UsageFault_Handler
 .word 0
 .word 0
 .word 0
 .word 0
 .word SVC_Handler
 .word DebugMon_Handler
 .word 0
 .word PendSV_Handler
 .word SysTick_Handler
 .word WWDG_IRQHandler
 .word PVD_PVM_IRQHandler
 .word TAMP_STAMP_IRQHandler
 .word RTC_WKUP_IRQHandler
 .word FLASH_IRQHandler
 .word RCC_IRQHandler
 .word EXTI0_IRQHandler
 .word EXTI1_IRQHandler
 .word EXTI2_IRQHandler
 .word EXTI3_IRQHandler
 .word EXTI4_IRQHandler
 .word DMA1_Channel1_IRQHandler
 .word DMA1_Channel2_IRQHandler
 .word DMA1_Channel3_IRQHandler
 .word DMA1_Channel4_IRQHandler
 .word DMA1_Channel5_IRQHandler
 .word DMA1_Channel6_IRQHandler
 .word DMA1_Channel7_IRQHandler
 .word ADC1_IRQHandler
 .word CAN1_TX_IRQHandler
 .word CAN1_RX0_IRQHandler
 .word CAN1_RX1_IRQHandler
 .word CAN1_SCE_IRQHandler
 .word EXTI9_5_IRQHandler
 .word TIM1_BRK_TIM15_IRQHandler
 .word TIM1_UP_TIM16_IRQHandler
 .word TIM1_TRG_COM_IRQHandler
 .word TIM1_CC_IRQHandler
 .word TIM2_IRQHandler
 <------------- cut --------------> 
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
 .weak NMI_Handler
 .thumb_set NMI_Handler,Default_Handler
 .weak HardFault_Handler
 .thumb_set HardFault_Handler,Default_Handler
 .weak MemManage_Handler
 .thumb_set MemManage_Handler,Default_Handler
 .weak BusFault_Handler
 .thumb_set BusFault_Handler,Default_Handler
 .weak UsageFault_Handler
 .thumb_set UsageFault_Handler,Default_Handler
 .weak SVC_Handler
 .thumb_set SVC_Handler,Default_Handler
 .weak DebugMon_Handler
 .thumb_set DebugMon_Handler,Default_Handler
 .weak PendSV_Handler
 .thumb_set PendSV_Handler,Default_Handler
 .weak SysTick_Handler
 .thumb_set SysTick_Handler,Default_Handler
 .weak WWDG_IRQHandler
 .thumb_set WWDG_IRQHandler,Default_Handler
 .weak PVD_PVM_IRQHandler
 .thumb_set PVD_PVM_IRQHandler,Default_Handler
 .weak TAMP_STAMP_IRQHandler
 .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
 .weak RTC_WKUP_IRQHandler
 .thumb_set RTC_WKUP_IRQHandler,Default_Handler
 .weak FLASH_IRQHandler
 .thumb_set FLASH_IRQHandler,Default_Handler
 .weak RCC_IRQHandler
 .thumb_set RCC_IRQHandler,Default_Handler
 .weak EXTI0_IRQHandler
 .thumb_set EXTI0_IRQHandler,Default_Handler
 .weak EXTI1_IRQHandler
 .thumb_set EXTI1_IRQHandler,Default_Handler
 .weak EXTI2_IRQHandler
 .thumb_set EXTI2_IRQHandler,Default_Handler
 .weak EXTI3_IRQHandler
 .thumb_set EXTI3_IRQHandler,Default_Handler
 .weak EXTI4_IRQHandler
 .thumb_set EXTI4_IRQHandler,Default_Handler
 .weak DMA1_Channel1_IRQHandler
 .thumb_set DMA1_Channel1_IRQHandler,Default_Handler
 .weak DMA1_Channel2_IRQHandler
 .thumb_set DMA1_Channel2_IRQHandler,Default_Handler
 .weak DMA1_Channel3_IRQHandler
 .thumb_set DMA1_Channel3_IRQHandler,Default_Handler
 .weak DMA1_Channel4_IRQHandler
 .thumb_set DMA1_Channel4_IRQHandler,Default_Handler
 .weak DMA1_Channel5_IRQHandler
 .thumb_set DMA1_Channel5_IRQHandler,Default_Handler
 .weak DMA1_Channel6_IRQHandler
 .thumb_set DMA1_Channel6_IRQHandler,Default_Handler
 .weak DMA1_Channel7_IRQHandler
 .thumb_set DMA1_Channel7_IRQHandler,Default_Handler
 .weak ADC1_IRQHandler
 .thumb_set ADC1_IRQHandler,Default_Handler
 .weak CAN1_TX_IRQHandler
 .thumb_set CAN1_TX_IRQHandler,Default_Handler
 .weak CAN1_RX0_IRQHandler
 .thumb_set CAN1_RX0_IRQHandler,Default_Handler
 .weak CAN1_RX1_IRQHandler
 .thumb_set CAN1_RX1_IRQHandler,Default_Handler
 .weak CAN1_SCE_IRQHandler
 .thumb_set CAN1_SCE_IRQHandler,Default_Handler
 <----------- cut ---------------->
 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

You don't need any assembly knowledge to understand it. The first thing is the Default_Handler routine. It is just an empty infinite loop. b Infinite_Loop means jump (branch) to the place where the label Infinite_Loop is placed, just an infinite loop.

Later on you have a definition of all handler symbols (+initial stack pointer), for example ADC1_IRQHandler (the interrupt that gets fired when ADC has done something).

Next a weak linkage is provided that points every of the handlers to the Default_Handler. If you enable ADC interrupts and not provide your own handler the default handler will be executed (which means that your CPU will lock up in an infinite loop, I prefer to put a breakpoint instruction in the default handler because it is much more visible in a debugger, than just seeing the board frozen).

To override the weak linkage you have to implement a function with the same name anywhere in your project. For example you can implement this function in main.c:

void ADC1_IRQHandler(void){
//save the measurement, do something...
}

The linker will simply pick your function instead of the weak one.

Due to the nice design of Cortex-M you don't have to use special attributes for the handler function (like for example the ISR() macro for AVR cores), so the interrupt handler (from CPU point of view) is a function just like as every other.

answered Mar 2, 2019 at 9:46
\$\endgroup\$
7
  • \$\begingroup\$ Thanks for reply. Can't i change the default interrupt handlers with my own functions. \$\endgroup\$ Commented Mar 2, 2019 at 9:49
  • 2
    \$\begingroup\$ Yes you can. Just write your own handlers and it will be used during link time. \$\endgroup\$ Commented Mar 2, 2019 at 10:14
  • \$\begingroup\$ how can i do that? I am confused at that point that how i can i link my function with that particular interrupt vector. \$\endgroup\$ Commented Mar 2, 2019 at 10:22
  • 2
    \$\begingroup\$ Open the startup code and see the vector names, then just implement a function with that name anywhere in your code. \$\endgroup\$ Commented Mar 2, 2019 at 10:25
  • 1
    \$\begingroup\$ You need to use the expected name for the interrupt handler you want to replace, or find the table of vectors in the boilerplate code and change the name mentioned there. \$\endgroup\$ Commented Mar 2, 2019 at 16:39

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.