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

Xmega128A1 Port strange behaviour

Posted by nachus001 on April 1, 2011
Dear all:

I used the FreeRtos port for the Xmega that is contributed here
http://interactive.freertos.org/attachments/token/wfsz46do1a8zcfz/?name=AVR_ATXMega128A1_WinAVR.zip
My setup is the last Freertos version, which compiles OK with no errors. The only file I've changed is PORT.c

and after some investigation I came to find a strange behaviour of the software or port.
I have 2 tasks a mutex and a binary semaphore for synchronization, fired from an interrupt vector

Task 1 takes the mutex when available and reads "protected" data then returns the mutex,

Task 2 is idle most of the time waiting for a semaphore. When semaphore fires, task 2 acess hardware, retrieves data from device, takes the mutex and writes to the "protected data", return the mutex then goes idle again

When I start the system like these


main()
{ /* pseudocoded for clarity*/
...
start_task_1@priority=5
start_task_2@priority =6

start_scheduler

}



the system works OK

but if I start the system with both tasks AT THE SAME PRIORITY
the system will only work if I start the task2 first
If I start Task1 first, the scheduler will switch to the task 1 code, but no to the task 2
In this case the task switcher will switch to task 1, and will stop switching.
Even with all the two interrupts enabled (tick timer and semaphore vector) at the same LEVEL (both high or both low)
it doesn't care. If I stop in a breakpoint placed in the task that's working (Task 1) and watch the hardware, I see that both interrupts are enabled, the PMIC_CTRL register is enabled, and the I bit is set, but no interrupt gets processed (altough both are acknowledged since it's individual flags so indicates, and PMIC_STATUS indicates an interrupt being executed)

This is very strange, since I've worked before with FreeRtos and The ATmega128 (classic AVR) with no problems.
What do you thing is causing this? Is there something in the hardware tht I'm missing?

Thanks in advance
Ignacio

RE: Xmega128A1 Port strange behaviour

Posted by Richard on April 2, 2011
I'm not familiar with that port, as it is a contributed port, but just some general tips:

1) Can you step through the code and see what is happening?
2) Is it possible you have a simple deadlock in your code?
3) Are you complying with all the usual rules about not using API function that don't end if FromISR() from an interrupt?
4) Do you have the run time stack checking switched on?

Regards.

RE: Xmega128A1 Port strange behaviour

Posted by nachus001 on April 2, 2011
Hi Richard:

Thanks for your response I'll answer your questions

1 Yes I can, and with Task1 working only I can see how it takes the mutex, returns the mutex and do other things
(which in no case do mess with interrupts or RTOS structures)

2 Frankly, I don't know. Maybe there is a deadlock if I set task1 (which runs all the time) priority greater than task2 (which runs only when there's a signal for it)

3 Yes I do. The ISR that fires Task 2 sets a semaphore with the proper "fromISR()" function

4 No. because I did't suspected there were some stack problem. For the record, I set (in FreeRTOSconfig.h) the Heap size to 20000. I let default minimal stack size and "TASK1" has a stack depth of 6000 bytes, Task2 has 1000 bytes

Thank you
Ignacio

RE: Xmega128A1 Port strange behaviour

Posted by nachus001 on April 4, 2011
Hi Rick:

I have done some investigation on the topic, and I found something that puzzles me
about this port.
I have found why the interrupts get clobbered. Theyre not disabled, but suspended.
Ive found that this occurs because in the context switch timer tick, the ISR service exits with the "RET" instruction
not with "RETI" (which would reenable the interrupt controller)

Notice that in the Xmega architecture the interrupts are not disabled by an interrupt call at general level.
They are disabled by "LEVEL" level, this is low, med and high levels. (for simplicity I use interrupts in only one level, usually all low) So, altough the interrupt enabling/disabling mechanism is controllable by the user, it's not visible when operated by interrupt calls, and "RETI" has compatibility with the classic megaAVR in the sense that it will reenable all the interrupts in a given level, so it must be present to exit the ISR.

Once clarified this, here's what I've found
When I start TASK2 and TASK1 (as explained on my first post) Everything works as intended
If I single step with the dissasembler, I can trace that the ISR(TCC0_OVF_vect, ISR_NAKED) is entered and
vPortYieldFromTick(); is executed properly. Terminating properly and exiting the ISR with "RETI"

Now, if I change the starting order of tasks (as explained in the first post), if I single step the program, once the tick ISR is reached the execution goes like this

ISR(TCC0_OVF_vect, ISR_NAKED) <--- ENTERS HERE BY TIMER INTERRUPT
{
vPortYieldFromTick();
|
|
|----> calls {
portSAVE_CONTEXT();
vTaskIncrementTick();
vTaskSwitchContext();
portRESTORE_CONTEXT(); <---EXITS BY THE FINAL "RET" INSIDE HERE

}


asm volatile ( "reti" );
}


And the "reti" on the end of the interrupt service is never reached, so the interrupts are never served and the program gets hanged, with the control switched to TASK1 (the first started task)

I can't understand why this happens. ay be there is an error with the push/pop sequence (I checked this and appears to be OK) or some severe memory/context misalignement. But in this case I can't say for sure, because the system would be resetting all the time, and that's not the case.

Thanks in advance
Ignacio

RE: Xmega128A1 Port strange behaviour

Posted by nachus001 on April 25, 2011
Hi Richard:

From almost a month with the issue, I have made some progress.

First, I've modified the vPortYieldFromTick() function with a final "reti" instead of the original "ret"
and all worked OK.

All okay for the given tasks described here, in any startup order, but when I added more tasks and semaphores, the system begun to fail again randomly. I debugged the application until I could trace the problem to the taskYield(); function

In my system, I have a number of interrupts being serviced which do force task switching when they have data for
the system tasks (usually, tasks that are top priority but are 99% of the time sleeping until there is data for them)
The interrupts routines are written more or less in this form

ISR(PORTA_INT0_vect)
{

signed portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;


xSemaphoreGiveFromISR( TIME_task_semaphore, &xHigherPriorityTaskWoken );


if( xHigherPriorityTaskWoken != pdFALSE )
{
taskYIELD();
}



}




If I comment the "if" statement (and therefore the"taskYield()") , the program works normally and doesn´t hang, but if I uncomment the "if" in the code the program hangs as described earlier and by the same mechanism.

So I think I've spotted the problem as a task or context switching from interrupt.
The Xmega program counter is 24 bits wide (contrary to the ATmega which is 16 bits wide), so, when an interrupt is serviced three bytes are saved in the stack (and also three bytes from PC have to be restored ) The port I'm using takes care of this, but, for some reason the system fails with taskYIELD() from an interrupt.

I don't know why taskYield() fails from and ISR routine since it uses the same portSAVE_CONTEXT(); portRESTORE_CONTEXT(); vTaskSwitchContext(); as in vPortYieldFromTick(), and it works

Not to speak why it fails randomly, after calling two or three times taskYield() from different ISR's before a failure.. It also works when called from a normal task. On the other hand there's no "from_ISR" yield function for AVR (at least not from my knowledge) . This context forcing is as in the provided "serial port" demo

Thanks in advance
Ignacio


[ 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