I did some more tests on the low performance of the IntervalTimer and found something strange. It looks like the ISR is called two two times in a row.
To dig further into this I did a minimal example showing the effect without using IntervalTimer at all. I just set the corresponding registers. The code sets up the PIT and channel 1 with a reload value of 100 (T=4.1µs). In the PIT ISR I loop through all four channels and generate a pulse if the TFLAG of a channel is set. The pulse pin number (0..3) corresponds to the PIT channel number. The strange thing is tht, after the first call of the ISR (with the correct TFLAG set), the ISR is called again. This time without any TFLAG set so that the code falls through the loop and pulses on pin 4.
This behavior
might be the reason for the suboptimal performance of the IntervallTimer (see #830). The code in the corresponding ISR from the interval timer needs to cycle through all the channels two times which costs about 1µs in total. Here the simple test code:
Code:
void pitIsr()
{
for (int i = 0; i < 4; i++)
{
if (IMXRT_PIT_CHANNELS[i].TFLG == 1) // if channel TFLG is set, delete it and generate pulse on pin i
{
IMXRT_PIT_CHANNELS[i].TFLG = 1;
digitalWriteFast(i, HIGH);
digitalWriteFast(i, LOW);
return;
}
}
//why is the code below called?
digitalWriteFast(4, HIGH);
digitalWriteFast(4, LOW);
}
void beginPIT(uint32_t cycles)
{
CCM_CCGR1 |= CCM_CCGR1_PIT(CCM_CCGR_ON);
PIT_MCR = 0;
IMXRT_PIT_CHANNELS[0].LDVAL = cycles;
IMXRT_PIT_CHANNELS[0].TFLG = 1;
IMXRT_PIT_CHANNELS[0].TCTRL = PIT_TCTRL_TEN | PIT_TCTRL_TIE;
attachInterruptVector(IRQ_PIT, pitIsr);
NVIC_ENABLE_IRQ(IRQ_PIT);
}
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
for (int i = 0; i < 5; i++) pinMode(i, OUTPUT);
beginPIT(100);
}
void loop()
{
digitalWriteFast(LED_BUILTIN, !digitalReadFast(LED_BUILTIN));
delay(250);
}
View attachment 15598