embedded - Safely detect, if function is called from an ISR?

ID : 274494

viewed : 45

Tags : embeddedcortex-m3embedded





Top 5 Answer for embedded - Safely detect, if function is called from an ISR?

vote vote

96

You need to test the VECTACTIVE field of the Interrupt Control State Register.

I use the following:

//! Test if in interrupt mode inline bool isInterrupt() {     return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0 ; } 

SCM and SCB_ICSR_VECTACTIVE_Msk are defined in the CMSIS (core_cm3.h), which I imagine would be included indirectly by your part specific header (lpc17xx.h or similar I guess). I am using C++, including stdbool.h in C will get you a bool type, or change to an int or typedef of your own.

It is then used thus for example:

void somefunction( char ch ) {     if( isInterrupt() )     {         // Do not block if ISR         send( ch, NO_WAIT ) ;     }     else     {         send( ch, TIMEOUT ) ;     } } 

If a solution is required that assumes no knowledge of the architecture consider the following:

volatile int interrupt_nest_count = 0 ; #define ENTER_ISR() interrupt_nest_count++ #define EXIT_ISR()  interrupt_nest_count-- #define IN_ISR() (interrupt_nest_count != 0)  void isrA() {      ENTER_ISR() ;      somefunction( 'a' ) ;      EXIT_ISR() ; }  void isrB() {      ENTER_ISR() ;      somefunction( 'b' ) ;      EXIT_ISR() ; }  void somefunction( char ch ) {     if( IN_ISR() )     {         // Do not block if ISR         send( ch, NO_WAIT ) ;     }     else     {         send( ch, TIMEOUT ) ;     } } 

However the question refers to safely detecting the interrupt context, and this relies on the enter/exit macros being added to all ISRs.

vote vote

85

After some discussion and more searching I found the right register: Interrupt Program Status Register: The IPSR contains the exception type number of the current Interrupt Service Routine (ISR). See the register summary in Table 626 for its attributes.

If a function isn't called from an isr the value of the register is IPSR == 0

vote vote

72

The simplest method is to pass the context as a parameter to the function. It is also platform independent.

typedef enum _context {     normal_context = 0,     isr_context = 1 } context; 

Call to the function from ISR:

func(param1, param2, isr_context); 

Call to the function from normal code:

func(param1, param2, normal_context); 

If the ISR code is not under your control and you are just passing a function pointer, then just use two different wrapper functions. One that passes isr_context and another that passes normal_context as a parameter to the function.

vote vote

65

The best way is probably to make two different functions: one that is called from the ISR and another that is called from the rest of the program.

If that isn't an option, then you could determine the caller with pure standard C, no registers needed:

inline void my_func (const char* caller);  static void isr (void) {   my_func(__func__); }   inline void my_func (const char* caller) {   if(strcmp(caller, "isr")==0)   {     // was called from isr   }   else   {     // called from elsewhere   } } 

If you give your ISRs smart names, the above code will be quick enough to run from an isr.

vote vote

55

Top 3 video Explaining embedded - Safely detect, if function is called from an ISR?







Related QUESTION?