ATMega640 port crashing at context switch

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_PREEMPTION        0
#define configUSE_IDLE_HOOK         0
#define configUSE_TICK_HOOK         0
#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_FACILITY    0
#define configUSE_16_BIT_TICKS      1
#define configIDLE_SHOULD_YIELD     1
#define configQUEUE_REGISTRY_SIZE   0
/* 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_vTaskPrioritySet        0
#define INCLUDE_uxTaskPriorityGet       0
#define INCLUDE_vTaskDelete             1
#define INCLUDE_vTaskCleanUpResources   0
#define INCLUDE_vTaskSuspend            0
#define INCLUDE_vTaskDelayUntil         1
#define INCLUDE_vTaskDelay              1
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 <FreeRTOS.h>
#include <task.h>
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.

ATMega640 port crashing at context switch

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.

ATMega640 port crashing at context switch

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 <stdlib.h>
#include <avr/interrupt.h>
#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 (  "push   r0                      nt"   
                    "in     r0, __SREG__            nt"   
                    "cli                            nt"   
                    "push   r0                      nt"   
                    "push   r1                      nt"   
                    "clr    r1                      nt"   
                    "push   r2                      nt"   
                    "push   r3                      nt"   
                    "push   r4                      nt"   
                    "push   r5                      nt"   
                    "push   r6                      nt"   
                    "push   r7                      nt"   
                    "push   r8                      nt"   
                    "push   r9                      nt"   
                    "push   r10                     nt"   
                    "push   r11                     nt"   
                    "push   r12                     nt"   
                    "push   r13                     nt"   
                    "push   r14                     nt"   
                    "push   r15                     nt"   
                    "push   r16                     nt"   
                    "push   r17                     nt"   
                    "push   r18                     nt"   
                    "push   r19                     nt"   
                    "push   r20                     nt"   
                    "push   r21                     nt"   
                    "push   r22                     nt"   
                    "push   r23                     nt"   
                    "push   r24                     nt"   
                    "push   r25                     nt"   
                    "push   r26                     nt"   
                    "push   r27                     nt"   
                    "push   r28                     nt"   
                    "push   r29                     nt"   
                    "push   r30                     nt"   
                    "push   r31                     nt"   
                    "lds    r26, pxCurrentTCB       nt"   
                    "lds    r27, pxCurrentTCB + 1   nt"   
                    "in     r0, 0x3d                nt"   
                    "st     x+, r0                  nt"   
                    "in     r0, 0x3e                nt"   
                    "st     x+, r0                  nt"   
                );
/* 
 * 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 (  "lds    r26, pxCurrentTCB       nt"   
                    "lds    r27, pxCurrentTCB + 1   nt"   
                    "ld     r28, x+                 nt"   
                    "out    __SP_L__, r28           nt"   
                    "ld     r29, x+                 nt"   
                    "out    __SP_H__, r29           nt"   
                    "pop    r31                     nt"   
                    "pop    r30                     nt"   
                    "pop    r29                     nt"   
                    "pop    r28                     nt"   
                    "pop    r27                     nt"   
                    "pop    r26                     nt"   
                    "pop    r25                     nt"   
                    "pop    r24                     nt"   
                    "pop    r23                     nt"   
                    "pop    r22                     nt"   
                    "pop    r21                     nt"   
                    "pop    r20                     nt"   
                    "pop    r19                     nt"   
                    "pop    r18                     nt"   
                    "pop    r17                     nt"   
                    "pop    r16                     nt"   
                    "pop    r15                     nt"   
                    "pop    r14                     nt"   
                    "pop    r13                     nt"   
                    "pop    r12                     nt"   
                    "pop    r11                     nt"   
                    "pop    r10                     nt"   
                    "pop    r9                      nt"   
                    "pop    r8                      nt"   
                    "pop    r7                      nt"   
                    "pop    r6                      nt"   
                    "pop    r5                      nt"   
                    "pop    r4                      nt"   
                    "pop    r3                      nt"   
                    "pop    r2                      nt"   
                    "pop    r1                      nt"   
                    "pop    r0                      nt"   
                    "out    __SREG__, r0            nt"   
                    "pop    r0                      nt"   
                );
/*-----------------------------------------------------------*/
/*
 * 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 portCHAR        char
#define portFLOAT       float
#define portDOUBLE      double
#define portLONG        long
#define portSHORT       int
#define portSTACK_TYPE  unsigned portCHAR
#define portBASE_TYPE   char
#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_ALIGNMENT          1
#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…

ATMega640 port crashing at context switch

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

ATMega640 port crashing at context switch

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?

ATMega640 port crashing at context switch

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

ATMega640 port crashing at context switch

Hi Gezab, I would be very interesting to work with / to test your FreeRtos port for Xmega! Regards,
apollionis

ATMega640 port crashing at context switch

Hi apollionis, Thanks for your interest, I have already uploaded it to /fr-content-src/uploads/2019/07/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

ATMega640 port crashing at context switch

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.

ATMega640 port crashing at context switch

ATxmega128A1 definitely has 1 24 bit PC. Return addresses on the HW stack are 3 bytes long. Geza