ATmegaxxxx - clarify initial stack setup

This commit is contained in:
Phillip Stevens 2020-04-11 18:37:00 +10:00
parent 10fcd90af1
commit 62682ebe5b

View file

@ -1,6 +1,6 @@
/* /*
* FreeRTOS Kernel V10.3.1 * FreeRTOS Kernel V10.3.1
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of * Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in * this software and associated documentation files (the "Software"), to deal in
@ -206,7 +206,7 @@ void wdt_interrupt_reset_enable (const uint8_t value)
* Macro to save all the general purpose registers, the save the stack pointer * Macro to save all the general purpose registers, the save the stack pointer
* into the TCB. * into the TCB.
* *
* The first thing we do is save the flags then disable interrupts. This is to * 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 * 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 * pushed the registers onto the stack - causing the 32 registers to be on the
* stack twice. * stack twice.
@ -221,7 +221,7 @@ void wdt_interrupt_reset_enable (const uint8_t value)
* #endif * #endif
* *
* #if defined(__AVR_3_BYTE_PC__) * #if defined(__AVR_3_BYTE_PC__)
* #define __EIND__ 0x3C * #define __EIND__ 0x3C
* #endif * #endif
* *
* The interrupts will have been disabled during the call to portSAVE_CONTEXT() * The interrupts will have been disabled during the call to portSAVE_CONTEXT()
@ -542,35 +542,28 @@ uint16_t usAddress;
/* The start of the task code will be popped off the stack last, so place /* The start of the task code will be popped off the stack last, so place
it on first. */ it on first. */
usAddress = ( uint16_t ) pxCode;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
#if defined(__AVR_3_BYTE_PC__) #if defined(__AVR_3_BYTE_PC__)
/* The AVR ATmega2560/ATmega2561 have 256KBytes of program memory and a 17-bit /* The AVR ATmega2560/ATmega2561 have 256KBytes of program memory and a 17-bit
* program counter. When a code address is stored on the stack, it takes 3 bytes * program counter. When a code address is stored on the stack, it takes 3 bytes
* instead of 2 for the other ATmega* chips. * instead of 2 for the other ATmega* chips.
* *
* Store 0 as the top byte since we force all task routines to the bottom 128K * Store 0 as the top byte since we force all task routines to the bottom 128K
* of flash. We do this by using the .lowtext label in the linker script. * of flash. We do this by using the .lowtext label in the linker script.
* *
* In order to do this properly, we would need to get a full 3-byte pointer to * In order to do this properly, we would need to get a full 3-byte pointer to
* pxCode. That requires a change to GCC. Not likely to happen any time soon. * pxCode. That requires a change to GCC. Not likely to happen any time soon.
*/ */
usAddress = ( uint16_t ) pxCode;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
*pxTopOfStack = 0; *pxTopOfStack = 0;
pxTopOfStack--; pxTopOfStack--;
#else
usAddress = ( uint16_t ) pxCode;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
#endif #endif
/* Next simulate the stack as if after a call to portSAVE_CONTEXT(). /* Next simulate the stack as if after a call to portSAVE_CONTEXT().
@ -598,7 +591,7 @@ uint16_t usAddress;
pxTopOfStack--; pxTopOfStack--;
#endif #endif
/* Now the remaining registers. The compiler expects R1 to be 0. */ /* Now the remaining registers. The compiler expects R1 to be 0. */
*pxTopOfStack = ( StackType_t ) 0x00; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x00; /* R1 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02; /* R2 */
@ -680,7 +673,7 @@ BaseType_t xPortStartScheduler( void )
/* Restore the context of the first task that is going to run. */ /* Restore the context of the first task that is going to run. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
/* Simulate a function call end as generated by the compiler. We will now /* 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. */ jump to the start of the task the context of which we have just restored. */
__asm__ __volatile__ ( "ret" ); __asm__ __volatile__ ( "ret" );
@ -705,7 +698,7 @@ void vPortEndScheduler( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* Manual context switch. The first thing we do is save the registers so we * Manual context switch. The first thing we do is save the registers so we
* can use a naked attribute. * can use a naked attribute.
*/ */
void vPortYield( void ) __attribute__ ( ( hot, flatten, naked ) ); void vPortYield( void ) __attribute__ ( ( hot, flatten, naked ) );
@ -720,8 +713,8 @@ void vPortYield( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* Context switch function used by the tick. This must be identical to * Context switch function used by the tick. This must be identical to
* vPortYield() from the call to vTaskSwitchContext() onwards. The only * vPortYield() from the call to vTaskSwitchContext() onwards. The only
* difference from vPortYield() is the tick count is incremented as the * difference from vPortYield() is the tick count is incremented as the
* call comes from the tick ISR. * call comes from the tick ISR.
*/ */
@ -774,7 +767,7 @@ uint8_t ucLowByte;
/* Adjust for correct value. */ /* Adjust for correct value. */
ulCompareMatch -= ( uint32_t ) 1; ulCompareMatch -= ( uint32_t ) 1;
/* Setup compare match value for compare match A. Interrupts are disabled /* Setup compare match value for compare match A. Interrupts are disabled
before this is called so we need not worry here. */ before this is called so we need not worry here. */
ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff ); ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
portOCRL = ucLowByte; portOCRL = ucLowByte;
@ -798,8 +791,8 @@ uint8_t ucLowByte;
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
/* /*
* Tick ISR for preemptive scheduler. We can use a naked attribute as * Tick ISR for preemptive scheduler. We can use a naked attribute as
* the context is saved at the start of vPortYieldFromTick(). The tick * the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved. * count is incremented after the context is saved.
* *
* use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler. * use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler.
@ -816,8 +809,8 @@ uint8_t ucLowByte;
#else #else
/* /*
* Tick ISR for the cooperative scheduler. All this does is increment the * 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 * tick count. We don't need to switch context, this can only be done by
* manual calls to taskYIELD(); * manual calls to taskYIELD();
* *
* use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler. * use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler.