This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Enable Reentrant interrupt handlers in kinetis K70

I have a TWR-K70F120M: kinetis k70 120MHz Tower System Module.

I have connected a elettric signal to PORTB and i have connected e isr handler to signal transition.

Electric signal

     _____          ______          ______

    |         |         |          |         |          |

__|          |_____|          |_____|          |_____  ------> PORTB  

  ( 1 )             ( 2 )                ( 3 )

     

Interrupt handler is called every transition of the elettric signal ( in the figure is 1,2,3 ).

The interrupt handler is the follow code:

#define EN_ERR_SCHEDULER_INT_TOO_LONG (10)

static bool wbFlag = false; /* control the reentrant function */

__ isr void isr_handler( void )

{

  /* l'interrupt precedente è durato troppo ? */

  if ( wbFlag != true )

  {

    /* flag reentrant function  */

    wbFlag = TRUE;  

  }

  else

  {  

    vDebugPrint( EN_ERR_SCHEDULER_INT_TOO_LONG );

  }

   while(1);

   wbFlag = false;

}

at the step ( 1 ) the program jump to the handler but not in the 2nd e third impulse. Is it possible to enable a reentrand interrupt in kinetis k70?

 

the setup is follow ( setup is call one time at the startup of the system ):

sllRq = 88; /*Port control module Pin Detect (Port B) */

void vEnableIrq (SLONG slIRQ)

{

  SLONG slDiv;

 

  /* Make sure that the IRQ is an allowable number. Right now up to 91 is

  * used.

  */

  if ( slIRQ > 91 )

  {

    vDebugPrint("\nERR! Invalid IRQ value passed to enable irq function!\n");

  }

 

  /* Determine which of the NVICISERs corresponds to the irq */

  slDiv = ( slIRQ / 32 );

 

  switch ( slDiv )

  {

    case 0x0:

      NVICICPR0 = 1 << ( slIRQ % 32 );

      NVICISER0 = 1 << ( slIRQ % 32 );

    break;

    case 0x1:

      NVICICPR1 = 1 << ( slIRQ % 32 );

      NVICISER1 = 1 << ( slIRQ % 32 );

    break;

    case 0x2: /* program execute this case !!!!! */

      NVICISER2 = 1 << ( slIRQ % 32 );

      NVICICPR2 = 1 << ( slIRQ % 32 );

      PORTB_PCR18 |= PORT_PCR_ISF(0) | PORT_PCR_IRQC(9) |  PORT_PCR_MUX(1);

      NVICIP88 = 0x00;

    break;

  }             

}

I need to control the reentrant interrupt because this application must check the excessive duration of the code in isr handler.

Parents
  • Hi,

    The NVIC in Cortex-M processors are not designed for handling reentrant interrupt requests. The NVIC design automatically block all interrupts of the same or lower priority when it is taken, so in normal use cases you wont be able to have reentrant interrupt handling.

    There is a software trick that enable some interrupts handlers to support reentrant, but this trick wont work if the new interrupt request arrived very shortly after the first one (it need some execution time in the ISR to switch the processor back into thread). This software trick is documented in "the Definitive Guide to the ARM Cortex-M3 and Cortex-M4 Processors, 3rd edition" (The example codes can be downloaded from http://booksite.elsevier.com/9780124080829/, but you might need to update the example in \ch_23_eg_3_reentrant_handler , see Errors in the Definitive Guide for ARM Cortex-M book series ).

    I guess the reason why you want reentrant ISR is to make sure each pulse in port B will trigger an ISR execution.

    In general, there is no way to guarantee the three ISRs are executed if these three pulses are very close to each other. E.g. If the first pulse occurred when the processor is executing an ISR, hence delaying the execution of the port B ISRs, the pending requests could merged together and hence you might just get one ISR execution.  To improve the solution slightly better, you can reduce the length of the port B ISR to minimum length, make it the highest priority in the system and do the actual processing in another ISR like PendSV. e.g.

    volatile int req_counter = 0; // request counter (global variable)

    volatile int ack_counter = 0; // acknowledge counter (global variable)

    void Port_B_Handler(void) // High priority

    {

      req_counter++;

      SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; // Set PendSV pending status

      return;

    }

    void PendSV_Handler(void) // Low priority

    {

      while (req_counter != ack_counter) {

        // do ISR processing ...

        ack_counter ++;

        }

    }

    But even this will not guarantee you will get one ISR per pulse if the pulses get too close to each other of if another ISR caused delay to the Port B ISR processing.

    regards,

    Joseph

Reply
  • Hi,

    The NVIC in Cortex-M processors are not designed for handling reentrant interrupt requests. The NVIC design automatically block all interrupts of the same or lower priority when it is taken, so in normal use cases you wont be able to have reentrant interrupt handling.

    There is a software trick that enable some interrupts handlers to support reentrant, but this trick wont work if the new interrupt request arrived very shortly after the first one (it need some execution time in the ISR to switch the processor back into thread). This software trick is documented in "the Definitive Guide to the ARM Cortex-M3 and Cortex-M4 Processors, 3rd edition" (The example codes can be downloaded from http://booksite.elsevier.com/9780124080829/, but you might need to update the example in \ch_23_eg_3_reentrant_handler , see Errors in the Definitive Guide for ARM Cortex-M book series ).

    I guess the reason why you want reentrant ISR is to make sure each pulse in port B will trigger an ISR execution.

    In general, there is no way to guarantee the three ISRs are executed if these three pulses are very close to each other. E.g. If the first pulse occurred when the processor is executing an ISR, hence delaying the execution of the port B ISRs, the pending requests could merged together and hence you might just get one ISR execution.  To improve the solution slightly better, you can reduce the length of the port B ISR to minimum length, make it the highest priority in the system and do the actual processing in another ISR like PendSV. e.g.

    volatile int req_counter = 0; // request counter (global variable)

    volatile int ack_counter = 0; // acknowledge counter (global variable)

    void Port_B_Handler(void) // High priority

    {

      req_counter++;

      SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; // Set PendSV pending status

      return;

    }

    void PendSV_Handler(void) // Low priority

    {

      while (req_counter != ack_counter) {

        // do ISR processing ...

        ack_counter ++;

        }

    }

    But even this will not guarantee you will get one ISR per pulse if the pulses get too close to each other of if another ISR caused delay to the Port B ISR processing.

    regards,

    Joseph

Children