AVR32 High Priority Interrupt Handler

bmenkveld wrote on Friday, November 21, 2008:


I’m working on an application running on an AVR32 UC3A0512 CPU.  One of the things the application has to manage is commutation of a stepper motor.  This requires accurate output updates at a rate of up to 10KHz.

I set up a timer tick interrupt to operate at a rate of 10KHz, and then poked a spare output in the ISR so I could observer the timing consistency on a scope.

What I found was very large jitter in the timing of the interrupt, with the ISR executing as much as 90us late.  That will obviously make for very large disruptions in the control of the stepper motor driver waveforms.

I tried increasing the timer tick interrupt priority from 0 to 3.  All other interrupt handlers run at priority 0 (the lowest), so I thought this would solve the problem.  Instead, it hardly made any difference.  The average jitter did seem to decrease somewhat, but there were still extreme cases of 90us.

Then I got looking at the FreeRTOS kernel code.  The vTick() handler for the RTOS timer tick interrupt is in port.c.  It encloses its central call to vTaskIncrementTick() in portENTER/EXIT_CRITICAL() calls.  When I commented these CRITICAL calls out, the jitter in my 10KHz ISR was reduced to 2us!

The portENTER_CRITICAL() call disables interrupts altogether to ensure the crucial kernel work doesn’t get messed up by an interrupt that might make some kernel call.  However, my high priority interrupt handler won’t make any kernel calls.

It seems to me that if my program never makes any kernel calls from any interrupt handler with a higher priority than vTick(), then there should not be a problem with removing the portENTER_CRITICAL() call from vTick().  Is that true?

At http://www.freertos.org/PC/index.html I did find the following under "Can interrupts be nested?":

"In the case that a very fast interrupt response is required for a certain peripheral then the peripheral priority can normally be set to above that of the kernel itself. This means the processing of the peripheral will never be delayed by the action of the kernel. "

That sounds like what I want, but it does not make any mention of removing the  portENTER_CRITICAL() call from vTick().

Does anyone know whether it is safe to do that?

On a side note, I was rather surprised to find the kernel taking this long to execute on a processor running at 66MHz.

Thanks in advance for any  help.

Bert Menkveld

davedoors wrote on Saturday, November 22, 2008:

I don’t think the link you posted is the one intended.

Here is a link that explains the interrupt priorities of the latest FreeRTOS ports which support interrupt nesting http://www.freertos.org/a00110.html#kernel_priority . The older ports generally don’t support interrupt nesting. I’m not familiar with the AVR32 code so don’t know which camp this falls into.

The link shows a diagram for a hypothetical processor where interrupt functions up to priority 4 can contain FreeRTOS API calls. Critical sections that protect kernel data structures have to mask interrupts up to 4 (in this hypothetical case) so interrupts at priority 4 and below will get jitter in their timing.  Interrupts running at priority 5 and above will never be masked by the kernel executing so will not experience any jitter over and above that which would normally be expected for the processor. In other words the kernel does not add any jitter.

The tick interrupt is not the best place to add such high frequency code. Take a look at this demo http://www.freertos.org/portLM3Sxxxx_Eclipse.html which shows a 20KHz timer running at a priority above configMAX_SYSCALL_PRIORITY and measures the jitter experienced. The max jitter settles around 120ns on a 50MHz processor, which is equal to the number of processor cycles that can be skipped when the processor performs tail chaining, so is what you would expect to see whether an RTOS was used or not.

How is the interrupt prioritization done on the AVR32? Is there an equivalent to an ARM7 FIQ that could be used to get the same result?

bmenkveld wrote on Saturday, November 22, 2008:

Hello Dave,

Thanks for the response.  You are quite right, the link I posted doesn’t work.  My browser doesn’t seem to show complete web addresses for the various pages on the freertos site.

I had also read the page you mention.  Unfortunately, AVR32 is not one of the ports that support interrupt nesting. 

The AVR32 does support 4 levels of prioritization for interrupt handlers (for interrupt groups, actually).  It seems to me that if I keep the OS and all the interrupt handlers that make OS calls at interrupt level 0 (the lowest level), then the OS shouldn’t care if some higher priority handler interrupts a low-priority handler, because that higher priority handler won’t make any OS calls.  Certainly that appears to be working for me.

However, looking over some of the low-level guts of the FreeRTOS code shows a frightening amount of complexity dealing with potentially interrupted interrupt handlers, so I’m worried I may be setting up the potential for some rare failure scenario that will come back and bite me in the future.


rnowotny wrote on Tuesday, November 25, 2008:

Dear Richard,
In the Documentation, it is noted that :
configKERNEL_INTERRUPT_PRIORITY is currently only in Cortex-M3, PIC24, dsPIC and PIC32 ports. configMAX_SYSCALL_INTERRUPT_PRIORITY is currently only available in the PIC32 and Cortex M3 ports. Other ports will get upgraded shortly.
Since i also need that function, may I kindly ask when that functionality will be available for the AVR32 (323) Port ?
yours sincerely
Robert Nowotny / Vienna

rnowotny wrote on Tuesday, November 25, 2008:

Correction - I mean the ATMega323 Port.
Yours sincerely
Robert / Vienna