|
NOTE:This is a read only archive of threads posted to the FreeRTOS support forum. Use these archive pages to search previous posts. New forum support threads can be started at the FreeRTOS forums.
FreeRTOS Support Archive
The FreeRTOS support forum can be used for active support both from Amazon Web Services and the community. In return for using our software for free, we request you play fair and do your bit to help others! Sign up for an account and receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum. Use these archive pages to search previous posts. New forum support threads can be started at the FreeRTOS forums.
[FreeRTOS Home]
[Live FreeRTOS Forum]
[FAQ]
[Archive Top]
[January 2011 Threads]
ATMega640 port crashing at context switchPosted 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_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 switchPosted by richardbarry 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.
ATMega640 port crashing at context switchPosted by jmr1972 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 <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 switchPosted by gezab 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
ATMega640 port crashing at context switchPosted 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?
ATMega640 port crashing at context switchPosted by davedoors 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
ATMega640 port crashing at context switchPosted 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
ATMega640 port crashing at context switchPosted by gezab on January 11, 2011 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 switchPosted by urka46 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.
ATMega640 port crashing at context switchPosted by gezab on January 17, 2011 ATxmega128A1 definitely has 1 24 bit PC. Return addresses on the HW stack are 3 bytes long.
Geza
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|
|