Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

Suggestion for AT91SAM7 port: enable FIQ

Posted by incrediball on April 13, 2008
I'm writing this because of my experiences last week trying to write a high speed interrupt for implementing an I²C slave receiver in firmware. I could not make use of the TWI peripheral since this was being used for something else and when I read the Atmel documentation I'm actually not even sure it supports slave mode anyway. Due to the baud rates involved, the interrupt had to be called and complete execution within microseconds. I realise that this is not an everyday situation but I have had to implement high speed interrupts in the past for playing back PCM, where any significant interrupt latencies would have introduced distortion in the sounds. So, I am sure that the need for fast interrupts is not too insignificant.

I implemented the necessary interrupt handler in ARM mode in RAM and although its execution time was acceptable, the interrupt latency often wasn't and events were being missed. This was due to two reasons:

1. Nested interrupts and interrupt priorities are not supported under FreeRTOS.

2. All interrupts are routinely disabled for comparably long periods under FreeRTOS.

I was initially surprised when I first stumbled over the first problem. I mean, the AT91SAM7 provides us with all this great 8 priority support and then it's not used. The portSAVE_CONTEXT macro, which is used by all interrupt handlers under FreeRTOS, leaves the processor in interrupt mode with interrupts disabled so any nesting of normal interrupts is currently not possible. The reasoning is explained under http://www.freertos.org/FAQISR.html#Nest although I do not agree entirely with the explanation since one of the arguments is based on the idea that the programmer may want to use priorities for implementing slow interrupts and not for implementing interrupts that are faster than FreeRTOS's own tick interrupt.

I managed to get around this limitation using the FIQ and the AIC's fast forcing feature. The FIQ can pre-empt regular interrupts because only the I bit is set in CPSR when an IRQ is raised. The F bit is only set as well if an FIQ is raised. Some changes are needed in the FreeRTOS code (which is the reason why I am writing this):

a. A stack for the FIQ interrupt must be defined. This is done by changing the FIQ_STACK_SIZE parameter in boot.s to a useful size.

b. At the end of boot.s the exceptions are handled. Currently the FIQ vector contains "ldr pc, _fiq", which just executes an endless loop. This must be changed to "ldr pc, [pc,#-0xF20]", which is the same instruction as for the IRQ but because the PC is 4 bytes further along, it actually loads the vector for the fast interrupt.

The interrupt handler is as usual has the naked attribute and compiled in ARM mode. The entry code is very simple:

asm volatile ("stmfd sp!, {r0-r7, lr}"); // save non-banked registers and lr

The exit code is also very simple:

asm volatile ("ldmia sp!, {r0-r7, lr} \n\t" // restore non-banked registers and lr
"subs pc,lr,#4"); // restore pc (return from interrupt)

Note that the interrupt handler can obviously not interact with FreeRTOS. It wouldn't make sense for it to do so, since it would only slow itself down, if it were to cause task switches and the like. The interrupt is executing outside of the "realm" of FreeRTOS and if it needs to do things such as signalling task switches or queuing data, other mechanisms must be used. For example, my I²C interrupt triggered another (normal) interrupt (using AT91F_AIC_Trig) when it had finished receiving some data. That interrupt then processed the raw data and queued it for a task to further process it.

So, this fixed the first problem but there was still often an unacceptable latency starting the interrupt. Despite the fact that FIQs were obviously never used under this FreeRTOS port (FIQs just caused everything to lock up if they did occur), the FIQ interrupt was being disabled by portDISABLE_INTERRUPTS, vPortDisableInterruptsFromThumb and vPortEnterCritical. FreeRTOS disables interrupts in order to protect certain data structures from changes made during an interrupt. However, if an interrupt does not interact with FreeRTOS at all and assuming that this is always the case, there is no reason why such an interrupt needs to be disabled. Especially if the interrupt is fast and there are no other side effects, it does not need to be disabled. So, this is the third change to the FreeRTOS code: the 0xC0 constants (I and F bits) in the above mentioned 3 macros/functions need changing to 0x80.

Once these changes were made, my I²C slave receiver interrupt finally worked fine, and without destabilizing FreeRTOS.


RE: Suggestion for AT91SAM7 port: enable FIQ

Posted by Dave on April 16, 2008
Thanks for taking the time to share this. I think it has been touched on a few times in the past - searching for FIQ might find the posts. This is one of the areas where the Cortex M3 shows itself as a much better architecture than the ARM7.

RE: Suggestion for AT91SAM7 port: enable FIQ

Posted by Marco Jakobs on November 13, 2009
Hi,
i have exactly the same problem with the FIQ and Free RTOS, using a AT91SAM7X512 and Rowley Crossstudio.

The FIQ stack size is set in Rowley to 512 bytes, i created a fiq_handler (still without functionality for testing), including your asm directives like this:

void fiq_handler (void)
{
asm volatile ("stmfd sp!, {r0-r7, lr}"); // save non-banked registers and lr
AT91C_BASE_AIC->AIC_ICCR = 1;// Clear Interrupt Source

AT91C_BASE_AIC->AIC_EOICR = 0;// End of interrupt
asm volatile ("ldmia sp!, {r0-r7, lr} \n\t" // restore non-banked registers and lr
"subs pc,lr,#4"); // restore pc (return from interrupt)
}

But when i activate this interrupt, the RTOS runs into the undef_handler, not starting any task.

I'm trapped with this issue at the moment, not knowing why this happens.

Background is the worse implementation of the hardware TWI of the Atmel AT91SAM7X. It automatically generates a stop after the TWI shift register is transferred with no new data written into TWI_THR. Fast TWi rates higher than 100kHz are not possible with this, because of the interrupt lengths using FREE RTOS. My intention is here to make the TWI transfers in FIQ interrupt ... but for this, i have to solve the issue of the FIQ usage.

Any ideas are highly appreciated.


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists