teensy 4.0 valid interrupt priority values

jrdarrah

Well-known member
I'm trying to set interrupt priorities on the teensy 4.0 and I don't get the expected result. Here is a test sketch that sets the priority on an external pin inteerupt and three interval timers,

Code:
#include "IntervalTimer.h"
int MPR121_irqPin = 20;                   // irq pin for Adafruit MPR121 breakout board, GPIO6-2
volatile double audioInterval =1000000;                   //set by using playing freq as index to audioRateA440 or audioRateA220
volatile uint32_t controlInterval = 10000;        // The fingerholes will be scanned for external changes 100 times per second
volatile uint32_t clockInterval = 250000;        // interval timer = 1/4 second.

/********************************************************************************
     variables related to the interrupt handler interval control timers
********************************************************************************/
IntervalTimer audioTimer;     //control time for sound production. The frequency will be adjusted by varying the interval
IntervalTimer controlTimer;   //used to scan for external changes to environment
IntervalTimer clockTimer;     //timer to keep track of 1/4 second intervals

void setup() {
  unsigned long delayStart = millis();
  Serial.begin(115200);
  while (!Serial && (millis() - delayStart) <= 1000);
  Serial.println("Serial Started");
  pinMode(MPR121_irqPin, INPUT);     //set irq pin as input
  attachInterrupt(MPR121_irqPin,readTouchInputs,FALLING);
  NVIC_SET_PRIORITY(IRQ_GPIO6789,127); 
  controlTimer.begin(scanInputs, controlInterval);
  controlTimer.priority(162);  
  audioTimer.begin(audioOscillator, audioInterval);
  audioTimer.priority(255);  
  clockTimer.begin(clockRoutine, clockInterval);
  clockTimer.priority(249);
for (int irqNr = 0; irqNr < NVIC_NUM_INTERRUPTS; irqNr++)
  {
      Serial.printf("IrqNr:%d PRIO:%d\n",irqNr, NVIC_GET_PRIORITY(irqNr));
  }
}

void scanInputs()
{
}
void readTouchInputs()
{
}
void audioOscillator()
{
}
void clockRoutine()
{
}
void loop() {
  // put your main code here, to run repeatedly:

}

In reading the fine print I can now see that the gpio pins share a common priority value. Same for the timer 0-3 per this document starting on page 43.

i.MX RT1060 Processor Reference Manual
Document Number: IMXRT1060RM, Rev. 3, 07/2021

I want to confirm that there is no way to set each of the 4 teensy timer interrupts to a different value,

Code:
  attachInterrupt(MPR121_irqPin,readTouchInputs,FALLING);
  NVIC_SET_PRIORITY(IRQ_GPIO6789,127); 
  controlTimer.begin(scanInputs, controlInterval);
  controlTimer.priority(162);  
  audioTimer.begin(audioOscillator, audioInterval);
  audioTimer.priority(255);  
  clockTimer.begin(clockRoutine, clockInterval);
  clockTimer.priority(249);

The result of my test:

IrqNr:122 PRIO:160 PIT Timer0-3 < rounded all of my priorities (162, 255, 249) down to 160
IrqNr:157 PRIO:112 GPIO 6/7/8/9 > rounded down from 127 to 112

Some of the online documentation states priorities go from 0-255 with 0 being the highest. What I'm seeing is the valid values are multiples of 16 (rounded down, Ex 127 for GPIO ended up as 112). In the case of the three timers, it seems to max out at 160.

What are the valid values for priority 0,16,32,48,64...or am I doing something wrong to be able to use all values 0-255.
Does the interval timer restrict the maximum value as I saw in my test, to 160?
 
I'm trying to set interrupt priorities on the teensy 4.0 and I don't get the expected result.

Does the interval timer restrict the maximum value as I saw in my test, to 160?

Here is priority() function from class IntervalTimer, from file cores\Teensy4\IntervalTimer.h. Looks like when you try to set the priority, it won't let you set the priority lower than for other IntervalTimer instances. Not sure why. You can set certainly get around that by calling NVIC_SET_PRIORITY rather than IntervalTimer::priority().

Code:
	// Set the interrupt priority level, controlling which other interrupts this
	// timer is allowed to interrupt. Lower numbers are higher priority, with 0
	// the highest and 255 the lowest. Most other interrupts default to 128. As
	// a general guideline, interrupt routines that run longer should be given
	// lower priority (higher numerical values).
	void priority(uint8_t n) {
		nvic_priority = n;
		if (channel) {
			int index = channel - IMXRT_PIT_CHANNELS;
			nvic_priorites[index] = nvic_priority;
			uint8_t top_priority = nvic_priorites[0];
			for (uint8_t i=1; i < (sizeof(nvic_priorites)/sizeof(nvic_priorites[0])); i++) {
				if (top_priority > nvic_priorites[i]) top_priority = nvic_priorites[i];
			}
			NVIC_SET_PRIORITY(IRQ_PIT, top_priority);
		}
	}
 
Thanks, that explains why all three of my interval timer requests got resolved to the lowest number (rounded down to a multiple of 16). I was hoping to assign three different values. In my app the audio oscillator should have the highest priority of the three. The other two aren't time critical, but the audio oscillator needs to send a new value to an external DAC roughly 44100 times a second though it will vary with pitch.

Based on your information, I ran another test. I set the priority for all three timers to 255. I did round down to 240. I'd still like confirmation about there being a specific list of valid values for priority. If that is the case I would prefer to use them in my code instead of continuing all values 0-255 and have it round down to the closest multiple of 16..
 
The processor priority levels go in groups of 16 from 0 highest to 255 lowest. 0-15 are all the same 'level', and so on.

Found this web comment that describes the levels in the PJRC NXP chips, K64 and other:
Code:
ARM has designed the NVIC controller to allow up to 256 levels of priority in the interrupts. Is up to the chip manufacturer to implement the whole 256 levels or to reduce it to save silicon space.

In the case of K64 devices, they support 16 levels of interrupts.
 
I want to confirm that there is no way to set each of the 4 teensy timer interrupts to a different value,

Confirm, on Teensy 4.0 the PIT timer has only a single interrupt slot, so all 4 timers get the same priority. It is a hardware limitation.

With older Teensy 3.x the timers did have separate interrupt NVIC slots, so each could be assigned a unique priority.

If you want to perform work at a lower priority, you could use an approach like the audio library where the hardware/DMA interrupt has a higher priority then uses software triggering to cause another lower priority interrupt to perform the CPU intensive work. That way other normal and higher priority interrupts are still able to function while the lower priority interrupt runs.

Also remember low numbers mean higher priority, so 0 is the highest priority that others can't interrupt and 255 is the lowest which others can interrupt.
 
Thanks, a visit to your audio library seems in order to see how the software interrupt triggering works.
 
Back
Top