Quality RTOS & Embedded Software

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




Loading

ATMega640 port crashing at context switch

Posted by thesa1nt01 on January 6, 2011
Salutations all,

We are working on porting the GCC ATMega323 FreeRTOS code to the ATMega640 on the Axon platform for use with a robot and we are not able to context switch. When vPortYield or vPortYieldFromTick is called, as soon as we step to portRESTORE_CONTEXT, registers 00-30 get the value 0x00 (R01 and R29 already had 0x00 it seems) and R31 keeps 0xFF, X and Y pointer get 0x0000 and Z pointer gets 0xFF00. Following this we are stepped back to int main().

We have two basic tasks, and only the initially created task gets to call taskYIELD.

I have scoured the forums and applied a few changes, to be listed, but most notably, since the program counter is three bytes long, we tried to account for the third byte as suggested by this post:

https://sourceforge.net/projects/freertos/forums/forum/382005/topic/1536028

both before, and after the initial two bytes, with no affect, and even came across a post where someone solved the problem by removing the third byte from their code.

We are primarily working in the simulator at this point, but have reproduced the error on two other simulators and two identical hardware platforms.

FreeRTOS V6.1.0
AVR Studio 4.18.716
WinAVR 20100110 (I think this is a version number but we also are using the latest version on other laptops)

The following sections were modified:


port.c

/* Start tasks with interrupts enables. */
#define portFLAGS_INT_ENABLED( ( portSTACK_TYPE ) 0x80 )

/* Hardware constants for timer 1. */
#define portCLEAR_COUNTER_ON_MATCH( ( unsigned char ) 0x08 )
#define portPRESCALE_64( ( unsigned char ) 0x03 )
#define portCLOCK_PRESCALER( ( unsigned long ) 64 )
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE( ( unsigned char ) 0x02 )

/*-----------------------------------------------------------*/


/* Enable the interrupt - this is okay as interrupt are currently globally
disabled. */
ucLowByte = TIMSK1;
ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
TIMSK1 = ucLowByte;




portable.h

#ifdef GCC_MEGA_AVR 
#include "../portable/GCC/ATMega640/portmacro.h"
#endif




FreeRTOSConfig.h

#define configUSE_PREEMPTION0
#define configUSE_IDLE_HOOK0
#define configUSE_TICK_HOOK0
#define configCPU_CLOCK_HZ( ( unsigned long ) 16000000 )
#define configTICK_RATE_HZ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES( ( unsigned portBASE_TYPE ) 4 )
#define configMINIMAL_STACK_SIZE( ( unsigned short ) 85 )
#define configTOTAL_HEAP_SIZE( (size_t ) ( 1500 ) )
#define configMAX_TASK_NAME_LEN( 8 )
#define configUSE_TRACE_FACILITY0
#define configUSE_16_BIT_TICKS1
#define configIDLE_SHOULD_YIELD1
#define configQUEUE_REGISTRY_SIZE0

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 1
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )

/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */

#define INCLUDE_vTaskPrioritySet0
#define INCLUDE_uxTaskPriorityGet0
#define INCLUDE_vTaskDelete1
#define INCLUDE_vTaskCleanUpResources0
#define INCLUDE_vTaskSuspend0
#define INCLUDE_vTaskDelayUntil1
#define INCLUDE_vTaskDelay1




We disabled the preemption in order to determine whether or not the tick had anything to do with it.
There were no change in symptoms.

Here's the main:


#include 
#include

int i, j;

void vTaskA(void* pvParameters){
for(;;){
i++;
taskYIELD();
}
}

void vTaskB(void* pvParameters){
for(;;){
j++;
taskYIELD();
}
}

int main(){


xTaskCreate(vTaskB, "B", 10, NULL, 1, NULL);
xTaskCreate(vTaskA, "A", 10, NULL, 1, NULL);
vTaskStartScheduler();
for(;;);
return 0;
}


Also, we compiled at optimization O3 and O0, with no change.

I hope this is enough information. I'm sure there is some simple silly solution, because there doesn't seem to be much left!
:)

Thanks in advance.

RE: ATMega640 port crashing at context switch

Posted by Richard on January 10, 2011
Does this help?

http://interactive.freertos.org/entries/139197-avr-atxmega128a1-winavr

You could also try searching avrfreaks.net, or seeing if somebody has a port there.

Regards.

RE: ATMega640 port crashing at context switch

Posted by JMR on January 10, 2011
Hi,
I did have a working port to the Xmega644 but haven't touched it in 2 years+ so won't be able to help with getting the port into the latest FreeRTOS version.
I seem to remember having to modify the portSAVE_CONTEXT() and portRESTORE_CONTEXT() macros to get it to work as well as the tick interrupt part of the port.c file.
here's the contents of port.c:
/*
FreeRTOS.org V4.6.1 - Copyright (C) 2003-2007 Richard Barry.

This file is part of the FreeRTOS.org distribution.

FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.

***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.

Also see http://www.SafeRTOS.com a version that has been certified for use
in safety critical systems, plus commercial licensing, development and
support options.
***************************************************************************
*/

/*

Changes from V2.6.0

+ AVR port - Replaced the inb() and outb() functions with direct memory
access. This allows the port to be built with the 20050414 build of
WinAVR.
*/

#include
#include

#include "FreeRTOS.h"
#include "task.h"

/*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the AVR port.
*----------------------------------------------------------*/

/* Start tasks with interrupts enables. */
#define portFLAGS_INT_ENABLED( ( portSTACK_TYPE ) 0x80 )

/* Hardware constants for timer 1. */
#define portCLEAR_COUNTER_ON_MATCH( ( unsigned portCHAR ) 0x08 )
#define portPRESCALE_64( ( unsigned portCHAR ) 0x03 )
#define portCLOCK_PRESCALER( ( unsigned portLONG ) 64 )
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE( ( unsigned portCHAR ) 0x02 )

/*-----------------------------------------------------------*/

/* We require the address of the pxCurrentTCB variable, but don't want to know
any details of its type. */
typedef void tskTCB;
extern volatile tskTCB * volatile pxCurrentTCB;

/*-----------------------------------------------------------*/

/*
* Macro to save all the general purpose registers, the save the stack pointer
* into the TCB.
*
* The first thing we do is save the flags then disable interrupts. This is to
* guard our stack against having a context switch interrupt after we have already
* pushed the registers onto the stack - causing the 32 registers to be on the
* stack twice.
*
* r1 is set to zero as the compiler expects it to be thus, however some
* of the math routines make use of R1.
*
* The interrupts will have been disabled during the call to portSAVE_CONTEXT()
* so we need not worry about reading/writing to the stack pointer.
*/

#define portSAVE_CONTEXT()\
asm volatile ("pushr0\n\t"\
"inr0, __SREG__\n\t"\
"cli\n\t"\
"pushr0\n\t"\
"pushr1\n\t"\
"clrr1\n\t"\
"pushr2\n\t"\
"pushr3\n\t"\
"pushr4\n\t"\
"pushr5\n\t"\
"pushr6\n\t"\
"pushr7\n\t"\
"pushr8\n\t"\
"pushr9\n\t"\
"pushr10\n\t"\
"pushr11\n\t"\
"pushr12\n\t"\
"pushr13\n\t"\
"pushr14\n\t"\
"pushr15\n\t"\
"pushr16\n\t"\
"pushr17\n\t"\
"pushr18\n\t"\
"pushr19\n\t"\
"pushr20\n\t"\
"pushr21\n\t"\
"pushr22\n\t"\
"pushr23\n\t"\
"pushr24\n\t"\
"pushr25\n\t"\
"pushr26\n\t"\
"pushr27\n\t"\
"pushr28\n\t"\
"pushr29\n\t"\
"pushr30\n\t"\
"pushr31\n\t"\
"ldsr26, pxCurrentTCB\n\t"\
"ldsr27, pxCurrentTCB + 1\n\t"\
"inr0, 0x3d\n\t"\
"stx+, r0\n\t"\
"inr0, 0x3e\n\t"\
"stx+, r0\n\t"\
);

/*
* Opposite to portSAVE_CONTEXT(). Interrupts will have been disabled during
* the context save so we can write to the stack pointer.
*/

#define portRESTORE_CONTEXT()\
asm volatile ("ldsr26, pxCurrentTCB\n\t"\
"ldsr27, pxCurrentTCB + 1\n\t"\
"ldr28, x+\n\t"\
"out__SP_L__, r28\n\t"\
"ldr29, x+\n\t"\
"out__SP_H__, r29\n\t"\
"popr31\n\t"\
"popr30\n\t"\
"popr29\n\t"\
"popr28\n\t"\
"popr27\n\t"\
"popr26\n\t"\
"popr25\n\t"\
"popr24\n\t"\
"popr23\n\t"\
"popr22\n\t"\
"popr21\n\t"\
"popr20\n\t"\
"popr19\n\t"\
"popr18\n\t"\
"popr17\n\t"\
"popr16\n\t"\
"popr15\n\t"\
"popr14\n\t"\
"popr13\n\t"\
"popr12\n\t"\
"popr11\n\t"\
"popr10\n\t"\
"popr9\n\t"\
"popr8\n\t"\
"popr7\n\t"\
"popr6\n\t"\
"popr5\n\t"\
"popr4\n\t"\
"popr3\n\t"\
"popr2\n\t"\
"popr1\n\t"\
"popr0\n\t"\
"out__SREG__, r0\n\t"\
"popr0\n\t"\
);

/*-----------------------------------------------------------*/

/*
* Perform hardware setup to enable ticks from timer 1, compare match A.
*/
static void prvSetupTimerInterrupt( void );
/*-----------------------------------------------------------*/

/*
* See header file for description.
*/
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
{
unsigned portSHORT usAddress;

/* Place a few bytes of known values on the bottom of the stack.
This is just useful for debugging. */

*pxTopOfStack = 0x11;
pxTopOfStack--;
*pxTopOfStack = 0x22;
pxTopOfStack--;
*pxTopOfStack = 0x33;
pxTopOfStack--;

/* Simulate how the stack would look after a call to vPortYield() generated by
the compiler. */

/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */

/* The start of the task code will be popped off the stack last, so place
it on first. */
usAddress = ( unsigned portSHORT ) pxCode;
*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned portSHORT ) 0x00ff );
pxTopOfStack--;

usAddress >>= 8;
*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned portSHORT ) 0x00ff );
pxTopOfStack--;

/* Next simulate the stack as if after a call to portSAVE_CONTEXT().
portSAVE_CONTEXT places the flags on the stack immediately after r0
to ensure the interrupts get disabled as soon as possible, and so ensuring
the stack use is minimal should a context switch interrupt occur. */
*pxTopOfStack = ( portSTACK_TYPE ) 0x00;/* R0 */
pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED;
pxTopOfStack--;


/* Now the remaining registers. The compiler expects R1 to be 0. */
*pxTopOfStack = ( portSTACK_TYPE ) 0x00;/* R1 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x02;/* R2 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x03;/* R3 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x04;/* R4 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x05;/* R5 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x06;/* R6 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x07;/* R7 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x08;/* R8 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x09;/* R9 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x10;/* R10 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x11;/* R11 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x12;/* R12 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x13;/* R13 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x14;/* R14 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x15;/* R15 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x16;/* R16 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x17;/* R17 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x18;/* R18 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x19;/* R19 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x20;/* R20 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x21;/* R21 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x22;/* R22 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x23;/* R23 */
pxTopOfStack--;

/* Place the parameter on the stack in the expected location. */
usAddress = ( unsigned portSHORT ) pvParameters;
*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned portSHORT ) 0x00ff );
pxTopOfStack--;

usAddress >>= 8;
*pxTopOfStack = ( portSTACK_TYPE ) ( usAddress & ( unsigned portSHORT ) 0x00ff );
pxTopOfStack--;

*pxTopOfStack = ( portSTACK_TYPE ) 0x26;/* R26 X */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x27;/* R27 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x28;/* R28 Y */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x29;/* R29 */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x30;/* R30 Z */
pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) 0x031;/* R31 */
pxTopOfStack--;

/*lint +e950 +e611 +e923 */

return pxTopOfStack;
}
/*-----------------------------------------------------------*/

portBASE_TYPE xPortStartScheduler( void )
{
/* In this port we ignore the parameter and use the configUSE_PREEMPTION
definition instead. */

/* Setup the hardware to generate the tick. */
prvSetupTimerInterrupt();

/* Restore the context of the first task that is going to run. */
portRESTORE_CONTEXT();

/* Simulate a function call end as generated by the compiler. We will now
jump to the start of the task the context of which we have just restored. */
asm volatile ( "ret" );

/* Should not get here. */
return pdTRUE;
}
/*-----------------------------------------------------------*/

void vPortEndScheduler( void )
{
/* It is unlikely that the AVR port will get stopped. If required simply
disable the tick interrupt here. */
}
/*-----------------------------------------------------------*/

/*
* Manual context switch. The first thing we do is save the registers so we
* can use a naked attribute.
*/
void vPortYield( void ) __attribute__ ( ( naked ) );
void vPortYield( void )
{
portSAVE_CONTEXT();
vTaskSwitchContext();
portRESTORE_CONTEXT();

asm volatile ( "ret" );
}
/*-----------------------------------------------------------*/

/*
* Context switch function used by the tick. This must be identical to
* vPortYield() from the call to vTaskSwitchContext() onwards. The only
* difference from vPortYield() is the tick count is incremented as the
* call comes from the tick ISR.
*/
void vPortYieldFromTick( void ) __attribute__ ( ( naked ) );
void vPortYieldFromTick( void )
{
portSAVE_CONTEXT();
vTaskIncrementTick();
vTaskSwitchContext();
portRESTORE_CONTEXT();

asm volatile ( "ret" );
}
/*-----------------------------------------------------------*/

/*
* Setup timer 1 compare match A to generate a tick interrupt.
*/
static void prvSetupTimerInterrupt( void )
{
unsigned portLONG ulCompareMatch;
unsigned portCHAR ucHighByte, ucLowByte;

/* Using 16bit timer 1 to generate the tick. Correct fuses must be
selected for the configCPU_CLOCK_HZ clock. */

ulCompareMatch = configCPU_CLOCK_HZ / portCLOCK_PRESCALER;

/* calculates the RTOS tick rate based on the timer's tick rate. */
ulCompareMatch /= configTICK_RATE_HZ;

/* Adjust for correct value. */
ulCompareMatch -= ( unsigned portLONG ) 1;
//ulCompareMatch = (unsigned portLONG) 8639;
/* Setup compare match value for compare match A. Interrupts are disabled
before this is called so we need not worry here. */
ucLowByte = ( unsigned portCHAR ) ( ulCompareMatch & ( unsigned portLONG ) 0xff );
ulCompareMatch >>= 8;
ucHighByte = ( unsigned portCHAR ) ( ulCompareMatch & ( unsigned portLONG ) 0xff );
OCR1AH = ucHighByte;
OCR1AL = ucLowByte;

/* Setup clock source and compare match behaviour. */
ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
TCCR1B = ucLowByte;

/* Enable the interrupt - this is okay as interrupt are currently globally
disabled. */
ucLowByte = TIMSK1;
ucLowByte |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
TIMSK1 = ucLowByte;
}
/*-----------------------------------------------------------*/

#if configUSE_PREEMPTION == 1

/*
* Tick ISR for preemptive scheduler. We can use a naked attribute as
* the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved.
*/
void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal, naked ) );
void SIG_OUTPUT_COMPARE1A( void )
{
vPortYieldFromTick();
asm volatile ( "reti" );
}
#else

/*
* Tick ISR for the cooperative scheduler. All this does is increment the
* tick count. We don't need to switch context, this can only be done by
* manual calls to taskYIELD();
*/
void SIG_OUTPUT_COMPARE1A( void ) __attribute__ ( ( signal ) );
void SIG_OUTPUT_COMPARE1A( void )
{
vTaskIncrementTick();
}
#endif


and here's my portmacro.h
/*
FreeRTOS.org V5.0.2 - Copyright (C) 2003-2008 Richard Barry.

This file is part of the FreeRTOS.org distribution.

FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

FreeRTOS.org is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with FreeRTOS.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.

***************************************************************************
***************************************************************************
* *
* SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, *
* and even write all or part of your application on your behalf. *
* See http://www.OpenRTOS.com for details of the services we provide to *
* expedite your project. *
* *
***************************************************************************
***************************************************************************

Please ensure to read the configuration and relevant port sections of the
online documentation.

http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.

http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.

http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/

/*
Changes from V1.2.3

+ portCPU_CLOSK_HZ definition changed to 8MHz base 10, previously it
base 16.
*/

#ifndef PORTMACRO_H
#define PORTMACRO_H

#ifdef __cplusplus
extern "C" {
#endif

/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the
* given hardware and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/

/* Type definitions. */
#define portCHARchar
#define portFLOATfloat
#define portDOUBLEdouble
#define portLONGlong
#define portSHORTint
#define portSTACK_TYPEunsigned portCHAR
#define portBASE_TYPEchar

#if( configUSE_16_BIT_TICKS == 1 )
typedef unsigned portSHORT portTickType;
#define portMAX_DELAY ( portTickType ) 0xffff
#else
typedef unsigned portLONG portTickType;
#define portMAX_DELAY ( portTickType ) 0xffffffff
#endif
/*-----------------------------------------------------------*/

/* Critical section management. */
#define portENTER_CRITICAL()asm volatile ( "in__tmp_reg__, __SREG__" :: );\
asm volatile ( "cli" :: );\
asm volatile ( "push__tmp_reg__" :: )

#define portEXIT_CRITICAL()asm volatile ( "pop__tmp_reg__" :: );\
asm volatile ( "out__SREG__, __tmp_reg__" :: )

#define portDISABLE_INTERRUPTS()asm volatile ( "cli" :: );
#define portENABLE_INTERRUPTS()asm volatile ( "sei" :: );
/*-----------------------------------------------------------*/

/* Architecture specifics. */
#define portSTACK_GROWTH( -1 )
#define portTICK_RATE_MS( ( portTickType ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT1
#define portNOP()asm volatile ( "nop" );
/*-----------------------------------------------------------*/

/* Kernel utilities. */
extern void vPortYield( void ) __attribute__ ( ( naked ) );
#define portYIELD()vPortYield()
/*-----------------------------------------------------------*/

/* Task function macros as described on the FreeRTOS.org WEB site. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )

#ifdef __cplusplus
}
#endif

#endif /* PORTMACRO_H */


I think that's all that needs modifying to get things up and running...

RE: ATMega640 port crashing at context switch

Posted by Geza Balazs on January 10, 2011
Hi,

Regarding the XMEGA, I think there have to be lots of modifications to the port files since (at least larger) XMEGAs use 24 bit addressing for the PC (and indirect calls/jumps and pointers - X, Y and Z) and have a different interrupt handling scheme. I am currently working on a project with ATXMEGA128A1, and I have a modified AVR port for FreeRTOS 6.1.0. Feel free to contact me if you need it.

However, I think the original part you intend to port FreeRTOS to (ATMEGA640) is not an XMEGA architecture.

Regards,
Geza

RE: ATMega640 port crashing at context switch

Posted by thesa1nt01 on January 11, 2011
Thanks all for your replies.
It turns out that my code was correct. I had ported it correctly according to the forums and the porting guide.
The problem was that I had set my stack depth for my tasks to only 10 bytes. This meant that when pxPortInitialiseStack was called the TCB for each task was over written after it was instantiated.
I set each to 100 bytes and all is well.

Thanks again.
Regards,

PS - Should I post a port somehow?

RE: ATMega640 port crashing at context switch

Posted by Dave on January 11, 2011
Thats good. If you have some working code then its always good to post it on the interactive site. Here is a good place http://interactive.freertos.org/forums/103473-atmel

RE: ATMega640 port crashing at context switch

Posted by apollionis on January 11, 2011
Hi Gezab,

I would be very interesting to work with / to test your FreeRtos port for Xmega!

Regards,
apollionis

RE: ATMega640 port crashing at context switch

Posted by Geza Balazs on January 11, 2011
Hi apollionis,

Thanks for your interest, I have already uploaded it to http://www.freertos.org/index.html?http://interactive.freertos.org/forums/103473-atmel.

Some changes compared to the original AVR port:
- Interrupts are always enabled globally (I flag is always set), only low-level interrupts are disabled during context switch and in critical sections in the interrupt controller.
- Software stack is extended with interrupt control register, RAMPX, RAMPZ, EIND and RAMPD. RAMPY is not saved since it is used for addressing the software stack (the TCB could be extended with RAMPY as well because the software stack address is saved in the TCB, however, since no 64k boundary check is done in the macros, it is easier to make the linker allocate the heap in the lowest 64k of the RAM and set RAMPY to 0).
- High- and mid-level interrupts can be used for rapid system response to events (like in my system, too), however, they must not interfere with the OS since the OS is not aware of them (they can appear at any time if they do proper register and context saving and restoring). When restoring the hardware stack pointer from the software stack, interrupts need to be disabled globally because mid- and high-level interrupts are not disabled during context switch.
- Interrupt routines that want to use the OS need to be low-level.
- Interrupt routines that use portSAVE_CONTEXT and portRESTORE_CONTEXT as a wrapper must return with reti directly after portRESTORE_CONTEXT. The reti instruction does not alter the I flag on Xmega but checks the interrupt status register to find out which level the interrupt is executing on. Not returning with reti is likely to cause the system to hang because low-level interrupts are no longer allowed to run.

That is all I can remember for now, please contact me if any more information is needed.

Regards,
Geza

RE: ATMega640 port crashing at context switch

Posted by Yuriy Kulikov on January 17, 2011
Hi everybody!

I am also using FreeRTOS for xmega and (formerly Atmega). As a hint I might suggest to add this code to main.c to prevent crashing


BTW, xmega128 has 16-bit program counter, hasn't it? xmega192 has 24-bit, though.
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName );
/* This function is called immediately after task context is saved into stack. This is the case
* when stack contains biggest amount of data. Hook function checks if there is a stack overflow
* for the current (switched) task.
* configCHECK_FOR_STACK_OVERFLOW should be defined as 1 to use StackOverflowHook.
*/

void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )
{
/* stop execution and report error */
while(true) LED_set(RED);
}”

and you will have to define
“#define configCHECK_FOR_STACK_OVERFLOW 1”

in FreeRTOSConfig.h

If I see red led, than I have to increase stack depth for a certain task.

RE: ATMega640 port crashing at context switch

Posted by Geza Balazs on January 17, 2011
ATxmega128A1 definitely has 1 24 bit PC. Return addresses on the HW stack are 3 bytes long.

Geza


[ 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