I am using MPLABX + Harmony framework to write code for a PIC32MZ1024EFK064.
My goal is, to trigger the ISR every microsecond. In order to test this, I toggle a LED after 1000000 cycles of the ISR:
uint32_t xxx = 0;
void __ISR(_TIMER_2_VECTOR, ipl1AUTO) IntHandlerDrvTmrInstance0(void)
{
xxx++;
if(xxx > 1000000){
xxx = 0;
blink();
}
PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_2);
}
Timer2 runs at 80MHz with a prescaler of 1 with a timer period of 80.
At my first attempt, the LED toggled every 4 seconds (ISR = every 4us).
I figured out that I can reach 2 seconds by changing the Postscaler of PBCLK7 from 2 to 1. (now the CPU-core runs at 160MHz instead of 80MHz).
But even when I change the timer period to 1, I only get my LED toggled every 2 seconds.
Any idea how to speed things up further here?
UPDATE:
The subroutine blink()
was too slow.
By manipulating the Register directly, it works at 1us
void __ISR(_TIMER_2_VECTOR, ipl1AUTO) IntHandlerDrvTmrInstance0(void)
{
LATBINV = 1<<8;
PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_2);
}
I am not very familiar with that specific microcontroller but have worked a lot with Microchip PICs, so here are some points you might want to look at:
1- First make sure your clocks (CPU and PBCLK) really run at the speed you think they run. You can usually output some of your internal clocks on an external pin (usually REFCLKO on PIC32s). That way you can measure them with an oscilloscope and make sure they are correctly configured.
2- Make sure you minimize the internal execution time of your interrupt. Check if PLIB_INT_SourceFlagClear() is a macro-like function or an actual function call. If this is a function call, you might want to work at the register level to avoid this overhead.
3- Enable compiler optimization. By the way, it is also a good practice when working with a global variable from within an interrupt to declare it as volatile (or declare it static inside your interrupt handler function).
4- Unless it is explicitely documented by Microchip, verify if you should clear your interrupt at the beginning of your interrupt handler instead of the end. What might happen in your case, especially if you set its period to a very short period of time, is that your timer expires again while you are still inside your interrupt handler but BEFORE you clear its flag. That would result in an extra delay before your interrupt fires again. What you want is to clear the flag as soon as possible so if the timer expires again, it sets the flag which will result in your interrupt handler to fire again as soon as it completes its execution. Of course that would not give any time for your background application to execute though...
5- I am also assuming that your timer is correctly configured, that is it reloads its internal count to 0 when the period expires, but take a look to make sure it is the case.
Franck