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
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
* pushed the registers onto the stack - causing the 32 registers to be on the
|
||||
* stack twice.
|
||||
|
@ -221,7 +221,7 @@ void wdt_interrupt_reset_enable (const uint8_t value)
|
|||
* #endif
|
||||
*
|
||||
* #if defined(__AVR_3_BYTE_PC__)
|
||||
* #define __EIND__ 0x3C
|
||||
* #define __EIND__ 0x3C
|
||||
* #endif
|
||||
*
|
||||
* 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
|
||||
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__)
|
||||
/* 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.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* 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--;
|
||||
#else
|
||||
usAddress = ( uint16_t ) pxCode;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
usAddress >>= 8;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
#endif
|
||||
|
||||
/* Next simulate the stack as if after a call to portSAVE_CONTEXT().
|
||||
|
@ -598,7 +591,7 @@ uint16_t usAddress;
|
|||
pxTopOfStack--;
|
||||
#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--;
|
||||
*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. */
|
||||
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. */
|
||||
__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.
|
||||
*/
|
||||
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
|
||||
* vPortYield() from the call to vTaskSwitchContext() onwards. The only
|
||||
* 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.
|
||||
*/
|
||||
|
@ -774,7 +767,7 @@ uint8_t ucLowByte;
|
|||
/* Adjust for correct value. */
|
||||
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. */
|
||||
ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
|
||||
portOCRL = ucLowByte;
|
||||
|
@ -798,8 +791,8 @@ uint8_t 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
|
||||
* 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.
|
||||
*
|
||||
* use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler.
|
||||
|
@ -816,8 +809,8 @@ uint8_t ucLowByte;
|
|||
#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
|
||||
* 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();
|
||||
*
|
||||
* 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