Style: Revert more uncrustified files

This commit is contained in:
Alfred Gedeon 2020-08-11 21:56:04 -07:00
parent 88e692ff55
commit 134063a82f
65 changed files with 29977 additions and 29667 deletions

View file

@ -1,111 +1,82 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"
; ; Variables used by scheduler
Variables used by scheduler ;------------------------------------------------------------------------------
;
------------------------------------------------------------------------------
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN usCriticalNesting EXTERN usCriticalNesting
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------ ; portSAVE_CONTEXT MACRO
; ; Saves the context of the general purpose registers, CS and ES (only in far
portSAVE_CONTEXT MACRO ; memory mode) registers the usCriticalNesting Value and the Stack Pointer
; ; of the active Task onto the task stack
Saves the context of the general purpose registers, CS and ES( only in far ;------------------------------------------------------------------------------
;
memory mode ) registers the usCriticalNesting Value and the Stack Pointer
;
of the active Task onto the task stack
;
------------------------------------------------------------------------------
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
PUSH AX; PUSH AX ; Save AX Register to stack.
Save AX Register to stack.
PUSH HL PUSH HL
MOV A, CS; MOV A, CS ; Save CS register.
Save CS register.
XCH A, X XCH A, X
MOV A, ES; MOV A, ES ; Save ES register.
Save ES register.
PUSH AX PUSH AX
PUSH DE; PUSH DE ; Save the remaining general purpose registers.
Save the remaining general purpose registers.
PUSH BC PUSH BC
MOVW AX, usCriticalNesting; MOVW AX, usCriticalNesting ; Save the usCriticalNesting value.
Save the usCriticalNesting value.
PUSH AX PUSH AX
MOVW AX, pxCurrentTCB; MOVW AX, pxCurrentTCB ; Save the Stack pointer.
Save the Stack pointer.
MOVW HL, AX MOVW HL, AX
MOVW AX, SP MOVW AX, SP
MOVW [HL], AX MOVW [HL], AX
ENDM ENDM
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------ ; portRESTORE_CONTEXT MACRO
; ; Restores the task Stack Pointer then use this to restore usCriticalNesting,
; general purpose registers and the CS and ES (only in far memory mode)
; of the selected task from the task stack
;------------------------------------------------------------------------------
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; MOVW AX, pxCurrentTCB ; Restore the Stack pointer.
Restores the task Stack Pointer then use this to restore usCriticalNesting,
;
general purpose registers and the CS and ES( only in far memory mode )
;
of the selected task from the task stack
;
------------------------------------------------------------------------------
portRESTORE_CONTEXT MACRO
MOVW AX, pxCurrentTCB;
Restore the Stack pointer.
MOVW HL, AX MOVW HL, AX
MOVW AX, [HL] MOVW AX, [HL]
MOVW SP, AX MOVW SP, AX
POP AX; POP AX ; Restore usCriticalNesting value.
Restore usCriticalNesting value.
MOVW usCriticalNesting, AX MOVW usCriticalNesting, AX
POP BC; POP BC ; Restore the necessary general purpose registers.
Restore the necessary general purpose registers.
POP DE POP DE
POP AX; POP AX ; Restore the ES register.
Restore the ES register.
MOV ES, A MOV ES, A
XCH A, X; XCH A, X ; Restore the CS register.
Restore the CS register.
MOV CS, A MOV CS, A
POP HL; POP HL ; Restore general purpose register HL.
Restore general purpose register HL. POP AX ; Restore AX.
POP AX;
Restore AX.
ENDM ENDM
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------

View file

@ -33,7 +33,7 @@
#include "task.h" #include "task.h"
/* The critical nesting value is initialised to a non zero value to ensure /* The critical nesting value is initialised to a non zero value to ensure
* interrupts don't accidentally become enabled before the scheduler is started. */ interrupts don't accidentally become enabled before the scheduler is started. */
#define portINITIAL_CRITICAL_NESTING (( uint16_t ) 10) #define portINITIAL_CRITICAL_NESTING (( uint16_t ) 10)
/* Initial PSW value allocated to a newly created task. /* Initial PSW value allocated to a newly created task.
@ -50,22 +50,22 @@
#define portPSW (0xc6UL) #define portPSW (0xc6UL)
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
* any details of its type. */ any details of its type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
/* Most ports implement critical sections by placing the interrupt flags on /* Most ports implement critical sections by placing the interrupt flags on
* the stack before disabling interrupts. Exiting the critical section is then the stack before disabling interrupts. Exiting the critical section is then
* simply a case of popping the flags from the stack. As 78K0 IAR does not use simply a case of popping the flags from the stack. As 78K0 IAR does not use
* a frame pointer this cannot be done as modifying the stack will clobber all a frame pointer this cannot be done as modifying the stack will clobber all
* the stack variables. Instead each task maintains a count of the critical the stack variables. Instead each task maintains a count of the critical
* section nesting depth. Each time a critical section is entered the count is section nesting depth. Each time a critical section is entered the count is
* incremented. Each time a critical section is left the count is decremented - incremented. Each time a critical section is left the count is decremented -
* with interrupts only being re-enabled if the count is zero. with interrupts only being re-enabled if the count is zero.
*
* usCriticalNesting will get set to zero when the scheduler starts, but must usCriticalNesting will get set to zero when the scheduler starts, but must
* not be initialised to zero as this will cause problems during the startup not be initialised to zero as this will cause problems during the startup
* sequence. */ sequence. */
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING; volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -81,16 +81,14 @@ static void prvSetupTimerInterrupt( void );
* *
* See the header file portable.h. * See the header file portable.h.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
uint32_t *pulLocal; uint32_t *pulLocal;
#if configMEMORY_MODE == 1 #if configMEMORY_MODE == 1
{ {
/* Parameters are passed in on the stack, and written using a 32bit value /* Parameters are passed in on the stack, and written using a 32bit value
* hence a space is left for the second two bytes. */ hence a space is left for the second two bytes. */
pxTopOfStack--; pxTopOfStack--;
/* Write in the parameter value. */ /* Write in the parameter value. */
@ -99,14 +97,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* These values are just spacers. The return address of the function /* These values are just spacers. The return address of the function
* would normally be written here. */ would normally be written here. */
*pxTopOfStack = ( StackType_t ) 0xcdcd; *pxTopOfStack = ( StackType_t ) 0xcdcd;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xcdcd; *pxTopOfStack = ( StackType_t ) 0xcdcd;
pxTopOfStack--; pxTopOfStack--;
/* The start address / PSW value is also written in as a 32bit value, /* The start address / PSW value is also written in as a 32bit value,
* so leave a space for the second two bytes. */ so leave a space for the second two bytes. */
pxTopOfStack--; pxTopOfStack--;
/* Task function start address combined with the PSW. */ /* Task function start address combined with the PSW. */
@ -118,11 +116,11 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) 0x1111; *pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--; pxTopOfStack--;
} }
#else /* if configMEMORY_MODE == 1 */ #else
{ {
/* Task function address is written to the stack first. As it is /* Task function address is written to the stack first. As it is
* written as a 32bit value a space is left on the stack for the second written as a 32bit value a space is left on the stack for the second
* two bytes. */ two bytes. */
pxTopOfStack--; pxTopOfStack--;
/* Task function start address combined with the PSW. */ /* Task function start address combined with the PSW. */
@ -134,7 +132,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
} }
#endif /* if configMEMORY_MODE == 1 */ #endif
/* An initial value for the HL register. */ /* An initial value for the HL register. */
*pxTopOfStack = ( StackType_t ) 0x2222; *pxTopOfStack = ( StackType_t ) 0x2222;
@ -151,11 +149,11 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Finally the critical section nesting count is set to zero when the task /* Finally the critical section nesting count is set to zero when the task
* first starts. */ first starts. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack we have generated so this can /* Return a pointer to the top of the stack we have generated so this can
* be stored in the task control block for the task. */ be stored in the task control block for the task. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -163,7 +161,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Setup the hardware to generate the tick. Interrupts are disabled when /* Setup the hardware to generate the tick. Interrupts are disabled when
* this function is called. */ this function is called. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Restore the context of the first task that is going to run. */ /* Restore the context of the first task that is going to run. */
@ -177,7 +175,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the 78K0R port will get stopped. If required simply /* It is unlikely that the 78K0R port will get stopped. If required simply
* disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -192,7 +190,7 @@ static void prvSetupTimerInterrupt( void )
TT0 = 0xff; TT0 = 0xff;
/* Interrupt of Timer Array Unit Channel 5 is disabled to set the interrupt /* Interrupt of Timer Array Unit Channel 5 is disabled to set the interrupt
* priority. */ priority. */
TMMK05 = 1; TMMK05 = 1;
/* Clear Timer Array Unit Channel 5 interrupt flag. */ /* Clear Timer Array Unit Channel 5 interrupt flag. */
@ -224,3 +222,4 @@ static void prvSetupTimerInterrupt( void )
TS0 |= 0x0020; TS0 |= 0x0020;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -142,3 +142,4 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -48,14 +48,14 @@
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
* this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
* floating point context after they have been created. A variable is stored as floating point context after they have been created. A variable is stored as
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
* does not have an FPU context, or any other value if the task does have an FPU does not have an FPU context, or any other value if the task does have an FPU
* context. */ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
@ -67,7 +67,7 @@
#define portAPSR_MODE_BITS_MASK ( 0x1F ) #define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user /* The value of the mode bits in the APSR when the CPU is executing in user
* mode. */ mode. */
#define portAPSR_USER_MODE ( 0x10 ) #define portAPSR_USER_MODE ( 0x10 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -86,21 +86,21 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This /* A variable is used to keep track of the critical section nesting. This
* variable has to be stored as part of the task context and must be initialised to variable has to be stored as part of the task context and must be initialised to
* a non zero value to ensure interrupts don't inadvertently become unmasked before a non zero value to ensure interrupts don't inadvertently become unmasked before
* the scheduler starts. As it is stored as part of the task context it will the scheduler starts. As it is stored as part of the task context it will
* automatically be set to 0 when the first task is started. */ automatically be set to 0 when the first task is started. */
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero /* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero
* then a floating point context must be saved and restored for the task. */ then a floating point context must be saved and restored for the task. */
uint32_t ulPortTaskHasFPUContext = pdFALSE; uint32_t ulPortTaskHasFPUContext = pdFALSE;
/* Set to 1 to pend a context switch from an ISR. */ /* Set to 1 to pend a context switch from an ISR. */
uint32_t ulPortYieldRequired = pdFALSE; uint32_t ulPortYieldRequired = pdFALSE;
/* Counts the interrupt nesting depth. A context switch is only performed if /* Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 0. */ if the nesting depth is 0. */
uint32_t ulPortInterruptNesting = 0UL; uint32_t ulPortInterruptNesting = 0UL;
@ -109,16 +109,14 @@ uint32_t ulPortInterruptNesting = 0UL;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. expected by the portRESTORE_CONTEXT() macro.
*
* The fist real value on the stack is the status register, which is set for The fist real value on the stack is the status register, which is set for
* system mode, with interrupts enabled. A few NULLs are added first to ensure system mode, with interrupts enabled. A few NULLs are added first to ensure
* GDB does not try decoding a non-existent return address. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack = NULL; *pxTopOfStack = NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = NULL; *pxTopOfStack = NULL;
@ -170,13 +168,13 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */ enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start without a floating point context. A task that uses
* the floating point hardware must call vPortTaskUsesFPU() before executing the floating point hardware must call vPortTaskUsesFPU() before executing
* any floating point instructions. */ any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack; return pxTopOfStack;
@ -186,17 +184,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ). should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */ defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL ); configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -205,9 +200,8 @@ BaseType_t xPortStartScheduler( void )
uint32_t ulAPSR; uint32_t ulAPSR;
/* Only continue if the CPU is not in User mode. The CPU must be in a /* Only continue if the CPU is not in User mode. The CPU must be in a
* Privileged mode for the scheduler to start. */ Privileged mode for the scheduler to start. */
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
@ -219,8 +213,8 @@ BaseType_t xPortStartScheduler( void )
} }
/* Will only get here if vTaskStartScheduler() was called with the CPU in /* Will only get here if vTaskStartScheduler() was called with the CPU in
* a non-privileged mode or the binary point register was not set to its lowest a non-privileged mode or the binary point register was not set to its lowest
* possible value. */ possible value. */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -228,7 +222,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */ Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -238,15 +232,15 @@ void vPortEnterCritical( void )
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */ assert function also uses a critical section. */
if( ulCriticalNesting == 1 ) if( ulCriticalNesting == 1 )
{ {
configASSERT( ulPortInterruptNesting == 0 ); configASSERT( ulPortInterruptNesting == 0 );
@ -259,15 +253,15 @@ void vPortExitCritical( void )
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
* exited. */ exited. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */ priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
* should be unmasked. */ should be unmasked. */
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
} }
@ -294,10 +288,13 @@ void vPortTaskUsesFPU( void )
uint32_t ulInitialFPSCR = 0; uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context). */ FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
__asm( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) ); __asm( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -1,29 +1,29 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
@ -33,30 +33,24 @@ EXTERN ulAsmAPIPriorityMask
portSAVE_CONTEXT macro portSAVE_CONTEXT macro
; ; Save the LR and SPSR onto the system mode stack before switching to
Save the LR and SPSR onto the system mode stack before switching to ; system mode to save the remaining system mode registers
;
system mode to save the remaining system mode registers
SRSDB sp!, #SYS_MODE SRSDB sp!, #SYS_MODE
CPS #SYS_MODE CPS #SYS_MODE
PUSH {R0-R12, R14} PUSH {R0-R12, R14}
; ; Push the critical nesting count
Push the critical nesting count
LDR R2, =ulCriticalNesting LDR R2, =ulCriticalNesting
LDR R1, [R2] LDR R1, [R2]
PUSH {R1} PUSH {R1}
; ; Does the task have a floating point context that needs saving? If
Does the task have a floating point context that needs saving ? If ; ulPortTaskHasFPUContext is 0 then no.
;
ulPortTaskHasFPUContext is 0 then no.
LDR R2, =ulPortTaskHasFPUContext LDR R2, =ulPortTaskHasFPUContext
LDR R3, [R2] LDR R3, [R2]
CMP R3, #0 CMP R3, #0
; ; Save the floating point context, if any
Save the floating point context, if any
FMRXNE R1, FPSCR FMRXNE R1, FPSCR
VPUSHNE {D0-D15} VPUSHNE {D0-D15}
#if configFPU_D32 == 1 #if configFPU_D32 == 1
@ -64,12 +58,10 @@ FMRXNE R1, FPSCR
#endif ; configFPU_D32 #endif ; configFPU_D32
PUSHNE {R1} PUSHNE {R1}
; ; Save ulPortTaskHasFPUContext itself
Save ulPortTaskHasFPUContext itself
PUSH {R3} PUSH {R3}
; ; Save the stack pointer in the TCB
Save the stack pointer in the TCB
LDR R0, =pxCurrentTCB LDR R0, =pxCurrentTCB
LDR R1, [R0] LDR R1, [R0]
STR SP, [R1] STR SP, [R1]
@ -80,23 +72,19 @@ endm
portRESTORE_CONTEXT macro portRESTORE_CONTEXT macro
; ; Set the SP to point to the stack of the task being restored.
Set the SP to point to the stack of the task being restored.
LDR R0, =pxCurrentTCB LDR R0, =pxCurrentTCB
LDR R1, [R0] LDR R1, [R0]
LDR SP, [R1] LDR SP, [R1]
; ; Is there a floating point context to restore? If the restored
Is there a floating point context to restore ? If the restored ; ulPortTaskHasFPUContext is zero then no.
;
ulPortTaskHasFPUContext is zero then no.
LDR R0, =ulPortTaskHasFPUContext LDR R0, =ulPortTaskHasFPUContext
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
CMP R1, #0 CMP R1, #0
; ; Restore the floating point context, if any
Restore the floating point context, if any
POPNE {R0} POPNE {R0}
#if configFPU_D32 == 1 #if configFPU_D32 == 1
VPOPNE {D16-D31} VPOPNE {D16-D31}
@ -104,24 +92,22 @@ Restore the floating point context, if any
VPOPNE {D0-D15} VPOPNE {D0-D15}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
; ; Restore the critical section nesting depth
Restore the critical section nesting depth
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
; ; Restore all system mode registers other than the SP (which is already
Restore all system mode registers other than the SP( which is already ; being used)
; POP {R0-R12, R14}
being used )
POP
{
R0 - R12, R14
}
Return to the task code, loading CPSR on the way.CPSR has the interrupt ; Return to the task code, loading CPSR on the way. CPSR has the interrupt
; ; enable bit set appropriately for the task about to execute.
enable bit set appropriately for the task about to execute.
RFEIA sp! RFEIA sp!
endm endm

View file

@ -64,7 +64,7 @@
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -112,17 +112,17 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these not required for this port but included in case common demo code that uses these
* macros is used. */ macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
* handler for whichever peripheral is used to generate the RTOS tick. */ handler for whichever peripheral is used to generate the RTOS tick. */
void FreeRTOS_Tick_Handler( void ); void FreeRTOS_Tick_Handler( void );
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU() /* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
* before any floating point instructions are executed. */ before any floating point instructions are executed. */
void vPortTaskUsesFPU( void ); void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
@ -151,11 +151,12 @@
#endif #endif
/* Suppress warnings that are generated by the IAR tools, but cannot be /* Suppress warnings that are generated by the IAR tools, but cannot be
* fixed in the source code because to do so would cause other compilers to fixed in the source code because to do so would cause other compilers to
* generate warnings. */ generate warnings. */
#pragma diag_suppress=Pe191 #pragma diag_suppress=Pe191
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
#endif /* __ICCARM__ */ #endif /* __ICCARM__ */
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -36,23 +36,23 @@
#include "task.h" #include "task.h"
#ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS #ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS
#error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */ #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET #ifndef configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET
#error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */ #error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configUNIQUE_INTERRUPT_PRIORITIES #ifndef configUNIQUE_INTERRUPT_PRIORITIES
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */ #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */ #error configSETUP_TICK_INTERRUPT() must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY #ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */ #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0 #if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
@ -80,18 +80,18 @@
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
* this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* In all GICs 255 can be written to the priority mask register to unmask all /* In all GICs 255 can be written to the priority mask register to unmask all
* (but the lowest) interrupt priority. */ (but the lowest) interrupt priority. */
#define portUNMASK_VALUE ( 0xFFUL ) #define portUNMASK_VALUE ( 0xFFUL )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
* floating point context after they have been created. A variable is stored as floating point context after they have been created. A variable is stored as
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
* does not have an FPU context, or any other value if the task does have an FPU does not have an FPU context, or any other value if the task does have an FPU
* context. */ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
@ -100,14 +100,14 @@
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
* point is zero. */ point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) #define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x1F ) #define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user /* The value of the mode bits in the APSR when the CPU is executing in user
* mode. */ mode. */
#define portAPSR_USER_MODE ( 0x10 ) #define portAPSR_USER_MODE ( 0x10 )
/* Macro to unmask all interrupt priorities. */ /* Macro to unmask all interrupt priorities. */
@ -136,21 +136,21 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This /* A variable is used to keep track of the critical section nesting. This
* variable has to be stored as part of the task context and must be initialised to variable has to be stored as part of the task context and must be initialised to
* a non zero value to ensure interrupts don't inadvertently become unmasked before a non zero value to ensure interrupts don't inadvertently become unmasked before
* the scheduler starts. As it is stored as part of the task context it will the scheduler starts. As it is stored as part of the task context it will
* automatically be set to 0 when the first task is started. */ automatically be set to 0 when the first task is started. */
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero /* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero
* then a floating point context must be saved and restored for the task. */ then a floating point context must be saved and restored for the task. */
uint32_t ulPortTaskHasFPUContext = pdFALSE; uint32_t ulPortTaskHasFPUContext = pdFALSE;
/* Set to 1 to pend a context switch from an ISR. */ /* Set to 1 to pend a context switch from an ISR. */
uint32_t ulPortYieldRequired = pdFALSE; uint32_t ulPortYieldRequired = pdFALSE;
/* Counts the interrupt nesting depth. A context switch is only performed if /* Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 0. */ if the nesting depth is 0. */
uint32_t ulPortInterruptNesting = 0UL; uint32_t ulPortInterruptNesting = 0UL;
@ -159,16 +159,14 @@ uint32_t ulPortInterruptNesting = 0UL;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. expected by the portRESTORE_CONTEXT() macro.
*
* The fist real value on the stack is the status register, which is set for The fist real value on the stack is the status register, which is set for
* system mode, with interrupts enabled. A few NULLs are added first to ensure system mode, with interrupts enabled. A few NULLs are added first to ensure
* GDB does not try decoding a non-existent return address. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack = NULL; *pxTopOfStack = NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = NULL; *pxTopOfStack = NULL;
@ -220,13 +218,13 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */ enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start without a floating point context. A task that uses
* the floating point hardware must call vPortTaskUsesFPU() before executing the floating point hardware must call vPortTaskUsesFPU() before executing
* any floating point instructions. */ any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack; return pxTopOfStack;
@ -236,17 +234,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ). should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */ defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL ); configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -255,17 +250,16 @@ BaseType_t xPortStartScheduler( void )
uint32_t ulAPSR; uint32_t ulAPSR;
/* Only continue if the CPU is not in User mode. The CPU must be in a /* Only continue if the CPU is not in User mode. The CPU must be in a
* Privileged mode for the scheduler to start. */ Privileged mode for the scheduler to start. */
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
if( ulAPSR != portAPSR_USER_MODE ) if( ulAPSR != portAPSR_USER_MODE )
{ {
/* Only continue if the binary point value is set to its lowest possible /* Only continue if the binary point value is set to its lowest possible
* setting. See the comments in vPortValidateInterruptPriority() below for setting. See the comments in vPortValidateInterruptPriority() below for
* more information. */ more information. */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
@ -279,8 +273,8 @@ BaseType_t xPortStartScheduler( void )
} }
/* Will only get here if vTaskStartScheduler() was called with the CPU in /* Will only get here if vTaskStartScheduler() was called with the CPU in
* a non-privileged mode or the binary point register was not set to its lowest a non-privileged mode or the binary point register was not set to its lowest
* possible value. */ possible value. */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -288,7 +282,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */ Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -299,15 +293,15 @@ void vPortEnterCritical( void )
ulPortSetInterruptMask(); ulPortSetInterruptMask();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */ assert function also uses a critical section. */
if( ulCriticalNesting == 1 ) if( ulCriticalNesting == 1 )
{ {
configASSERT( ulPortInterruptNesting == 0 ); configASSERT( ulPortInterruptNesting == 0 );
@ -320,15 +314,15 @@ void vPortExitCritical( void )
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
* exited. */ exited. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */ priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
* should be unmasked. */ should be unmasked. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
@ -338,8 +332,8 @@ void vPortExitCritical( void )
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
/* Set interrupt mask before altering scheduler structures. The tick /* Set interrupt mask before altering scheduler structures. The tick
* handler runs at the lowest priority, so interrupts cannot already be masked, handler runs at the lowest priority, so interrupts cannot already be masked,
* so there is no need to save and restore the current mask value. */ so there is no need to save and restore the current mask value. */
__disable_irq(); __disable_irq();
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm( "DSB \n" __asm( "DSB \n"
@ -363,7 +357,7 @@ void vPortTaskUsesFPU( void )
uint32_t ulInitialFPSCR = 0; uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context). */ FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
@ -385,7 +379,6 @@ uint32_t ulPortSetInterruptMask( void )
uint32_t ulReturn; uint32_t ulReturn;
__disable_irq(); __disable_irq();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{ {
/* Interrupts were already masked. */ /* Interrupts were already masked. */
@ -398,7 +391,6 @@ uint32_t ulPortSetInterruptMask( void )
__asm( "DSB \n" __asm( "DSB \n"
"ISB \n" ); "ISB \n" );
} }
__enable_irq(); __enable_irq();
return ulReturn; return ulReturn;
@ -410,36 +402,38 @@ uint32_t ulPortSetInterruptMask( void )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
/* The following assertion will fail if a service routine (ISR) for /* The following assertion will fail if a service routine (ISR) for
* an interrupt that has been assigned a priority above an interrupt that has been assigned a priority above
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
* function. ISR safe FreeRTOS API functions must *only* be called function. ISR safe FreeRTOS API functions must *only* be called
* from interrupts that have been assigned a priority at or below from interrupts that have been assigned a priority at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Numerically low interrupt priority numbers represent logically high Numerically low interrupt priority numbers represent logically high
* interrupt priorities, therefore the priority of the interrupt must interrupt priorities, therefore the priority of the interrupt must
* be set to a value equal to or numerically *higher* than be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY. configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. interrupt entry is as fast and simple as possible.
*
* The following links provide detailed information: The following links provide detailed information:
* http://www.freertos.org/RTOS-Cortex-M3-M4.html http://www.freertos.org/RTOS-Cortex-M3-M4.html
* http://www.freertos.org/FAQHelp.html */ http://www.freertos.org/FAQHelp.html */
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits /* Priority grouping: The interrupt controller (GIC) allows the bits
* that define each interrupt's priority to be split between bits that that define each interrupt's priority to be split between bits that
* define the interrupt's pre-emption priority bits and bits that define define the interrupt's pre-emption priority bits and bits that define
* the interrupt's sub-priority. For simplicity all bits must be defined the interrupt's sub-priority. For simplicity all bits must be defined
* to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
* this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
*
* The priority grouping is configured by the GIC's binary point register The priority grouping is configured by the GIC's binary point register
* (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest (ICCBPR). Writting 0 to ICCBPR will ensure it is set to its lowest
* possible value (which may be above 0). */ possible value (which may be above 0). */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -1,29 +1,29 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
EXTERN vTaskSwitchContext EXTERN vTaskSwitchContext
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
@ -33,41 +33,33 @@ EXTERN ulAsmAPIPriorityMask
portSAVE_CONTEXT macro portSAVE_CONTEXT macro
; ; Save the LR and SPSR onto the system mode stack before switching to
Save the LR and SPSR onto the system mode stack before switching to ; system mode to save the remaining system mode registers
;
system mode to save the remaining system mode registers
SRSDB sp!, #SYS_MODE SRSDB sp!, #SYS_MODE
CPS #SYS_MODE CPS #SYS_MODE
PUSH {R0-R12, R14} PUSH {R0-R12, R14}
; ; Push the critical nesting count
Push the critical nesting count
LDR R2, =ulCriticalNesting LDR R2, =ulCriticalNesting
LDR R1, [R2] LDR R1, [R2]
PUSH {R1} PUSH {R1}
; ; Does the task have a floating point context that needs saving? If
Does the task have a floating point context that needs saving ? If ; ulPortTaskHasFPUContext is 0 then no.
;
ulPortTaskHasFPUContext is 0 then no.
LDR R2, =ulPortTaskHasFPUContext LDR R2, =ulPortTaskHasFPUContext
LDR R3, [R2] LDR R3, [R2]
CMP R3, #0 CMP R3, #0
; ; Save the floating point context, if any
Save the floating point context, if any
FMRXNE R1, FPSCR FMRXNE R1, FPSCR
VPUSHNE {D0-D15} VPUSHNE {D0-D15}
VPUSHNE {D16-D31} VPUSHNE {D16-D31}
PUSHNE {R1} PUSHNE {R1}
; ; Save ulPortTaskHasFPUContext itself
Save ulPortTaskHasFPUContext itself
PUSH {R3} PUSH {R3}
; ; Save the stack pointer in the TCB
Save the stack pointer in the TCB
LDR R0, =pxCurrentTCB LDR R0, =pxCurrentTCB
LDR R1, [R0] LDR R1, [R0]
STR SP, [R1] STR SP, [R1]
@ -78,52 +70,46 @@ endm
portRESTORE_CONTEXT macro portRESTORE_CONTEXT macro
; ; Set the SP to point to the stack of the task being restored.
Set the SP to point to the stack of the task being restored.
LDR R0, =pxCurrentTCB LDR R0, =pxCurrentTCB
LDR R1, [R0] LDR R1, [R0]
LDR SP, [R1] LDR SP, [R1]
; ; Is there a floating point context to restore? If the restored
Is there a floating point context to restore ? If the restored ; ulPortTaskHasFPUContext is zero then no.
;
ulPortTaskHasFPUContext is zero then no.
LDR R0, =ulPortTaskHasFPUContext LDR R0, =ulPortTaskHasFPUContext
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
CMP R1, #0 CMP R1, #0
; ; Restore the floating point context, if any
Restore the floating point context, if any
POPNE {R0} POPNE {R0}
VPOPNE {D16-D31} VPOPNE {D16-D31}
VPOPNE {D0-D15} VPOPNE {D0-D15}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
; ; Restore the critical section nesting depth
Restore the critical section nesting depth
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
; ; Ensure the priority mask is correct for the critical nesting depth
Ensure the priority mask is correct for the critical nesting depth
LDR R2, =portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS LDR R2, =portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS
CMP R1, #0 CMP R1, #0
MOVEQ R4, #255 MOVEQ R4, #255
LDRNE R4, =( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) LDRNE R4, =( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT )
STR R4, [r2] STR R4, [r2]
; ; Restore all system mode registers other than the SP (which is already
Restore all system mode registers other than the SP( which is already ; being used)
; POP {R0-R12, R14}
being used )
POP
{
R0 - R12, R14
}
Return to the task code, loading CPSR on the way. ; Return to the task code, loading CPSR on the way.
RFEIA sp! RFEIA sp!
endm endm

View file

@ -64,7 +64,7 @@
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -103,7 +103,7 @@
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
/* These macros do not globally disable/enable interrupts. They do mask off /* These macros do not globally disable/enable interrupts. They do mask off
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */ interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
@ -114,17 +114,17 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these not required for this port but included in case common demo code that uses these
* macros is used. */ macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
* handler for whichever peripheral is used to generate the RTOS tick. */ handler for whichever peripheral is used to generate the RTOS tick. */
void FreeRTOS_Tick_Handler( void ); void FreeRTOS_Tick_Handler( void );
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU() /* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
* before any floating point instructions are executed. */ before any floating point instructions are executed. */
void vPortTaskUsesFPU( void ); void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
@ -161,8 +161,8 @@
#endif #endif
/* Suppress warnings that are generated by the IAR tools, but cannot be /* Suppress warnings that are generated by the IAR tools, but cannot be
* fixed in the source code because to do so would cause other compilers to fixed in the source code because to do so would cause other compilers to
* generate warnings. */ generate warnings. */
#pragma diag_suppress=Pe191 #pragma diag_suppress=Pe191
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
@ -170,7 +170,7 @@
/* The number of bits to shift for an interrupt priority is dependent on the /* The number of bits to shift for an interrupt priority is dependent on the
* number of bits implemented by the interrupt controller. */ number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16 #if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4 #define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3 #define portMAX_BINARY_POINT_VALUE 3
@ -186,9 +186,9 @@
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0 #define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */ #else
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */ #endif
/* Interrupt controller access addresses. */ /* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 ) #define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
@ -206,3 +206,4 @@
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) ) #define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -48,14 +48,14 @@
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /* A critical section is exited when the critical section nesting count reaches
* this value. */ this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* Tasks are not created with a floating point context, but can be given a /* Tasks are not created with a floating point context, but can be given a
* floating point context after they have been created. A variable is stored as floating point context after they have been created. A variable is stored as
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
* does not have an FPU context, or any other value if the task does have an FPU does not have an FPU context, or any other value if the task does have an FPU
* context. */ context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
@ -67,12 +67,12 @@
#define portAPSR_MODE_BITS_MASK ( 0x1F ) #define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user /* The value of the mode bits in the APSR when the CPU is executing in user
* mode. */ mode. */
#define portAPSR_USER_MODE ( 0x10 ) #define portAPSR_USER_MODE ( 0x10 )
/* Let the user override the pre-loading of the initial LR with the address of /* Let the user override the pre-loading of the initial LR with the address of
* prvTaskExitError() in case it messes up unwinding of the stack in the prvTaskExitError() in case it messes up unwinding of the stack in the
* debugger. */ debugger. */
#ifdef configTASK_RETURN_ADDRESS #ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else #else
@ -95,21 +95,21 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This /* A variable is used to keep track of the critical section nesting. This
* variable has to be stored as part of the task context and must be initialised to variable has to be stored as part of the task context and must be initialised to
* a non zero value to ensure interrupts don't inadvertently become unmasked before a non zero value to ensure interrupts don't inadvertently become unmasked before
* the scheduler starts. As it is stored as part of the task context it will the scheduler starts. As it is stored as part of the task context it will
* automatically be set to 0 when the first task is started. */ automatically be set to 0 when the first task is started. */
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then /* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then
* a floating point context must be saved and restored for the task. */ a floating point context must be saved and restored for the task. */
volatile uint32_t ulPortTaskHasFPUContext = pdFALSE; volatile uint32_t ulPortTaskHasFPUContext = pdFALSE;
/* Set to 1 to pend a context switch from an ISR. */ /* Set to 1 to pend a context switch from an ISR. */
volatile uint32_t ulPortYieldRequired = pdFALSE; volatile uint32_t ulPortYieldRequired = pdFALSE;
/* Counts the interrupt nesting depth. A context switch is only performed if /* Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 0. */ if the nesting depth is 0. */
volatile uint32_t ulPortInterruptNesting = 0UL; volatile uint32_t ulPortInterruptNesting = 0UL;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -117,16 +117,14 @@ volatile uint32_t ulPortInterruptNesting = 0UL;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. expected by the portRESTORE_CONTEXT() macro.
*
* The fist real value on the stack is the status register, which is set for The fist real value on the stack is the status register, which is set for
* system mode, with interrupts enabled. A few NULLs are added first to ensure system mode, with interrupts enabled. A few NULLs are added first to ensure
* GDB does not try decoding a non-existent return address. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
@ -178,13 +176,13 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */ enabled. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
pxTopOfStack--; pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start without a floating point context. A task that uses
* the floating point hardware must call vPortTaskUsesFPU() before executing the floating point hardware must call vPortTaskUsesFPU() before executing
* any floating point instructions. */ any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack; return pxTopOfStack;
@ -194,17 +192,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ). should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */ defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL ); configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -213,9 +208,8 @@ BaseType_t xPortStartScheduler( void )
uint32_t ulAPSR; uint32_t ulAPSR;
/* Only continue if the CPU is not in User mode. The CPU must be in a /* Only continue if the CPU is not in User mode. The CPU must be in a
* Privileged mode for the scheduler to start. */ Privileged mode for the scheduler to start. */
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
@ -230,10 +224,10 @@ BaseType_t xPortStartScheduler( void )
} }
/* Will only get here if vTaskStartScheduler() was called with the CPU in /* Will only get here if vTaskStartScheduler() was called with the CPU in
* a non-privileged mode or the binary point register was not set to its lowest a non-privileged mode or the binary point register was not set to its lowest
* possible value. prvTaskExitError() is referenced to prevent a compiler possible value. prvTaskExitError() is referenced to prevent a compiler
* warning about it being defined but not referenced in the case that the user warning about it being defined but not referenced in the case that the user
* defines their own exit address. */ defines their own exit address. */
( void ) prvTaskExitError; ( void ) prvTaskExitError;
return 0; return 0;
} }
@ -242,7 +236,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */ Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -252,15 +246,15 @@ void vPortEnterCritical( void )
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */ assert function also uses a critical section. */
if( ulCriticalNesting == 1 ) if( ulCriticalNesting == 1 )
{ {
configASSERT( ulPortInterruptNesting == 0 ); configASSERT( ulPortInterruptNesting == 0 );
@ -273,15 +267,15 @@ void vPortExitCritical( void )
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being
* exited. */ exited. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */ priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /* Critical nesting has reached zero so all interrupt priorities
* should be unmasked. */ should be unmasked. */
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
} }
@ -311,10 +305,12 @@ void vPortTaskUsesFPU( void )
uint32_t ulInitialFPSCR = 0; uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the /* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context). */ FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) ); __asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -61,7 +61,7 @@
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -87,8 +87,7 @@
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#define portYIELD() \ #define portYIELD() __asm volatile ( "SWI 0 \n" \
__asm volatile ( "SWI 0 \n"\
"ISB " ); "ISB " );
@ -106,12 +105,11 @@
#define portINTERRUPT_ENABLE_BIT ( 1 << 7 ) #define portINTERRUPT_ENABLE_BIT ( 1 << 7 )
/* In the absence of a priority mask register, these functions and macros /* In the absence of a priority mask register, these functions and macros
* globally enable and disable interrupts. */ globally enable and disable interrupts. */
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portENABLE_INTERRUPTS() __asm volatile ( "CPSIE i \n" ); #define portENABLE_INTERRUPTS() __asm volatile ( "CPSIE i \n" );
#define portDISABLE_INTERRUPTS() \ #define portDISABLE_INTERRUPTS() __asm volatile ( "CPSID i \n" \
__asm volatile ( "CPSID i \n" \
"DSB \n" \ "DSB \n" \
"ISB " ); "ISB " );
#pragma inline #pragma inline
@ -120,7 +118,6 @@
volatile uint32_t ulCPSR; volatile uint32_t ulCPSR;
__asm volatile ( "MRS %0, CPSR" : "=r" (ulCPSR) ); __asm volatile ( "MRS %0, CPSR" : "=r" (ulCPSR) );
ulCPSR &= portINTERRUPT_ENABLE_BIT; ulCPSR &= portINTERRUPT_ENABLE_BIT;
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
return ulCPSR; return ulCPSR;
@ -132,17 +129,17 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these not required for this port but included in case common demo code that uses these
* macros is used. */ macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /* Prototype of the FreeRTOS tick handler. This must be installed as the
* handler for whichever peripheral is used to generate the RTOS tick. */ handler for whichever peripheral is used to generate the RTOS tick. */
void FreeRTOS_Tick_Handler( void ); void FreeRTOS_Tick_Handler( void );
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU() /* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
* before any floating point instructions are executed. */ before any floating point instructions are executed. */
void vPortTaskUsesFPU( void ); void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
@ -170,8 +167,8 @@
#define portINLINE inline #define portINLINE inline
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
* the source code because to do so would cause other compilers to generate the source code because to do so would cause other compilers to generate
* warnings. */ warnings. */
#pragma diag_suppress=Pe191 #pragma diag_suppress=Pe191
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
@ -181,3 +178,4 @@
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -48,7 +48,7 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Stores the critical section nesting. This must not be initialised to 0. /* Stores the critical section nesting. This must not be initialised to 0.
* It will be initialised when a task starts. */ It will be initialised when a task starts. */
#define portNO_CRITICAL_NESTING ( ( UBaseType_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( UBaseType_t ) 0 )
UBaseType_t uxCriticalNesting = 0x50; UBaseType_t uxCriticalNesting = 0x50;
@ -70,15 +70,13 @@ extern void vPortStart( void );
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
uint16_t usAddress; uint16_t usAddress;
StackType_t *pxTopOfHardwareStack; StackType_t *pxTopOfHardwareStack;
/* Place a few bytes of known values on the bottom of the stack. /* Place a few bytes of known values on the bottom of the stack.
* This is just useful for debugging. */ This is just useful for debugging. */
*pxTopOfStack = 0x11; *pxTopOfStack = 0x11;
pxTopOfStack--; pxTopOfStack--;
@ -88,7 +86,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Remember where the top of the hardware stack is - this is required /* Remember where the top of the hardware stack is - this is required
* below. */ below. */
pxTopOfHardwareStack = pxTopOfStack; pxTopOfHardwareStack = pxTopOfStack;
@ -99,20 +97,20 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
/* The IAR compiler requires two stacks per task. First there is the /* The IAR compiler requires two stacks per task. First there is the
* hardware call stack which uses the AVR stack pointer. Second there is the hardware call stack which uses the AVR stack pointer. Second there is the
* software stack (local variables, parameter passing, etc.) which uses the software stack (local variables, parameter passing, etc.) which uses the
* AVR Y register. AVR Y register.
*
* This function places both stacks within the memory block passed in as the This function places both stacks within the memory block passed in as the
* first parameter. The hardware stack is placed at the bottom of the memory first parameter. The hardware stack is placed at the bottom of the memory
* block. A gap is then left for the hardware stack to grow. Next the software block. A gap is then left for the hardware stack to grow. Next the software
* stack is placed. The amount of space between the software and hardware stack is placed. The amount of space between the software and hardware
* stacks is defined by configCALL_STACK_SIZE. stacks is defined by configCALL_STACK_SIZE.
*
*
*
* The first part of the stack is the hardware stack. Place the start The first part of the stack is the hardware stack. Place the start
* address of the task on the hardware stack. */ address of the task on the hardware stack. */
usAddress = ( uint16_t ) pxCode; usAddress = ( uint16_t ) pxCode;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--; pxTopOfStack--;
@ -123,23 +121,23 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
/* Leave enough space for the hardware stack before starting the software /* Leave enough space for the hardware stack before starting the software
* stack. The '- 2' is because we have already used two spaces for the stack. The '- 2' is because we have already used two spaces for the
* address of the start of the task. */ address of the start of the task. */
pxTopOfStack -= ( configCALL_STACK_SIZE - 2 ); pxTopOfStack -= ( configCALL_STACK_SIZE - 2 );
/* Next simulate the stack as if after a call to portSAVE_CONTEXT(). /* Next simulate the stack as if after a call to portSAVE_CONTEXT().
* portSAVE_CONTEXT places the flags on the stack immediately after r0 portSAVE_CONTEXT places the flags on the stack immediately after r0
* to ensure the interrupts get disabled as soon as possible, and so ensuring to ensure the interrupts get disabled as soon as possible, and so ensuring
* the stack use is minimal should a context switch interrupt occur. */ the stack use is minimal should a context switch interrupt occur. */
*pxTopOfStack = ( StackType_t ) 0x00; /* R0 */ *pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED; *pxTopOfStack = portFLAGS_INT_ENABLED;
pxTopOfStack--; pxTopOfStack--;
/* Next place the address of the hardware stack. This is required so /* Next place the address of the hardware stack. This is required so
* the AVR stack pointer can be restored to point to the hardware stack. */ the AVR stack pointer can be restored to point to the hardware stack. */
pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS; pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS;
usAddress = ( uint16_t ) pxTopOfHardwareStack; usAddress = ( uint16_t ) pxTopOfHardwareStack;
@ -154,6 +152,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
/* Now the remaining registers. */ /* Now the remaining registers. */
*pxTopOfStack = ( StackType_t ) 0x01; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01; /* R1 */
pxTopOfStack--; pxTopOfStack--;
@ -217,7 +216,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The Y register is not stored as it is used as the software stack and /* The Y register is not stored as it is used as the software stack and
* gets saved into the task control block. */ gets saved into the task control block. */
*pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */ *pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */
pxTopOfStack--; pxTopOfStack--;
@ -238,8 +237,8 @@ BaseType_t xPortStartScheduler( void )
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Restore the context of the first task that is going to run. /* Restore the context of the first task that is going to run.
* Normally we would just call portRESTORE_CONTEXT() here, but as the IAR Normally we would just call portRESTORE_CONTEXT() here, but as the IAR
* compiler does not fully support inline assembler we have to make a call.*/ compiler does not fully support inline assembler we have to make a call.*/
vPortStart(); vPortStart();
/* Should not get here! */ /* Should not get here! */
@ -250,7 +249,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the AVR port will get stopped. If required simply /* It is unlikely that the AVR port will get stopped. If required simply
* disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -263,7 +262,7 @@ static void prvSetupTimerInterrupt( void )
uint8_t ucHighByte, ucLowByte; uint8_t ucHighByte, ucLowByte;
/* Using 16bit timer 1 to generate the tick. Correct fuses must be /* Using 16bit timer 1 to generate the tick. Correct fuses must be
* selected for the configCPU_CLOCK_HZ clock. */ selected for the configCPU_CLOCK_HZ clock. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
@ -274,7 +273,7 @@ static void prvSetupTimerInterrupt( void )
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 );
ulCompareMatch >>= 8; ulCompareMatch >>= 8;
ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff ); ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
@ -286,7 +285,7 @@ static void prvSetupTimerInterrupt( void )
TCCR1B = ucLowByte; TCCR1B = ucLowByte;
/* Enable the interrupt - this is okay as interrupt are currently globally /* Enable the interrupt - this is okay as interrupt are currently globally
* disabled. */ disabled. */
TIMSK |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE; TIMSK |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -318,7 +317,7 @@ static void prvSetupTimerInterrupt( void )
{ {
xTaskIncrementTick(); xTaskIncrementTick();
} }
#endif /* if configUSE_PREEMPTION == 1 */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
@ -331,9 +330,10 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == portNO_CRITICAL_NESTING ) if( uxCriticalNesting == portNO_CRITICAL_NESTING )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
} }
} }

View file

@ -26,10 +26,10 @@
*/ */
/* /*
* Changes from V1.2.3 Changes from V1.2.3
*
+ portCPU_CLOSK_HZ definition changed to 8MHz base 10, previously it + portCPU_CLOSK_HZ definition changed to 8MHz base 10, previously it
+ base 16. base 16.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -108,3 +108,5 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,5 +1,4 @@
/*This file has been prepared for Doxygen automatic documentation generation.*/ /*This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file ********************************************************************* /*! \file *********************************************************************
* *
* \brief FreeRTOS port source for AVR32 UC3. * \brief FreeRTOS port source for AVR32 UC3.
@ -130,7 +129,7 @@ int __low_level_init( void )
sizeof( DBG_USART_GPIO_MAP ) / sizeof( DBG_USART_GPIO_MAP[0] ) ); sizeof( DBG_USART_GPIO_MAP ) / sizeof( DBG_USART_GPIO_MAP[0] ) );
usart_init_rs232(configDBG_USART, &DBG_USART_OPTIONS, configCPU_CLOCK_HZ); usart_init_rs232(configDBG_USART, &DBG_USART_OPTIONS, configCPU_CLOCK_HZ);
} }
#endif /* if configDBG */ #endif
/* Request initialization of data segments. */ /* Request initialization of data segments. */
return 1; return 1;
@ -138,8 +137,7 @@ int __low_level_init( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Added as there is no such function in FreeRTOS. */ /* Added as there is no such function in FreeRTOS. */
void * pvPortRealloc( void * pv, void *pvPortRealloc( void *pv, size_t xWantedSize )
size_t xWantedSize )
{ {
void *pvReturn; void *pvReturn;
@ -154,11 +152,10 @@ void * pvPortRealloc( void * pv,
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */ simply increment the system tick. */
/* The preemptive scheduler is defined as "naked" as the full context is saved /* The preemptive scheduler is defined as "naked" as the full context is saved
* on entry as part of the context switch. */ on entry as part of the context switch. */
#pragma shadow_registers = full /* Naked. */ #pragma shadow_registers = full // Naked.
static void vTick( void ) static void vTick( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
@ -168,14 +165,13 @@ static void vTick( void )
/* Clear the interrupt flag. */ /* Clear the interrupt flag. */
prvClearTcInt(); prvClearTcInt();
#else #else
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ) /* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
* clock cycles from now. */ clock cycles from now. */
prvScheduleNextTick(); prvScheduleNextTick();
#endif #endif
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS /* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
* calls in a critical section . */ calls in a critical section . */
portENTER_CRITICAL(); portENTER_CRITICAL();
xTaskIncrementTick(); xTaskIncrementTick();
portEXIT_CRITICAL(); portEXIT_CRITICAL();
@ -185,7 +181,7 @@ static void vTick( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#pragma shadow_registers = full /* Naked. */ #pragma shadow_registers = full // Naked.
void SCALLYield( void ) void SCALLYield( void )
{ {
/* Save the context of the interrupted task. */ /* Save the context of the interrupted task. */
@ -196,9 +192,9 @@ void SCALLYield( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The code generated by the GCC compiler uses the stack in different ways at /* The code generated by the GCC compiler uses the stack in different ways at
* different optimisation levels. The interrupt flags can therefore not always different optimisation levels. The interrupt flags can therefore not always
* be saved to the stack. Instead the critical section nesting level is stored be saved to the stack. Instead the critical section nesting level is stored
* in a variable, which is then saved as part of the stack context. */ in a variable, which is then saved as part of the stack context. */
#pragma optimize = no_inline #pragma optimize = no_inline
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
@ -206,8 +202,8 @@ void vPortEnterCritical( void )
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -218,7 +214,6 @@ void vPortExitCritical( void )
if(ulCriticalNesting > portNO_CRITICAL_NESTING) if(ulCriticalNesting > portNO_CRITICAL_NESTING)
{ {
ulCriticalNesting--; ulCriticalNesting--;
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Enable all interrupt/exception. */ /* Enable all interrupt/exception. */
@ -234,12 +229,10 @@ void vPortExitCritical( void )
* *
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* When the task starts, it will expect to find the function parameter in R12. */ /* When the task starts, it will expect to find the function parameter in R12. */
pxTopOfStack--; pxTopOfStack--;
@ -268,7 +261,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -282,12 +275,12 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the AVR32 port will require this function as there /* It is unlikely that the AVR32 port will require this function as there
* is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ) /* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
* clock cycles from now. */ clock cycles from now. */
#if( configTICK_USE_TC==0 ) #if( configTICK_USE_TC==0 )
static void prvScheduleFirstTick(void) static void prvScheduleFirstTick(void)
{ {
@ -295,14 +288,12 @@ void vPortEndScheduler( void )
lCycles = Get_system_register(AVR32_COUNT); lCycles = Get_system_register(AVR32_COUNT);
lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ); lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
// If lCycles ends up to be 0, make it 1 so that the COMPARE and exception
/* If lCycles ends up to be 0, make it 1 so that the COMPARE and exception */ // generation feature does not get disabled.
/* generation feature does not get disabled. */
if(0 == lCycles) if(0 == lCycles)
{ {
lCycles++; lCycles++;
} }
Set_system_register(AVR32_COMPARE, lCycles); Set_system_register(AVR32_COMPARE, lCycles);
} }
@ -313,39 +304,36 @@ void vPortEndScheduler( void )
lCycles = Get_system_register(AVR32_COMPARE); lCycles = Get_system_register(AVR32_COMPARE);
lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ); lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
// If lCycles ends up to be 0, make it 1 so that the COMPARE and exception
/* If lCycles ends up to be 0, make it 1 so that the COMPARE and exception */ // generation feature does not get disabled.
/* generation feature does not get disabled. */
if(0 == lCycles) if(0 == lCycles)
{ {
lCycles++; lCycles++;
} }
lCount = Get_system_register(AVR32_COUNT); lCount = Get_system_register(AVR32_COUNT);
if( lCycles < lCount ) if( lCycles < lCount )
{ /* We missed a tick, recover for the next. */ { // We missed a tick, recover for the next.
lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ); lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
} }
Set_system_register(AVR32_COMPARE, lCycles); Set_system_register(AVR32_COMPARE, lCycles);
} }
#else /* if ( configTICK_USE_TC == 0 ) */ #else
#pragma optimize = no_inline #pragma optimize = no_inline
static void prvClearTcInt(void) static void prvClearTcInt(void)
{ {
AVR32_TC.channel[configTICK_TC_CHANNEL].sr; AVR32_TC.channel[configTICK_TC_CHANNEL].sr;
} }
#endif /* if ( configTICK_USE_TC == 0 ) */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Setup the timer to generate the tick interrupts. */ /* Setup the timer to generate the tick interrupts. */
static void prvSetupTimerInterrupt(void) static void prvSetupTimerInterrupt(void)
{ {
#if( configTICK_USE_TC==1 ) #if( configTICK_USE_TC==1 )
volatile avr32_tc_t *tc = &AVR32_TC; volatile avr32_tc_t *tc = &AVR32_TC;
/* Options for waveform genration. */ // Options for waveform genration.
tc_waveform_opt_t waveform_opt = tc_waveform_opt_t waveform_opt =
{ {
.channel = configTICK_TC_CHANNEL, /* Channel selection. */ .channel = configTICK_TC_CHANNEL, /* Channel selection. */
@ -383,13 +371,14 @@ static void prvSetupTimerInterrupt( void )
.lovrs=0, .lovrs=0,
.covfs=0, .covfs=0,
}; };
#endif /* if ( configTICK_USE_TC == 1 ) */
#endif
/* Disable all interrupt/exception. */ /* Disable all interrupt/exception. */
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Register the compare interrupt handler to the interrupt controller and /* Register the compare interrupt handler to the interrupt controller and
* enable the compare interrupt. */ enable the compare interrupt. */
#if( configTICK_USE_TC==1 ) #if( configTICK_USE_TC==1 )
{ {
@ -399,8 +388,8 @@ static void prvSetupTimerInterrupt( void )
tc_init_waveform(tc, &waveform_opt); tc_init_waveform(tc, &waveform_opt);
/* Set the compare triggers. /* Set the compare triggers.
* Remember TC counter is 16-bits, so counting second is not possible! Remember TC counter is 16-bits, so counting second is not possible!
* That's why we configure it to count ms. */ That's why we configure it to count ms. */
tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4) / configTICK_RATE_HZ ); tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4) / configTICK_RATE_HZ );
tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt ); tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt );
@ -408,10 +397,10 @@ static void prvSetupTimerInterrupt( void )
/* Start the timer/counter. */ /* Start the timer/counter. */
tc_start(tc, configTICK_TC_CHANNEL); tc_start(tc, configTICK_TC_CHANNEL);
} }
#else /* if ( configTICK_USE_TC == 1 ) */ #else
{ {
INTC_register_interrupt((__int_handler)&vTick, AVR32_CORE_COMPARE_IRQ, INT0); INTC_register_interrupt((__int_handler)&vTick, AVR32_CORE_COMPARE_IRQ, INT0);
prvScheduleFirstTick(); prvScheduleFirstTick();
} }
#endif /* if ( configTICK_USE_TC == 1 ) */ #endif
} }

View file

@ -1,5 +1,4 @@
/*This file has been prepared for Doxygen automatic documentation generation.*/ /*This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file ********************************************************************* /*! \file *********************************************************************
* *
* \brief FreeRTOS port header for AVR32 UC3. * \brief FreeRTOS port header for AVR32 UC3.
@ -151,8 +150,7 @@
/* Added as there is no such function in FreeRTOS. */ /* Added as there is no such function in FreeRTOS. */
extern void * pvPortRealloc( void * pv, extern void *pvPortRealloc( void *pv, size_t xSize );
size_t xSize );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -209,25 +207,25 @@
* are not the same between INT0..3 exceptions and the scall exception. * are not the same between INT0..3 exceptions and the scall exception.
*/ */
/* Task context stack layout: */ // Task context stack layout:
/* R8 (*) */ // R8 (*)
/* R9 (*) */ // R9 (*)
/* R10 (*) */ // R10 (*)
/* R11 (*) */ // R11 (*)
/* R12 (*) */ // R12 (*)
/* R14/LR (*) */ // R14/LR (*)
/* R15/PC (*) */ // R15/PC (*)
/* SR (*) */ // SR (*)
/* R0 */ // R0
/* R1 */ // R1
/* R2 */ // R2
/* R3 */ // R3
/* R4 */ // R4
/* R5 */ // R5
/* R6 */ // R6
/* R7 */ // R7
/* ulCriticalNesting */ // ulCriticalNesting
/* (*) automatically done for INT0..INT3, but not for SCALL */ // (*) automatically done for INT0..INT3, but not for SCALL
/* /*
* The ISR used for the scheduler tick depends on whether the cooperative or * The ISR used for the scheduler tick depends on whether the cooperative or
@ -262,7 +260,7 @@
); \ ); \
} }
#else /* if configUSE_PREEMPTION == 0 */ #else
/* /*
* portSAVE_CONTEXT_OS_INT() for OS Tick exception. * portSAVE_CONTEXT_OS_INT() for OS Tick exception.
@ -370,7 +368,7 @@
pxCurrentTCB; \ pxCurrentTCB; \
} }
#endif /* if configUSE_PREEMPTION == 0 */ #endif
/* /*
@ -528,7 +526,7 @@
); \ ); \
} }
#else /* if configUSE_PREEMPTION == 0 */ #else
/* /*
* ISR entry and exit macros. These are only required if a task switch * ISR entry and exit macros. These are only required if a task switch
@ -640,7 +638,7 @@
pxCurrentTCB; \ pxCurrentTCB; \
} }
#endif /* if configUSE_PREEMPTION == 0 */ #endif
#define portYIELD() {__asm__ __volatile__ ("scall");} #define portYIELD() {__asm__ __volatile__ ("scall");}

View file

@ -1,9 +1,8 @@
/*This file is prepared for Doxygen automatic documentation generation.*/ /*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file ********************************************************************* /*! \file *********************************************************************
* *
* \brief System-specific implementation of the \ref __read function used by * \brief System-specific implementation of the \ref __read function used by
* the standard library. the standard library.
* *
* - Compiler: IAR EWAVR32 * - Compiler: IAR EWAVR32
* - Supported devices: All AVR32 devices with a USART module can be used. * - Supported devices: All AVR32 devices with a USART module can be used.
@ -66,14 +65,12 @@ extern volatile avr32_usart_t * volatile stdio_usart_base;
* \return The number of bytes read, \c 0 at the end of the file, or * \return The number of bytes read, \c 0 at the end of the file, or
* \c _LLIO_ERROR on failure. * \c _LLIO_ERROR on failure.
*/ */
size_t __read( int handle, size_t __read(int handle, uint8_t *buffer, size_t size)
uint8_t * buffer,
size_t size )
{ {
int nChars = 0; int nChars = 0;
/* This implementation only reads from stdin. */ // This implementation only reads from stdin.
/* For all other file handles, it returns failure. */ // For all other file handles, it returns failure.
if (handle != _LLIO_STDIN) if (handle != _LLIO_STDIN)
{ {
return _LLIO_ERROR; return _LLIO_ERROR;
@ -82,11 +79,8 @@ size_t __read( int handle,
for (; size > 0; --size) for (; size > 0; --size)
{ {
int c = usart_getchar(stdio_usart_base); int c = usart_getchar(stdio_usart_base);
if (c < 0) if (c < 0)
{
break; break;
}
*buffer++ = c; *buffer++ = c;
++nChars; ++nChars;

View file

@ -1,9 +1,8 @@
/*This file is prepared for Doxygen automatic documentation generation.*/ /*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file ********************************************************************* /*! \file *********************************************************************
* *
* \brief System-specific implementation of the \ref __write function used by * \brief System-specific implementation of the \ref __write function used by
* the standard library. the standard library.
* *
* - Compiler: IAR EWAVR32 * - Compiler: IAR EWAVR32
* - Supported devices: All AVR32 devices with a USART module can be used. * - Supported devices: All AVR32 devices with a USART module can be used.
@ -53,7 +52,7 @@ _STD_BEGIN
#pragma module_name = "?__write" #pragma module_name = "?__write"
/*! Pointer to the base of the USART module instance to use for stdio. */ //! Pointer to the base of the USART module instance to use for stdio.
__no_init volatile avr32_usart_t *volatile stdio_usart_base; __no_init volatile avr32_usart_t *volatile stdio_usart_base;
@ -70,21 +69,19 @@ __no_init volatile avr32_usart_t * volatile stdio_usart_base;
* *
* \return The number of bytes written, or \c _LLIO_ERROR on failure. * \return The number of bytes written, or \c _LLIO_ERROR on failure.
*/ */
size_t __write( int handle, size_t __write(int handle, const uint8_t *buffer, size_t size)
const uint8_t * buffer,
size_t size )
{ {
size_t nChars = 0; size_t nChars = 0;
if (buffer == 0) if (buffer == 0)
{ {
/* This means that we should flush internal buffers. */ // This means that we should flush internal buffers.
return 0; return 0;
} }
/* This implementation only writes to stdout and stderr. */ // This implementation only writes to stdout and stderr.
/* For all other file handles, it returns failure. */ // For all other file handles, it returns failure.
if( ( handle != _LLIO_STDOUT ) && ( handle != _LLIO_STDERR ) ) if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR)
{ {
return _LLIO_ERROR; return _LLIO_ERROR;
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,71 +1,63 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Context save and restore macro definitions ; Context save and restore macro definitions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
; ; Push R0 as we are going to use the register.
Push R0 as we are going to use the register.
STMDB SP!, {R0} STMDB SP!, {R0}
; ; Set R0 to point to the task stack pointer.
Set R0 to point to the task stack pointer.
STMDB SP, {SP}^ STMDB SP, {SP}^
NOP NOP
SUB SP, SP, #4 SUB SP, SP, #4
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push the return address onto the stack.
Push the return address onto the stack.
STMDB R0!, {LR} STMDB R0!, {LR}
; ; Now we have saved LR we can use it instead of R0.
Now we have saved LR we can use it instead of R0.
MOV LR, R0 MOV LR, R0
; ; Pop R0 so we can save it onto the system mode stack.
Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Push all the system mode registers onto the task stack.
STMDB LR, {R0-LR}^ STMDB LR, {R0-LR}^
NOP NOP
SUB LR, LR, #60 SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push the SPSR onto the task stack.
MRS R0, SPSR MRS R0, SPSR
STMDB LR!, {R0} STMDB LR!, {R0}
@ -73,8 +65,7 @@ LDR R0, = ulCriticalNesting
LDR R0, [R0] LDR R0, [R0]
STMDB LR!, {R0} STMDB LR!, {R0}
; ; Store the new top of stack for the task.
Store the new top of stack for the task.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
STR LR, [R0] STR LR, [R0]
@ -84,40 +75,31 @@ ENDM
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; ; Set the LR to the task stack.
Set the LR to the task stack.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
LDR LR, [R0] LDR LR, [R0]
; ; The critical nesting depth is the first item on the stack.
The critical nesting depth is the first item on the stack. ; Load it into the ulCriticalNesting variable.
;
Load it into the ulCriticalNesting variable.
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
LDMFD LR!, {R1} LDMFD LR!, {R1}
STR R1, [R0] STR R1, [R0]
; ; Get the SPSR from the stack.
Get the SPSR from the stack.
LDMFD LR!, {R0} LDMFD LR!, {R0}
MSR SPSR_cxsf, R0 MSR SPSR_cxsf, R0
; ; Restore all system mode registers for the task.
Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^ LDMFD LR, {R0-R14}^
NOP NOP
; ; Restore the return address.
Restore the return address.
LDR LR, [LR, #+60] LDR LR, [LR, #+60]
; ; And return - correcting the offset in the LR to obtain the
; correct address.
And return -correcting the offset in the LR to obtain the
;
correct address.
SUBS PC, LR, #4 SUBS PC, LR, #4
ENDM ENDM

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -59,8 +59,8 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* ulCriticalNesting will get set to zero when the first task starts. It /* ulCriticalNesting will get set to zero when the first task starts. It
* cannot be initialised to 0 as this will cause interrupts to be enabled cannot be initialised to 0 as this will cause interrupts to be enabled
* during the kernel initialisation process. */ during the kernel initialisation process. */
uint32_t ulCriticalNesting = ( uint32_t ) 9999; uint32_t ulCriticalNesting = ( uint32_t ) 9999;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -71,24 +71,22 @@ uint32_t ulCriticalNesting = ( uint32_t ) 9999;
* *
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
* is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
* start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
* as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -122,7 +120,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
* R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
@ -138,8 +136,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Interrupt flags cannot always be stored on the stack and will /* Interrupt flags cannot always be stored on the stack and will
* instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
* tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -151,7 +149,7 @@ BaseType_t xPortStartScheduler( void )
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -165,22 +163,22 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
* is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */ simply increment the system tick. */
static __arm __irq void vPortNonPreemptiveTick( void ); static __arm __irq void vPortNonPreemptiveTick( void );
static __arm __irq void vPortNonPreemptiveTick( void ) static __arm __irq void vPortNonPreemptiveTick( void )
{ {
uint32_t ulDummy; uint32_t ulDummy;
/* Increment the tick count - which may wake some tasks but as the /* Increment the tick count - which may wake some tasks but as the
* preemptive scheduler is not being used any woken task is not given preemptive scheduler is not being used any woken task is not given
* processor time no matter what its priority. */ processor time no matter what its priority. */
xTaskIncrementTick(); xTaskIncrementTick();
/* Clear the PIT interrupt. */ /* Clear the PIT interrupt. */
@ -190,12 +188,12 @@ void vPortEndScheduler( void )
AT91C_BASE_AIC->AIC_EOICR = ulDummy; AT91C_BASE_AIC->AIC_EOICR = ulDummy;
} }
#else /* if configUSE_PREEMPTION == 0 */ #else
/* Currently the IAR port requires the preemptive tick function to be /* Currently the IAR port requires the preemptive tick function to be
* defined in an asm file. */ defined in an asm file. */
#endif /* if configUSE_PREEMPTION == 0 */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -204,19 +202,23 @@ static void prvSetupTimerInterrupt( void )
AT91PS_PITC pxPIT = AT91C_BASE_PITC; AT91PS_PITC pxPIT = AT91C_BASE_PITC;
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends /* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
* on whether the preemptive or cooperative scheduler is being used. */ on whether the preemptive or cooperative scheduler is being used. */
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPortNonPreemptiveTick ); AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPortNonPreemptiveTick );
#else #else
extern void ( vPortPreemptiveTick )( void ); extern void ( vPortPreemptiveTick )( void );
AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPortPreemptiveTick ); AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPortPreemptiveTick );
#endif #endif
/* Configure the PIT period. */ /* Configure the PIT period. */
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE; pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
/* Enable the interrupt. Global interrupts are disables at this point so /* Enable the interrupt. Global interrupts are disables at this point so
* this is safe. */ this is safe. */
AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_SYS ); AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_SYS );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -227,8 +229,8 @@ void vPortEnterCritical( void )
__disable_interrupt(); __disable_interrupt();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -241,7 +243,7 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
* re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
__enable_interrupt(); __enable_interrupt();
@ -249,3 +251,9 @@ void vPortExitCritical( void )
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -107,3 +107,5 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,44 +1,36 @@
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Context save and restore macro definitions ; Context save and restore macro definitions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
; ; Push R0 as we are going to use the register.
Push R0 as we are going to use the register.
STMDB SP!, {R0} STMDB SP!, {R0}
; ; Set R0 to point to the task stack pointer.
Set R0 to point to the task stack pointer.
STMDB SP, {SP}^ STMDB SP, {SP}^
NOP NOP
SUB SP, SP, #4 SUB SP, SP, #4
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push the return address onto the stack.
Push the return address onto the stack.
STMDB R0!, {LR} STMDB R0!, {LR}
; ; Now we have saved LR we can use it instead of R0.
Now we have saved LR we can use it instead of R0.
MOV LR, R0 MOV LR, R0
; ; Pop R0 so we can save it onto the system mode stack.
Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Push all the system mode registers onto the task stack.
STMDB LR, {R0-LR}^ STMDB LR, {R0-LR}^
NOP NOP
SUB LR, LR, #60 SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push the SPSR onto the task stack.
MRS R0, SPSR MRS R0, SPSR
STMDB LR!, {R0} STMDB LR!, {R0}
@ -46,8 +38,7 @@ LDR R0, = ulCriticalNesting
LDR R0, [R0] LDR R0, [R0]
STMDB LR!, {R0} STMDB LR!, {R0}
; ; Store the new top of stack for the task.
Store the new top of stack for the task.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
STR LR, [R0] STR LR, [R0]
@ -57,40 +48,31 @@ ENDM
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; ; Set the LR to the task stack.
Set the LR to the task stack.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
LDR LR, [R0] LDR LR, [R0]
; ; The critical nesting depth is the first item on the stack.
The critical nesting depth is the first item on the stack. ; Load it into the ulCriticalNesting variable.
;
Load it into the ulCriticalNesting variable.
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
LDMFD LR!, {R1} LDMFD LR!, {R1}
STR R1, [R0] STR R1, [R0]
; ; Get the SPSR from the stack.
Get the SPSR from the stack.
LDMFD LR!, {R0} LDMFD LR!, {R0}
MSR SPSR_cxsf, R0 MSR SPSR_cxsf, R0
; ; Restore all system mode registers for the task.
Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^ LDMFD LR, {R0-R14}^
NOP NOP
; ; Restore the return address.
Restore the return address.
LDR LR, [LR, #+60] LDR LR, [LR, #+60]
; ; And return - correcting the offset in the LR to obtain the
; correct address.
And return -correcting the offset in the LR to obtain the
;
correct address.
SUBS PC, LR, #4 SUBS PC, LR, #4
ENDM ENDM

View file

@ -74,8 +74,8 @@ static void prvSetupTimerInterrupt( void );
static void vPortTickISR( void ); static void vPortTickISR( void );
/* ulCriticalNesting will get set to zero when the first task starts. It /* ulCriticalNesting will get set to zero when the first task starts. It
* cannot be initialised to 0 as this will cause interrupts to be enabled cannot be initialised to 0 as this will cause interrupts to be enabled
* during the kernel initialisation process. */ during the kernel initialisation process. */
uint32_t ulCriticalNesting = ( uint32_t ) 9999; uint32_t ulCriticalNesting = ( uint32_t ) 9999;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -86,24 +86,22 @@ uint32_t ulCriticalNesting = ( uint32_t ) 9999;
* *
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
* is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
* start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
* as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -137,7 +135,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
* R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
@ -154,8 +152,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Interrupt flags cannot always be stored on the stack and will /* Interrupt flags cannot always be stored on the stack and will
* instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
* tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -167,7 +165,7 @@ BaseType_t xPortStartScheduler( void )
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -181,7 +179,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
* is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -190,8 +188,8 @@ static __arm void vPortTickISR( void )
volatile uint32_t ulDummy; volatile uint32_t ulDummy;
/* Increment the tick count - which may wake some tasks but as the /* Increment the tick count - which may wake some tasks but as the
* preemptive scheduler is not being used any woken task is not given preemptive scheduler is not being used any woken task is not given
* processor time no matter what its priority. */ processor time no matter what its priority. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
vTaskSwitchContext(); vTaskSwitchContext();
@ -228,8 +226,8 @@ void vPortEnterCritical( void )
__disable_irq(); __disable_irq();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -242,7 +240,7 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
* re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
__enable_irq(); __enable_irq();
@ -250,3 +248,9 @@ void vPortExitCritical( void )
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -110,3 +110,5 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,71 +1,63 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Context save and restore macro definitions ; Context save and restore macro definitions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
; ; Push R0 as we are going to use the register.
Push R0 as we are going to use the register.
STMDB SP!, {R0} STMDB SP!, {R0}
; ; Set R0 to point to the task stack pointer.
Set R0 to point to the task stack pointer.
STMDB SP, {SP}^ STMDB SP, {SP}^
NOP NOP
SUB SP, SP, #4 SUB SP, SP, #4
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push the return address onto the stack.
Push the return address onto the stack.
STMDB R0!, {LR} STMDB R0!, {LR}
; ; Now we have saved LR we can use it instead of R0.
Now we have saved LR we can use it instead of R0.
MOV LR, R0 MOV LR, R0
; ; Pop R0 so we can save it onto the system mode stack.
Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Push all the system mode registers onto the task stack.
STMDB LR, {R0-LR}^ STMDB LR, {R0-LR}^
NOP NOP
SUB LR, LR, #60 SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push the SPSR onto the task stack.
MRS R0, SPSR MRS R0, SPSR
STMDB LR!, {R0} STMDB LR!, {R0}
@ -73,8 +65,7 @@ LDR R0, = ulCriticalNesting
LDR R0, [R0] LDR R0, [R0]
STMDB LR!, {R0} STMDB LR!, {R0}
; ; Store the new top of stack for the task.
Store the new top of stack for the task.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
STR LR, [R0] STR LR, [R0]
@ -84,40 +75,31 @@ ENDM
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; ; Set the LR to the task stack.
Set the LR to the task stack.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
LDR LR, [R0] LDR LR, [R0]
; ; The critical nesting depth is the first item on the stack.
The critical nesting depth is the first item on the stack. ; Load it into the ulCriticalNesting variable.
;
Load it into the ulCriticalNesting variable.
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
LDMFD LR!, {R1} LDMFD LR!, {R1}
STR R1, [R0] STR R1, [R0]
; ; Get the SPSR from the stack.
Get the SPSR from the stack.
LDMFD LR!, {R0} LDMFD LR!, {R0}
MSR SPSR_cxsf, R0 MSR SPSR_cxsf, R0
; ; Restore all system mode registers for the task.
Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^ LDMFD LR, {R0-R14}^
NOP NOP
; ; Restore the return address.
Restore the return address.
LDR LR, [LR, #+60] LDR LR, [LR, #+60]
; ; And return - correcting the offset in the LR to obtain the
; correct address.
And return -correcting the offset in the LR to obtain the
;
correct address.
SUBS PC, LR, #4 SUBS PC, LR, #4
ENDM ENDM

View file

@ -30,11 +30,11 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
* Changes from V3.2.2 Changes from V3.2.2
*
+ Bug fix - The prescale value for the timer setup is now written to T0PR + Bug fix - The prescale value for the timer setup is now written to T0PR
+ instead of T0PC. This bug would have had no effect unless a prescale instead of T0PC. This bug would have had no effect unless a prescale
+ value was actually used. value was actually used.
*/ */
/* Standard includes. */ /* Standard includes. */
@ -83,8 +83,8 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* ulCriticalNesting will get set to zero when the first task starts. It /* ulCriticalNesting will get set to zero when the first task starts. It
* cannot be initialised to 0 as this will cause interrupts to be enabled cannot be initialised to 0 as this will cause interrupts to be enabled
* during the kernel initialisation process. */ during the kernel initialisation process. */
uint32_t ulCriticalNesting = ( uint32_t ) 9999; uint32_t ulCriticalNesting = ( uint32_t ) 9999;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -95,20 +95,18 @@ uint32_t ulCriticalNesting = ( uint32_t ) 9999;
* *
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
* start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
* as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -142,7 +140,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
* R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
@ -158,8 +156,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Interrupt flags cannot always be stored on the stack and will /* Interrupt flags cannot always be stored on the stack and will
* instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
* tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -171,7 +169,7 @@ BaseType_t xPortStartScheduler( void )
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -185,20 +183,20 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
* is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 0 #if configUSE_PREEMPTION == 0
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */ simply increment the system tick. */
static __arm __irq void vPortNonPreemptiveTick( void ); static __arm __irq void vPortNonPreemptiveTick( void );
static __arm __irq void vPortNonPreemptiveTick( void ) static __arm __irq void vPortNonPreemptiveTick( void )
{ {
/* Increment the tick count - which may wake some tasks but as the /* Increment the tick count - which may wake some tasks but as the
* preemptive scheduler is not being used any woken task is not given preemptive scheduler is not being used any woken task is not given
* processor time no matter what its priority. */ processor time no matter what its priority. */
xTaskIncrementTick(); xTaskIncrementTick();
/* Ready for the next interrupt. */ /* Ready for the next interrupt. */
@ -206,10 +204,10 @@ void vPortEndScheduler( void )
VICVectAddr = portCLEAR_VIC_INTERRUPT; VICVectAddr = portCLEAR_VIC_INTERRUPT;
} }
#else /* if configUSE_PREEMPTION == 0 */ #else
/* This function is called from an asm wrapper, so does not require the __irq /* This function is called from an asm wrapper, so does not require the __irq
* keyword. */ keyword. */
void vPortPreemptiveTick( void ); void vPortPreemptiveTick( void );
void vPortPreemptiveTick( void ) void vPortPreemptiveTick( void )
{ {
@ -217,8 +215,8 @@ void vPortEndScheduler( void )
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* The new tick value might unblock a task. Ensure the highest task that /* The new tick value might unblock a task. Ensure the highest task that
* is ready to execute is the task that will execute when the tick ISR is ready to execute is the task that will execute when the tick ISR
* exits. */ exits. */
vTaskSwitchContext(); vTaskSwitchContext();
} }
@ -227,7 +225,7 @@ void vPortEndScheduler( void )
VICVectAddr = portCLEAR_VIC_INTERRUPT; VICVectAddr = portCLEAR_VIC_INTERRUPT;
} }
#endif /* if configUSE_PREEMPTION == 0 */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -236,14 +234,14 @@ static void prvSetupTimerInterrupt( void )
uint32_t ulCompareMatch; uint32_t ulCompareMatch;
/* A 1ms tick does not require the use of the timer prescale. This is /* A 1ms tick does not require the use of the timer prescale. This is
* defaulted to zero but can be used if necessary. */ defaulted to zero but can be used if necessary. */
T0PR = portPRESCALE_VALUE; T0PR = portPRESCALE_VALUE;
/* Calculate the match value required for our wanted tick rate. */ /* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ; ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Protect against divide by zero. Using an if() statement still results /* Protect against divide by zero. Using an if() statement still results
* in a warning - hence the #if. */ in a warning - hence the #if. */
#if portPRESCALE_VALUE != 0 #if portPRESCALE_VALUE != 0
{ {
ulCompareMatch /= ( portPRESCALE_VALUE + 1 ); ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
@ -260,7 +258,7 @@ static void prvSetupTimerInterrupt( void )
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT; VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
/* The ISR installed depends on whether the preemptive or cooperative /* The ISR installed depends on whether the preemptive or cooperative
* scheduler is being used. */ scheduler is being used. */
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
{ {
extern void ( vPortPreemptiveTickEntry )( void ); extern void ( vPortPreemptiveTickEntry )( void );
@ -273,12 +271,12 @@ static void prvSetupTimerInterrupt( void )
VICVectAddr0 = ( int32_t ) vPortNonPreemptiveTick; VICVectAddr0 = ( int32_t ) vPortNonPreemptiveTick;
} }
#endif /* if configUSE_PREEMPTION == 1 */ #endif
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE; VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
/* Start the timer - interrupts are disabled when this function is called /* Start the timer - interrupts are disabled when this function is called
* so it is okay to do this here. */ so it is okay to do this here. */
T0TCR = portENABLE_TIMER; T0TCR = portENABLE_TIMER;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -289,8 +287,8 @@ void vPortEnterCritical( void )
__disable_interrupt(); __disable_interrupt();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -303,7 +301,7 @@ void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
* re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
__enable_interrupt(); __enable_interrupt();
@ -311,3 +309,9 @@ void vPortExitCritical( void )
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -109,3 +109,5 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -34,24 +34,24 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Constants required for hardware setup. The tick ISR runs off the ACLK, /* Constants required for hardware setup. The tick ISR runs off the ACLK,
* not the MCLK. */ not the MCLK. */
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 ) #define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 ) #define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 ) #define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
* any details of its type. */ any details of its type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
/* Each task maintains a count of the critical section nesting depth. Each /* Each task maintains a count of the critical section nesting depth. Each
* time a critical section is entered the count is incremented. Each time a time a critical section is entered the count is incremented. Each time a
* critical section is exited the count is decremented - with interrupts only critical section is exited the count is decremented - with interrupts only
* being re-enabled if the count is zero. being re-enabled if the count is zero.
*
* usCriticalNesting will get set to zero when the scheduler starts, but must usCriticalNesting will get set to zero when the scheduler starts, but must
* not be initialised to zero as this will cause problems during the startup not be initialised to zero as this will cause problems during the startup
* sequence. */ sequence. */
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING; volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -69,26 +69,24 @@ void vPortSetupTimerInterrupt( void );
* *
* See the header file portable.h. * See the header file portable.h.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* /*
* Place a few bytes of known values on the bottom of the stack. Place a few bytes of known values on the bottom of the stack.
* This is just useful for debugging and can be included if required. This is just useful for debugging and can be included if required.
*
*pxTopOfStack = ( StackType_t ) 0x1111; *pxTopOfStack = ( StackType_t ) 0x1111;
* pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x2222; *pxTopOfStack = ( StackType_t ) 0x2222;
* pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x3333; *pxTopOfStack = ( StackType_t ) 0x3333;
* pxTopOfStack--; pxTopOfStack--;
*/ */
/* The msp430 automatically pushes the PC then SR onto the stack before /* The msp430 automatically pushes the PC then SR onto the stack before
* executing an ISR. We want the stack to look just as if this has happened executing an ISR. We want the stack to look just as if this has happened
* so place a pointer to the start of the task on the stack first - followed so place a pointer to the start of the task on the stack first - followed
* by the flags we want the task to use when it starts up. */ by the flags we want the task to use when it starts up. */
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED; *pxTopOfStack = portFLAGS_INT_ENABLED;
@ -113,7 +111,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
* R15. */ R15. */
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
@ -125,12 +123,12 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* A variable is used to keep track of the critical section nesting. /* A variable is used to keep track of the critical section nesting.
* This variable has to be stored as part of the task context and is This variable has to be stored as part of the task context and is
* initially set to zero. */ initially set to zero. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack we have generated so this can /* Return a pointer to the top of the stack we have generated so this can
* be stored in the task control block for the task. */ be stored in the task control block for the task. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -138,7 +136,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the MSP430 port will get stopped. If required simply /* It is unlikely that the MSP430 port will get stopped. If required simply
* disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -170,3 +168,6 @@ void vPortSetupTimerInterrupt( void )
TACTL |= MC_1; TACTL |= MC_1;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -72,12 +72,13 @@ pop r5
pop r4 pop r4
/* The last thing on the stack will be the status register. /* The last thing on the stack will be the status register.
* Ensure the power down bits are clear ready for the next Ensure the power down bits are clear ready for the next
* time this power down register is popped from the stack. */ time this power down register is popped from the stack. */
bic.w #0xf0,0(SP) bic.w #0xf0,0(SP)
reti reti
endm endm
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#endif /* ifndef PORTASM_H */ #endif

View file

@ -130,3 +130,4 @@ extern void vPortYield( void );
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -60,3 +60,4 @@
#endif #endif
#endif /* DATA_MODEL_H */ #endif /* DATA_MODEL_H */

View file

@ -34,24 +34,24 @@
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Constants required for hardware setup. The tick ISR runs off the ACLK, /* Constants required for hardware setup. The tick ISR runs off the ACLK,
* not the MCLK. */ not the MCLK. */
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 ) #define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 ) #define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 ) #define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
* any details of its type. */ any details of its type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
/* Each task maintains a count of the critical section nesting depth. Each /* Each task maintains a count of the critical section nesting depth. Each
* time a critical section is entered the count is incremented. Each time a time a critical section is entered the count is incremented. Each time a
* critical section is exited the count is decremented - with interrupts only critical section is exited the count is decremented - with interrupts only
* being re-enabled if the count is zero. being re-enabled if the count is zero.
*
* usCriticalNesting will get set to zero when the scheduler starts, but must usCriticalNesting will get set to zero when the scheduler starts, but must
* not be initialised to zero as this will cause problems during the startup not be initialised to zero as this will cause problems during the startup
* sequence. */ sequence. */
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING; volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -69,28 +69,26 @@ void vPortSetupTimerInterrupt( void );
* *
* See the header file portable.h. * See the header file portable.h.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
uint16_t *pusTopOfStack; uint16_t *pusTopOfStack;
uint32_t *pulTopOfStack; uint32_t *pulTopOfStack;
/* /*
* Place a few bytes of known values on the bottom of the stack. Place a few bytes of known values on the bottom of the stack.
* This is just useful for debugging and can be included if required. This is just useful for debugging and can be included if required.
*
*pxTopOfStack = ( StackType_t ) 0x1111; *pxTopOfStack = ( StackType_t ) 0x1111;
* pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x2222; *pxTopOfStack = ( StackType_t ) 0x2222;
* pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x3333; *pxTopOfStack = ( StackType_t ) 0x3333;
*/ */
/* StackType_t is either 16 bits or 32 bits depending on the data model. /* StackType_t is either 16 bits or 32 bits depending on the data model.
* Some stacked items do not change size depending on the data model so have Some stacked items do not change size depending on the data model so have
* to be explicitly cast to the correct size so this function will work to be explicitly cast to the correct size so this function will work
* whichever data model is being used. */ whichever data model is being used. */
if( sizeof( StackType_t ) == sizeof( uint16_t ) ) if( sizeof( StackType_t ) == sizeof( uint16_t ) )
{ {
/* Make room for a 20 bit value stored as a 32 bit value. */ /* Make room for a 20 bit value stored as a 32 bit value. */
@ -102,7 +100,6 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
{ {
pulTopOfStack = ( uint32_t * ) pxTopOfStack; pulTopOfStack = ( uint32_t * ) pxTopOfStack;
} }
*pulTopOfStack = ( uint32_t ) pxCode; *pulTopOfStack = ( uint32_t ) pxCode;
pusTopOfStack = ( uint16_t * ) pulTopOfStack; pusTopOfStack = ( uint16_t * ) pulTopOfStack;
@ -139,20 +136,20 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x4444; *pxTopOfStack = ( StackType_t ) 0x4444;
pxTopOfStack--; pxTopOfStack--;
#else /* ifdef PRELOAD_REGISTER_VALUES */ #else
pxTopOfStack -= 3; pxTopOfStack -= 3;
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack -= 9; pxTopOfStack -= 9;
#endif /* ifdef PRELOAD_REGISTER_VALUES */ #endif
/* A variable is used to keep track of the critical section nesting. /* A variable is used to keep track of the critical section nesting.
* This variable has to be stored as part of the task context and is This variable has to be stored as part of the task context and is
* initially set to zero. */ initially set to zero. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack we have generated so this can /* Return a pointer to the top of the stack we have generated so this can
* be stored in the task control block for the task. */ be stored in the task control block for the task. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -160,7 +157,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the MSP430 port will get stopped. If required simply /* It is unlikely that the MSP430 port will get stopped. If required simply
* disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -181,3 +178,5 @@ __interrupt __raw void vTickISREntry( void )
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF ); __bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
vPortTickISR(); vPortTickISR();
} }

View file

@ -135,7 +135,8 @@ extern void vPortYield( void );
void vApplicationSetupTimerInterrupt( void ); void vApplicationSetupTimerInterrupt( void );
/* sizeof( int ) != sizeof( long ) so a full printf() library is required if /* sizeof( int ) != sizeof( long ) so a full printf() library is required if
* run time stats information is to be displayed. */ run time stats information is to be displayed. */
#define portLU_PRINTF_SPECIFIER_REQUIRED #define portLU_PRINTF_SPECIFIER_REQUIRED
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -38,20 +38,20 @@
#include "string.h" #include "string.h"
#ifdef configCLINT_BASE_ADDRESS #ifdef configCLINT_BASE_ADDRESS
#warning The configCLINT_BASE_ADDRESS constant has been deprecated. configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS are currently being derived from the (possibly 0) configCLINT_BASE_ADDRESS setting. Please update to define configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS dirctly in place of configCLINT_BASE_ADDRESS. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */ #warning The configCLINT_BASE_ADDRESS constant has been deprecated. configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS are currently being derived from the (possibly 0) configCLINT_BASE_ADDRESS setting. Please update to define configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS dirctly in place of configCLINT_BASE_ADDRESS. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#endif #endif
#ifndef configMTIME_BASE_ADDRESS #ifndef configMTIME_BASE_ADDRESS
#warning configMTIME_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtime register then set configMTIME_BASE_ADDRESS to the mapped address. Otherwise set configMTIME_BASE_ADDRESS to 0. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */ #warning configMTIME_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtime register then set configMTIME_BASE_ADDRESS to the mapped address. Otherwise set configMTIME_BASE_ADDRESS to 0. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#endif #endif
#ifndef configMTIMECMP_BASE_ADDRESS #ifndef configMTIMECMP_BASE_ADDRESS
#warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */ #warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#endif #endif
/* Let the user override the pre-loading of the initial LR with the address of /* Let the user override the pre-loading of the initial LR with the address of
* prvTaskExitError() in case it messes up unwinding of the stack in the prvTaskExitError() in case it messes up unwinding of the stack in the
* debugger. */ debugger. */
#ifdef configTASK_RETURN_ADDRESS #ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else #else
@ -59,19 +59,19 @@
#endif #endif
/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS /* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS
* to use a statically allocated array as the interrupt stack. Alternative leave to use a statically allocated array as the interrupt stack. Alternative leave
* configISR_STACK_SIZE_WORDS undefined and update the linker script so that a configISR_STACK_SIZE_WORDS undefined and update the linker script so that a
* linker variable names __freertos_irq_stack_top has the same value as the top linker variable names __freertos_irq_stack_top has the same value as the top
* of the stack used by main. Using the linker script method will repurpose the of the stack used by main. Using the linker script method will repurpose the
* stack that was used by main before the scheduler was started for use as the stack that was used by main before the scheduler was started for use as the
* interrupt stack after the scheduler has started. */ interrupt stack after the scheduler has started. */
#ifdef configISR_STACK_SIZE_WORDS #ifdef configISR_STACK_SIZE_WORDS
static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 }; static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 };
const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] ); const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] );
/* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for /* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for
* the task stacks, and so will legitimately appear in many positions within the task stacks, and so will legitimately appear in many positions within
* the ISR stack. */ the ISR stack. */
#define portISR_STACK_FILL_BYTE 0xee #define portISR_STACK_FILL_BYTE 0xee
#else #else
extern const uint32_t __freertos_irq_stack_top[]; extern const uint32_t __freertos_irq_stack_top[];
@ -95,23 +95,21 @@ uint32_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS;
volatile uint64_t * pullMachineTimerCompareRegister = NULL; volatile uint64_t * pullMachineTimerCompareRegister = NULL;
/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task /* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task
* stack checking. A problem in the ISR stack will trigger an assert, not call the stack checking. A problem in the ISR stack will trigger an assert, not call the
* stack overflow hook function (because the stack overflow hook is specific to a stack overflow hook function (because the stack overflow hook is specific to a
* task stack, not the ISR stack). */ task stack, not the ISR stack). */
#if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 ) #if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 )
#warning This path not tested, or even compiled yet. #warning This path not tested, or even compiled yet.
static const uint8_t ucExpectedStackBytes[] = static const uint8_t ucExpectedStackBytes[] = {
{
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \
portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \
}; \
#define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) )
#else /* if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 ) */ #else
/* Define the function away. */ /* Define the function away. */
#define portCHECK_ISR_STACK() #define portCHECK_ISR_STACK()
#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */ #endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */
@ -128,7 +126,6 @@ volatile uint64_t * pullMachineTimerCompareRegister = NULL;
volatile uint32_t ulHartId; volatile uint32_t ulHartId;
__asm volatile( "csrr %0, 0xf14" : "=r"( ulHartId ) ); /* 0xf14 is hartid. */ __asm volatile( "csrr %0, 0xf14" : "=r"( ulHartId ) ); /* 0xf14 is hartid. */
pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) ); pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) );
do do
@ -159,13 +156,13 @@ BaseType_t xPortStartScheduler( void )
volatile uint32_t mtvec = 0; volatile uint32_t mtvec = 0;
/* Check the least significant two bits of mtvec are 00 - indicating /* Check the least significant two bits of mtvec are 00 - indicating
* single vector mode. */ single vector mode. */
__asm volatile( "csrr %0, 0x305" : "=r"( mtvec ) ); /* 0x305 is mtvec. */ __asm volatile( "csrr %0, 0x305" : "=r"( mtvec ) ); /* 0x305 is mtvec. */
configASSERT( ( mtvec & 0x03UL ) == 0 ); configASSERT( ( mtvec & 0x03UL ) == 0 );
/* Check alignment of the interrupt stack - which is the same as the /* Check alignment of the interrupt stack - which is the same as the
* stack that was being used by main() prior to the scheduler being stack that was being used by main() prior to the scheduler being
* started. */ started. */
configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 ); configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 );
#ifdef configISR_STACK_SIZE_WORDS #ifdef configISR_STACK_SIZE_WORDS
@ -177,15 +174,15 @@ BaseType_t xPortStartScheduler( void )
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* If there is a CLINT then it is ok to use the default implementation /* If there is a CLINT then it is ok to use the default implementation
* in this file, otherwise vPortSetupTimerInterrupt() must be implemented to in this file, otherwise vPortSetupTimerInterrupt() must be implemented to
* configure whichever clock is to be used to generate the tick interrupt. */ configure whichever clock is to be used to generate the tick interrupt. */
vPortSetupTimerInterrupt(); vPortSetupTimerInterrupt();
#if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) ) #if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) )
{ {
/* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11 /* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11
* for external interrupt. _RB_ What happens here when mtime is not present as for external interrupt. _RB_ What happens here when mtime is not present as
* with pulpino? */ with pulpino? */
__asm volatile( "csrs 0x304, %0" :: "r"(0x880) ); /* 0x304 is mie. */ __asm volatile( "csrs 0x304, %0" :: "r"(0x880) ); /* 0x304 is mie. */
} }
#else #else
@ -198,7 +195,7 @@ BaseType_t xPortStartScheduler( void )
xPortStartFirstTask(); xPortStartFirstTask();
/* Should not get here as after calling xPortStartFirstTask() only tasks /* Should not get here as after calling xPortStartFirstTask() only tasks
* should be executing. */ should be executing. */
return pdFAIL; return pdFAIL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -206,7 +203,10 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented. */ /* Not implemented. */
for( ; ; ) for( ;; );
{
}
} }

View file

@ -57,9 +57,9 @@
#define portBASE_TYPE int32_t #define portBASE_TYPE int32_t
#define portUBASE_TYPE uint32_t #define portUBASE_TYPE uint32_t
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#else /* if __riscv_xlen == 64 */ #else
#error Assembler did not define __riscv_xlen #error Assembler did not define __riscv_xlen
#endif /* if __riscv_xlen == 64 */ #endif
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
@ -75,7 +75,7 @@
#define portSHORT short #define portSHORT short
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -124,8 +124,8 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /* Task function macros as described on the FreeRTOS.org WEB site. These are
* not necessary for to use this port. They are defined so the common demo files not necessary for to use this port. They are defined so the common demo files
* (which build with all the ports) will build. */ (which build with all the ports) will build. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
@ -143,31 +143,29 @@
/* Suppress warnings that are generated by the IAR tools, but cannot be fixed in /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in
* the source code because to do so would cause other compilers to generate the source code because to do so would cause other compilers to generate
* warnings. */ warnings. */
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
/* configCLINT_BASE_ADDRESS is a legacy definition that was replaced by the /* configCLINT_BASE_ADDRESS is a legacy definition that was replaced by the
* configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS definitions. For configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS definitions. For
* backward compatibility derive the newer definitions from the old if the old backward compatibility derive the newer definitions from the old if the old
* definition is found. */ definition is found. */
#if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 ) #if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 )
/* Legacy case where configCLINT_BASE_ADDRESS was defined as 0 to indicate /* Legacy case where configCLINT_BASE_ADDRESS was defined as 0 to indicate
* there was no CLINT. Equivalent now is to set the MTIME and MTIMECMP there was no CLINT. Equivalent now is to set the MTIME and MTIMECMP
* addresses to 0. */ addresses to 0. */
#define configMTIME_BASE_ADDRESS ( 0 ) #define configMTIME_BASE_ADDRESS ( 0 )
#define configMTIMECMP_BASE_ADDRESS ( 0 ) #define configMTIMECMP_BASE_ADDRESS ( 0 )
#elif defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) #elif defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS )
/* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of /* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of
* the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses
* from the CLINT address. */ from the CLINT address. */
#define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL ) #define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL )
#define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL ) #define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL )
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS ) #elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS )
#error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https: /*www.freertos.org/Using-FreeRTOS-on-RISC-V.html */ #error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.freertos.org/Using-FreeRTOS-on-RISC-V.html
#endif /* if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 ) */ #endif
@ -176,3 +174,4 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,112 +1,83 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"
; ; Variables used by scheduler
Variables used by scheduler ;------------------------------------------------------------------------------
;
------------------------------------------------------------------------------
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN usCriticalNesting EXTERN usCriticalNesting
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------ ; portSAVE_CONTEXT MACRO
; ; Saves the context of the general purpose registers, CS and ES (only in far
portSAVE_CONTEXT MACRO ; memory mode) registers the usCriticalNesting Value and the Stack Pointer
; ; of the active Task onto the task stack
Saves the context of the general purpose registers, CS and ES( only in far ;------------------------------------------------------------------------------
;
memory mode ) registers the usCriticalNesting Value and the Stack Pointer
;
of the active Task onto the task stack
;
------------------------------------------------------------------------------
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
PUSH AX; PUSH AX ; Save AX Register to stack.
Save AX Register to stack.
PUSH HL PUSH HL
MOV A, CS; MOV A, CS ; Save CS register.
Save CS register.
XCH A, X XCH A, X
MOV A, ES; MOV A, ES ; Save ES register.
Save ES register.
PUSH AX PUSH AX
PUSH DE; PUSH DE ; Save the remaining general purpose registers.
Save the remaining general purpose registers.
PUSH BC PUSH BC
MOVW AX, usCriticalNesting; MOVW AX, usCriticalNesting ; Save the usCriticalNesting value.
Save the usCriticalNesting value.
PUSH AX PUSH AX
MOVW AX, pxCurrentTCB; MOVW AX, pxCurrentTCB ; Save the Stack pointer.
Save the Stack pointer.
MOVW HL, AX MOVW HL, AX
MOVW AX, SP MOVW AX, SP
MOVW [HL], AX MOVW [HL], AX
ENDM ENDM
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------ ; portRESTORE_CONTEXT MACRO
; ; Restores the task Stack Pointer then use this to restore usCriticalNesting,
; general purpose registers and the CS and ES (only in far memory mode)
; of the selected task from the task stack
;------------------------------------------------------------------------------
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; MOVW AX, pxCurrentTCB ; Restore the Stack pointer.
Restores the task Stack Pointer then use this to restore usCriticalNesting,
;
general purpose registers and the CS and ES( only in far memory mode )
;
of the selected task from the task stack
;
------------------------------------------------------------------------------
portRESTORE_CONTEXT MACRO
MOVW AX, pxCurrentTCB;
Restore the Stack pointer.
MOVW HL, AX MOVW HL, AX
MOVW AX, [HL] MOVW AX, [HL]
MOVW SP, AX MOVW SP, AX
POP AX; POP AX ; Restore usCriticalNesting value.
Restore usCriticalNesting value.
MOVW usCriticalNesting, AX MOVW usCriticalNesting, AX
POP BC; POP BC ; Restore the necessary general purpose registers.
Restore the necessary general purpose registers.
POP DE POP DE
POP AX; POP AX ; Restore the ES register.
Restore the ES register.
MOV ES, A MOV ES, A
XCH A, X; XCH A, X ; Restore the CS register.
Restore the CS register.
MOV CS, A MOV CS, A
POP HL; POP HL ; Restore general purpose register HL.
Restore general purpose register HL. POP AX ; Restore AX.
POP AX;
Restore AX.
ENDM ENDM
; ;------------------------------------------------------------------------------
------------------------------------------------------------------------------

View file

@ -30,7 +30,7 @@
#include "task.h" #include "task.h"
/* The critical nesting value is initialised to a non zero value to ensure /* The critical nesting value is initialised to a non zero value to ensure
* interrupts don't accidentally become enabled before the scheduler is started. */ interrupts don't accidentally become enabled before the scheduler is started. */
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 ) #define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
/* Initial PSW value allocated to a newly created task. /* Initial PSW value allocated to a newly created task.
@ -47,18 +47,18 @@
#define portPSW ( 0xc6UL ) #define portPSW ( 0xc6UL )
/* The address of the pxCurrentTCB variable, but don't know or need to know its /* The address of the pxCurrentTCB variable, but don't know or need to know its
* type. */ type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
/* Each task maintains a count of the critical section nesting depth. Each time /* Each task maintains a count of the critical section nesting depth. Each time
* a critical section is entered the count is incremented. Each time a critical a critical section is entered the count is incremented. Each time a critical
* section is exited the count is decremented - with interrupts only being section is exited the count is decremented - with interrupts only being
* re-enabled if the count is zero. re-enabled if the count is zero.
*
* usCriticalNesting will get set to zero when the scheduler starts, but must usCriticalNesting will get set to zero when the scheduler starts, but must
* not be initialised to zero as that could cause problems during the startup not be initialised to zero as that could cause problems during the startup
* sequence. */ sequence. */
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING; volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -71,9 +71,8 @@ volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
*/ */
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
/* The user has not provided their own tick interrupt configuration so use /* The user has not provided their own tick interrupt configuration so use
* the definition in this file (which uses the interval timer). */ the definition in this file (which uses the interval timer). */
#define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt() #define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
@ -96,20 +95,18 @@ static void prvTaskExitError( void );
* *
* See the header file portable.h. * See the header file portable.h.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
uint32_t *pulLocal; uint32_t *pulLocal;
/* With large code and large data sizeof( StackType_t ) == 2, and /* With large code and large data sizeof( StackType_t ) == 2, and
* sizeof( StackType_t * ) == 4. With small code and small data sizeof( StackType_t * ) == 4. With small code and small data
* sizeof( StackType_t ) == 2 and sizeof( StackType_t * ) == 2. */ sizeof( StackType_t ) == 2 and sizeof( StackType_t * ) == 2. */
#if __DATA_MODEL__ == __DATA_MODEL_FAR__ #if __DATA_MODEL__ == __DATA_MODEL_FAR__
{ {
/* Parameters are passed in on the stack, and written using a 32-bit value /* Parameters are passed in on the stack, and written using a 32-bit value
* hence a space is left for the second two bytes. */ hence a space is left for the second two bytes. */
pxTopOfStack--; pxTopOfStack--;
/* Write in the parameter value. */ /* Write in the parameter value. */
@ -118,15 +115,15 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* The return address, leaving space for the first two bytes of the /* The return address, leaving space for the first two bytes of the
* 32-bit value. See the comments above the prvTaskExitError() prototype 32-bit value. See the comments above the prvTaskExitError() prototype
* at the top of this file. */ at the top of this file. */
pxTopOfStack--; pxTopOfStack--;
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) prvTaskExitError; *pulLocal = ( uint32_t ) prvTaskExitError;
pxTopOfStack--; pxTopOfStack--;
/* The start address / PSW value is also written in as a 32-bit value, /* The start address / PSW value is also written in as a 32-bit value,
* so leave a space for the second two bytes. */ so leave a space for the second two bytes. */
pxTopOfStack--; pxTopOfStack--;
/* Task function start address combined with the PSW. */ /* Task function start address combined with the PSW. */
@ -138,18 +135,18 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) 0x1111; *pxTopOfStack = ( StackType_t ) 0x1111;
pxTopOfStack--; pxTopOfStack--;
} }
#else /* if __DATA_MODEL__ == __DATA_MODEL_FAR__ */ #else
{ {
/* The return address, leaving space for the first two bytes of the /* The return address, leaving space for the first two bytes of the
* 32-bit value. See the comments above the prvTaskExitError() prototype 32-bit value. See the comments above the prvTaskExitError() prototype
* at the top of this file. */ at the top of this file. */
pxTopOfStack--; pxTopOfStack--;
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) prvTaskExitError; *pulLocal = ( uint32_t ) prvTaskExitError;
pxTopOfStack--; pxTopOfStack--;
/* Task function. Again as it is written as a 32-bit value a space is /* Task function. Again as it is written as a 32-bit value a space is
* left on the stack for the second two bytes. */ left on the stack for the second two bytes. */
pxTopOfStack--; pxTopOfStack--;
/* Task function start address combined with the PSW. */ /* Task function start address combined with the PSW. */
@ -161,7 +158,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack--;
} }
#endif /* if __DATA_MODEL__ == __DATA_MODEL_FAR__ */ #endif
/* An initial value for the HL register. */ /* An initial value for the HL register. */
*pxTopOfStack = ( StackType_t ) 0x2222; *pxTopOfStack = ( StackType_t ) 0x2222;
@ -178,11 +175,11 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Finally the critical section nesting count is set to zero when the task /* Finally the critical section nesting count is set to zero when the task
* first starts. */ first starts. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* Return a pointer to the top of the stack that has been generated so it /* Return a pointer to the top of the stack that has been generated so it
* can be stored in the task control block for the task. */ can be stored in the task control block for the task. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -190,35 +187,32 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ). should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */ defined, then stop here so application writers can catch the error. */
configASSERT( usCriticalNesting == ~0U ); configASSERT( usCriticalNesting == ~0U );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Setup the hardware to generate the tick. Interrupts are disabled when /* Setup the hardware to generate the tick. Interrupts are disabled when
* this function is called. */ this function is called. */
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
/* Restore the context of the first task that is going to run. */ /* Restore the context of the first task that is going to run. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Execution should not reach here as the tasks are now running! /* Execution should not reach here as the tasks are now running!
* prvSetupTimerInterrupt() is called here to prevent the compiler outputting prvSetupTimerInterrupt() is called here to prevent the compiler outputting
* a warning about a statically declared function not being referenced in the a warning about a statically declared function not being referenced in the
* case that the application writer has provided their own tick interrupt case that the application writer has provided their own tick interrupt
* configuration routine (and defined configSETUP_TICK_INTERRUPT() such that configuration routine (and defined configSETUP_TICK_INTERRUPT() such that
* their own routine will be called in place of prvSetupTimerInterrupt()). */ their own routine will be called in place of prvSetupTimerInterrupt()). */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
return pdTRUE; return pdTRUE;
} }
@ -258,7 +252,7 @@ static void prvSetupTimerInterrupt( void )
/* Enable INTIT interrupt. */ /* Enable INTIT interrupt. */
ITMK = ( uint8_t ) 0; ITMK = ( uint8_t ) 0;
} }
#endif /* ifdef RTCEN */ #endif
#ifdef TMKAEN #ifdef TMKAEN
{ {
@ -280,6 +274,7 @@ static void prvSetupTimerInterrupt( void )
/* Enable INTIT interrupt. */ /* Enable INTIT interrupt. */
TMKAMK = ( uint8_t ) 0; TMKAMK = ( uint8_t ) 0;
} }
#endif /* ifdef TMKAEN */ #endif
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -141,3 +141,4 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -45,11 +45,11 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Tasks should start with interrupts enabled and in Supervisor mode, therefore /* Tasks should start with interrupts enabled and in Supervisor mode, therefore
* PSW is set with U and I set, and PM and IPL clear. */ PSW is set with U and I set, and PM and IPL clear. */
#define portINITIAL_PSW ( ( StackType_t ) 0x00030000 ) #define portINITIAL_PSW ( ( StackType_t ) 0x00030000 )
/* The peripheral clock is divided by this value before being supplying the /* The peripheral clock is divided by this value before being supplying the
* CMT. */ CMT. */
#if ( configUSE_TICKLESS_IDLE == 0 ) #if ( configUSE_TICKLESS_IDLE == 0 )
/* If tickless idle is not used then the divisor can be fixed. */ /* If tickless idle is not used then the divisor can be fixed. */
#define portCLOCK_DIVISOR 8UL #define portCLOCK_DIVISOR 8UL
@ -65,7 +65,7 @@
/* Keys required to lock and unlock access to certain system registers /* Keys required to lock and unlock access to certain system registers
* respectively. */ respectively. */
#define portUNLOCK_KEY 0xA50B #define portUNLOCK_KEY 0xA50B
#define portLOCK_KEY 0xA500 #define portLOCK_KEY 0xA500
@ -91,9 +91,8 @@ __interrupt static void prvTickISR( void );
*/ */
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
/* The user has not provided their own tick interrupt configuration so use /* The user has not provided their own tick interrupt configuration so use
* the definition in this file (which uses the interval timer). */ the definition in this file (which uses the interval timer). */
#define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt() #define configSETUP_TICK_INTERRUPT() prvSetupTimerInterrupt()
#endif /* configSETUP_TICK_INTERRUPT */ #endif /* configSETUP_TICK_INTERRUPT */
@ -118,34 +117,32 @@ static const uint32_t ulMatchValueForOneTick = ( ( configPERIPHERAL_CLOCK_HZ / p
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
/* Holds the maximum number of ticks that can be suppressed - which is /* Holds the maximum number of ticks that can be suppressed - which is
* basically how far into the future an interrupt can be generated. Set basically how far into the future an interrupt can be generated. Set
* during initialisation. This is the maximum possible value that the during initialisation. This is the maximum possible value that the
* compare match register can hold divided by ulMatchValueForOneTick. */ compare match register can hold divided by ulMatchValueForOneTick. */
static const TickType_t xMaximumPossibleSuppressedTicks = USHRT_MAX / ( ( configPERIPHERAL_CLOCK_HZ / portCLOCK_DIVISOR ) / configTICK_RATE_HZ ); static const TickType_t xMaximumPossibleSuppressedTicks = USHRT_MAX / ( ( configPERIPHERAL_CLOCK_HZ / portCLOCK_DIVISOR ) / configTICK_RATE_HZ );
/* Flag set from the tick interrupt to allow the sleep processing to know if /* Flag set from the tick interrupt to allow the sleep processing to know if
* sleep mode was exited because of a tick interrupt, or an interrupt sleep mode was exited because of a tick interrupt, or an interrupt
* generated by something else. */ generated by something else. */
static volatile uint32_t ulTickFlag = pdFALSE; static volatile uint32_t ulTickFlag = pdFALSE;
/* The CMT counter is stopped temporarily each time it is re-programmed. /* The CMT counter is stopped temporarily each time it is re-programmed.
* The following constant offsets the CMT counter match value by the number of The following constant offsets the CMT counter match value by the number of
* CMT counts that would typically be missed while the counter was stopped to CMT counts that would typically be missed while the counter was stopped to
* compensate for the lost time. The large difference between the divided CMT compensate for the lost time. The large difference between the divided CMT
* clock and the CPU clock means it is likely ulStoppedTimerCompensation will clock and the CPU clock means it is likely ulStoppedTimerCompensation will
* equal zero - and be optimised away. */ equal zero - and be optimised away. */
static const uint32_t ulStoppedTimerCompensation = 100UL / ( configCPU_CLOCK_HZ / ( configPERIPHERAL_CLOCK_HZ / portCLOCK_DIVISOR ) ); static const uint32_t ulStoppedTimerCompensation = 100UL / ( configCPU_CLOCK_HZ / ( configPERIPHERAL_CLOCK_HZ / portCLOCK_DIVISOR ) );
#endif /* if configUSE_TICKLESS_IDLE == 1 */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* Offset to end up on 8 byte boundary. */ /* Offset to end up on 8 byte boundary. */
pxTopOfStack--; pxTopOfStack--;
@ -160,8 +157,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
/* When debugging it can be useful if every register is set to a known /* When debugging it can be useful if every register is set to a known
* value. Otherwise code space can be saved by just setting the registers value. Otherwise code space can be saved by just setting the registers
* that need to be set. */ that need to be set. */
#ifdef USE_FULL_REGISTER_INITIALISATION #ifdef USE_FULL_REGISTER_INITIALISATION
{ {
pxTopOfStack--; pxTopOfStack--;
@ -194,13 +191,13 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = 0x22222222; *pxTopOfStack = 0x22222222;
pxTopOfStack--; pxTopOfStack--;
} }
#else /* ifdef USE_FULL_REGISTER_INITIALISATION */ #else
{ {
/* Leave space for the registers that will get popped from the stack /* Leave space for the registers that will get popped from the stack
* when the task first starts executing. */ when the task first starts executing. */
pxTopOfStack -= 15; pxTopOfStack -= 15;
} }
#endif /* ifdef USE_FULL_REGISTER_INITIALISATION */ #endif
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */
pxTopOfStack--; pxTopOfStack--;
@ -218,10 +215,10 @@ BaseType_t xPortStartScheduler( void )
if( pxCurrentTCB != NULL ) if( pxCurrentTCB != NULL )
{ {
/* Call an application function to set up the timer that will generate /* Call an application function to set up the timer that will generate
* the tick interrupt. This way the application can decide which the tick interrupt. This way the application can decide which
* peripheral to use. If tickless mode is used then the default peripheral to use. If tickless mode is used then the default
* implementation defined in this file (which uses CMT0) should not be implementation defined in this file (which uses CMT0) should not be
* overridden. */ overridden. */
configSETUP_TICK_INTERRUPT(); configSETUP_TICK_INTERRUPT();
/* Enable the software interrupt. */ /* Enable the software interrupt. */
@ -238,11 +235,11 @@ BaseType_t xPortStartScheduler( void )
} }
/* Execution should not reach here as the tasks are now running! /* Execution should not reach here as the tasks are now running!
* prvSetupTimerInterrupt() is called here to prevent the compiler outputting prvSetupTimerInterrupt() is called here to prevent the compiler outputting
* a warning about a statically declared function not being referenced in the a warning about a statically declared function not being referenced in the
* case that the application writer has provided their own tick interrupt case that the application writer has provided their own tick interrupt
* configuration routine (and defined configSETUP_TICK_INTERRUPT() such that configuration routine (and defined configSETUP_TICK_INTERRUPT() such that
* their own routine will be called in place of prvSetupTimerInterrupt()). */ their own routine will be called in place of prvSetupTimerInterrupt()). */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Should not get here. */ /* Should not get here. */
@ -257,7 +254,7 @@ __interrupt static void prvTickISR( void )
__enable_interrupt(); __enable_interrupt();
/* Increment the tick, and perform any processing the new tick value /* Increment the tick, and perform any processing the new tick value
* necessitates. */ necessitates. */
__set_interrupt_level( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __set_interrupt_level( configMAX_SYSCALL_INTERRUPT_PRIORITY );
{ {
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
@ -273,7 +270,7 @@ __interrupt static void prvTickISR( void )
ulTickFlag = pdTRUE; ulTickFlag = pdTRUE;
/* If this is the first tick since exiting tickless mode then the CMT /* If this is the first tick since exiting tickless mode then the CMT
* compare match value needs resetting. */ compare match value needs resetting. */
CMT0.CMCOR = ( uint16_t ) ulMatchValueForOneTick; CMT0.CMCOR = ( uint16_t ) ulMatchValueForOneTick;
} }
#endif #endif
@ -283,7 +280,7 @@ __interrupt static void prvTickISR( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */ Artificially force an assert. */
configASSERT( pxCurrentTCB == NULL ); configASSERT( pxCurrentTCB == NULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -322,11 +319,11 @@ static void prvSetupTimerInterrupt( void )
{ {
CMT0.CMCR.BIT.CKS = 0; CMT0.CMCR.BIT.CKS = 0;
} }
#else /* if portCLOCK_DIVISOR == 512 */ #else
{ {
#error Invalid portCLOCK_DIVISOR setting #error Invalid portCLOCK_DIVISOR setting
} }
#endif /* if portCLOCK_DIVISOR == 512 */ #endif
/* Enable the interrupt... */ /* Enable the interrupt... */
@ -348,8 +345,8 @@ static void prvSetupTimerInterrupt( void )
configPRE_SLEEP_PROCESSING( xExpectedIdleTime ); configPRE_SLEEP_PROCESSING( xExpectedIdleTime );
/* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING() /* xExpectedIdleTime being set to 0 by configPRE_SLEEP_PROCESSING()
* means the application defined code has already executed the WAIT means the application defined code has already executed the WAIT
* instruction. */ instruction. */
if( xExpectedIdleTime > 0 ) if( xExpectedIdleTime > 0 )
{ {
__wait_for_interrupt(); __wait_for_interrupt();
@ -378,41 +375,38 @@ static void prvSetupTimerInterrupt( void )
} }
/* Calculate the reload value required to wait xExpectedIdleTime tick /* Calculate the reload value required to wait xExpectedIdleTime tick
* periods. */ periods. */
ulMatchValue = ulMatchValueForOneTick * xExpectedIdleTime; ulMatchValue = ulMatchValueForOneTick * xExpectedIdleTime;
if( ulMatchValue > ulStoppedTimerCompensation ) if( ulMatchValue > ulStoppedTimerCompensation )
{ {
/* Compensate for the fact that the CMT is going to be stopped /* Compensate for the fact that the CMT is going to be stopped
* momentarily. */ momentarily. */
ulMatchValue -= ulStoppedTimerCompensation; ulMatchValue -= ulStoppedTimerCompensation;
} }
/* Stop the CMT momentarily. The time the CMT is stopped for is /* Stop the CMT momentarily. The time the CMT is stopped for is
* accounted for as best it can be, but using the tickless mode will accounted for as best it can be, but using the tickless mode will
* inevitably result in some tiny drift of the time maintained by the inevitably result in some tiny drift of the time maintained by the
* kernel with respect to calendar time. */ kernel with respect to calendar time. */
CMT.CMSTR0.BIT.STR0 = 0; CMT.CMSTR0.BIT.STR0 = 0;
while( CMT.CMSTR0.BIT.STR0 == 1 ) while( CMT.CMSTR0.BIT.STR0 == 1 )
{ {
/* Nothing to do here. */ /* Nothing to do here. */
} }
/* Critical section using the global interrupt bit as the i bit is /* Critical section using the global interrupt bit as the i bit is
* automatically reset by the WAIT instruction. */ automatically reset by the WAIT instruction. */
__disable_interrupt(); __disable_interrupt();
/* The tick flag is set to false before sleeping. If it is true when /* The tick flag is set to false before sleeping. If it is true when
* sleep mode is exited then sleep mode was probably exited because the sleep mode is exited then sleep mode was probably exited because the
* tick was suppressed for the entire xExpectedIdleTime period. */ tick was suppressed for the entire xExpectedIdleTime period. */
ulTickFlag = pdFALSE; ulTickFlag = pdFALSE;
/* If a context switch is pending then abandon the low power entry as /* If a context switch is pending then abandon the low power entry as
* the context switch might have been pended by an external interrupt that the context switch might have been pended by an external interrupt that
* requires processing. */ requires processing. */
eSleepAction = eTaskConfirmSleepModeStatus(); eSleepAction = eTaskConfirmSleepModeStatus();
if( eSleepAction == eAbortSleep ) if( eSleepAction == eAbortSleep )
{ {
/* Restart tick. */ /* Restart tick. */
@ -431,7 +425,7 @@ static void prvSetupTimerInterrupt( void )
SYSTEM.PRCR.WORD = portLOCK_KEY; SYSTEM.PRCR.WORD = portLOCK_KEY;
/* Sleep until something happens. Calling prvSleep() will /* Sleep until something happens. Calling prvSleep() will
* automatically reset the i bit in the PSW. */ automatically reset the i bit in the PSW. */
prvSleep( xExpectedIdleTime ); prvSleep( xExpectedIdleTime );
/* Restart the CMT. */ /* Restart the CMT. */
@ -451,7 +445,7 @@ static void prvSetupTimerInterrupt( void )
SYSTEM.PRCR.WORD = portLOCK_KEY; SYSTEM.PRCR.WORD = portLOCK_KEY;
/* Adjust the match value to take into account that the current /* Adjust the match value to take into account that the current
* time slice is already partially complete. */ time slice is already partially complete. */
ulMatchValue -= ( uint32_t ) CMT0.CMCNT; ulMatchValue -= ( uint32_t ) CMT0.CMCNT;
CMT0.CMCOR = ( uint16_t ) ulMatchValue; CMT0.CMCOR = ( uint16_t ) ulMatchValue;
@ -460,15 +454,14 @@ static void prvSetupTimerInterrupt( void )
CMT.CMSTR0.BIT.STR0 = 1; CMT.CMSTR0.BIT.STR0 = 1;
/* Sleep until something happens. Calling prvSleep() will /* Sleep until something happens. Calling prvSleep() will
* automatically reset the i bit in the PSW. */ automatically reset the i bit in the PSW. */
prvSleep( xExpectedIdleTime ); prvSleep( xExpectedIdleTime );
/* Stop CMT. Again, the time the SysTick is stopped for is /* Stop CMT. Again, the time the SysTick is stopped for is
* accounted for as best it can be, but using the tickless mode will accounted for as best it can be, but using the tickless mode will
* inevitably result in some tiny drift of the time maintained by the inevitably result in some tiny drift of the time maintained by the
* kernel with respect to calendar time. */ kernel with respect to calendar time. */
CMT.CMSTR0.BIT.STR0 = 0; CMT.CMSTR0.BIT.STR0 = 0;
while( CMT.CMSTR0.BIT.STR0 == 1 ) while( CMT.CMSTR0.BIT.STR0 == 1 )
{ {
/* Nothing to do here. */ /* Nothing to do here. */
@ -479,44 +472,45 @@ static void prvSetupTimerInterrupt( void )
if( ulTickFlag != pdFALSE ) if( ulTickFlag != pdFALSE )
{ {
/* The tick interrupt has already executed, although because /* The tick interrupt has already executed, although because
* this function is called with the scheduler suspended the actual this function is called with the scheduler suspended the actual
* tick processing will not occur until after this function has tick processing will not occur until after this function has
* exited. Reset the match value with whatever remains of this exited. Reset the match value with whatever remains of this
* tick period. */ tick period. */
ulMatchValue = ulMatchValueForOneTick - ulCurrentCount; ulMatchValue = ulMatchValueForOneTick - ulCurrentCount;
CMT0.CMCOR = ( uint16_t ) ulMatchValue; CMT0.CMCOR = ( uint16_t ) ulMatchValue;
/* The tick interrupt handler will already have pended the tick /* The tick interrupt handler will already have pended the tick
* processing in the kernel. As the pending tick will be processing in the kernel. As the pending tick will be
* processed as soon as this function exits, the tick value processed as soon as this function exits, the tick value
* maintained by the tick is stepped forward by one less than the maintained by the tick is stepped forward by one less than the
* time spent sleeping. The actual stepping of the tick appears time spent sleeping. The actual stepping of the tick appears
* later in this function. */ later in this function. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL; ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
} }
else else
{ {
/* Something other than the tick interrupt ended the sleep. /* Something other than the tick interrupt ended the sleep.
* How many complete tick periods passed while the processor was How many complete tick periods passed while the processor was
* sleeping? */ sleeping? */
ulCompleteTickPeriods = ulCurrentCount / ulMatchValueForOneTick; ulCompleteTickPeriods = ulCurrentCount / ulMatchValueForOneTick;
/* The match value is set to whatever fraction of a single tick /* The match value is set to whatever fraction of a single tick
* period remains. */ period remains. */
ulMatchValue = ulCurrentCount - ( ulCompleteTickPeriods * ulMatchValueForOneTick ); ulMatchValue = ulCurrentCount - ( ulCompleteTickPeriods * ulMatchValueForOneTick );
CMT0.CMCOR = ( uint16_t ) ulMatchValue; CMT0.CMCOR = ( uint16_t ) ulMatchValue;
} }
/* Restart the CMT so it runs up to the match value. The match value /* Restart the CMT so it runs up to the match value. The match value
* will get set to the value required to generate exactly one tick period will get set to the value required to generate exactly one tick period
* the next time the CMT interrupt executes. */ the next time the CMT interrupt executes. */
CMT0.CMCNT = 0; CMT0.CMCNT = 0;
CMT.CMSTR0.BIT.STR0 = 1; CMT.CMSTR0.BIT.STR0 = 1;
/* Wind the tick forward by the number of tick periods that the CPU /* Wind the tick forward by the number of tick periods that the CPU
* remained in a low power state. */ remained in a low power state. */
vTaskStepTick( ulCompleteTickPeriods ); vTaskStepTick( ulCompleteTickPeriods );
} }
} }
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */

View file

@ -49,7 +49,7 @@
*/ */
/* Type definitions - these are a bit legacy and not really used now, other than /* Type definitions - these are a bit legacy and not really used now, other than
* portSTACK_TYPE and portBASE_TYPE. */ portSTACK_TYPE and portBASE_TYPE. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
@ -71,7 +71,7 @@
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -94,14 +94,14 @@
#define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) { portYIELD(); } #define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) { portYIELD(); }
/* These macros should not be called directly, but through the /* These macros should not be called directly, but through the
* taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is
* performed if configASSERT() is defined to ensure an assertion handler does not performed if configASSERT() is defined to ensure an assertion handler does not
* inadvertently attempt to lower the IPL when the call to assert was triggered inadvertently attempt to lower the IPL when the call to assert was triggered
* because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY
* when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API
* functions are those that end in FromISR. FreeRTOS maintains a separate functions are those that end in FromISR. FreeRTOS maintains a separate
* interrupt API to ensure API function and interrupt entry is as fast and as interrupt API to ensure API function and interrupt entry is as fast and as
* simple as possible. */ simple as possible. */
#define portENABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) 0 ) #define portENABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) 0 )
#ifdef configASSERT #ifdef configASSERT
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( __get_interrupt_level() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) ) #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( __get_interrupt_level() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
@ -138,8 +138,8 @@
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prevent warnings of undefined behaviour: the order of volatile accesses is /* Prevent warnings of undefined behaviour: the order of volatile accesses is
* undefined - all warnings have been manually checked and are not an issue, and undefined - all warnings have been manually checked and are not an issue, and
* the warnings cannot be prevent by code changes without undesirable effects. */ the warnings cannot be prevent by code changes without undesirable effects. */
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
#ifdef __cplusplus #ifdef __cplusplus
@ -147,3 +147,4 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -42,7 +42,7 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Tasks should start with interrupts enabled and in Supervisor mode, therefore /* Tasks should start with interrupts enabled and in Supervisor mode, therefore
* PSW is set with U and I set, and PM and IPL clear. */ PSW is set with U and I set, and PM and IPL clear. */
#define portINITIAL_PSW ( ( StackType_t ) 0x00030000 ) #define portINITIAL_PSW ( ( StackType_t ) 0x00030000 )
#define portINITIAL_FPSW ( ( StackType_t ) 0x00000100 ) #define portINITIAL_FPSW ( ( StackType_t ) 0x00000100 )
@ -69,9 +69,7 @@ extern void * pxCurrentTCB;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* R0 is not included as it is the stack pointer. */ /* R0 is not included as it is the stack pointer. */
@ -82,8 +80,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
/* When debugging it can be useful if every register is set to a known /* When debugging it can be useful if every register is set to a known
* value. Otherwise code space can be saved by just setting the registers value. Otherwise code space can be saved by just setting the registers
* that need to be set. */ that need to be set. */
#ifdef USE_FULL_REGISTER_INITIALISATION #ifdef USE_FULL_REGISTER_INITIALISATION
{ {
pxTopOfStack--; pxTopOfStack--;
@ -116,11 +114,11 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = 0x22222222; *pxTopOfStack = 0x22222222;
pxTopOfStack--; pxTopOfStack--;
} }
#else /* ifdef USE_FULL_REGISTER_INITIALISATION */ #else
{ {
pxTopOfStack -= 15; pxTopOfStack -= 15;
} }
#endif /* ifdef USE_FULL_REGISTER_INITIALISATION */ #endif
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */
pxTopOfStack--; pxTopOfStack--;
@ -142,8 +140,8 @@ BaseType_t xPortStartScheduler( void )
if( pxCurrentTCB != NULL ) if( pxCurrentTCB != NULL )
{ {
/* Call an application function to set up the timer that will generate the /* Call an application function to set up the timer that will generate the
* tick interrupt. This way the application can decide which peripheral to tick interrupt. This way the application can decide which peripheral to
* use. A demo application is provided to show a suitable example. */ use. A demo application is provided to show a suitable example. */
vApplicationSetupTimerInterrupt(); vApplicationSetupTimerInterrupt();
/* Enable the software interrupt. */ /* Enable the software interrupt. */
@ -171,7 +169,7 @@ __interrupt void vTickISR( void )
__enable_interrupt(); __enable_interrupt();
/* Increment the tick, and perform any processing the new tick value /* Increment the tick, and perform any processing the new tick value
* necessitates. */ necessitates. */
__set_interrupt_level( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __set_interrupt_level( configMAX_SYSCALL_INTERRUPT_PRIORITY );
{ {
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
@ -186,7 +184,10 @@ __interrupt void vTickISR( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */ Artificially force an assert. */
configASSERT( pxCurrentTCB == NULL ); configASSERT( pxCurrentTCB == NULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -46,7 +46,7 @@
*/ */
/* Type definitions - these are a bit legacy and not really used now, other than /* Type definitions - these are a bit legacy and not really used now, other than
* portSTACK_TYPE and portBASE_TYPE. */ portSTACK_TYPE and portBASE_TYPE. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
@ -68,7 +68,7 @@
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -80,9 +80,9 @@
#define portNOP() __no_operation() #define portNOP() __no_operation()
/* Yield equivalent to "*portITU_SWINTR = 0x01; ( void ) *portITU_SWINTR;" /* Yield equivalent to "*portITU_SWINTR = 0x01; ( void ) *portITU_SWINTR;"
* where portITU_SWINTR is the location of the software interrupt register where portITU_SWINTR is the location of the software interrupt register
* (0x000872E0). Don't rely on the assembler to select a register, so instead (0x000872E0). Don't rely on the assembler to select a register, so instead
* save and restore clobbered registers manually. */ save and restore clobbered registers manually. */
#define portYIELD() \ #define portYIELD() \
__asm volatile \ __asm volatile \
( \ ( \
@ -96,14 +96,14 @@
#define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) portYIELD() #define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) portYIELD()
/* These macros should not be called directly, but through the /* These macros should not be called directly, but through the
* taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is
* performed if configASSERT() is defined to ensure an assertion handler does not performed if configASSERT() is defined to ensure an assertion handler does not
* inadvertently attempt to lower the IPL when the call to assert was triggered inadvertently attempt to lower the IPL when the call to assert was triggered
* because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY
* when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API
* functions are those that end in FromISR. FreeRTOS maintains a separate functions are those that end in FromISR. FreeRTOS maintains a separate
* interrupt API to ensure API function and interrupt entry is as fast and as interrupt API to ensure API function and interrupt entry is as fast and as
* simple as possible. */ simple as possible. */
#define portENABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) 0 ) #define portENABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) 0 )
#ifdef configASSERT #ifdef configASSERT
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( __get_interrupt_level() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) ) #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( __get_interrupt_level() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
@ -136,3 +136,4 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -42,7 +42,7 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Tasks should start with interrupts enabled and in Supervisor mode, therefore /* Tasks should start with interrupts enabled and in Supervisor mode, therefore
* PSW is set with U and I set, and PM and IPL clear. */ PSW is set with U and I set, and PM and IPL clear. */
#define portINITIAL_PSW ( ( StackType_t ) 0x00030000 ) #define portINITIAL_PSW ( ( StackType_t ) 0x00030000 )
#define portINITIAL_FPSW ( ( StackType_t ) 0x00000100 ) #define portINITIAL_FPSW ( ( StackType_t ) 0x00000100 )
@ -69,9 +69,7 @@ extern void * pxCurrentTCB;
/* /*
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
/* R0 is not included as it is the stack pointer. */ /* R0 is not included as it is the stack pointer. */
@ -82,8 +80,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) pxCode;
/* When debugging it can be useful if every register is set to a known /* When debugging it can be useful if every register is set to a known
* value. Otherwise code space can be saved by just setting the registers value. Otherwise code space can be saved by just setting the registers
* that need to be set. */ that need to be set. */
#ifdef USE_FULL_REGISTER_INITIALISATION #ifdef USE_FULL_REGISTER_INITIALISATION
{ {
pxTopOfStack--; pxTopOfStack--;
@ -116,11 +114,11 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = 0x22222222; *pxTopOfStack = 0x22222222;
pxTopOfStack--; pxTopOfStack--;
} }
#else /* ifdef USE_FULL_REGISTER_INITIALISATION */ #else
{ {
pxTopOfStack -= 15; pxTopOfStack -= 15;
} }
#endif /* ifdef USE_FULL_REGISTER_INITIALISATION */ #endif
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R1 */
pxTopOfStack--; pxTopOfStack--;
@ -150,8 +148,8 @@ BaseType_t xPortStartScheduler( void )
if( pxCurrentTCB != NULL ) if( pxCurrentTCB != NULL )
{ {
/* Call an application function to set up the timer that will generate the /* Call an application function to set up the timer that will generate the
* tick interrupt. This way the application can decide which peripheral to tick interrupt. This way the application can decide which peripheral to
* use. A demo application is provided to show a suitable example. */ use. A demo application is provided to show a suitable example. */
vApplicationSetupTimerInterrupt(); vApplicationSetupTimerInterrupt();
/* Enable the software interrupt. */ /* Enable the software interrupt. */
@ -179,7 +177,7 @@ __interrupt void vTickISR( void )
__enable_interrupt(); __enable_interrupt();
/* Increment the tick, and perform any processing the new tick value /* Increment the tick, and perform any processing the new tick value
* necessitates. */ necessitates. */
__set_interrupt_level( configMAX_SYSCALL_INTERRUPT_PRIORITY ); __set_interrupt_level( configMAX_SYSCALL_INTERRUPT_PRIORITY );
{ {
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
@ -194,7 +192,10 @@ __interrupt void vTickISR( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */ Artificially force an assert. */
configASSERT( pxCurrentTCB == NULL ); configASSERT( pxCurrentTCB == NULL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -46,7 +46,7 @@
*/ */
/* Type definitions - these are a bit legacy and not really used now, other than /* Type definitions - these are a bit legacy and not really used now, other than
* portSTACK_TYPE and portBASE_TYPE. */ portSTACK_TYPE and portBASE_TYPE. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
@ -68,7 +68,7 @@
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
* not need to be guarded with a critical section. */ not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1 #define portTICK_TYPE_IS_ATOMIC 1
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -80,9 +80,9 @@
#define portNOP() __no_operation() #define portNOP() __no_operation()
/* Yield equivalent to "*portITU_SWINTR = 0x01; ( void ) *portITU_SWINTR;" /* Yield equivalent to "*portITU_SWINTR = 0x01; ( void ) *portITU_SWINTR;"
* where portITU_SWINTR is the location of the software interrupt register where portITU_SWINTR is the location of the software interrupt register
* (0x000872E0). Don't rely on the assembler to select a register, so instead (0x000872E0). Don't rely on the assembler to select a register, so instead
* save and restore clobbered registers manually. */ save and restore clobbered registers manually. */
#define portYIELD() \ #define portYIELD() \
__asm volatile \ __asm volatile \
( \ ( \
@ -96,14 +96,14 @@
#define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) portYIELD() #define portYIELD_FROM_ISR( x ) if( ( x ) != pdFALSE ) portYIELD()
/* These macros should not be called directly, but through the /* These macros should not be called directly, but through the
* taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is taskENTER_CRITICAL() and taskEXIT_CRITICAL() macros. An extra check is
* performed if configASSERT() is defined to ensure an assertion handler does not performed if configASSERT() is defined to ensure an assertion handler does not
* inadvertently attempt to lower the IPL when the call to assert was triggered inadvertently attempt to lower the IPL when the call to assert was triggered
* because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY because the IPL value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY
* when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API when an ISR safe FreeRTOS API function was executed. ISR safe FreeRTOS API
* functions are those that end in FromISR. FreeRTOS maintains a separate functions are those that end in FromISR. FreeRTOS maintains a separate
* interrupt API to ensure API function and interrupt entry is as fast and as interrupt API to ensure API function and interrupt entry is as fast and as
* simple as possible. */ simple as possible. */
#define portENABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) 0 ) #define portENABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) 0 )
#ifdef configASSERT #ifdef configASSERT
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( __get_interrupt_level() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) ) #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( __get_interrupt_level() <= configMAX_SYSCALL_INTERRUPT_PRIORITY ) )
@ -132,8 +132,8 @@
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
/* Prevent warnings of undefined behaviour: the order of volatile accesses is /* Prevent warnings of undefined behaviour: the order of volatile accesses is
* undefined - all warnings have been manually checked and are not an issue, and undefined - all warnings have been manually checked and are not an issue, and
* the warnings cannot be prevent by code changes without undesirable effects. */ the warnings cannot be prevent by code changes without undesirable effects. */
#pragma diag_suppress=Pa082 #pragma diag_suppress=Pa082
#ifdef __cplusplus #ifdef __cplusplus
@ -141,3 +141,4 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,71 +1,63 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Context save and restore macro definitions ; Context save and restore macro definitions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
; ; Push R0 as we are going to use the register.
Push R0 as we are going to use the register.
STMDB SP!, {R0} STMDB SP!, {R0}
; ; Set R0 to point to the task stack pointer.
Set R0 to point to the task stack pointer.
STMDB SP, {SP}^ STMDB SP, {SP}^
NOP NOP
SUB SP, SP, #4 SUB SP, SP, #4
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push the return address onto the stack.
Push the return address onto the stack.
STMDB R0!, {LR} STMDB R0!, {LR}
; ; Now we have saved LR we can use it instead of R0.
Now we have saved LR we can use it instead of R0.
MOV LR, R0 MOV LR, R0
; ; Pop R0 so we can save it onto the system mode stack.
Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Push all the system mode registers onto the task stack.
STMDB LR, {R0-LR}^ STMDB LR, {R0-LR}^
NOP NOP
SUB LR, LR, #60 SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push the SPSR onto the task stack.
MRS R0, SPSR MRS R0, SPSR
STMDB LR!, {R0} STMDB LR!, {R0}
@ -73,8 +65,7 @@ LDR R0, = ulCriticalNesting
LDR R0, [R0] LDR R0, [R0]
STMDB LR!, {R0} STMDB LR!, {R0}
; ; Store the new top of stack for the task.
Store the new top of stack for the task.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
STR LR, [R0] STR LR, [R0]
@ -84,40 +75,31 @@ ENDM
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; ; Set the LR to the task stack.
Set the LR to the task stack.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
LDR LR, [R0] LDR LR, [R0]
; ; The critical nesting depth is the first item on the stack.
The critical nesting depth is the first item on the stack. ; Load it into the ulCriticalNesting variable.
;
Load it into the ulCriticalNesting variable.
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
LDMFD LR!, {R1} LDMFD LR!, {R1}
STR R1, [R0] STR R1, [R0]
; ; Get the SPSR from the stack.
Get the SPSR from the stack.
LDMFD LR!, {R0} LDMFD LR!, {R0}
MSR SPSR_cxsf, R0 MSR SPSR_cxsf, R0
; ; Restore all system mode registers for the task.
Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^ LDMFD LR, {R0-R14}^
NOP NOP
; ; Restore the return address.
Restore the return address.
LDR LR, [LR, #+60] LDR LR, [LR, #+60]
; ; And return - correcting the offset in the LR to obtain the
; correct address.
And return -correcting the offset in the LR to obtain the
;
correct address.
SUBS PC, LR, #4 SUBS PC, LR, #4
ENDM ENDM

View file

@ -57,13 +57,13 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* ulCriticalNesting will get set to zero when the first task starts. It /* ulCriticalNesting will get set to zero when the first task starts. It
* cannot be initialised to 0 as this will cause interrupts to be enabled cannot be initialised to 0 as this will cause interrupts to be enabled
* during the kernel initialisation process. */ during the kernel initialisation process. */
uint32_t ulCriticalNesting = ( uint32_t ) 9999; uint32_t ulCriticalNesting = ( uint32_t ) 9999;
/* Tick interrupt routines for cooperative and preemptive operation /* Tick interrupt routines for cooperative and preemptive operation
* respectively. The preemptive version is not defined as __irq as it is called respectively. The preemptive version is not defined as __irq as it is called
* from an asm wrapper function. */ from an asm wrapper function. */
__arm __irq void vPortNonPreemptiveTick( void ); __arm __irq void vPortNonPreemptiveTick( void );
void vPortPreemptiveTick( void ); void vPortPreemptiveTick( void );
@ -75,24 +75,22 @@ void vPortPreemptiveTick( void );
* *
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
* is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
* start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
* as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -126,7 +124,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
* R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
@ -142,8 +140,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Interrupt flags cannot always be stored on the stack and will /* Interrupt flags cannot always be stored on the stack and will
* instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
* tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -155,7 +153,7 @@ BaseType_t xPortStartScheduler( void )
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -169,17 +167,17 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
* is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* The cooperative scheduler requires a normal IRQ service routine to /* The cooperative scheduler requires a normal IRQ service routine to
* simply increment the system tick. */ simply increment the system tick. */
__arm __irq void vPortNonPreemptiveTick( void ) __arm __irq void vPortNonPreemptiveTick( void )
{ {
/* Increment the tick count - which may wake some tasks but as the /* Increment the tick count - which may wake some tasks but as the
* preemptive scheduler is not being used any woken task is not given preemptive scheduler is not being used any woken task is not given
* processor time no matter what its priority. */ processor time no matter what its priority. */
xTaskIncrementTick(); xTaskIncrementTick();
/* Clear the interrupt in the watchdog and EIC. */ /* Clear the interrupt in the watchdog and EIC. */
@ -189,7 +187,7 @@ __arm __irq void vPortNonPreemptiveTick( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* This function is called from an asm wrapper, so does not require the __irq /* This function is called from an asm wrapper, so does not require the __irq
* keyword. */ keyword. */
void vPortPreemptiveTick( void ) void vPortPreemptiveTick( void )
{ {
/* Increment the tick counter. */ /* Increment the tick counter. */
@ -219,7 +217,7 @@ static void prvSetupTimerInterrupt( void )
WDG_ECITConfig( ENABLE ); WDG_ECITConfig( ENABLE );
/* Start the timer - interrupts are actually disabled at this point so /* Start the timer - interrupts are actually disabled at this point so
* it is safe to do this here. */ it is safe to do this here. */
WDG_CntOnOffConfig( ENABLE ); WDG_CntOnOffConfig( ENABLE );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -230,8 +228,8 @@ __arm __interwork void vPortEnterCritical( void )
__disable_interrupt(); __disable_interrupt();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -244,7 +242,7 @@ __arm __interwork void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
* re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
__enable_interrupt(); __enable_interrupt();
@ -252,3 +250,9 @@ __arm __interwork void vPortExitCritical( void )
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -117,3 +117,5 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,71 +1,63 @@
;/* ;/*
* ; * 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
* ; * the Software without restriction, including without limitation the rights to ; * the Software without restriction, including without limitation the rights to
* ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of ; * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* ; * the Software, and to permit persons to whom the Software is furnished to do so, ; * the Software, and to permit persons to whom the Software is furnished to do so,
* ; * subject to the following conditions: ; * subject to the following conditions:
* ; * ; *
* ; * The above copyright notice and this permission notice shall be included in all ; * The above copyright notice and this permission notice shall be included in all
* ; * copies or substantial portions of the Software. ; * copies or substantial portions of the Software.
* ; * ; *
* ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS ; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR ; * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER ; * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN ; * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ; * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* ; * ; *
* ; * http://www.FreeRTOS.org ; * http://www.FreeRTOS.org
* ; * http://aws.amazon.com/freertos ; * http://aws.amazon.com/freertos
* ; * ; *
* ; * 1 tab == 4 spaces! ; * 1 tab == 4 spaces!
* ; */ ; */
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Context save and restore macro definitions ; Context save and restore macro definitions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
; ; Push R0 as we are going to use the register.
Push R0 as we are going to use the register.
STMDB SP!, {R0} STMDB SP!, {R0}
; ; Set R0 to point to the task stack pointer.
Set R0 to point to the task stack pointer.
STMDB SP, {SP}^ STMDB SP, {SP}^
NOP NOP
SUB SP, SP, #4 SUB SP, SP, #4
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push the return address onto the stack.
Push the return address onto the stack.
STMDB R0!, {LR} STMDB R0!, {LR}
; ; Now we have saved LR we can use it instead of R0.
Now we have saved LR we can use it instead of R0.
MOV LR, R0 MOV LR, R0
; ; Pop R0 so we can save it onto the system mode stack.
Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Push all the system mode registers onto the task stack.
STMDB LR, {R0-LR}^ STMDB LR, {R0-LR}^
NOP NOP
SUB LR, LR, #60 SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push the SPSR onto the task stack.
MRS R0, SPSR MRS R0, SPSR
STMDB LR!, {R0} STMDB LR!, {R0}
@ -73,8 +65,7 @@ LDR R0, = ulCriticalNesting
LDR R0, [R0] LDR R0, [R0]
STMDB LR!, {R0} STMDB LR!, {R0}
; ; Store the new top of stack for the task.
Store the new top of stack for the task.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
STR LR, [R0] STR LR, [R0]
@ -84,40 +75,31 @@ ENDM
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; ; Set the LR to the task stack.
Set the LR to the task stack.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
LDR LR, [R0] LDR LR, [R0]
; ; The critical nesting depth is the first item on the stack.
The critical nesting depth is the first item on the stack. ; Load it into the ulCriticalNesting variable.
;
Load it into the ulCriticalNesting variable.
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
LDMFD LR!, {R1} LDMFD LR!, {R1}
STR R1, [R0] STR R1, [R0]
; ; Get the SPSR from the stack.
Get the SPSR from the stack.
LDMFD LR!, {R0} LDMFD LR!, {R0}
MSR SPSR_cxsf, R0 MSR SPSR_cxsf, R0
; ; Restore all system mode registers for the task.
Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^ LDMFD LR, {R0-R14}^
NOP NOP
; ; Restore the return address.
Restore the return address.
LDR LR, [LR, #+60] LDR LR, [LR, #+60]
; ; And return - correcting the offset in the LR to obtain the
; correct address.
And return -correcting the offset in the LR to obtain the
;
correct address.
SUBS PC, LR, #4 SUBS PC, LR, #4
ENDM ENDM

View file

@ -55,8 +55,8 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* ulCriticalNesting will get set to zero when the first task starts. It /* ulCriticalNesting will get set to zero when the first task starts. It
* cannot be initialised to 0 as this will cause interrupts to be enabled cannot be initialised to 0 as this will cause interrupts to be enabled
* during the kernel initialisation process. */ during the kernel initialisation process. */
uint32_t ulCriticalNesting = ( uint32_t ) 9999; uint32_t ulCriticalNesting = ( uint32_t ) 9999;
/* Tick interrupt routines for preemptive operation. */ /* Tick interrupt routines for preemptive operation. */
@ -70,24 +70,22 @@ __arm void vPortPreemptiveTick( void );
* *
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
* is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
* start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
* as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -121,7 +119,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
* R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
@ -130,8 +128,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Interrupt flags cannot always be stored on the stack and will /* Interrupt flags cannot always be stored on the stack and will
* instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
* tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -143,7 +141,7 @@ BaseType_t xPortStartScheduler( void )
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -157,7 +155,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
* is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -209,8 +207,8 @@ __arm __interwork void vPortEnterCritical( void )
__disable_interrupt(); __disable_interrupt();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -223,7 +221,7 @@ __arm __interwork void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
* re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
__enable_interrupt(); __enable_interrupt();
@ -231,3 +229,9 @@ __arm __interwork void vPortExitCritical( void )
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -108,3 +108,5 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -28,44 +28,36 @@
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulCriticalNesting EXTERN ulCriticalNesting
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Context save and restore macro definitions ; Context save and restore macro definitions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
; ; Push R0 as we are going to use the register.
Push R0 as we are going to use the register.
STMDB SP!, {R0} STMDB SP!, {R0}
; ; Set R0 to point to the task stack pointer.
Set R0 to point to the task stack pointer.
STMDB SP, {SP}^ STMDB SP, {SP}^
NOP NOP
SUB SP, SP, #4 SUB SP, SP, #4
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push the return address onto the stack.
Push the return address onto the stack.
STMDB R0!, {LR} STMDB R0!, {LR}
; ; Now we have saved LR we can use it instead of R0.
Now we have saved LR we can use it instead of R0.
MOV LR, R0 MOV LR, R0
; ; Pop R0 so we can save it onto the system mode stack.
Pop R0 so we can save it onto the system mode stack.
LDMIA SP!, {R0} LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Push all the system mode registers onto the task stack.
STMDB LR, {R0-LR}^ STMDB LR, {R0-LR}^
NOP NOP
SUB LR, LR, #60 SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push the SPSR onto the task stack.
MRS R0, SPSR MRS R0, SPSR
STMDB LR!, {R0} STMDB LR!, {R0}
@ -73,8 +65,7 @@ LDR R0, = ulCriticalNesting
LDR R0, [R0] LDR R0, [R0]
STMDB LR!, {R0} STMDB LR!, {R0}
; ; Store the new top of stack for the task.
Store the new top of stack for the task.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
STR LR, [R0] STR LR, [R0]
@ -84,40 +75,31 @@ ENDM
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
; ; Set the LR to the task stack.
Set the LR to the task stack.
LDR R1, =pxCurrentTCB LDR R1, =pxCurrentTCB
LDR R0, [R1] LDR R0, [R1]
LDR LR, [R0] LDR LR, [R0]
; ; The critical nesting depth is the first item on the stack.
The critical nesting depth is the first item on the stack. ; Load it into the ulCriticalNesting variable.
;
Load it into the ulCriticalNesting variable.
LDR R0, =ulCriticalNesting LDR R0, =ulCriticalNesting
LDMFD LR!, {R1} LDMFD LR!, {R1}
STR R1, [R0] STR R1, [R0]
; ; Get the SPSR from the stack.
Get the SPSR from the stack.
LDMFD LR!, {R0} LDMFD LR!, {R0}
MSR SPSR_cxsf, R0 MSR SPSR_cxsf, R0
; ; Restore all system mode registers for the task.
Restore all system mode registers for the task.
LDMFD LR, {R0-R14}^ LDMFD LR, {R0-R14}^
NOP NOP
; ; Restore the return address.
Restore the return address.
LDR LR, [LR, #+60] LDR LR, [LR, #+60]
; ; And return - correcting the offset in the LR to obtain the
; correct address.
And return -correcting the offset in the LR to obtain the
;
correct address.
SUBS PC, LR, #4 SUBS PC, LR, #4
ENDM ENDM

View file

@ -90,13 +90,13 @@
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/* ulCriticalNesting will get set to zero when the first task starts. It /* ulCriticalNesting will get set to zero when the first task starts. It
* cannot be initialised to 0 as this will cause interrupts to be enabled cannot be initialised to 0 as this will cause interrupts to be enabled
* during the kernel initialisation process. */ during the kernel initialisation process. */
uint32_t ulCriticalNesting = ( uint32_t ) 9999; uint32_t ulCriticalNesting = ( uint32_t ) 9999;
/* Tick interrupt routines for cooperative and preemptive operation /* Tick interrupt routines for cooperative and preemptive operation
* respectively. The preemptive version is not defined as __irq as it is called respectively. The preemptive version is not defined as __irq as it is called
* from an asm wrapper function. */ from an asm wrapper function. */
void WDG_IRQHandler( void ); void WDG_IRQHandler( void );
/* VIC interrupt default handler. */ /* VIC interrupt default handler. */
@ -115,24 +115,22 @@ static void prvDefaultHandler( void );
* *
* See header file for description. * See header file for description.
*/ */
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
StackType_t *pxOriginalTOS; StackType_t *pxOriginalTOS;
pxOriginalTOS = pxTopOfStack; pxOriginalTOS = pxTopOfStack;
/* To ensure asserts in tasks.c don't fail, although in this case the assert /* To ensure asserts in tasks.c don't fail, although in this case the assert
* is not really required. */ is not really required. */
pxTopOfStack--; pxTopOfStack--;
/* Setup the initial stack of the task. The stack is set exactly as /* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. */ expected by the portRESTORE_CONTEXT() macro. */
/* First on the stack is the return address - which in this case is the /* First on the stack is the return address - which in this case is the
* start of the task. The offset is added to make the return address appear start of the task. The offset is added to make the return address appear
* as it would within an IRQ ISR. */ as it would within an IRQ ISR. */
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; *pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
pxTopOfStack--; pxTopOfStack--;
@ -166,7 +164,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* When the task starts is will expect to find the function parameter in
* R0. */ R0. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--; pxTopOfStack--;
@ -175,8 +173,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--; pxTopOfStack--;
/* Interrupt flags cannot always be stored on the stack and will /* Interrupt flags cannot always be stored on the stack and will
* instead be stored in a variable, which is then saved as part of the instead be stored in a variable, which is then saved as part of the
* tasks context. */ tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack; return pxTopOfStack;
@ -188,7 +186,7 @@ BaseType_t xPortStartScheduler( void )
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/* Start the timer that generates the tick ISR. Interrupts are disabled /* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */ here already. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Start the first task. */ /* Start the first task. */
@ -202,20 +200,18 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the ARM port will require this function as there /* It is unlikely that the ARM port will require this function as there
* is nothing to return to. */ is nothing to return to. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* This function is called from an asm wrapper, so does not require the __irq /* This function is called from an asm wrapper, so does not require the __irq
* keyword. */ keyword. */
#if configUSE_WATCHDOG_TICK == 1 #if configUSE_WATCHDOG_TICK == 1
static void prvFindFactors( u32 n, static void prvFindFactors(u32 n, u16 *a, u32 *b)
u16 * a,
u32 * b )
{ {
/* This function is copied from the ST STR7 library and is /* This function is copied from the ST STR7 library and is
* copyright STMicroelectronics. Reproduced with permission. */ copyright STMicroelectronics. Reproduced with permission. */
u32 b0; u32 b0;
u16 a0; u16 a0;
@ -228,23 +224,17 @@ void vPortEndScheduler( void )
{ {
*b = n / *a; *b = n / *a;
err = (int32_t)*a * (int32_t)*b - (int32_t)n; err = (int32_t)*a * (int32_t)*b - (int32_t)n;
if (abs(err) > (*a / 2)) if (abs(err) > (*a / 2))
{ {
(*b)++; (*b)++;
err = (int32_t)*a * (int32_t)*b - (int32_t)n; err = (int32_t)*a * (int32_t)*b - (int32_t)n;
} }
if (abs(err) < abs(err_min)) if (abs(err) < abs(err_min))
{ {
err_min = err; err_min = err;
a0 = *a; a0 = *a;
b0 = *b; b0 = *b;
if (err == 0) break;
if( err == 0 )
{
break;
}
} }
} }
@ -260,7 +250,7 @@ void vPortEndScheduler( void )
uint32_t n = configCPU_PERIPH_HZ / configTICK_RATE_HZ, b; uint32_t n = configCPU_PERIPH_HZ / configTICK_RATE_HZ, b;
/* Configure the watchdog as a free running timer that generates a /* Configure the watchdog as a free running timer that generates a
* periodic interrupt. */ periodic interrupt. */
SCU_APBPeriphClockConfig( __WDG, ENABLE ); SCU_APBPeriphClockConfig( __WDG, ENABLE );
WDG_DeInit(); WDG_DeInit();
@ -298,14 +288,12 @@ void vPortEndScheduler( void )
} }
} }
#else /* if configUSE_WATCHDOG_TICK == 1 */ #else
static void prvFindFactors( u32 n, static void prvFindFactors(u32 n, u8 *a, u16 *b)
u8 * a,
u16 * b )
{ {
/* This function is copied from the ST STR7 library and is /* This function is copied from the ST STR7 library and is
* copyright STMicroelectronics. Reproduced with permission. */ copyright STMicroelectronics. Reproduced with permission. */
u16 b0; u16 b0;
u8 a0; u8 a0;
@ -319,23 +307,17 @@ void vPortEndScheduler( void )
{ {
*b = n / *a; *b = n / *a;
err = (int32_t)*a * (int32_t)*b - (int32_t)n; err = (int32_t)*a * (int32_t)*b - (int32_t)n;
if (abs(err) > (*a / 2)) if (abs(err) > (*a / 2))
{ {
(*b)++; (*b)++;
err = (int32_t)*a * (int32_t)*b - (int32_t)n; err = (int32_t)*a * (int32_t)*b - (int32_t)n;
} }
if (abs(err) < abs(err_min)) if (abs(err) < abs(err_min))
{ {
err_min = err; err_min = err;
a0 = *a; a0 = *a;
b0 = *b; b0 = *b;
if (err == 0) break;
if( err == 0 )
{
break;
}
} }
} }
@ -406,8 +388,8 @@ __arm __interwork void vPortEnterCritical( void )
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Now interrupts are disabled ulCriticalNesting can be accessed /* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ portENTER_CRITICAL() has been called. */
ulCriticalNesting++; ulCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -420,7 +402,7 @@ __arm __interwork void vPortExitCritical( void )
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be /* If the nesting level has reached zero then interrupts should be
* re-enabled. */ re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
@ -432,3 +414,8 @@ __arm __interwork void vPortExitCritical( void )
static void prvDefaultHandler( void ) static void prvDefaultHandler( void )
{ {
} }

View file

@ -110,3 +110,5 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -30,25 +30,20 @@ EXTERN usCriticalNesting
#include "FreeRTOSConfig.h" #include "FreeRTOSConfig.h"
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Context save and restore macro definitions ; Context save and restore macro definitions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
portSAVE_CONTEXT MACRO portSAVE_CONTEXT MACRO
add - 0x0C, sp; add -0x0C,sp ; prepare stack to save necessary values
prepare stack to save necessary values st.w lp,8[sp] ; store LP to stack
st.w lp, 8[ sp ];
store LP to stack
stsr 0,r31 stsr 0,r31
st.w lp, 4[ sp ]; st.w lp,4[sp] ; store EIPC to stack
store EIPC to stack
stsr 1,lp stsr 1,lp
st.w lp, 0[ sp ]; st.w lp,0[sp] ; store EIPSW to stack
store EIPSW to stack
#if configDATA_MODE == 1 ; Using the Tiny data model #if configDATA_MODE == 1 ; Using the Tiny data model
prepare { r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30 }, 76, sp; prepare {r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30},76,sp ; save general purpose registers
save general purpose registers
sst.w r19,72[ep] sst.w r19,72[ep]
sst.w r18,68[ep] sst.w r18,68[ep]
sst.w r17,64[ep] sst.w r17,64[ep]
@ -66,8 +61,7 @@ store EIPSW to stack
sst.w r5,16[ep] sst.w r5,16[ep]
sst.w r4,12[ep] sst.w r4,12[ep]
#else ; Using the Small/Large data model #else ; Using the Small/Large data model
prepare { r20, r21, r22, r23, r24, r26, r27, r28, r29, r30 }, 72, sp; prepare {r20,r21,r22,r23,r24,r26,r27,r28,r29,r30},72,sp ; save general purpose registers
save general purpose registers
sst.w r19,68[ep] sst.w r19,68[ep]
sst.w r18,64[ep] sst.w r18,64[ep]
sst.w r17,60[ep] sst.w r17,60[ep]
@ -86,12 +80,10 @@ store EIPSW to stack
#endif /* configDATA_MODE */ #endif /* configDATA_MODE */
sst.w r2,8[ep] sst.w r2,8[ep]
sst.w r1,4[ep] sst.w r1,4[ep]
MOVHI hi1( usCriticalNesting ), r0, r1; MOVHI hi1(usCriticalNesting),r0,r1 ; save usCriticalNesting value to stack
save usCriticalNesting value to stack
ld.w lw1(usCriticalNesting)[r1],r2 ld.w lw1(usCriticalNesting)[r1],r2
sst.w r2,0[ep] sst.w r2,0[ep]
MOVHI hi1( pxCurrentTCB ), r0, r1; MOVHI hi1(pxCurrentTCB),r0,r1 ; save SP to top of current TCB
save SP to top of current TCB
ld.w lw1(pxCurrentTCB)[r1],r2 ld.w lw1(pxCurrentTCB)[r1],r2
st.w sp,0[r2] st.w sp,0[r2]
ENDM ENDM
@ -99,20 +91,15 @@ ENDM
portRESTORE_CONTEXT MACRO portRESTORE_CONTEXT MACRO
MOVHI hi1( pxCurrentTCB ), r0, r1; MOVHI hi1(pxCurrentTCB),r0,r1 ; get Stackpointer address
get Stackpointer address
ld.w lw1(pxCurrentTCB)[r1],sp ld.w lw1(pxCurrentTCB)[r1],sp
MOV sp,r1 MOV sp,r1
ld.w 0[ r1 ], sp; ld.w 0[r1],sp ; load stackpointer
load stackpointer MOV sp,ep ; set stack pointer to element pointer
MOV sp, ep; sld.w 0[ep],r1 ; load usCriticalNesting value from stack
set stack pointer to element pointer
sld.w 0[ ep ], r1;
load usCriticalNesting value from stack
MOVHI hi1(usCriticalNesting),r0,r2 MOVHI hi1(usCriticalNesting),r0,r2
st.w r1,lw1(usCriticalNesting)[r2] st.w r1,lw1(usCriticalNesting)[r2]
sld.w 4[ ep ], r1; sld.w 4[ep],r1 ; restore general purpose registers
restore general purpose registers
sld.w 8[ep],r2 sld.w 8[ep],r2
#if configDATA_MODE == 1 ; Using Tiny data model #if configDATA_MODE == 1 ; Using Tiny data model
sld.w 12[ep],r4 sld.w 12[ep],r4
@ -150,16 +137,12 @@ sld.w 8[ ep ], r2
sld.w 68[ep],r19 sld.w 68[ep],r19
dispose 72,{r20,r21,r22,r23,r24,r26,r27,r28,r29,r30} dispose 72,{r20,r21,r22,r23,r24,r26,r27,r28,r29,r30}
#endif /* configDATA_MODE */ #endif /* configDATA_MODE */
ld.w 0[ sp ], lp; ld.w 0[sp],lp ; restore EIPSW from stack
restore EIPSW from stack
ldsr lp,1 ldsr lp,1
ld.w 4[ sp ], lp; ld.w 4[sp],lp ; restore EIPC from stack
restore EIPC from stack
ldsr lp,0 ldsr lp,0
ld.w 8[ sp ], lp; ld.w 8[sp],lp ; restore LP from stack
restore LP from stack add 0x0C,sp ; set SP to right position
add 0x0C, sp;
set SP to right position
RETI RETI

View file

@ -33,14 +33,14 @@
#include "task.h" #include "task.h"
/* Critical nesting should be initialised to a non zero value so interrupts don't /* Critical nesting should be initialised to a non zero value so interrupts don't
* accidentally get enabled before the scheduler is started. */ accidentally get enabled before the scheduler is started. */
#define portINITIAL_CRITICAL_NESTING (( StackType_t ) 10) #define portINITIAL_CRITICAL_NESTING (( StackType_t ) 10)
/* The PSW value assigned to tasks when they start to run for the first time. */ /* The PSW value assigned to tasks when they start to run for the first time. */
#define portPSW (( StackType_t ) 0x00000000) #define portPSW (( StackType_t ) 0x00000000)
/* We require the address of the pxCurrentTCB variable, but don't want to know /* We require the address of the pxCurrentTCB variable, but don't want to know
* any details of its type. */ any details of its type. */
typedef void TCB_t; typedef void TCB_t;
extern volatile TCB_t * volatile pxCurrentTCB; extern volatile TCB_t * volatile pxCurrentTCB;
@ -52,9 +52,7 @@ volatile StackType_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
static void prvSetupTimerInterrupt( void ); static void prvSetupTimerInterrupt( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
TaskFunction_t pxCode,
void * pvParameters )
{ {
*pxTopOfStack = ( StackType_t ) pxCode; /* Task function start address */ *pxTopOfStack = ( StackType_t ) pxCode; /* Task function start address */
pxTopOfStack--; pxTopOfStack--;
@ -137,7 +135,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Setup the hardware to generate the tick. Interrupts are disabled when /* Setup the hardware to generate the tick. Interrupts are disabled when
* this function is called. */ this function is called. */
prvSetupTimerInterrupt(); prvSetupTimerInterrupt();
/* Restore the context of the first task that is going to run. */ /* Restore the context of the first task that is going to run. */
@ -151,7 +149,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the V850ES/Fx3 port will get stopped. If required simply /* It is unlikely that the V850ES/Fx3 port will get stopped. If required simply
* disable the tick interrupt here. */ disable the tick interrupt here. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -181,3 +179,5 @@ static void prvSetupTimerInterrupt( void )
TM0CE = 1; /* TMM0 operation enable */ TM0CE = 1; /* TMM0 operation enable */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -132,3 +132,4 @@
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */