mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-12 00:57:44 -04:00
ATmegaxxxx - clarify initial stack setup
This commit is contained in:
parent
10fcd90af1
commit
62682ebe5b
1 changed files with 23 additions and 30 deletions
|
@ -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.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue