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
  • That re-entrant interrupt handler in your book works fabulously for me. Really brilliant code.

    I was trying to write similar handler (I have it documented here https://sites.google.com/site/sippeyfunlabs/how-to-run-re-entrant-task-scheduler-on-arm-cortex-m4 ). It does work for simple test case but start to fail in real program. It causes stack related hard fault occasionally. However, I can confirm my code handles stack correctly with debugging info. The rest of program can not be wrong either, they are mostly pure float point math calculation in C. I turned off the lazy stacking and it still behaves the same.

    Even if your code already solve my problem, I am still willing to figure out why. Comparing your code with mine, I found that you are using SVC to recover to the normal program. Since all my code runs in privileged mode always, is it also ok to manually recover stack and avoid using SVC? Existence of fp stack frame can be figured from LR and the existence of aligner is bit 9(reserved) of psr. Is that correct? Moreover, if psr is finally recovered from stack, why it is necessary to save it at the beginning? Is that to keep 8 bytes alignment when pushing lr?

    Sorry to bring up so many stuff that seems not really related to OP's question. I did not find PM feature in this place.

Reply
  • That re-entrant interrupt handler in your book works fabulously for me. Really brilliant code.

    I was trying to write similar handler (I have it documented here https://sites.google.com/site/sippeyfunlabs/how-to-run-re-entrant-task-scheduler-on-arm-cortex-m4 ). It does work for simple test case but start to fail in real program. It causes stack related hard fault occasionally. However, I can confirm my code handles stack correctly with debugging info. The rest of program can not be wrong either, they are mostly pure float point math calculation in C. I turned off the lazy stacking and it still behaves the same.

    Even if your code already solve my problem, I am still willing to figure out why. Comparing your code with mine, I found that you are using SVC to recover to the normal program. Since all my code runs in privileged mode always, is it also ok to manually recover stack and avoid using SVC? Existence of fp stack frame can be figured from LR and the existence of aligner is bit 9(reserved) of psr. Is that correct? Moreover, if psr is finally recovered from stack, why it is necessary to save it at the beginning? Is that to keep 8 bytes alignment when pushing lr?

    Sorry to bring up so many stuff that seems not really related to OP's question. I did not find PM feature in this place.

Children
  • Hi,

    The biggest problem about returning to normal program is the need to restore the IT/ICI bits in EPSR.

    The only way to do it is to use an exception return, that's why I used an SVC to handle this.

    (You cannot write to EPSR using MSR, see

    Cortex-M4 Devices Generic User Guide: 2.1.3. Core registers)

    Otherwise, you lose the IT/ICI status if the interrupt was taking place during a LDM/STM/PUSH/POP instruction or an IT sequence,

    regards,

    Joseph

  • Thank you for your timely reply. You are exactly right. That solves my confusion about why my code works abnormally only for certain programs but not others. If at the time of interrupt, the core is executing a PUSH, POP, it will do that twice and mess up the stack? Debugging my code seems confirmed the stack has duplicated data when hard fault happens. Those may be data that got pushed twice. Since there are no way to write to EPSR as you said, SVC seems the only option.

    Thank you for the clarification and the code that save my day.

    Peng

  • Hi Peng,

    The losing of ICI bit is less likely to be a issue. The PUSH/POP will just restart from the first transfer, from the same address. The bigger problem is the losing of the IT status. Losting the condition execution information mean the wrong instructions could get executed, or instruction that should have been skipped is executed.

    Also, as you are using my Cortex-M3/M4 book, I think it worth mentioning that the errors in my books are documented in

    Errors in the Definitive Guide for ARM Cortex-M book series

    regards,

    Joseph