strange FreeRtos Xmega128A1 port behavior

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi guys:

I posted this in the Freertos forum at sourceforge
But I think it's useful to post it here, because it's related to Xmega and GCC, and perhaps it end up being useful to someone else. I'll resume, since I've posted three times and did some tracing in between.

My problem is as follows

I used the FreeRtos port for the Xmega that is contributed here http://interactive.freertos.org/...

My setup is FreeRTOS 6.1.1 WinAVR 20100110 Astudio4.18 b716
I made the "de rigueur" file replacement , "port.c" and "portmacro.h"

With the RTOS port so installed I tested a simple system which work this way:

It has 2 tasks a mutex and a binary semaphore for synchronization fired from an interrupt vector (using the "fromISR" routines) 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 the semaphore. When semaphore fires (it's given), 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 this way: (semaphore and mutex are started OK, the same for the two tasks)


main() { /* pseudocoded for clarity ... */  

start_task_1@priority=1 
start_task_2@priority =2 
start_scheduler()

} 

the system works OK but if I start the system with both tasks AT THE SAME PRIORITY (this is both tasks at priority 1 or 2) 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 (Deferring the CPU control to TASK1 forever)

I traced this behaviour to the following:
Single stepping the source at Disassembler level, when the timer tick ISR gets serviced it exits the ISR with a "RET" instruction, not with "RETI" this way:

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

asm volatile ( "reti" ); 
} 

by this the interrupts at that level (usually all LOW or all HIGH as a security measure) get clobbered and no other interrupt can be serviced, because for the interrupt controller there is an interrupt being served (which is reflected in the PMIC.STATUS register)

I simply have no idea why the tick interrupt is exiting in the "ret" inside portRESTORE_CONTEXT(), let alone of why the system works normally when raising TASK2 priority, or starting TASK2 first (in case both tasks are at same priority)!!
For me, this points to a severe context switch/stack/memory misalignement, but I don't know why the system works in the first place an doesn't keep crashing.

The worst is that I've worked before with FreeRtos and The ATmega128 (classic AVR) with zero problems (well, nothing that can't be fixed by reading internet). What do you thing is causing this behavior? Is there something in the hardware that I'm missing?

Any clues are welcomed
Thanks in advance
Nachus