Quality RTOS & Embedded Software

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




Loading

Get exceptions when interrupts are nested

Posted by ayazar on November 1, 2017

Hello,

I am experimenting with FreeRTOS v9.0.0 on Zynq by expanding the example project. There are 3 interrupt sources and they are async. to each other, for example one interrupt is from serial port receive action and another one is generated from an input pin which occurs independently from serial channel. I also log during runtime on RAM using trace provided by FreeRTOS and analyze the results using free edition of Tracealyzer. At the beginning, I assigned different priorites to each interrupt. These priorites were appropriate such that I was able to call ..FromISR() functions inside ISRs. However the code showed up problems when it ran about 5 minutes. At some point, in order to debug problem I assigned same priorites to all interrupts. Then, I did lots of change and since it is a learning project for me I didn't use version control (!).

Now, the code runs more than 24 hours without any problem but I realized that if I configure interrupts with different priorites as in before, I get different ARM exceptions (sometimes "undefined", somtimes "data abort" and some times "prefetch abort"). I verify that problem occurs when an interrupt is nested with another one by looking trace logs with Tracealyzer.

I know that this is an general question and it may not be related with FreeRTOS directly but I want to hear suggestions if any. Can there be any misusage of FreeRTOS API functions such that there is a problem only a nested interrupt is occured? As I said, code works well if I don't use nested interrupts. Additionaly, there is no shared data between ISR functions. I am not very familiar with FreeRTOS internals and ARM itself so I can't comment by thinking what FreeRTOS does when a nested interrupt occurs. In interrupts, I either send a message to a queue or give a semaphore. Enabling/disabling trace functions on the code doesn't change the result.

I would appreciate any ideas.

Best, Alper


Get exceptions when interrupts are nested

Posted by rtel on November 1, 2017

First thing - do you have configASSERT() defined to something that will halt the processor?

You can cause a problem if you use an API function that does not end in "FromISR" inside an ISR, or if you call an API function that does end in "FromISR" but from an interrupt that has a priority above configMAXAPICALLINTERRUPTPRIORITY (see http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html)

Finally, depending on GCC version, you can get into problems if nested interrupts use floating point registers, and that can happen even if you don't explicitly perform floating point operations - for example if the compiler's libraries are optimized to the point that floating point registers are used (because they are wide and can move more bytes with fewer operations) in memcpy() calls (which are used inside FreeRTOS API functions). There are some notes on that on the same link above.


Get exceptions when interrupts are nested

Posted by ayazar on November 10, 2017

Hi,

configASSERT() is defined as in the example Zynq code. This is the assert handler:

~~~ void vAssertCalled( const char * pcFile, unsigned long ulLine ) { volatile unsigned long ul = 0;

( void ) pcFile;
( void ) ulLine;

taskENTER_CRITICAL();
{
	/* Set ul to a non-zero value using the debugger to step out of this
	function. */
	while( ul == 0 )
	{
		portNOP();
	}
}
taskEXIT_CRITICAL();

} ~~~

I have verified that when a FreeRTOS function is asserted, I could catch this behaviour by putting a breakpoint on line with "portNOP();". So when this problem occurs, assert() is never called.

I make sure that all API functions end in FromISR.

For priorities, if I assign a wrong priority without considering configMAXAPICALLINTERRUPTPRIORITY, vAssertCalled() is called immediately even interrupts aren't nested. Therefore, I am sure that priorites are OK.

This port defines its own memcpy() function and I compile the code with no optimization. So I think that, VFP registers aren't used but i will check the compiled code. Even if they are used, is nested intterrupt sitution the only trigger of the error. I mean that FreeRTOS API functions are called from tasks and ISRs even if interrupts aren't nested. If floating point registers are used, do they cause error only if interrupts are nested?

BTW, configUSETASKFPU_SUPPORT is 2 in my case.

Thank you.

P.S. Disassembly of memcpy() function is posted below. I am not ARM assembly expert but I don't think that there is any floating point instruction.

~~~ 123 void memcpy( void *pvDest, const void *pvSource, size_t xBytes ) 0010ed7c: sub sp, r11, #0 0010ed80: pop {r11} 0010ed84: bx lr 124 { 125 / The compiler used during development seems to err unless these volatiles are 126 included at -O3 optimisation. / memcpy: 0010ed88: push {r11} 0010ed8c: add r11, sp, #0 0010ed90: sub sp, sp, #36 0010ed94: str r0, [r11, #-24] 0010ed98: str r1, [r11, #-28] 0010ed9c: str r2, [r11, #-32] 127 volatile unsigned char *pcDest = ( volatile unsigned char * ) pvDest, *pcSource = ( volatile unsigned char * ) pvSource; 128 size_t x; 129
130 / Extremely crude standard library implementations in lieu of having a C 131 library. */ 0010eda0: ldr r3, [r11, #-24] 0010eda4: str r3, [r11, #-12] 0010eda8: ldr r3, [r11, #-28] 0010edac: str r3, [r11, #-16] 132 if( pvDest != pvSource ) 133 { 0010edb0: ldr r2, [r11, #-24] 0010edb4: ldr r3, [r11, #-28] 0010edb8: cmp r2, r3 0010edbc: beq +72 ; addr=0x0010ee0c: memcpy + 0x00000084 134 for( x = 0; x < xBytes; x++ ) 135 { 0010edc0: mov r3, #0 0010edc4: str r3, [r11, #-8] 0010edc8: b +44 ; addr=0x0010edfc: memcpy + 0x00000074 136 pcDest[ x ] = pcSource[ x ]; 137 } 138 } 139
0010edcc: ldr r2, [r11, #-12] 0010edd0: ldr r3, [r11, #-8] 0010edd4: add r3, r2, r3 0010edd8: ldr r1, [r11, #-16] 0010eddc: ldr r2, [r11, #-8] 0010ede0: add r2, r1, r2 0010ede4: ldrb r2, [r2] 0010ede8: uxtb r2, r2 0010edec: strb r2, [r3] 134 for( x = 0; x < xBytes; x++ ) 135 { 0010edf0: ldr r3, [r11, #-8] 0010edf4: add r3, r3, #1 0010edf8: str r3, [r11, #-8] 0010edfc: ldr r2, [r11, #-8] 0010ee00: ldr r3, [r11, #-32] 0010ee04: cmp r2, r3 0010ee08: bcc -68 ; addr=0x0010edcc: memcpy + 0x00000044 140 return pvDest; 0010ee0c: ldr r3, [r11, #-24] 141 } ~~~


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




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

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

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

OpenRTOS and SafeRTOS