Interrupt priority for attachInterrupt?

Bill Greiman

Well-known member
I am trying to get FreeRTOS 8.0.1 running on Teensy 3.x and Due.

It appears that attachInterrupt is set to priority 128 for Teensy3. Is this true?

Are any other hardware interrupts set to a numerical value less than 128 (higher priority since zero is the "highest" priority in Cortex M).

On Due the attachInterrupt priority appears to be zero. If true, this seems like an unfortunate choice since zero is the "highest" priority.

All PIO priorities are set like this in WInterrupts.c for Due.
Code:
	NVIC_SetPriority(PIOA_IRQn, 0);

FreeRTOS 8.0.1 forbids all calls from an ISR at numerical priority zero so I need to decide how to handle Due.
 
It appears that attachInterrupt is set to priority 128 for Teensy3. Is this true?

Yes, on Teensy all the interrupts default to priority 128.

On my TO-DO list is an option for attachInterrupt to specify the priority.

Are any other hardware interrupts set to a numerical value less than 128 (higher priority since zero is the "highest" priority in Cortex M).

Yes. USB defaults to 112, the hardware serial ports default to 64, and systick defaults to 0.

Some of the libraries raise or lower their interrupt priority.

On Due the attachInterrupt priority appears to be zero. If true, this seems like an unfortunate choice since zero is the "highest" priority.

Yes, there are many unfortunate choices in Arduino Due's core library. That stuff is all controlled by the Arduino Team.
 
it would be great if we could set the attachInterrupt priority.

As mentioned here my DMX signal on the RX pin is sometimes preventing an attachInterrupt read on Pin2.

A solution would be much appreciated.
 
it would be great if we could set the attachInterrupt priority.

As mentioned here my DMX signal on the RX pin is sometimes preventing an attachInterrupt read on Pin2.

A solution would be much appreciated.

For ARM-Teensy, there is a macro in kinetis.h : NVIC_SET_PRIORITY(irqnum, priority)
For other Arduino-boards, this forum is the wrong place...

Edit: Changing the priorities of existing interrupts (like usb for example) may result in unexpected side-effects. 128(="Medium setting" on T3.x) is a very good choice for the most cases.
 
Last edited:
thanks for the reply.
I saw the NVIC_SET_PRIORITY but i did not know how to set it from within my sketch and how to set it for the right pin. in my case pin 2.

right now i am doing this:
Code:
  pinMode(zeroCrossPin, INPUT);
  attachInterrupt(zeroCrossPin, zero_crosss_interrupt, RISING);

BTW this is for a teensy 3.1.

thanks.
 
Ok, you have to find out on which port is your pin (this is NOT compatible to other Arduinos), it's visible on the schematics (if i remember correctly), or simply set the priority for all ports.
Kinetis.h:
Code:
	IRQ_PORTA =		87,
	IRQ_PORTB =		88,
	IRQ_PORTC =		89,
	IRQ_PORTD =		90,
	IRQ_PORTE =		91,
You have to add 16 to these numbers: NVIC_SET_PRIORITY(IRQ_PORTE+16, priority)
Code:
// 0 = highest priority
// Cortex-M4: 0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240
// Cortex-M0: 0,64,128,192

Edit: The lower the value you choose, the faster should be your interrupt-code... :)
 
Last edited:
NVIC_SET_PRIORITY(IRQ_PORTD +16, 60)

One note: 60 is the same as 48,49..63 so for better readability i would choose 48 (= 3 << 4)

Ooops... sorry, i'm not sure with this +16.. perhaps i should read the manual again.
Try without "+16" :)
+16 was for the vectortable.. haha, i'm getting old... really, i'm not sure at the moment.
Perhaps others know it better ... :)
 
Last edited:
Hi,

I would like be able to set interrupt priority as well, and I was wondering if there as a table somewhere that would give me the port corresponding to a pin, or if I have to build it myself from the schematics ?
 
There are tons of tables built into the headers and code for the Teensy processor in use.

Cool thing is they work out in the compiler.

just do :: attachinterrupt( Pin#, ...
 
Thanks, I have noticed all these tables, but I could not find the one I'm talking about.
I'm not trying to attach an interrupt, I already figured that out.
I'm talking about setting the priority of any pin without having to figure out manually the port to which the pin is assigned.
 
Here a quick sketch showing how to extract this information. One probably can find a more intelligent way but this is doing what you need.

Code:
#include "Arduino.h"

const char *portName(volatile void *address)
{
  static char result[50];
  char P;
  int irq;

  switch ((unsigned)address)
  {
  case (unsigned)&GPIOA_PDOR:
    P = 'A';
    irq = IRQ_PORTA;
    break;
  case (unsigned)&GPIOB_PDOR:
    P = 'B';
    irq = IRQ_PORTB;
    break;
  case (unsigned)&GPIOC_PDOR:
    P = 'C';
    irq = IRQ_PORTC;
    break;
  case (unsigned)&GPIOD_PDOR:
    P = 'D';
    irq = IRQ_PORTD;
    break;
  default:
    irq = 0;
    P = 'X';
  }

  sprintf(result, "Port-%c (%p) IRQ Nr: %d", P, address, irq);
  return result;
}

void setup()
{
  while (!Serial);
    
  Serial.printf("Pin: 0, %s\n", portName(&CORE_PIN0_PORTREG));
  Serial.printf("Pin: 1, %s\n", portName(&CORE_PIN1_PORTREG));
  Serial.printf("Pin: 2, %s\n", portName(&CORE_PIN2_PORTREG));
  Serial.printf("Pin: 3, %s\n", portName(&CORE_PIN3_PORTREG));
  Serial.printf("Pin: 4, %s\n", portName(&CORE_PIN4_PORTREG));
  Serial.printf("Pin: 5, %s\n", portName(&CORE_PIN5_PORTREG));
  Serial.printf("Pin: 6, %s\n", portName(&CORE_PIN6_PORTREG));
  Serial.printf("Pin: 7, %s\n", portName(&CORE_PIN7_PORTREG));
  Serial.println("and so on...");   
}

void loop()
{
}

Output:
Code:
Pin: 0, Port-B (0x400ff040) IRQ Nr: 88
Pin: 1, Port-B (0x400ff040) IRQ Nr: 88
Pin: 2, Port-D (0x400ff0c0) IRQ Nr: 90
Pin: 3, Port-A (0x400ff000) IRQ Nr: 87
Pin: 4, Port-A (0x400ff000) IRQ Nr: 87
Pin: 5, Port-D (0x400ff0c0) IRQ Nr: 90
Pin: 6, Port-D (0x400ff0c0) IRQ Nr: 90
Pin: 7, Port-D (0x400ff0c0) IRQ Nr: 90
and so on...
 
Yes, on Teensy all the interrupts default to priority 128.

On my TO-DO list is an option for attachInterrupt to specify the priority.



Yes. USB defaults to 112, the hardware serial ports default to 64, and systick defaults to 0.

Some of the libraries raise or lower their interrupt priority.



Yes, there are many unfortunate choices in Arduino Due's core library. That stuff is all controlled by the Arduino Team.

Ahha! This must be why my interrupt-based bitbanging went all catty-wampus after I tried to use the host USB port.

Was the ability to specify priority ever added to the teensyduino code? If not, is there any sort of reference that goes over which Teensy versions have mutable interrupt priority, and how to go about changing it? My project started out on a 3.6 and I moved over to 4.1 in hopes the extra horsepower would help out; I'd be stoked if I could move back to the 3.6 and save the 4.1 for more exciting things. (As it is currently, I'm using the 4.1 to run the host USB interface, connected to the 3.6 via 8 pins. The 3.6 is programmed to behave like a parallel-in serial-out shift register, a technique I like to refer to as "the brute force and ignorance approach")

Is the 112 number applicable to the host USB as well as the regular USB, or does it have a different priority? (Or, can they have separate priorities, but they just so happen to be set the same? What kind of side effects do you get if you're late servicing USB interrupts?
 
I am trying to apply this to my code on a Teensy4.1 with an external ADC with an interrupt on data ready.

Input is to pin 24 but the port naming convention seems to be very different to the Teensy 3.x. ie no PortA, PortB etc

From the schematic:
Screenshot 2022-05-31 192008.jpg

From: imxrt.h:

IRQ_GPIO1_0_15 = 80,
IRQ_GPIO1_16_31 = 81,
IRQ_GPIO2_0_15 = 82,
IRQ_GPIO2_16_31 = 83,
IRQ_GPIO3_0_15 = 84,
IRQ_GPIO3_16_31 = 85,
IRQ_GPIO4_0_15 = 86,
IRQ_GPIO4_16_31 = 87,
IRQ_GPIO5_0_15 = 88,
IRQ_GPIO5_16_31 = 89,

None of these seem to obviously map to the labels in the schematic for 4.1....

Anyone able to steet me out of the fog?
 
This seems to have worked:

NVIC_SET_PRIORITY(IRQ_GPIO1_16_31, 16);

Not sure how that group relates to what's on the schematic but it does the trick....
 
@strud - as @defragster mentioned by pointing to that other thread, is that at startup time, the Teensy switches all of the IO pins to fast mode, so instead of GPIO1-4 the pins are on GPIO6-9
With the code:
Code:
#if defined(__IMXRT1062__)
	// Use fast GPIO6, GPIO7, GPIO8, GPIO9
	IOMUXC_GPR_GPR26 = 0xFFFFFFFF;
	IOMUXC_GPR_GPR27 = 0xFFFFFFFF;
	IOMUXC_GPR_GPR28 = 0xFFFFFFFF;
	IOMUXC_GPR_GPR29 = 0xFFFFFFFF;
#endif
And as mentioned in that thread: NVIC_SET_PRIORITY(IRQ_GPIO6789, 0);
All of the pins go through one interrupt for GPIO6-9

But setting this one interrupt priority to the highest priority, will do so for all of the interrupts setup with attachInterrupt(...)

There are some other approaches you can potentially take that might speed it up. But can make the code less portable.
That is those IOMUXC_ registers are setup to be on a pin by pin setting. So each port has up to 32 pins and setting the corresponding bit in the correct register will return that pin to be in normal mode...
So for Pin 24, looking at my excel...
screenshot.jpg
I see it is GPIO 1 pin 12 (or in Fast mode GPIO 6)

So as an alternative you could, switch pin 12 on GPIO 1 (IOMUXC_GPR_GPR26) bit 12 to 0
You could setup your own Interrupt handler attachIntteruptVector(IRQ_GPIO1_0_15, <your function>)
Set the priority.

And then you need to provide your own interrupt handling code, that has to do the maintenance to setup the specific pin to interrupt and to clear the interrupt in the handler...
And if you only setup one pin this way on that Port/pin range, then your code interrupt code can be specific, by simply clearing the interrupt state in the appropriate register and then do your
own stuff.
 
Back
Top