Author Topic: issue prioritizing interrupts  (Read 4946 times)

Offline sullivanag

  • Newbie
  • *
  • Posts: 7
    • View Profile
issue prioritizing interrupts
« on: May 14, 2019, 04:33:12 PM »
Hello,

I am having an issue with prioritization of two interrupts.  The higher priority interrupt is being delayed by the lower priority interrupt.  I have included the code below.  Hopefully someone can point out my mistake.  One interrupt is on a PIT timer that we call the Real Time (RT) interrupt.  It simply increments a counter and toggles an LED on/off periodically.  The other interrupt (Serial Data - SD) is triggered on the falling edge of a GPIO pin.  It is critical that when the SD interrupt triggers, that we interrupt to grab data from other pins.  This is not happening.  If the RT Interrupt is processing, and the SD interrupt triggers, it is delayed until the RT interrupt completes.

I'll post code below.  That interrupt routines are just contain demonstration code.  They do simple LED toggles and we added delays so our oscilloscope could catch them.

I'll try to emphasize this issue below using 0's and 1's.  The SD interrupt should trigger uniformly.  The RT interrupt should not delay the SD interrupt.

RT  00000000111100000000111100000000111100000000

SD  01010101000101010010000010101010000010101010


If anyone can shed some light on this, it would be very helpful.  Oh, We are using the Kinetis K64F BTW.


**********************************************************

RT interrupt code:

PIT_SETUP pit3_setup;

pit3_setup.int_type = PIT_INTERRUPT;
pit3_setup.int_handler = RealTimeInterrupt;
pit3_setup.int_priority = 11;
pit3_setup.ucPIT = 3;                           // use PIT channel 3
pit3_setup.mode = PIT_PERIODIC;                     // periodic PIT interrupt
pit3_setup.count_delay = PIT_MS_DELAY(10);            // 10 ms delay

fnConfigureInterrupt((void *)&pit3_setup);            // enter interrupt for PIT3


void RealTimeInterrupt( void )
{
   char a[10000];
   short i;

   GreenLED( ON );

//   This is a small delay (approx 2.5 msec) for the oscilloscope to work properly!
   for( i = 0; i < 10000; i++ ) {
      a = 0;
   }

   GreenLED( OFF );

}

****************************************************************

SD interrupt code:

INTERRUPT_SETUP SD_Interrupt_setup;

SD_Interrupt_setup.int_priority   = 10;
SD_Interrupt_setup.int_port       = PORTC;
SD_Interrupt_setup.int_port_bits  = PORTC_BIT2;
SD_Interrupt_setup.int_port_sense = IRQ_FALLING_EDGE;
SD_Interrupt_setup.int_handler    = BOARD_INTREQ_IRQ_HANDLER;

fnConfigureInterrupt( (void *)&SD_Interrupt_setup );

void BOARD_INTREQ_IRQ_HANDLER( void )

void SerialDataInterrupt( void )
{
   BlueLED(ON);

   char a[10000];
   short i;

   for( i = 0; i < 1000; i++ ) {
      a = 0;
   }

   BlueLED(OFF);
}

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: issue prioritizing interrupts
« Reply #1 on: May 14, 2019, 05:11:34 PM »
Hi

The default configuration doesn't allow nested interrupts. This is because nested interrupts need to be used carefully since if they use shared resources they could cause some form of corruption if the shared resources are not carefully protected against race states (eg. one interrupt interrupting another at a critical moment and causing data corruption).

See the user interrupt call back in the PIT handler, for example:

                uDisable_Interrupt();
                    pit_interrupt_handler[iChannel]();                   // call handling function
                uEnable_Interrupt();


As you see, interrupts are disabled globally when the user handler is called, which means that the routines can use OS calls or write output to the debug interface without needing to carefully consider potential dangers of being interrupted by other routines that could cause corruption when the tried to do this same.

In the case of a situation where this (on-the-safe-side) strategy can result in unacceptable delays there are two possibilities (although one needs to still consider what can and can't be done in the higher priority routines to ensure that it is not potentially causing corruption):

1. In the user call back re-enable global interrupts, do the work, disable global interrupts (retaining compatibility with callback interface but allowing higher priority interrupts to interrupt the region):

                uEnable_Interrupt();
                do_our_work();
                uDisable_Interrupt();


2. Use the option

#define SYSTEM_NO_DISABLE_LEVEL       (3 << __NVIC_PRIORITY_SHIFT)   // allow interrupts of higher priority than this to not be blocked in critical regions

- this can only be used on Cortex-m4 (not coretx-m0+) and is only available in the professional version

This doesn't disable interrupts globally (whenever a protect region is entered) but instead sets the interrupt priority mask to this level. With this setting all interrupts with a higher priority than 3 would never be blocked and all with this level or lower will behave as in the default configuration.

Regards

Mark





Offline sullivanag

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: issue prioritizing interrupts
« Reply #2 on: May 14, 2019, 06:50:55 PM »
Mark,

Thank you for the quick reply.  That was the issue.  My interrupts are triggering perfectly now.  I have limited embedded programming experience, but I am learning. 

-Andy

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: issue prioritizing interrupts
« Reply #3 on: May 14, 2019, 10:43:20 PM »
Hi Andy

I am pleased to hear that you could improve the situation to suit your requirement.
Which of the two solutions did you use?

Regards

Mark

Offline sullivanag

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: issue prioritizing interrupts
« Reply #4 on: May 15, 2019, 02:38:46 AM »
Mark,

I used option 1, which was to call uEnable_Interrupt() at the start of our PIT interrupt.  Analyzing both interrupt timings on a scope shows them behaving exactly how they should.  I am currently playing around with the opensource version of uTasker.  You created a demo for me maybe 6-8 weeks ago.  I had posted on the NXP forums about about needing to send TCP data (57 byte structures) at a 20 millisecond rate.  That is how I found out about uTasker.

The TCP code took me a little while to understand, as I am used to Berkely sockets.  My LAN interface is working great now.  I am very impressed with all of the features of uTasker.  uTasker has saved me a lot of time.  What a great project!

-Andy

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: issue prioritizing interrupts
« Reply #5 on: May 15, 2019, 11:34:24 AM »
Andy

Yes, now I remember - this is your post: https://community.nxp.com/thread/496428

Don't forget to update the post once you are finished since it is always good to see that someone has been able to benefit from the features and especially when it has allowed faster project realisation.

At the moment I am working on an i.MX RT port of the project which allows Kinetis projects to be moved to these faster (and cheaper) devices [600MHz for < $5 with Ethernet] without any effort. Rather than needing to learn details about the other processor family (which however shares some peripherals with the Kinetis) and rewrite application and use different libraries one can select an iMX target instead of the present Kinetis target and build for that it - application code remains the same as long as it uses the uTasker peripheral interfaces. I have made one video explaining the (strange) GPIO setup in the i.MX and how compatibility is maintained for user: https://www.youtube.com/watch?v=SmFTi8hlba0

Regards

Mark

Offline sullivanag

  • Newbie
  • *
  • Posts: 7
    • View Profile
Re: issue prioritizing interrupts
« Reply #6 on: May 23, 2019, 01:29:25 AM »
Mark,

I have updated my original post on the NXP community forums.  Thank you again. 

Andy