Style: Revert more uncrustified files

This commit is contained in:
Alfred Gedeon 2020-08-11 21:56:04 -07:00 committed by alfred gedeon
parent c272a13203
commit 54ee4d62bd
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 usCriticalNesting
EXTERN pxCurrentTCB
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 ; Save CS register.
MOV A, CS; XCH A, X
Save CS register. MOV A, ES ; Save ES register.
XCH A, X PUSH AX
MOV A, ES; PUSH DE ; Save the remaining general purpose registers.
Save ES register. PUSH BC
PUSH AX MOVW AX, usCriticalNesting ; Save the usCriticalNesting value.
PUSH DE; PUSH AX
Save the remaining general purpose registers. MOVW AX, pxCurrentTCB ; Save the Stack pointer.
PUSH BC MOVW HL, AX
MOVW AX, usCriticalNesting; MOVW AX, SP
Save the usCriticalNesting value. MOVW [HL], AX
PUSH AX ENDM
MOVW AX, pxCurrentTCB; ;------------------------------------------------------------------------------
Save the Stack pointer.
MOVW HL, AX
MOVW AX, SP
MOVW[ HL ], AX
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, MOVW HL, AX
; MOVW AX, [HL]
general purpose registers and the CS and ES( only in far memory mode ) MOVW SP, AX
; POP AX ; Restore usCriticalNesting value.
of the selected task from the task stack MOVW usCriticalNesting, AX
; POP BC ; Restore the necessary general purpose registers.
------------------------------------------------------------------------------ POP DE
portRESTORE_CONTEXT MACRO POP AX ; Restore the ES register.
MOVW AX, pxCurrentTCB; MOV ES, A
Restore the Stack pointer. XCH A, X ; Restore the CS register.
MOVW HL, AX MOV CS, A
MOVW AX, [ HL ] POP HL ; Restore general purpose register HL.
MOVW SP, AX POP AX ; Restore AX.
POP AX; ENDM
Restore usCriticalNesting value. ;------------------------------------------------------------------------------
MOVW usCriticalNesting, AX
POP BC;
Restore the necessary general purpose registers.
POP DE
POP AX;
Restore the ES register.
MOV ES, A
XCH A, X;
Restore the CS register.
MOV CS, A
POP HL;
Restore general purpose register HL.
POP AX;
Restore AX.
ENDM
;
------------------------------------------------------------------------------

View file

@ -33,8 +33,8 @@
#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.
* 1100011000000000 * 1100011000000000
@ -47,25 +47,25 @@
* |--------------------- Zero Flag set * |--------------------- Zero Flag set
* ---------------------- Global Interrupt Flag set (enabled) * ---------------------- Global Interrupt Flag set (enabled)
*/ */
#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,146 +81,145 @@ 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. */
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) pvParameters; *pulLocal = ( uint32_t ) pvParameters;
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. */
pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--;
/* Task function start address combined with the PSW. */ /* An initial value for the AX register. */
pulLocal = ( uint32_t * ) pxTopOfStack; *pxTopOfStack = ( StackType_t ) 0x1111;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) ); pxTopOfStack--;
pxTopOfStack--; }
#else
{
/* 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
two bytes. */
pxTopOfStack--;
/* An initial value for the AX register. */ /* Task function start address combined with the PSW. */
*pxTopOfStack = ( StackType_t ) 0x1111; pulLocal = ( uint32_t * ) pxTopOfStack;
pxTopOfStack--; *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
} pxTopOfStack--;
#else /* if configMEMORY_MODE == 1 */
{
/* 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
* two bytes. */
pxTopOfStack--;
/* Task function start address combined with the PSW. */ /* The parameter is passed in AX. */
pulLocal = ( uint32_t * ) pxTopOfStack; *pxTopOfStack = ( StackType_t ) pvParameters;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) ); pxTopOfStack--;
pxTopOfStack--; }
#endif
/* The parameter is passed in AX. */ /* An initial value for the HL register. */
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) 0x2222;
pxTopOfStack--; pxTopOfStack--;
}
#endif /* if configMEMORY_MODE == 1 */
/* An initial value for the HL register. */ /* CS and ES registers. */
*pxTopOfStack = ( StackType_t ) 0x2222; *pxTopOfStack = ( StackType_t ) 0x0F00;
pxTopOfStack--; pxTopOfStack--;
/* CS and ES registers. */ /* Finally the remaining general purpose registers DE and BC */
*pxTopOfStack = ( StackType_t ) 0x0F00; *pxTopOfStack = ( StackType_t ) 0xDEDE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBCBC;
pxTopOfStack--;
/* Finally the remaining general purpose registers DE and BC */ /* Finally the critical section nesting count is set to zero when the task
*pxTopOfStack = ( StackType_t ) 0xDEDE; first starts. */
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
*pxTopOfStack = ( StackType_t ) 0xBCBC;
pxTopOfStack--;
/* Finally the critical section nesting count is set to zero when the task /* Return a pointer to the top of the stack we have generated so this can
* first starts. */ be stored in the task control block for the task. */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING; return pxTopOfStack;
/* 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. */
return 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. */
vPortStart(); vPortStart();
/* Should not get here as the tasks are now running! */ /* Should not get here as the tasks are now running! */
return pdTRUE; return pdTRUE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
/* Setup channel 5 of the TAU to generate the tick interrupt. */ /* Setup channel 5 of the TAU to generate the tick interrupt. */
/* First the Timer Array Unit has to be enabled. */ /* First the Timer Array Unit has to be enabled. */
TAU0EN = 1; TAU0EN = 1;
/* To configure the Timer Array Unit all Channels have to first be stopped. */ /* To configure the Timer Array Unit all Channels have to first be stopped. */
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. */
TMIF05 = 0; TMIF05 = 0;
/* Set Timer Array Unit Channel 5 interrupt priority */ /* Set Timer Array Unit Channel 5 interrupt priority */
TMPR005 = 0; TMPR005 = 0;
TMPR105 = 0; TMPR105 = 0;
/* Set Timer Array Unit Channel 5 Mode as interval timer. */ /* Set Timer Array Unit Channel 5 Mode as interval timer. */
TMR05 = 0x0000; TMR05 = 0x0000;
/* Set the compare match value according to the tick rate we want. */ /* Set the compare match value according to the tick rate we want. */
TDR05 = ( TickType_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); TDR05 = ( TickType_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
/* Set Timer Array Unit Channel 5 output mode */ /* Set Timer Array Unit Channel 5 output mode */
TOM0 &= ~0x0020; TOM0 &= ~0x0020;
/* Set Timer Array Unit Channel 5 output level */ /* Set Timer Array Unit Channel 5 output level */
TOL0 &= ~0x0020; TOL0 &= ~0x0020;
/* Set Timer Array Unit Channel 5 output enable */ /* Set Timer Array Unit Channel 5 output enable */
TOE0 &= ~0x0020; TOE0 &= ~0x0020;
/* Interrupt of Timer Array Unit Channel 5 enabled */ /* Interrupt of Timer Array Unit Channel 5 enabled */
TMMK05 = 0; TMMK05 = 0;
/* Start Timer Array Unit Channel 5.*/ /* Start Timer Array Unit Channel 5.*/
TS0 |= 0x0020; TS0 |= 0x0020;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,11 +26,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -44,101 +44,102 @@
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portBASE_TYPE short #define portBASE_TYPE short
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if (configUSE_16_BIT_TICKS==1)
typedef unsigned int TickType_t; typedef unsigned int TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Interrupt control macros. */ /* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() __asm( "DI" ) #define portDISABLE_INTERRUPTS() __asm ( "DI" )
#define portENABLE_INTERRUPTS() __asm( "EI" ) #define portENABLE_INTERRUPTS() __asm ( "EI" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section control macros. */ /* Critical section control macros. */
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
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 */ \ /* directly. Increment ulCriticalNesting to keep a count of how many */ \
/* times portENTER_CRITICAL() has been called. */ \ /* times portENTER_CRITICAL() has been called. */ \
usCriticalNesting++; \ usCriticalNesting++; \
} }
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
/* Decrement the nesting count as we are leaving a critical section. */ \ /* Decrement the nesting count as we are leaving a critical section. */ \
usCriticalNesting--; \ usCriticalNesting--; \
\ \
/* 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( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
extern void vPortStart( void ); extern void vPortStart( void );
#define portYIELD() __asm( "BRK" ) #define portYIELD() __asm( "BRK" )
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext() #define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
#define portNOP() __asm( "NOP" ) #define portNOP() __asm( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardwware specifics. */ /* Hardwware specifics. */
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
static __interrupt void P0_isr( void ); static __interrupt void P0_isr (void);
/* --------------------------------------------------------------------------*/ /* --------------------------------------------------------------------------*/
/* Option-bytes and security ID */ /* Option-bytes and security ID */
/* --------------------------------------------------------------------------*/ /* --------------------------------------------------------------------------*/
#define OPT_BYTES_SIZE 4 #define OPT_BYTES_SIZE 4
#define SECU_ID_SIZE 10 #define SECU_ID_SIZE 10
#define WATCHDOG_DISABLED 0x00 #define WATCHDOG_DISABLED 0x00
#define LVI_ENABLED 0xFE #define LVI_ENABLED 0xFE
#define LVI_DISABLED 0xFF #define LVI_DISABLED 0xFF
#define RESERVED_FF 0xFF #define RESERVED_FF 0xFF
#define OCD_DISABLED 0x04 #define OCD_DISABLED 0x04
#define OCD_ENABLED 0x81 #define OCD_ENABLED 0x81
#define OCD_ENABLED_ERASE 0x80 #define OCD_ENABLED_ERASE 0x80
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -33,42 +33,42 @@
#include "task.h" #include "task.h"
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if ( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt. A default that uses the PIT is provided in the official demo application. #error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt. A default that uses the PIT is provided in the official demo application.
#endif #endif
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt. A default that uses the PIT is provided in the official demo application. #error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt. A default that uses the PIT is provided in the official demo application.
#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. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* 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 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -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,195 +109,192 @@ 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
* system mode, with interrupts enabled. A few NULLs are added first to ensure
* GDB does not try decoding a non-existent return address. */
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) 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
/* The task will start in THUMB mode. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack = NULL;
} pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
pxTopOfStack--; if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{
/* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
/* Next the return address, which in this case is the start of the task. */ pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
/* Next all the registers other than the stack pointer. */ /* Next the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* R14 */ *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* Next all the registers other than the stack pointer. */
* enabled. */ *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* R14 */
*pxTopOfStack = portNO_CRITICAL_NESTING; pxTopOfStack--;
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start with a critical nesting count of 0 as interrupts are
* the floating point hardware must call vPortTaskUsesFPU() before executing enabled. */
* any floating point instructions. */ *pxTopOfStack = portNO_CRITICAL_NESTING;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; pxTopOfStack--;
return pxTopOfStack; /* The task will start without a floating point context. A task that uses
the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return 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
* defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ; ; ) Artificially force an assert() to be triggered if configASSERT() is
{ defined, then stop here so application writers can catch the error. */
} configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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;
configASSERT( ulAPSR != portAPSR_USER_MODE );
ulAPSR &= portAPSR_MODE_BITS_MASK; if( ulAPSR != portAPSR_USER_MODE )
configASSERT( ulAPSR != portAPSR_USER_MODE ); {
/* Start the timer that generates the tick ISR. */
configSETUP_TICK_INTERRUPT();
vPortRestoreTaskContext();
}
if( ulAPSR != portAPSR_USER_MODE ) /* 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
/* Start the timer that generates the tick ISR. */ possible value. */
configSETUP_TICK_INTERRUPT(); return 0;
vPortRestoreTaskContext();
}
/* 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
* possible value. */
return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) 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 );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) 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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
ulPortYieldRequired = pdTRUE; ulPortYieldRequired = pdTRUE;
} }
portENABLE_INTERRUPTS(); portENABLE_INTERRUPTS();
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortTaskUsesFPU( void ) 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,127 +1,113 @@
; /* ;/*
* ; * 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
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulPortTaskHasFPUContext EXTERN ulPortTaskHasFPUContext
EXTERN ulAsmAPIPriorityMask 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
; SRSDB sp!, #SYS_MODE
system mode to save the remaining system mode registers CPS #SYS_MODE
SRSDB sp !, # SYS_MODE PUSH {R0-R12, R14}
CPS # SYS_MODE
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.
; LDR R2, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is 0 then no. LDR R3, [R2]
LDR R2, = ulPortTaskHasFPUContext CMP R3, #0
LDR R3, [ R2 ]
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
VPUSHNE { D16 - D31 } VPUSHNE {D16-D31}
#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 ]
endm 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.
; LDR R0, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is zero then no. POP {R1}
LDR R0, = ulPortTaskHasFPUContext STR R1, [R0]
POP { R1 } CMP R1, #0
STR R1, [ R0 ]
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}
#endif; configFPU_D32 #endif ; configFPU_D32
VPOPNE { D0 - D15 } VPOPNE {D0-D15}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
; Restore the critical section nesting depth
LDR R0, =ulCriticalNesting
POP {R1}
STR R1, [R0]
; Restore all system mode registers other than the SP (which is already
; being used)
POP {R0-R12, R14}
; Return to the task code, loading CPSR on the way. CPSR has the interrupt
; enable bit set appropriately for the task about to execute.
RFEIA sp!
endm
;
Restore the critical section nesting depth
LDR R0, = ulCriticalNesting
POP { R1 }
STR R1, [ R0 ]
;
Restore all system mode registers other than the SP( which is already
;
being used )
POP
{
R0 - R12, R14
}
Return to the task code, loading CPSR on the way.CPSR has the interrupt
;
enable bit set appropriately for the task about to execute.
RFEIA sp !
endm

View file

@ -26,136 +26,137 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
/* IAR includes. */ /* IAR includes. */
#ifdef __ICCARM__ #ifdef __ICCARM__
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
* *
* The settings in this file configure FreeRTOS correctly for the given hardware * The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler. * and compiler.
* *
* These settings should not be altered. * These settings should not be altered.
*----------------------------------------------------------- *-----------------------------------------------------------
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired )\
{ \ { \
extern uint32_t ulPortYieldRequired; \ extern uint32_t ulPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ulPortYieldRequired = pdTRUE; \ ulPortYieldRequired = pdTRUE; \
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#define portYIELD() __asm volatile ( "SWI 0" ); __ISB() #define portYIELD() __asm volatile ( "SWI 0" ); __ISB()
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
*----------------------------------------------------------*/ *----------------------------------------------------------*/
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
#define portENTER_CRITICAL() vPortEnterCritical(); #define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical(); #define portEXIT_CRITICAL() vPortExitCritical();
#define portDISABLE_INTERRUPTS() __disable_irq(); __DSB(); __ISB() /* No priority mask register so global disable is used. */ #define portDISABLE_INTERRUPTS() __disable_irq(); __DSB(); __ISB() /* No priority mask register so global disable is used. */
#define portENABLE_INTERRUPTS() __enable_irq() #define portENABLE_INTERRUPTS() __enable_irq()
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_state(); __disable_irq() /* No priority mask register so global disable is used. */ #define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_state(); __disable_irq() /* No priority mask register so global disable is used. */
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) __set_interrupt_state( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) __set_interrupt_state(x)
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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()
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#define portNOP() __asm volatile ( "NOP" ) #define portNOP() __asm volatile( "NOP" )
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#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,89 +36,89 @@
#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
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0 #error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
#endif #endif
#if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES #if configMAX_API_CALL_INTERRUPT_PRIORITY > configUNIQUE_INTERRUPT_PRIORITIES
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority #error configMAX_API_CALL_INTERRUPT_PRIORITY must be less than or equal to configUNIQUE_INTERRUPT_PRIORITIES as the lower the numeric priority value the higher the logical interrupt priority
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if ( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/* In case security extensions are implemented. */ /* In case security extensions are implemented. */
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#endif #endif
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT() #define configCLEAR_TICK_INTERRUPT()
#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. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#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. */
#define portCLEAR_INTERRUPT_MASK() \ #define portCLEAR_INTERRUPT_MASK() \
{ \ { \
__disable_irq(); \ __disable_irq(); \
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
__asm( "DSB \n" \ __asm( "DSB \n" \
"ISB \n"); \ "ISB \n" ); \
__enable_irq(); \ __enable_irq(); \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -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,287 +159,281 @@ 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
* system mode, with interrupts enabled. A few NULLs are added first to ensure
* GDB does not try decoding a non-existent return address. */
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) 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
/* The task will start in THUMB mode. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack = NULL;
} pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
pxTopOfStack--; if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{
/* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
/* Next the return address, which in this case is the start of the task. */ pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
/* Next all the registers other than the stack pointer. */ /* Next the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* R14 */ *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* Next all the registers other than the stack pointer. */
* enabled. */ *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* R14 */
*pxTopOfStack = portNO_CRITICAL_NESTING; pxTopOfStack--;
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start with a critical nesting count of 0 as interrupts are
* the floating point hardware must call vPortTaskUsesFPU() before executing enabled. */
* any floating point instructions. */ *pxTopOfStack = portNO_CRITICAL_NESTING;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; pxTopOfStack--;
return pxTopOfStack; /* The task will start without a floating point context. A task that uses
the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return 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
* defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ; ; ) Artificially force an assert() to be triggered if configASSERT() is
{ defined, then stop here so application writers can catch the error. */
} configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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;
configASSERT( ulAPSR != portAPSR_USER_MODE );
ulAPSR &= portAPSR_MODE_BITS_MASK; if( ulAPSR != portAPSR_USER_MODE )
configASSERT( ulAPSR != portAPSR_USER_MODE ); {
/* Only continue if the binary point value is set to its lowest possible
setting. See the comments in vPortValidateInterruptPriority() below for
more information. */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ulAPSR != portAPSR_USER_MODE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
{ {
/* Only continue if the binary point value is set to its lowest possible /* Start the timer that generates the tick ISR. */
* setting. See the comments in vPortValidateInterruptPriority() below for configSETUP_TICK_INTERRUPT();
* more information. */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) __enable_irq();
{ vPortRestoreTaskContext();
/* Start the timer that generates the tick ISR. */ }
configSETUP_TICK_INTERRUPT(); }
__enable_irq(); /* Will only get here if vTaskStartScheduler() was called with the CPU in
vPortRestoreTaskContext(); a non-privileged mode or the binary point register was not set to its lowest
} possible value. */
} return 0;
/* 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
* possible value. */
return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */ /* Disable interrupts as per portDISABLE_INTERRUPTS(); */
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 );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) 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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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"
"ISB \n"); "ISB \n" );
__enable_irq(); __enable_irq();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
ulPortYieldRequired = pdTRUE; ulPortYieldRequired = pdTRUE;
} }
/* Ensure all interrupt priorities are active again. */ /* Ensure all interrupt priorities are active again. */
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortTaskUsesFPU( void ) 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) );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortClearInterruptMask( uint32_t ulNewMaskValue ) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{ {
if( ulNewMaskValue == pdFALSE ) if( ulNewMaskValue == pdFALSE )
{ {
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
uint32_t ulPortSetInterruptMask( void ) 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 ) )
{
/* Interrupts were already masked. */
ulReturn = pdTRUE;
}
else
{
ulReturn = pdFALSE;
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm( "DSB \n"
"ISB \n" );
}
__enable_irq();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) return ulReturn;
{
/* Interrupts were already masked. */
ulReturn = pdTRUE;
}
else
{
ulReturn = pdFALSE;
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm( "DSB \n"
"ISB \n");
}
__enable_irq();
return ulReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
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
* interrupt priorities, therefore the priority of the interrupt must
* be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible.
*
* The following links provide detailed information:
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
* http://www.freertos.org/FAQHelp.html */
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits Numerically low interrupt priority numbers represent logically high
* that define each interrupt's priority to be split between bits that interrupt priorities, therefore the priority of the interrupt must
* define the interrupt's pre-emption priority bits and bits that define be set to a value equal to or numerically *higher* than
* the interrupt's sub-priority. For simplicity all bits must be defined configMAX_SYSCALL_INTERRUPT_PRIORITY.
* to be pre-emption priority bits. The following assertion will fail if
* this is not the case (if some bits represent a sub-priority). FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible.
* 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 The following links provide detailed information:
* possible value (which may be above 0). */ http://www.freertos.org/RTOS-Cortex-M3-M4.html
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); http://www.freertos.org/FAQHelp.html */
} configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits
that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority).
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
possible value (which may be above 0). */
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
}
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -1,129 +1,115 @@
; /* ;/*
* ; * 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
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN ulPortTaskHasFPUContext EXTERN ulPortTaskHasFPUContext
EXTERN ulAsmAPIPriorityMask 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
; SRSDB sp!, #SYS_MODE
system mode to save the remaining system mode registers CPS #SYS_MODE
SRSDB sp !, # SYS_MODE PUSH {R0-R12, R14}
CPS # SYS_MODE
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.
; LDR R2, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is 0 then no. LDR R3, [R2]
LDR R2, = ulPortTaskHasFPUContext CMP R3, #0
LDR R3, [ R2 ]
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 ]
endm 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.
; LDR R0, =ulPortTaskHasFPUContext
ulPortTaskHasFPUContext is zero then no. POP {R1}
LDR R0, = ulPortTaskHasFPUContext STR R1, [R0]
POP { R1 } CMP R1, #0
STR R1, [ R0 ]
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
LDR R0, =ulCriticalNesting
POP {R1}
STR R1, [R0]
; Ensure the priority mask is correct for the critical nesting depth
LDR R2, =portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS
CMP R1, #0
MOVEQ R4, #255
LDRNE R4, =( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT )
STR R4, [r2]
; Restore all system mode registers other than the SP (which is already
; being used)
POP {R0-R12, R14}
; Return to the task code, loading CPSR on the way.
RFEIA sp!
endm
;
Restore the critical section nesting depth
LDR R0, = ulCriticalNesting
POP { R1 }
STR R1, [ R0 ]
;
Ensure the priority mask is correct for the critical nesting depth
LDR R2, = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS
CMP R1, # 0
MOVEQ R4, # 255
LDRNE R4, = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT )
STR R4, [ r2 ]
;
Restore all system mode registers other than the SP( which is already
;
being used )
POP
{
R0 - R12, R14
}
Return to the task code, loading CPSR on the way.
RFEIA sp !
endm

View file

@ -26,183 +26,184 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
/* IAR includes. */ /* IAR includes. */
#ifdef __ICCARM__ #ifdef __ICCARM__
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
* *
* The settings in this file configure FreeRTOS correctly for the given hardware * The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler. * and compiler.
* *
* These settings should not be altered. * These settings should not be altered.
*----------------------------------------------------------- *-----------------------------------------------------------
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired )\
{ \ { \
extern uint32_t ulPortYieldRequired; \ extern uint32_t ulPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ulPortYieldRequired = pdTRUE; \ ulPortYieldRequired = pdTRUE; \
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#define portYIELD() __asm( "SWI 0" ); #define portYIELD() __asm( "SWI 0" );
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
*----------------------------------------------------------*/ *----------------------------------------------------------*/
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );
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()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) #define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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()
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL ) #define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL ) #define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __CLZ( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */ #endif /* configASSERT */
#define portNOP() __asm volatile ( "NOP" ) #define portNOP() __asm volatile( "NOP" )
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#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__ */
/* 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
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3 #define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2 #define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2 #define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1 #define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1 #define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#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 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 ) #define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 ) #define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 ) #define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) ) #define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET ) #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) ) #define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
#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

@ -33,50 +33,50 @@
#include "task.h" #include "task.h"
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Check the configuration. */ /* Check the configuration. */
#if ( configMAX_PRIORITIES > 32 ) #if( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif #endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifndef configSETUP_TICK_INTERRUPT #ifndef configSETUP_TICK_INTERRUPT
#error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt. #error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt.
#endif #endif
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt. #error configCLEAR_TICK_INTERRUPT must be defined in FreeRTOSConfig.h to clear which ever interrupt was used to generate the tick interrupt.
#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. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* 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 )
/* 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
#define portTASK_RETURN_ADDRESS prvTaskExitError #define portTASK_RETURN_ADDRESS prvTaskExitError
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -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,204 +117,200 @@ 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
* system mode, with interrupts enabled. A few NULLs are added first to ensure
* GDB does not try decoding a non-existent return address. */
*pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) 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
/* The task will start in THUMB mode. */ GDB does not try decoding a non-existent return address. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack = ( StackType_t ) NULL;
} pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
pxTopOfStack--; if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL )
{
/* The task will start in THUMB mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
/* Next the return address, which in this case is the start of the task. */ pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
/* Next all the registers other than the stack pointer. */ /* Next the return address, which in this case is the start of the task. */
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */ *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /* Next all the registers other than the stack pointer. */
* enabled. */ *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
*pxTopOfStack = portNO_CRITICAL_NESTING; pxTopOfStack--;
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* The task will start without a floating point context. A task that uses /* The task will start with a critical nesting count of 0 as interrupts are
* the floating point hardware must call vPortTaskUsesFPU() before executing enabled. */
* any floating point instructions. */ *pxTopOfStack = portNO_CRITICAL_NESTING;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; pxTopOfStack--;
return pxTopOfStack; /* The task will start without a floating point context. A task that uses
the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return 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
* defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ; ; ) Artificially force an assert() to be triggered if configASSERT() is
{ defined, then stop here so application writers can catch the error. */
} configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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;
configASSERT( ulAPSR != portAPSR_USER_MODE );
ulAPSR &= portAPSR_MODE_BITS_MASK; if( ulAPSR != portAPSR_USER_MODE )
configASSERT( ulAPSR != portAPSR_USER_MODE ); {
/* Start the timer that generates the tick ISR. */
portDISABLE_INTERRUPTS();
configSETUP_TICK_INTERRUPT();
if( ulAPSR != portAPSR_USER_MODE ) /* Start the first task executing. */
{ vPortRestoreTaskContext();
/* Start the timer that generates the tick ISR. */ }
portDISABLE_INTERRUPTS();
configSETUP_TICK_INTERRUPT();
/* Start the first task executing. */ /* Will only get here if vTaskStartScheduler() was called with the CPU in
vPortRestoreTaskContext(); a non-privileged mode or the binary point register was not set to its lowest
} possible value. prvTaskExitError() is referenced to prevent a compiler
warning about it being defined but not referenced in the case that the user
/* Will only get here if vTaskStartScheduler() was called with the CPU in defines their own exit address. */
* a non-privileged mode or the binary point register was not set to its lowest ( void ) prvTaskExitError;
* possible value. prvTaskExitError() is referenced to prevent a compiler return 0;
* warning about it being defined but not referenced in the case that the user
* defines their own exit address. */
( void ) prvTaskExitError;
return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) 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 );
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) 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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
uint32_t ulInterruptStatus; uint32_t ulInterruptStatus;
ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
/* Increment the RTOS tick. */ /* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
ulPortYieldRequired = pdTRUE; ulPortYieldRequired = pdTRUE;
} }
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus ); portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus );
configCLEAR_TICK_INTERRUPT(); configCLEAR_TICK_INTERRUPT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortTaskUsesFPU( void ) 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

@ -26,13 +26,13 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -45,139 +45,137 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired )\
{ \ { \
extern volatile uint32_t ulPortYieldRequired; \ extern volatile uint32_t ulPortYieldRequired; \
\ \
if( xSwitchRequired != pdFALSE ) \ if( xSwitchRequired != pdFALSE ) \
{ \ { \
ulPortYieldRequired = pdTRUE; \ ulPortYieldRequired = pdTRUE; \
} \ } \
} }
#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 ");
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
*----------------------------------------------------------*/ *----------------------------------------------------------*/
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
extern void vPortInstallFreeRTOSVectorTable( void ); extern void vPortInstallFreeRTOSVectorTable( void );
/* The I bit within the CPSR. */ /* The I bit within the CPSR. */
#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 static inline uint32_t portINLINE_SET_INTERRUPT_MASK_FROM_ISR( void )
static inline uint32_t portINLINE_SET_INTERRUPT_MASK_FROM_ISR( void ) {
{ 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;
portDISABLE_INTERRUPTS();
return ulCPSR;
}
ulCPSR &= portINTERRUPT_ENABLE_BIT; #define portSET_INTERRUPT_MASK_FROM_ISR() portINLINE_SET_INTERRUPT_MASK_FROM_ISR()
portDISABLE_INTERRUPTS(); #define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) if( x == 0 ) portENABLE_INTERRUPTS()
return ulCPSR;
}
#define portSET_INTERRUPT_MASK_FROM_ISR() portINLINE_SET_INTERRUPT_MASK_FROM_ISR()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) if( x == 0 ) portENABLE_INTERRUPTS()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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()
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL ) #define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL ) #define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __CLZ( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) __CLZ( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#define portNOP() __asm volatile ( "NOP" ) #define portNOP() __asm volatile( "NOP" )
#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
#ifdef __cplusplus #ifdef __cplusplus
} /* extern C */ } /* extern C */
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -31,25 +31,25 @@
#include "task.h" #include "task.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the AVR/IAR port. * Implementation of functions defined in portable.h for the AVR/IAR port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Start tasks with interrupts enables. */ /* Start tasks with interrupts enables. */
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x80 ) #define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x80 )
/* Hardware constants for timer 1. */ /* Hardware constants for timer 1. */
#define portCLEAR_COUNTER_ON_MATCH ( ( uint8_t ) 0x08 ) #define portCLEAR_COUNTER_ON_MATCH ( ( uint8_t ) 0x08 )
#define portPRESCALE_64 ( ( uint8_t ) 0x03 ) #define portPRESCALE_64 ( ( uint8_t ) 0x03 )
#define portCLOCK_PRESCALER ( ( uint32_t ) 64 ) #define portCLOCK_PRESCALER ( ( uint32_t ) 64 )
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE ( ( uint8_t ) 0x10 ) #define portCOMPARE_MATCH_A_INTERRUPT_ENABLE ( ( uint8_t ) 0x10 )
/* The number of bytes used on the hardware stack by the task start address. */ /* The number of bytes used on the hardware stack by the task start address. */
#define portBYTES_USED_BY_RETURN_ADDRESS ( 2 ) #define portBYTES_USED_BY_RETURN_ADDRESS ( 2 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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,187 +70,186 @@ 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--;
*pxTopOfStack = 0x22; *pxTopOfStack = 0x22;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x33; *pxTopOfStack = 0x33;
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;
/* Simulate how the stack would look after a call to vPortYield(). */ /* Simulate how the stack would look after a call to vPortYield(). */
/*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */
/* 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
* 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
* stack is placed. The amount of space between the software and hardware
* stacks is defined by configCALL_STACK_SIZE.
*
*
*
* The first part of the stack is the hardware stack. Place the start
* address of the task on the hardware stack. */
usAddress = ( uint16_t ) pxCode;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8; This function places both stacks within the memory block passed in as the
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); first parameter. The hardware stack is placed at the bottom of the memory
pxTopOfStack--; 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
stacks is defined by configCALL_STACK_SIZE.
/* Leave enough space for the hardware stack before starting the software
* stack. The '- 2' is because we have already used two spaces for the
* address of the start of the task. */
pxTopOfStack -= ( configCALL_STACK_SIZE - 2 );
/* Next simulate the stack as if after a call to portSAVE_CONTEXT(). The first part of the stack is the hardware stack. Place the start
* portSAVE_CONTEXT places the flags on the stack immediately after r0 address of the task on the hardware stack. */
* to ensure the interrupts get disabled as soon as possible, and so ensuring usAddress = ( uint16_t ) pxCode;
* the stack use is minimal should a context switch interrupt occur. */ *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
*pxTopOfStack = ( StackType_t ) 0x00; /* R0 */ pxTopOfStack--;
pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED;
pxTopOfStack--;
/* Next place the address of the hardware stack. This is required so usAddress >>= 8;
* the AVR stack pointer can be restored to point to the hardware stack. */ *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS; pxTopOfStack--;
usAddress = ( uint16_t ) pxTopOfHardwareStack;
/* SPL */
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
/* SPH */ /* Leave enough space for the hardware stack before starting the software
usAddress >>= 8; stack. The '- 2' is because we have already used two spaces for the
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); address of the start of the task. */
pxTopOfStack--; pxTopOfStack -= ( configCALL_STACK_SIZE - 2 );
/* Now the remaining registers. */ /* Next simulate the stack as if after a call to portSAVE_CONTEXT().
*pxTopOfStack = ( StackType_t ) 0x01; /* R1 */ portSAVE_CONTEXT places the flags on the stack immediately after r0
pxTopOfStack--; to ensure the interrupts get disabled as soon as possible, and so ensuring
*pxTopOfStack = ( StackType_t ) 0x02; /* R2 */ the stack use is minimal should a context switch interrupt occur. */
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 */ pxTopOfStack--;
pxTopOfStack--; *pxTopOfStack = portFLAGS_INT_ENABLED;
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 */ pxTopOfStack--;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x13; /* R13 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x14; /* R14 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x15; /* R15 */
pxTopOfStack--;
/* Place the parameter on the stack in the expected location. */ /* Next place the address of the hardware stack. This is required so
usAddress = ( uint16_t ) pvParameters; the AVR stack pointer can be restored to point to the hardware stack. */
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS;
pxTopOfStack--; usAddress = ( uint16_t ) pxTopOfHardwareStack;
usAddress >>= 8; /* SPL */
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff ); *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x18; /* R18 */ /* SPH */
pxTopOfStack--; usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) 0x19; /* R19 */ *pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x20; /* R20 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x21; /* R21 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22; /* R22 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x23; /* R23 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x24; /* R24 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x25; /* R25 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x26; /* R26 X */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x27; /* R27 */
pxTopOfStack--;
/* The Y register is not stored as it is used as the software stack and
* gets saved into the task control block. */
*pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x031; /* R31 */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING; /* Critical nesting is zero when the task starts. */
/*lint +e950 +e611 +e923 */ /* Now the remaining registers. */
*pxTopOfStack = ( StackType_t ) 0x01; /* R1 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02; /* R2 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03; /* R3 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04; /* R4 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05; /* R5 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06; /* R6 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07; /* R7 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08; /* R8 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09; /* R9 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10; /* R10 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11; /* R11 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12; /* R12 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x13; /* R13 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x14; /* R14 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x15; /* R15 */
pxTopOfStack--;
return pxTopOfStack; /* Place the parameter on the stack in the expected location. */
usAddress = ( uint16_t ) pvParameters;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
usAddress >>= 8;
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x18; /* R18 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x19; /* R19 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x20; /* R20 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x21; /* R21 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22; /* R22 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x23; /* R23 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x24; /* R24 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x25; /* R25 */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x26; /* R26 X */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x27; /* R27 */
pxTopOfStack--;
/* The Y register is not stored as it is used as the software stack and
gets saved into the task control block. */
*pxTopOfStack = ( StackType_t ) 0x30; /* R30 Z */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x031; /* R31 */
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING; /* Critical nesting is zero when the task starts. */
/*lint +e950 +e611 +e923 */
return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Setup the hardware to generate the tick. */ /* Setup the hardware to generate the tick. */
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! */
return pdTRUE; return pdTRUE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -259,81 +258,82 @@ void vPortEndScheduler( void )
*/ */
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
uint32_t ulCompareMatch; uint32_t ulCompareMatch;
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;
/* We only have 16 bits so have to scale to get our required tick rate. */ /* We only have 16 bits so have to scale to get our required tick rate. */
ulCompareMatch /= portCLOCK_PRESCALER; ulCompareMatch /= portCLOCK_PRESCALER;
/* Adjust for correct value. */ /* Adjust for correct value. */
ulCompareMatch -= ( uint32_t ) 1; ulCompareMatch -= ( uint32_t ) 1;
/* Setup compare match value for compare match A. Interrupts are disabled /* Setup compare match value for compare match A. Interrupts are disabled
* before this is called so we need not worry here. */ before this is called so we need not worry here. */
ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff ); ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
ulCompareMatch >>= 8; ulCompareMatch >>= 8;
ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff ); ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
OCR1AH = ucHighByte; OCR1AH = ucHighByte;
OCR1AL = ucLowByte; OCR1AL = ucLowByte;
/* Setup clock source and compare match behaviour. */ /* Setup clock source and compare match behaviour. */
ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64; ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_PREEMPTION == 1 #if configUSE_PREEMPTION == 1
/* /*
* Tick ISR for preemptive scheduler. We can use a __task attribute as * Tick ISR for preemptive scheduler. We can use a __task attribute as
* the context is saved at the start of vPortYieldFromTick(). The tick * the context is saved at the start of vPortYieldFromTick(). The tick
* count is incremented after the context is saved. * count is incremented after the context is saved.
*/ */
__task void SIG_OUTPUT_COMPARE1A( void ) __task void SIG_OUTPUT_COMPARE1A( void )
{ {
vPortYieldFromTick(); vPortYieldFromTick();
asm ( "reti" ); asm( "reti" );
} }
#else #else
/* /*
* Tick ISR for the cooperative scheduler. All this does is increment the * Tick ISR for the cooperative scheduler. All this does is increment the
* tick count. We don't need to switch context, this can only be done by * tick count. We don't need to switch context, this can only be done by
* manual calls to taskYIELD(); * manual calls to taskYIELD();
* *
* THE INTERRUPT VECTOR IS POPULATED IN portmacro.s90. DO NOT INSTALL * THE INTERRUPT VECTOR IS POPULATED IN portmacro.s90. DO NOT INSTALL
* IT HERE USING THE USUAL PRAGMA. * IT HERE USING THE USUAL PRAGMA.
*/ */
__interrupt void SIG_OUTPUT_COMPARE1A( void ) __interrupt void SIG_OUTPUT_COMPARE1A( void )
{ {
xTaskIncrementTick(); xTaskIncrementTick();
} }
#endif /* if configUSE_PREEMPTION == 1 */ #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
uxCriticalNesting++; uxCriticalNesting++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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,18 +26,18 @@
*/ */
/* /*
* 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
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -50,61 +50,63 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT int #define portSHORT int
#define portSTACK_TYPE uint8_t #define portSTACK_TYPE uint8_t
#define portBASE_TYPE char #define portBASE_TYPE char
#define portPOINTER_SIZE_TYPE uint16_t #define portPOINTER_SIZE_TYPE uint16_t
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef signed char BaseType_t; typedef signed char BaseType_t;
typedef unsigned char UBaseType_t; typedef unsigned char UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() asm ( "cli" ) #define portDISABLE_INTERRUPTS() asm( "cli" )
#define portENABLE_INTERRUPTS() asm ( "sei" ) #define portENABLE_INTERRUPTS() asm( "sei" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 1 #define portBYTE_ALIGNMENT 1
#define portNOP() asm ( "nop" ) #define portNOP() asm( "nop" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Kernel utilities. */ /* Kernel utilities. */
void vPortYield( void ); void vPortYield( void );
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
#ifdef IAR_MEGA_AVR #ifdef IAR_MEGA_AVR
#define outb( PORT, VALUE ) PORT = VALUE #define outb( PORT, VALUE ) PORT = VALUE
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#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.
@ -51,26 +50,26 @@
#include "gpio.h" #include "gpio.h"
#if configDBG #if configDBG
#include "usart.h" #include "usart.h"
#endif #endif
#if ( configTICK_USE_TC == 1 ) #if( configTICK_USE_TC==1 )
#include "tc.h" #include "tc.h"
#endif #endif
/* Constants required to setup the task context. */ /* Constants required to setup the task context. */
#define portINITIAL_SR ( ( StackType_t ) 0x00400000 ) /* AVR32 : [M2:M0]=001 I1M=0 I0M=0, GM=0 */ #define portINITIAL_SR ( ( StackType_t ) 0x00400000 ) /* AVR32 : [M2:M0]=001 I1M=0 I0M=0, GM=0 */
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 0 )
/* Each task maintains its own critical nesting variable. */ /* Each task maintains its own critical nesting variable. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
#if ( configTICK_USE_TC == 0 ) #if( configTICK_USE_TC==0 )
static void prvScheduleNextTick( void ); static void prvScheduleNextTick( void );
#else #else
static void prvClearTcInt( void ); static void prvClearTcInt( void );
#endif #endif
/* Setup the timer to generate the tick interrupts. */ /* Setup the timer to generate the tick interrupts. */
@ -82,149 +81,145 @@ static void prvSetupTimerInterrupt( void );
* Low-level initialization routine called during startup, before the main * Low-level initialization routine called during startup, before the main
* function. * function.
*/ */
int __low_level_init( void ) int __low_level_init(void)
{ {
#if configHEAP_INIT #if configHEAP_INIT
#pragma segment = "HEAP" #pragma segment = "HEAP"
BaseType_t * pxMem; BaseType_t *pxMem;
#endif #endif
/* Enable exceptions. */ /* Enable exceptions. */
ENABLE_ALL_EXCEPTIONS(); ENABLE_ALL_EXCEPTIONS();
/* Initialize interrupt handling. */ /* Initialize interrupt handling. */
INTC_init_interrupts(); INTC_init_interrupts();
#if configHEAP_INIT #if configHEAP_INIT
{ {
/* Initialize the heap used by malloc. */ /* Initialize the heap used by malloc. */
for( pxMem = __segment_begin( "HEAP" ); pxMem < ( BaseType_t * ) __segment_end( "HEAP" ); ) for( pxMem = __segment_begin( "HEAP" ); pxMem < ( BaseType_t * ) __segment_end( "HEAP" ); )
{ {
*pxMem++ = 0xA5A5A5A5; *pxMem++ = 0xA5A5A5A5;
} }
} }
#endif #endif
/* Code section present if and only if the debug trace is activated. */ /* Code section present if and only if the debug trace is activated. */
#if configDBG #if configDBG
{ {
static const gpio_map_t DBG_USART_GPIO_MAP = static const gpio_map_t DBG_USART_GPIO_MAP =
{ {
{ configDBG_USART_RX_PIN, configDBG_USART_RX_FUNCTION }, { configDBG_USART_RX_PIN, configDBG_USART_RX_FUNCTION },
{ configDBG_USART_TX_PIN, configDBG_USART_TX_FUNCTION } { configDBG_USART_TX_PIN, configDBG_USART_TX_FUNCTION }
}; };
static const usart_options_t DBG_USART_OPTIONS = static const usart_options_t DBG_USART_OPTIONS =
{ {
.baudrate = configDBG_USART_BAUDRATE, .baudrate = configDBG_USART_BAUDRATE,
.charlength = 8, .charlength = 8,
.paritytype = USART_NO_PARITY, .paritytype = USART_NO_PARITY,
.stopbits = USART_1_STOPBIT, .stopbits = USART_1_STOPBIT,
.channelmode = USART_NORMAL_CHMODE .channelmode = USART_NORMAL_CHMODE
}; };
/* Initialize the USART used for the debug trace with the configured parameters. */ /* Initialize the USART used for the debug trace with the configured parameters. */
extern volatile avr32_usart_t * volatile stdio_usart_base; extern volatile avr32_usart_t *volatile stdio_usart_base;
stdio_usart_base = configDBG_USART; stdio_usart_base = configDBG_USART;
gpio_enable_module( DBG_USART_GPIO_MAP, gpio_enable_module( DBG_USART_GPIO_MAP,
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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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;
vTaskSuspendAll(); vTaskSuspendAll();
{ {
pvReturn = realloc( pv, xWantedSize ); pvReturn = realloc( pv, xWantedSize );
} }
xTaskResumeAll(); xTaskResumeAll();
return pvReturn; return pvReturn;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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. */
portSAVE_CONTEXT_OS_INT(); portSAVE_CONTEXT_OS_INT();
#if ( configTICK_USE_TC == 1 ) #if( configTICK_USE_TC==1 )
/* 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)
clock cycles from now. */
prvScheduleNextTick();
#endif
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ) /* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
* clock cycles from now. */ calls in a critical section . */
prvScheduleNextTick(); portENTER_CRITICAL();
#endif xTaskIncrementTick();
portEXIT_CRITICAL();
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS /* Restore the context of the "elected task". */
* calls in a critical section . */ portRESTORE_CONTEXT_OS_INT();
portENTER_CRITICAL();
xTaskIncrementTick();
portEXIT_CRITICAL();
/* Restore the context of the "elected task". */
portRESTORE_CONTEXT_OS_INT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#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. */
portSAVE_CONTEXT_SCALL(); portSAVE_CONTEXT_SCALL();
vTaskSwitchContext(); vTaskSwitchContext();
portRESTORE_CONTEXT_SCALL(); portRESTORE_CONTEXT_SCALL();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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 )
{ {
/* Disable interrupts */ /* Disable interrupts */
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++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#pragma optimize = no_inline #pragma optimize = no_inline
void vPortExitCritical( void ) 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. */ portENABLE_INTERRUPTS();
portENABLE_INTERRUPTS(); }
} }
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -234,184 +229,178 @@ 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--;
*pxTopOfStack-- = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack-- = ( StackType_t ) 0x08080808; /* R8 */
*pxTopOfStack-- = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack-- = ( StackType_t ) 0x09090909; /* R9 */
*pxTopOfStack-- = ( StackType_t ) 0x0A0A0A0A; /* R10 */ *pxTopOfStack-- = ( StackType_t ) 0x0A0A0A0A; /* R10 */
*pxTopOfStack-- = ( StackType_t ) 0x0B0B0B0B; /* R11 */ *pxTopOfStack-- = ( StackType_t ) 0x0B0B0B0B; /* R11 */
*pxTopOfStack-- = ( StackType_t ) pvParameters; /* R12 */ *pxTopOfStack-- = ( StackType_t ) pvParameters; /* R12 */
*pxTopOfStack-- = ( StackType_t ) 0xDEADBEEF; /* R14/LR */ *pxTopOfStack-- = ( StackType_t ) 0xDEADBEEF; /* R14/LR */
*pxTopOfStack-- = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; /* R15/PC */ *pxTopOfStack-- = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; /* R15/PC */
*pxTopOfStack-- = ( StackType_t ) portINITIAL_SR; /* SR */ *pxTopOfStack-- = ( StackType_t ) portINITIAL_SR; /* SR */
*pxTopOfStack-- = ( StackType_t ) 0xFF0000FF; /* R0 */ *pxTopOfStack-- = ( StackType_t ) 0xFF0000FF; /* R0 */
*pxTopOfStack-- = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack-- = ( StackType_t ) 0x01010101; /* R1 */
*pxTopOfStack-- = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack-- = ( StackType_t ) 0x02020202; /* R2 */
*pxTopOfStack-- = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack-- = ( StackType_t ) 0x03030303; /* R3 */
*pxTopOfStack-- = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack-- = ( StackType_t ) 0x04040404; /* R4 */
*pxTopOfStack-- = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack-- = ( StackType_t ) 0x05050505; /* R5 */
*pxTopOfStack-- = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack-- = ( StackType_t ) 0x06060606; /* R6 */
*pxTopOfStack-- = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack-- = ( StackType_t ) 0x07070707; /* R7 */
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_NESTING; /* ulCriticalNesting */ *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_NESTING; /* ulCriticalNesting */
return pxTopOfStack; return 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. */
portRESTORE_CONTEXT(); portRESTORE_CONTEXT();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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)
{ {
uint32_t lCycles; uint32_t lCycles;
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
// generation feature does not get disabled.
if(0 == lCycles)
{
lCycles++;
}
Set_system_register(AVR32_COMPARE, lCycles);
}
#pragma optimize = no_inline
static void prvScheduleNextTick(void)
{
uint32_t lCycles, lCount;
/* If lCycles ends up to be 0, make it 1 so that the COMPARE and exception */ lCycles = Get_system_register(AVR32_COMPARE);
/* generation feature does not get disabled. */ lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
if( 0 == lCycles ) // If lCycles ends up to be 0, make it 1 so that the COMPARE and exception
{ // generation feature does not get disabled.
lCycles++; if(0 == lCycles)
} {
lCycles++;
Set_system_register( AVR32_COMPARE, lCycles ); }
} lCount = Get_system_register(AVR32_COUNT);
if( lCycles < lCount )
#pragma optimize = no_inline { // We missed a tick, recover for the next.
static void prvScheduleNextTick( void ) lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ);
{ }
uint32_t lCycles, lCount; Set_system_register(AVR32_COMPARE, lCycles);
}
lCycles = Get_system_register( AVR32_COMPARE ); #else
lCycles += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); #pragma optimize = no_inline
static void prvClearTcInt(void)
/* If lCycles ends up to be 0, make it 1 so that the COMPARE and exception */ {
/* generation feature does not get disabled. */ AVR32_TC.channel[configTICK_TC_CHANNEL].sr;
if( 0 == lCycles ) }
{ #endif
lCycles++;
}
lCount = Get_system_register( AVR32_COUNT );
if( lCycles < lCount )
{ /* We missed a tick, recover for the next. */
lCycles += ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
}
Set_system_register( AVR32_COMPARE, lCycles );
}
#else /* if ( configTICK_USE_TC == 0 ) */
#pragma optimize = no_inline
static void prvClearTcInt( void )
{
AVR32_TC.channel[ configTICK_TC_CHANNEL ].sr;
}
#endif /* if ( configTICK_USE_TC == 0 ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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;
/* Options for waveform genration. */ volatile avr32_tc_t *tc = &AVR32_TC;
tc_waveform_opt_t waveform_opt =
{
.channel = configTICK_TC_CHANNEL, /* Channel selection. */
.bswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOB. */ // Options for waveform genration.
.beevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOB. */ tc_waveform_opt_t waveform_opt =
.bcpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOB. */ {
.bcpb = TC_EVT_EFFECT_NOOP, /* RB compare effect on TIOB. */ .channel = configTICK_TC_CHANNEL, /* Channel selection. */
.aswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOA. */ .bswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOB. */
.aeevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOA. */ .beevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOB. */
.acpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOA: toggle. */ .bcpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOB. */
.acpa = TC_EVT_EFFECT_NOOP, /* RA compare effect on TIOA: toggle (other possibilities are none, set and clear). */ .bcpb = TC_EVT_EFFECT_NOOP, /* RB compare effect on TIOB. */
.wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER, /* Waveform selection: Up mode without automatic trigger on RC compare. */ .aswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOA. */
.enetrg = FALSE, /* External event trigger enable. */ .aeevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOA. */
.eevt = 0, /* External event selection. */ .acpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOA: toggle. */
.eevtedg = TC_SEL_NO_EDGE, /* External event edge selection. */ .acpa = TC_EVT_EFFECT_NOOP, /* RA compare effect on TIOA: toggle (other possibilities are none, set and clear). */
.cpcdis = FALSE, /* Counter disable when RC compare. */
.cpcstop = FALSE, /* Counter clock stopped with RC compare. */
.burst = FALSE, /* Burst signal selection. */ .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,/* Waveform selection: Up mode without automatic trigger on RC compare. */
.clki = FALSE, /* Clock inversion. */ .enetrg = FALSE, /* External event trigger enable. */
.tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */ .eevt = 0, /* External event selection. */
}; .eevtedg = TC_SEL_NO_EDGE, /* External event edge selection. */
.cpcdis = FALSE, /* Counter disable when RC compare. */
.cpcstop = FALSE, /* Counter clock stopped with RC compare. */
tc_interrupt_t tc_interrupt = .burst = FALSE, /* Burst signal selection. */
{ .clki = FALSE, /* Clock inversion. */
.etrgs = 0, .tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */
.ldrbs = 0, };
.ldras = 0,
.cpcs = 1,
.cpbs = 0,
.cpas = 0,
.lovrs = 0,
.covfs = 0,
};
#endif /* if ( configTICK_USE_TC == 1 ) */
/* Disable all interrupt/exception. */ tc_interrupt_t tc_interrupt =
portDISABLE_INTERRUPTS(); {
.etrgs=0,
.ldrbs=0,
.ldras=0,
.cpcs =1,
.cpbs =0,
.cpas =0,
.lovrs=0,
.covfs=0,
};
/* Register the compare interrupt handler to the interrupt controller and #endif
* enable the compare interrupt. */
#if ( configTICK_USE_TC == 1 ) /* Disable all interrupt/exception. */
{ portDISABLE_INTERRUPTS();
INTC_register_interrupt( ( __int_handler ) & vTick, configTICK_TC_IRQ, INT0 );
/* Initialize the timer/counter. */ /* Register the compare interrupt handler to the interrupt controller and
tc_init_waveform( tc, &waveform_opt ); enable the compare interrupt. */
/* Set the compare triggers. #if( configTICK_USE_TC==1 )
* Remember TC counter is 16-bits, so counting second is not possible! {
* That's why we configure it to count ms. */ INTC_register_interrupt((__int_handler)&vTick, configTICK_TC_IRQ, INT0);
tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4 ) / configTICK_RATE_HZ );
tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt ); /* Initialize the timer/counter. */
tc_init_waveform(tc, &waveform_opt);
/* Start the timer/counter. */ /* Set the compare triggers.
tc_start( tc, configTICK_TC_CHANNEL ); Remember TC counter is 16-bits, so counting second is not possible!
} That's why we configure it to count ms. */
#else /* if ( configTICK_USE_TC == 1 ) */ tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4) / configTICK_RATE_HZ );
{
INTC_register_interrupt( ( __int_handler ) & vTick, AVR32_CORE_COMPARE_IRQ, INT0 ); tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt );
prvScheduleFirstTick();
} /* Start the timer/counter. */
#endif /* if ( configTICK_USE_TC == 1 ) */ tc_start(tc, configTICK_TC_CHANNEL);
}
#else
{
INTC_register_interrupt((__int_handler)&vTick, AVR32_CORE_COMPARE_IRQ, INT0);
prvScheduleFirstTick();
}
#endif
} }

File diff suppressed because it is too large Load diff

View file

@ -1,18 +1,17 @@
/*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.
* - AppNote: * - AppNote:
* *
* \author Atmel Corporation: http://www.atmel.com \n * \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/ * Support and FAQ: http://support.atmel.no/
* *
******************************************************************************/ ******************************************************************************/
/* Copyright (c) 2007, Atmel Corporation All rights reserved. /* Copyright (c) 2007, Atmel Corporation All rights reserved.
* *
@ -53,7 +52,7 @@ _STD_BEGIN
#pragma module_name = "?__read" #pragma module_name = "?__read"
extern volatile avr32_usart_t * volatile stdio_usart_base; extern volatile avr32_usart_t *volatile stdio_usart_base;
/*! \brief Reads a number of bytes, at most \a size, into the memory area /*! \brief Reads a number of bytes, at most \a size, into the memory area
@ -66,33 +65,28 @@ 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;
} }
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)
break;
if( c < 0 ) *buffer++ = c;
{ ++nChars;
break; }
}
*buffer++ = c; return nChars;
++nChars;
}
return nChars;
} }

View file

@ -1,18 +1,17 @@
/*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.
* - AppNote: * - AppNote:
* *
* \author Atmel Corporation: http://www.atmel.com \n * \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/ * Support and FAQ: http://support.atmel.no/
* *
******************************************************************************/ ******************************************************************************/
/* Copyright (c) 2007, Atmel Corporation All rights reserved. /* Copyright (c) 2007, Atmel Corporation All rights reserved.
* *
@ -53,8 +52,8 @@ _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;
/*! \brief Writes a number of bytes, at most \a size, from the memory area /*! \brief Writes a number of bytes, at most \a size, from the memory area
@ -70,36 +69,34 @@ __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.
return 0;
}
// This implementation only writes to stdout and stderr.
// For all other file handles, it returns failure.
if (handle != _LLIO_STDOUT && handle != _LLIO_STDERR)
{
return _LLIO_ERROR;
}
for (; size != 0; --size)
{
if (usart_putchar(stdio_usart_base, *buffer++) < 0)
{ {
/* This means that we should flush internal buffers. */ return _LLIO_ERROR;
return 0;
} }
/* This implementation only writes to stdout and stderr. */ ++nChars;
/* For all other file handles, it returns failure. */ }
if( ( handle != _LLIO_STDOUT ) && ( handle != _LLIO_STDERR ) )
{
return _LLIO_ERROR;
}
for( ; size != 0; --size ) return nChars;
{
if( usart_putchar( stdio_usart_base, *buffer++ ) < 0 )
{
return _LLIO_ERROR;
}
++nChars;
}
return nChars;
} }

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,123 +1,105 @@
; /* ;/*
* ; * 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.
MOV LR, R0
Now we have saved LR we can use it instead of R0. ; Pop R0 so we can save it onto the system mode stack.
MOV LR, R0 LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Pop R0 so we can save it onto the system mode stack. STMDB LR, {R0-LR}^
LDMIA SP !, { R0 } NOP
SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push all the system mode registers onto the task stack. MRS R0, SPSR
STMDB LR, { R0 - LR } ^ STMDB LR!, {R0}
NOP
SUB LR, LR, # 60
; LDR R0, =ulCriticalNesting
Push the SPSR onto the task stack. LDR R0, [R0]
MRS R0, SPSR STMDB LR!, {R0}
STMDB LR !, { R0 }
LDR R0, = ulCriticalNesting ; Store the new top of stack for the task.
LDR R0, [ R0 ] LDR R1, =pxCurrentTCB
STMDB LR !, { R0 } LDR R0, [R1]
STR LR, [R0]
; ENDM
Store the new top of stack for the task.
LDR R1, = pxCurrentTCB
LDR R0, [ R1 ]
STR LR, [ R0 ]
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.
; LDR R0, =ulCriticalNesting
Load it into the ulCriticalNesting variable. LDMFD LR!, {R1}
LDR R0, = ulCriticalNesting STR R1, [R0]
LDMFD LR !, { R1 }
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.
SUBS PC, LR, #4
And return -correcting the offset in the LR to obtain the ENDM
;
correct address.
SUBS PC, LR, # 4
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

@ -26,8 +26,8 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Atmel ARM7 port. * Implementation of functions defined in portable.h for the Atmel ARM7 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Standard includes. */ /* Standard includes. */
@ -38,29 +38,29 @@
#include "task.h" #include "task.h"
/* Constants required to setup the initial stack. */ /* Constants required to setup the initial stack. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
/* Constants required to setup the PIT. */ /* Constants required to setup the PIT. */
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 ) #define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS ) #define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
#define portINT_LEVEL_SENSITIVE 0 #define portINT_LEVEL_SENSITIVE 0
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 ) #define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 ) #define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Setup the PIT to generate the tick interrupts. */ /* Setup the PIT to generate the tick interrupts. */
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,181 +71,189 @@ 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--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
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--;
/* The status register is set for system mode, with interrupts enabled. */ /* The status register is set for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL )
{
/* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
pxTopOfStack--;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL ) /* 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
/* We want the task to start in thumb mode. */ tasks context. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack = portNO_CRITICAL_NESTING;
}
pxTopOfStack--; return pxTopOfStack;
/* 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
* tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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
preemptive scheduler is not being used any woken task is not given
processor time no matter what its priority. */
xTaskIncrementTick();
/* Clear the PIT interrupt. */
ulDummy = AT91C_BASE_PITC->PITC_PIVR;
/* End the interrupt in the AIC. */
AT91C_BASE_AIC->AIC_EOICR = ulDummy;
}
/* Increment the tick count - which may wake some tasks but as the #else
* preemptive scheduler is not being used any woken task is not given
* processor time no matter what its priority. */
xTaskIncrementTick();
/* Clear the PIT interrupt. */ /* Currently the IAR port requires the preemptive tick function to be
ulDummy = AT91C_BASE_PITC->PITC_PIVR; defined in an asm file. */
/* End the interrupt in the AIC. */ #endif
AT91C_BASE_AIC->AIC_EOICR = ulDummy;
}
#else /* if configUSE_PREEMPTION == 0 */
/* Currently the IAR port requires the preemptive tick function to be
* defined in an asm file. */
#endif /* if configUSE_PREEMPTION == 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) 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 );
#else
extern void( vPortPreemptiveTick )( void );
AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void ( * )( void ) )vPortPreemptiveTick );
#endif
/* Configure the PIT period. */ AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPortNonPreemptiveTick );
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
/* Enable the interrupt. Global interrupts are disables at this point so #else
* this is safe. */
AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_SYS ); extern void ( vPortPreemptiveTick )( void );
AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, AT91C_ID_SYS, AT91C_AIC_PRIOR_HIGHEST, portINT_LEVEL_SENSITIVE, ( void (*)(void) ) vPortPreemptiveTick );
#endif
/* Configure the PIT period. */
pxPIT->PITC_PIMR = portPIT_ENABLE | portPIT_INT_ENABLE | portPIT_COUNTER_VALUE;
/* Enable the interrupt. Global interrupts are disables at this point so
this is safe. */
AT91F_AIC_EnableIt( AT91C_BASE_AIC, AT91C_ID_SYS );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts first! */ /* Disable interrupts first! */
__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++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -27,11 +27,11 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -44,66 +44,68 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm ( "SWI 0" ) #define portYIELD() asm ( "SWI 0" )
#define portNOP() asm ( "NOP" ) #define portNOP() asm ( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
__arm __interwork void vPortDisableInterruptsFromThumb( void ); __arm __interwork void vPortDisableInterruptsFromThumb( void );
__arm __interwork void vPortEnableInterruptsFromThumb( void ); __arm __interwork void vPortEnableInterruptsFromThumb( void );
__arm __interwork void vPortEnterCritical( void ); __arm __interwork void vPortEnterCritical( void );
__arm __interwork void vPortExitCritical( void ); __arm __interwork void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() __disable_interrupt() #define portDISABLE_INTERRUPTS() __disable_interrupt()
#define portENABLE_INTERRUPTS() __enable_interrupt() #define portENABLE_INTERRUPTS() __enable_interrupt()
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern void vTaskSwitchContext( void ); \ extern void vTaskSwitchContext( void ); \
\ \
if( xSwitchRequired ) \ if( xSwitchRequired ) \
{ \ { \
vTaskSwitchContext(); \ vTaskSwitchContext(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,96 +1,78 @@
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.
MOV LR, R0
Now we have saved LR we can use it instead of R0. ; Pop R0 so we can save it onto the system mode stack.
MOV LR, R0 LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Pop R0 so we can save it onto the system mode stack. STMDB LR, {R0-LR}^
LDMIA SP !, { R0 } NOP
SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push all the system mode registers onto the task stack. MRS R0, SPSR
STMDB LR, { R0 - LR } ^ STMDB LR!, {R0}
NOP
SUB LR, LR, # 60
; LDR R0, =ulCriticalNesting
Push the SPSR onto the task stack. LDR R0, [R0]
MRS R0, SPSR STMDB LR!, {R0}
STMDB LR !, { R0 }
LDR R0, = ulCriticalNesting ; Store the new top of stack for the task.
LDR R0, [ R0 ] LDR R1, =pxCurrentTCB
STMDB LR !, { R0 } LDR R0, [R1]
STR LR, [R0]
; ENDM
Store the new top of stack for the task.
LDR R1, = pxCurrentTCB
LDR R0, [ R1 ]
STR LR, [ R0 ]
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.
; LDR R0, =ulCriticalNesting
Load it into the ulCriticalNesting variable. LDMFD LR!, {R1}
LDR R0, = ulCriticalNesting STR R1, [R0]
LDMFD LR !, { R1 }
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.
SUBS PC, LR, #4
And return -correcting the offset in the LR to obtain the ENDM
;
correct address.
SUBS PC, LR, # 4
ENDM

View file

@ -26,8 +26,8 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Atmel ARM7 port. * Implementation of functions defined in portable.h for the Atmel ARM7 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Standard includes. */ /* Standard includes. */
@ -50,21 +50,21 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Constants required to setup the initial stack. */ /* Constants required to setup the initial stack. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
/* Constants required to setup the PIT. */ /* Constants required to setup the PIT. */
#define port1MHz_IN_Hz ( 1000000ul ) #define port1MHz_IN_Hz ( 1000000ul )
#define port1SECOND_IN_uS ( 1000000.0 ) #define port1SECOND_IN_uS ( 1000000.0 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
#define portINT_LEVEL_SENSITIVE 0 #define portINT_LEVEL_SENSITIVE 0
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 ) #define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 ) #define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Setup the PIT to generate the tick interrupts. */ /* Setup the PIT to generate the tick interrupts. */
@ -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,167 +86,171 @@ 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--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
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--;
/* The status register is set for system mode, with interrupts enabled. */ /* The status register is set for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
#ifdef THUMB_INTERWORK
{
/* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
#endif
pxTopOfStack--;
#ifdef THUMB_INTERWORK /* 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
/* We want the task to start in thumb mode. */ tasks context. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack = portNO_CRITICAL_NESTING;
}
#endif
pxTopOfStack--; return pxTopOfStack;
/* 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
* tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static __arm void vPortTickISR( void ) 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();
} }
/* Clear the PIT interrupt. */ /* Clear the PIT interrupt. */
ulDummy = AT91C_BASE_PITC->PITC_PIVR; ulDummy = AT91C_BASE_PITC->PITC_PIVR;
/* To remove compiler warning. */ /* To remove compiler warning. */
( void ) ulDummy; ( void ) ulDummy;
/* The AIC is cleared in the asm wrapper, outside of this function. */ /* The AIC is cleared in the asm wrapper, outside of this function. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
const uint32_t ulPeriodIn_uS = ( 1.0 / ( double ) configTICK_RATE_HZ ) * port1SECOND_IN_uS; const uint32_t ulPeriodIn_uS = ( 1.0 / ( double ) configTICK_RATE_HZ ) * port1SECOND_IN_uS;
/* Setup the PIT for the required frequency. */ /* Setup the PIT for the required frequency. */
PIT_Init( ulPeriodIn_uS, BOARD_MCK / port1MHz_IN_Hz ); PIT_Init( ulPeriodIn_uS, BOARD_MCK / port1MHz_IN_Hz );
/* Setup the PIT interrupt. */ /* Setup the PIT interrupt. */
AIC_DisableIT( AT91C_ID_SYS ); AIC_DisableIT( AT91C_ID_SYS );
AIC_ConfigureIT( AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, vPortTickISR ); AIC_ConfigureIT( AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, vPortTickISR );
AIC_EnableIT( AT91C_ID_SYS ); AIC_EnableIT( AT91C_ID_SYS );
PIT_EnableIT(); PIT_EnableIT();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts first! */ /* Disable interrupts first! */
__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++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -27,13 +27,13 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -46,67 +46,69 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm ( "SWI 0" ) #define portYIELD() asm ( "SWI 0" )
#define portNOP() asm ( "NOP" ) #define portNOP() asm ( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
__arm __interwork void vPortDisableInterruptsFromThumb( void ); __arm __interwork void vPortDisableInterruptsFromThumb( void );
__arm __interwork void vPortEnableInterruptsFromThumb( void ); __arm __interwork void vPortEnableInterruptsFromThumb( void );
__arm __interwork void vPortEnterCritical( void ); __arm __interwork void vPortEnterCritical( void );
__arm __interwork void vPortExitCritical( void ); __arm __interwork void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() __disable_irq() #define portDISABLE_INTERRUPTS() __disable_irq()
#define portENABLE_INTERRUPTS() __enable_irq() #define portENABLE_INTERRUPTS() __enable_irq()
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern void vTaskSwitchContext( void ); \ extern void vTaskSwitchContext( void ); \
\ \
if( xSwitchRequired ) \ if( xSwitchRequired ) \
{ \ { \
vTaskSwitchContext(); \ vTaskSwitchContext(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,123 +1,105 @@
; /* ;/*
* ; * 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.
MOV LR, R0
Now we have saved LR we can use it instead of R0. ; Pop R0 so we can save it onto the system mode stack.
MOV LR, R0 LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Pop R0 so we can save it onto the system mode stack. STMDB LR, {R0-LR}^
LDMIA SP !, { R0 } NOP
SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push all the system mode registers onto the task stack. MRS R0, SPSR
STMDB LR, { R0 - LR } ^ STMDB LR!, {R0}
NOP
SUB LR, LR, # 60
; LDR R0, =ulCriticalNesting
Push the SPSR onto the task stack. LDR R0, [R0]
MRS R0, SPSR STMDB LR!, {R0}
STMDB LR !, { R0 }
LDR R0, = ulCriticalNesting ; Store the new top of stack for the task.
LDR R0, [ R0 ] LDR R1, =pxCurrentTCB
STMDB LR !, { R0 } LDR R0, [R1]
STR LR, [R0]
; ENDM
Store the new top of stack for the task.
LDR R1, = pxCurrentTCB
LDR R0, [ R1 ]
STR LR, [ R0 ]
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.
; LDR R0, =ulCriticalNesting
Load it into the ulCriticalNesting variable. LDMFD LR!, {R1}
LDR R0, = ulCriticalNesting STR R1, [R0]
LDMFD LR !, { R1 }
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.
SUBS PC, LR, #4
And return -correcting the offset in the LR to obtain the ENDM
;
correct address.
SUBS PC, LR, # 4
ENDM

View file

@ -26,16 +26,16 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the Philips ARM7 port. * Implementation of functions defined in portable.h for the Philips ARM7 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* /*
* 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. */
#include <stdlib.h> #include <stdlib.h>
@ -46,36 +46,36 @@
#include "task.h" #include "task.h"
/* Constants required to setup the tick ISR. */ /* Constants required to setup the tick ISR. */
#define portENABLE_TIMER ( ( uint8_t ) 0x01 ) #define portENABLE_TIMER ( ( uint8_t ) 0x01 )
#define portPRESCALE_VALUE 0x00 #define portPRESCALE_VALUE 0x00
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 ) #define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 ) #define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
/* Constants required to setup the initial stack. */ /* Constants required to setup the initial stack. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
/* Constants required to setup the PIT. */ /* Constants required to setup the PIT. */
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 ) #define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS ) #define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
/* Constants required to handle interrupts. */ /* Constants required to handle interrupts. */
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 ) #define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 ) #define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
#define portINT_LEVEL_SENSITIVE 0 #define portINT_LEVEL_SENSITIVE 0
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 ) #define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 ) #define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
/* Constants required to setup the VIC for the tick ISR. */ /* Constants required to setup the VIC for the tick ISR. */
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 ) #define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 ) #define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 ) #define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -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,219 +95,223 @@ 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--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
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--;
/* The status register is set for system mode, with interrupts enabled. */ /* The status register is set for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL )
{
/* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
pxTopOfStack--;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL ) /* 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
/* We want the task to start in thumb mode. */ tasks context. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack = portNO_CRITICAL_NESTING;
}
pxTopOfStack--; return pxTopOfStack;
/* 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
* tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
T0IR = portTIMER_MATCH_ISR_BIT;
VICVectAddr = portCLEAR_VIC_INTERRUPT;
}
/* Ready for the next interrupt. */ #else
T0IR = portTIMER_MATCH_ISR_BIT;
VICVectAddr = portCLEAR_VIC_INTERRUPT;
}
#else /* if configUSE_PREEMPTION == 0 */ /* This function is called from an asm wrapper, so does not require the __irq
keyword. */
void vPortPreemptiveTick( void );
void vPortPreemptiveTick( void )
{
/* Increment the tick counter. */
if( xTaskIncrementTick() != pdFALSE )
{
/* 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
exits. */
vTaskSwitchContext();
}
/* Ready for the next interrupt. */
T0IR = portTIMER_MATCH_ISR_BIT;
VICVectAddr = portCLEAR_VIC_INTERRUPT;
}
/* This function is called from an asm wrapper, so does not require the __irq #endif
* keyword. */
void vPortPreemptiveTick( void );
void vPortPreemptiveTick( void )
{
/* Increment the tick counter. */
if( xTaskIncrementTick() != pdFALSE )
{
/* 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
* exits. */
vTaskSwitchContext();
}
/* Ready for the next interrupt. */
T0IR = portTIMER_MATCH_ISR_BIT;
VICVectAddr = portCLEAR_VIC_INTERRUPT;
}
#endif /* if configUSE_PREEMPTION == 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) 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 );
} }
#endif #endif
T0MR0 = ulCompareMatch; T0MR0 = ulCompareMatch;
/* Generate tick with timer 0 compare match. */ /* Generate tick with timer 0 compare match. */
T0MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH; T0MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
/* Setup the VIC for the timer. */ /* Setup the VIC for the timer. */
VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT ); VICIntSelect &= ~( portTIMER_VIC_CHANNEL_BIT );
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT; VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
/* The ISR installed depends on whether the preemptive or cooperative
scheduler is being used. */
#if configUSE_PREEMPTION == 1
{
extern void ( vPortPreemptiveTickEntry )( void );
/* The ISR installed depends on whether the preemptive or cooperative VICVectAddr0 = ( uint32_t ) vPortPreemptiveTickEntry;
* scheduler is being used. */ }
#if configUSE_PREEMPTION == 1 #else
{ {
extern void( vPortPreemptiveTickEntry )( void ); extern void ( vNonPreemptiveTick )( void );
VICVectAddr0 = ( uint32_t ) vPortPreemptiveTickEntry; VICVectAddr0 = ( int32_t ) vPortNonPreemptiveTick;
} }
#else #endif
{
extern void( vNonPreemptiveTick )( void );
VICVectAddr0 = ( int32_t ) vPortNonPreemptiveTick; VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE;
}
#endif /* if configUSE_PREEMPTION == 1 */
VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE; /* Start the timer - interrupts are disabled when this function is called
so it is okay to do this here. */
/* Start the timer - interrupts are disabled when this function is called T0TCR = portENABLE_TIMER;
* so it is okay to do this here. */
T0TCR = portENABLE_TIMER;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEnterCritical( void ) void vPortEnterCritical( void )
{ {
/* Disable interrupts first! */ /* Disable interrupts first! */
__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++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -27,13 +27,13 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -46,66 +46,68 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm ( "SWI 0" ) #define portYIELD() asm ( "SWI 0" )
#define portNOP() asm ( "NOP" ) #define portNOP() asm ( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
__arm __interwork void vPortDisableInterruptsFromThumb( void ); __arm __interwork void vPortDisableInterruptsFromThumb( void );
__arm __interwork void vPortEnableInterruptsFromThumb( void ); __arm __interwork void vPortEnableInterruptsFromThumb( void );
__arm __interwork void vPortEnterCritical( void ); __arm __interwork void vPortEnterCritical( void );
__arm __interwork void vPortExitCritical( void ); __arm __interwork void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() __disable_interrupt() #define portDISABLE_INTERRUPTS() __disable_interrupt()
#define portENABLE_INTERRUPTS() __enable_interrupt() #define portENABLE_INTERRUPTS() __enable_interrupt()
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern void vTaskSwitchContext( void ); \ extern void vTaskSwitchContext( void ); \
\ \
if( xSwitchRequired ) \ if( xSwitchRequired ) \
{ \ { \
vTaskSwitchContext(); \ vTaskSwitchContext(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -30,28 +30,28 @@
#include "task.h" #include "task.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the MSP430 port. * Implementation of functions defined in portable.h for the MSP430 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* 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,76 +69,74 @@ 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--;
* pxTopOfStack = ( StackType_t ) 0x2222;
* pxTopOfStack--;
* pxTopOfStack = ( StackType_t ) 0x3333;
* pxTopOfStack--;
*/
/* The msp430 automatically pushes the PC then SR onto the stack before *pxTopOfStack = ( StackType_t ) 0x1111;
* executing an ISR. We want the stack to look just as if this has happened pxTopOfStack--;
* so place a pointer to the start of the task on the stack first - followed *pxTopOfStack = ( StackType_t ) 0x2222;
* by the flags we want the task to use when it starts up. */ pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; *pxTopOfStack = ( StackType_t ) 0x3333;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portFLAGS_INT_ENABLED; */
pxTopOfStack--;
/* Next the general purpose registers. */ /* The msp430 automatically pushes the PC then SR onto the stack before
*pxTopOfStack = ( StackType_t ) 0x4444; executing an ISR. We want the stack to look just as if this has happened
pxTopOfStack--; so place a pointer to the start of the task on the stack first - followed
*pxTopOfStack = ( StackType_t ) 0x5555; by the flags we want the task to use when it starts up. */
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) pxCode;
*pxTopOfStack = ( StackType_t ) 0x6666; pxTopOfStack--;
pxTopOfStack--; *pxTopOfStack = portFLAGS_INT_ENABLED;
*pxTopOfStack = ( StackType_t ) 0x7777; pxTopOfStack--;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x8888;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x9999;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaa;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xbbbb;
pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in /* Next the general purpose registers. */
* R15. */ *pxTopOfStack = ( StackType_t ) 0x4444;
*pxTopOfStack = ( StackType_t ) pvParameters; pxTopOfStack--;
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x6666;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x7777;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x8888;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x9999;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaa;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xbbbb;
pxTopOfStack--;
/* When the task starts is will expect to find the function parameter in
R15. */
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xdddd;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xeeee;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xffff;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xdddd; /* A variable is used to keep track of the critical section nesting.
pxTopOfStack--; This variable has to be stored as part of the task context and is
*pxTopOfStack = ( StackType_t ) 0xeeee; initially set to zero. */
pxTopOfStack--; *pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
*pxTopOfStack = ( StackType_t ) 0xffff;
pxTopOfStack--;
/* A variable is used to keep track of the critical section nesting. /* Return a pointer to the top of the stack we have generated so this can
* This variable has to be stored as part of the task context and is be stored in the task control block for the task. */
* initially set to zero. */ return pxTopOfStack;
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_SECTION_NESTING;
/* 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. */
return 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. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -148,25 +146,28 @@ void vPortEndScheduler( void )
*/ */
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
/* Ensure the timer is stopped. */ /* Ensure the timer is stopped. */
TACTL = 0; TACTL = 0;
/* Run the timer of the ACLK. */ /* Run the timer of the ACLK. */
TACTL = TASSEL_1; TACTL = TASSEL_1;
/* Clear everything to start with. */ /* Clear everything to start with. */
TACTL |= TACLR; TACTL |= TACLR;
/* Set the compare match value according to the tick rate we want. */ /* Set the compare match value according to the tick rate we want. */
TACCR0 = portACLK_FREQUENCY_HZ / configTICK_RATE_HZ; TACCR0 = portACLK_FREQUENCY_HZ / configTICK_RATE_HZ;
/* Enable the interrupts. */ /* Enable the interrupts. */
TACCTL0 = CCIE; TACCTL0 = CCIE;
/* Start up clean. */ /* Start up clean. */
TACTL |= TACLR; TACTL |= TACLR;
/* Up mode. */ /* Up mode. */
TACTL |= MC_1; TACTL |= MC_1;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -30,54 +30,55 @@
portSAVE_CONTEXT macro portSAVE_CONTEXT macro
IMPORT pxCurrentTCB IMPORT pxCurrentTCB
IMPORT usCriticalNesting IMPORT usCriticalNesting
/* Save the remaining registers. */ /* Save the remaining registers. */
push r4 push r4
push r5 push r5
push r6 push r6
push r7 push r7
push r8 push r8
push r9 push r9
push r10 push r10
push r11 push r11
push r12 push r12
push r13 push r13
push r14 push r14
push r15 push r15
mov.w &usCriticalNesting, r14 mov.w &usCriticalNesting, r14
push r14 push r14
mov.w &pxCurrentTCB, r12 mov.w &pxCurrentTCB, r12
mov.w r1, 0 ( r12 ) mov.w r1, 0(r12)
endm endm
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
portRESTORE_CONTEXT macro portRESTORE_CONTEXT macro
mov.w & pxCurrentTCB, r12 mov.w &pxCurrentTCB, r12
mov.w @r12, r1 mov.w @r12, r1
pop r15 pop r15
mov.w r15, &usCriticalNesting mov.w r15, &usCriticalNesting
pop r15 pop r15
pop r14 pop r14
pop r13 pop r13
pop r12 pop r12
pop r11 pop r11
pop r10 pop r10
pop r9 pop r9
pop r8 pop r8
pop r7 pop r7
pop r6 pop r6
pop r5 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

@ -39,66 +39,66 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT int #define portSHORT int
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portBASE_TYPE short #define portBASE_TYPE short
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Interrupt control macros. */ /* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() _DINT(); _NOP() #define portDISABLE_INTERRUPTS() _DINT(); _NOP()
#define portENABLE_INTERRUPTS() _EINT(); _NOP() #define portENABLE_INTERRUPTS() _EINT(); _NOP()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section control macros. */ /* Critical section control macros. */
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
\ \
/* Now interrupts are disabled usCriticalNesting can be accessed */ \ /* Now interrupts are disabled usCriticalNesting can be accessed */ \
/* directly. Increment ulCriticalNesting to keep a count of how many */ \ /* directly. Increment ulCriticalNesting to keep a count of how many */ \
/* times portENTER_CRITICAL() has been called. */ \ /* times portENTER_CRITICAL() has been called. */ \
usCriticalNesting++; \ usCriticalNesting++; \
} }
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
/* Decrement the nesting count as we are leaving a critical section. */ \ /* Decrement the nesting count as we are leaving a critical section. */ \
usCriticalNesting--; \ usCriticalNesting--; \
\ \
/* 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( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
@ -107,26 +107,27 @@ typedef unsigned short UBaseType_t;
* Manual context switch called by portYIELD or taskYIELD. * Manual context switch called by portYIELD or taskYIELD.
*/ */
extern void vPortYield( void ); extern void vPortYield( void );
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() #define portNOP()
#define portPOINTER_SIZE_TYPE uint16_t #define portPOINTER_SIZE_TYPE uint16_t
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#if configINTERRUPT_EXAMPLE_METHOD == 2 #if configINTERRUPT_EXAMPLE_METHOD == 2
extern void vTaskSwitchContext( void ); extern void vTaskSwitchContext( void );
#define portYIELD_FROM_ISR( x ) if( x ) vTaskSwitchContext() #define portYIELD_FROM_ISR( x ) if( x ) vTaskSwitchContext()
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -29,34 +29,35 @@
#define DATA_MODEL_H #define DATA_MODEL_H
#if __DATA_MODEL__ == __DATA_MODEL_SMALL__ #if __DATA_MODEL__ == __DATA_MODEL_SMALL__
#define pushm_x pushm.w #define pushm_x pushm.w
#define popm_x popm.w #define popm_x popm.w
#define push_x push.w #define push_x push.w
#define pop_x pop.w #define pop_x pop.w
#define mov_x mov.w #define mov_x mov.w
#define cmp_x cmp.w #define cmp_x cmp.w
#endif #endif
#if __DATA_MODEL__ == __DATA_MODEL_MEDIUM__ #if __DATA_MODEL__ == __DATA_MODEL_MEDIUM__
#define pushm_x pushm.a #define pushm_x pushm.a
#define popm_x popm.a #define popm_x popm.a
#define push_x pushx.a #define push_x pushx.a
#define pop_x popx.a #define pop_x popx.a
#define mov_x mov.w #define mov_x mov.w
#define cmp_x cmp.w #define cmp_x cmp.w
#endif #endif
#if __DATA_MODEL__ == __DATA_MODEL_LARGE__ #if __DATA_MODEL__ == __DATA_MODEL_LARGE__
#define pushm_x pushm.a #define pushm_x pushm.a
#define popm_x popm.a #define popm_x popm.a
#define push_x pushx.a #define push_x pushx.a
#define pop_x popx.a #define pop_x popx.a
#define mov_x movx.a #define mov_x movx.a
#define cmp_x cmpx.a #define cmp_x cmpx.a
#endif #endif
#ifndef pushm_x #ifndef pushm_x
#error The assembler options must define one of the following symbols: __DATA_MODEL_SMALL__, __DATA_MODEL_MEDIUM__, or __DATA_MODEL_LARGE__ #error The assembler options must define one of the following symbols: __DATA_MODEL_SMALL__, __DATA_MODEL_MEDIUM__, or __DATA_MODEL_LARGE__
#endif #endif
#endif /* DATA_MODEL_H */ #endif /* DATA_MODEL_H */

View file

@ -30,28 +30,28 @@
#include "task.h" #include "task.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the MSP430X port. * Implementation of functions defined in portable.h for the MSP430X port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* 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,98 +69,95 @@ 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. */
pusTopOfStack = ( uint16_t * ) pxTopOfStack; pusTopOfStack = ( uint16_t * ) pxTopOfStack;
pusTopOfStack--; pusTopOfStack--;
pulTopOfStack = ( uint32_t * ) pusTopOfStack; pulTopOfStack = ( uint32_t * ) pusTopOfStack;
} }
else else
{ {
pulTopOfStack = ( uint32_t * ) pxTopOfStack; pulTopOfStack = ( uint32_t * ) pxTopOfStack;
} }
*pulTopOfStack = ( uint32_t ) pxCode;
pusTopOfStack = ( uint16_t * ) pulTopOfStack;
pusTopOfStack--;
*pusTopOfStack = portFLAGS_INT_ENABLED;
pusTopOfStack -= ( sizeof( StackType_t ) / 2 );
/* From here on the size of stacked items depends on the memory model. */
pxTopOfStack = ( StackType_t * ) pusTopOfStack;
*pulTopOfStack = ( uint32_t ) pxCode; /* Next the general purpose registers. */
#ifdef PRELOAD_REGISTER_VALUES
pusTopOfStack = ( uint16_t * ) pulTopOfStack; *pxTopOfStack = ( StackType_t ) 0xffff;
pusTopOfStack--; pxTopOfStack--;
*pusTopOfStack = portFLAGS_INT_ENABLED; *pxTopOfStack = ( StackType_t ) 0xeeee;
pusTopOfStack -= ( sizeof( StackType_t ) / 2 ); pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xdddd;
/* From here on the size of stacked items depends on the memory model. */ pxTopOfStack--;
pxTopOfStack = ( StackType_t * ) pusTopOfStack; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--;
/* Next the general purpose registers. */ *pxTopOfStack = ( StackType_t ) 0xbbbb;
#ifdef PRELOAD_REGISTER_VALUES pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xffff; *pxTopOfStack = ( StackType_t ) 0xaaaa;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xeeee; *pxTopOfStack = ( StackType_t ) 0x9999;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xdddd; *pxTopOfStack = ( StackType_t ) 0x8888;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; *pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xbbbb; *pxTopOfStack = ( StackType_t ) 0x6666;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xaaaa; *pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x9999; *pxTopOfStack = ( StackType_t ) 0x4444;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x8888; #else
pxTopOfStack--; pxTopOfStack -= 3;
*pxTopOfStack = ( StackType_t ) 0x5555; *pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--; pxTopOfStack -= 9;
*pxTopOfStack = ( StackType_t ) 0x6666; #endif
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x5555;
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x4444;
pxTopOfStack--;
#else /* ifdef PRELOAD_REGISTER_VALUES */
pxTopOfStack -= 3;
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack -= 9;
#endif /* ifdef PRELOAD_REGISTER_VALUES */
/* 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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -169,15 +166,17 @@ void vPortEndScheduler( void )
*/ */
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
vApplicationSetupTimerInterrupt(); vApplicationSetupTimerInterrupt();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#pragma vector=configTICK_VECTOR #pragma vector=configTICK_VECTOR
__interrupt __raw void vTickISREntry( void ) __interrupt __raw void vTickISREntry( void )
{ {
extern void vPortTickISR( void ); extern void vPortTickISR( void );
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF ); __bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
vPortTickISR(); vPortTickISR();
} }

View file

@ -42,72 +42,72 @@
#include "msp430.h" #include "msp430.h"
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT int #define portSHORT int
#define portBASE_TYPE short #define portBASE_TYPE short
/* The stack type changes depending on the data model. */ /* The stack type changes depending on the data model. */
#if ( __DATA_MODEL__ == __DATA_MODEL_SMALL__ ) #if( __DATA_MODEL__ == __DATA_MODEL_SMALL__ )
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portPOINTER_SIZE_TYPE uint16_t #define portPOINTER_SIZE_TYPE uint16_t
#else #else
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#endif #endif
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Interrupt control macros. */ /* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() _DINT(); _NOP() #define portDISABLE_INTERRUPTS() _DINT(); _NOP()
#define portENABLE_INTERRUPTS() _EINT(); _NOP() #define portENABLE_INTERRUPTS() _EINT(); _NOP()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section control macros. */ /* Critical section control macros. */
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
portDISABLE_INTERRUPTS(); \ portDISABLE_INTERRUPTS(); \
\ \
/* Now interrupts are disabled usCriticalNesting can be accessed */ \ /* Now interrupts are disabled usCriticalNesting can be accessed */ \
/* directly. Increment ulCriticalNesting to keep a count of how many */ \ /* directly. Increment ulCriticalNesting to keep a count of how many */ \
/* times portENTER_CRITICAL() has been called. */ \ /* times portENTER_CRITICAL() has been called. */ \
usCriticalNesting++; \ usCriticalNesting++; \
} }
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
/* Decrement the nesting count as we are leaving a critical section. */ \ /* Decrement the nesting count as we are leaving a critical section. */ \
usCriticalNesting--; \ usCriticalNesting--; \
\ \
/* 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( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
@ -116,26 +116,27 @@ typedef unsigned short UBaseType_t;
* Manual context switch called by portYIELD or taskYIELD. * Manual context switch called by portYIELD or taskYIELD.
*/ */
extern void vPortYield( void ); extern void vPortYield( void );
#define portYIELD() vPortYield() #define portYIELD() vPortYield()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __no_operation() #define portNOP() __no_operation()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#define portYIELD_FROM_ISR( x ) if( x ) vPortYield() #define portYIELD_FROM_ISR( x ) if( x ) vPortYield()
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

@ -53,16 +53,16 @@
#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__ #ifndef __FREERTOS_RISC_V_EXTENSIONS_H__
#define __FREERTOS_RISC_V_EXTENSIONS_H__ #define __FREERTOS_RISC_V_EXTENSIONS_H__
#define portasmHAS_SIFIVE_CLINT 1 #define portasmHAS_SIFIVE_CLINT 1
#define portasmHAS_MTIME 1 #define portasmHAS_MTIME 1
#define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */ #define portasmADDITIONAL_CONTEXT_SIZE 0 /* Must be even number on 32-bit cores. */
portasmSAVE_ADDITIONAL_REGISTERS MACRO portasmSAVE_ADDITIONAL_REGISTERS MACRO
/* No additional registers to save, so this macro does nothing. */ /* No additional registers to save, so this macro does nothing. */
ENDM ENDM
portasmRESTORE_ADDITIONAL_REGISTERS MACRO portasmRESTORE_ADDITIONAL_REGISTERS MACRO
/* No additional registers to restore, so this macro does nothing. */ /* No additional registers to restore, so this macro does nothing. */
ENDM ENDM
#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */ #endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */

View file

@ -26,8 +26,8 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the RISC-V RV32 port. * Implementation of functions defined in portable.h for the RISC-V RV32 port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -38,44 +38,44 @@
#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
#define portTASK_RETURN_ADDRESS prvTaskExitError #define portTASK_RETURN_ADDRESS prvTaskExitError
#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[];
const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top; const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top;
#endif #endif
/* /*
@ -83,130 +83,130 @@
* file is weak to allow application writers to change the timer used to * file is weak to allow application writers to change the timer used to
* generate the tick interrupt. * generate the tick interrupt.
*/ */
void vPortSetupTimerInterrupt( void ) __attribute__( ( weak ) ); void vPortSetupTimerInterrupt( void ) __attribute__(( weak ));
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Used to program the machine timer compare register. */ /* Used to program the machine timer compare register. */
uint64_t ullNextTime = 0ULL; uint64_t ullNextTime = 0ULL;
const uint64_t * pullNextTime = &ullNextTime; const uint64_t *pullNextTime = &ullNextTime;
const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */ const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */
uint32_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS; 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 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) #if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 )
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
uint32_t ulCurrentTimeHigh, ulCurrentTimeLow; uint32_t ulCurrentTimeHigh, ulCurrentTimeLow;
volatile uint32_t * const pulTimeHigh = ( uint32_t * ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */ volatile uint32_t * const pulTimeHigh = ( uint32_t * ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */
volatile uint32_t * const pulTimeLow = ( uint32_t * ) ( configMTIME_BASE_ADDRESS ); volatile uint32_t * const pulTimeLow = ( uint32_t * ) ( configMTIME_BASE_ADDRESS );
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
{
ulCurrentTimeHigh = *pulTimeHigh;
ulCurrentTimeLow = *pulTimeLow;
} while( ulCurrentTimeHigh != *pulTimeHigh );
do ullNextTime = ( uint64_t ) ulCurrentTimeHigh;
{ ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */
ulCurrentTimeHigh = *pulTimeHigh; ullNextTime |= ( uint64_t ) ulCurrentTimeLow;
ulCurrentTimeLow = *pulTimeLow; ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
} while( ulCurrentTimeHigh != *pulTimeHigh ); *pullMachineTimerCompareRegister = ullNextTime;
ullNextTime = ( uint64_t ) ulCurrentTimeHigh; /* Prepare the time to use after the next tick interrupt. */
ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */ ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
ullNextTime |= ( uint64_t ) ulCurrentTimeLow; }
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
*pullMachineTimerCompareRegister = ullNextTime;
/* Prepare the time to use after the next tick interrupt. */
ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick;
}
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */ #endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void xPortStartFirstTask( void ); extern void xPortStartFirstTask( void );
#if ( configASSERT_DEFINED == 1 ) #if( configASSERT_DEFINED == 1 )
{ {
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
{ {
memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) ); memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) );
} }
#endif /* configISR_STACK_SIZE_WORDS */ #endif /* configISR_STACK_SIZE_WORDS */
} }
#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
{ {
/* Enable external interrupts. */ /* Enable external interrupts. */
__asm volatile ( "csrs 0x304, %0" ::"r" ( 0x800 ) ); /* 304 is mie. */ __asm volatile( "csrs 0x304, %0" :: "r"(0x800) ); /* 304 is mie. */
} }
#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */ #endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */
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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented. */ /* Not implemented. */
for( ; ; ) for( ;; );
{
}
} }

View file

@ -27,13 +27,13 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#include "intrinsics.h" #include "intrinsics.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -46,133 +46,132 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#if __riscv_xlen == 64 #if __riscv_xlen == 64
#define portSTACK_TYPE uint64_t #define portSTACK_TYPE uint64_t
#define portBASE_TYPE int64_t #define portBASE_TYPE int64_t
#define portUBASE_TYPE uint64_t #define portUBASE_TYPE uint64_t
#define portMAX_DELAY ( TickType_t ) 0xffffffffffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffffffffffUL
#define portPOINTER_SIZE_TYPE uint64_t #define portPOINTER_SIZE_TYPE uint64_t
#elif __riscv_xlen == 32 #elif __riscv_xlen == 32
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#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;
typedef portBASE_TYPE BaseType_t; typedef portBASE_TYPE BaseType_t;
typedef portUBASE_TYPE UBaseType_t; typedef portUBASE_TYPE UBaseType_t;
typedef portUBASE_TYPE TickType_t; typedef portUBASE_TYPE TickType_t;
/* Legacy type definitions. */ /* Legacy type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specifics. */ /* Architecture specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#ifdef __riscv64 #ifdef __riscv64
#error This is the RV32 port that has not yet been adapted for 64. #error This is the RV32 port that has not yet been adapted for 64.
#define portBYTE_ALIGNMENT 16 #define portBYTE_ALIGNMENT 16
#else #else
#define portBYTE_ALIGNMENT 16 #define portBYTE_ALIGNMENT 16
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Scheduler utilities. */ /* Scheduler utilities. */
extern void vTaskSwitchContext( void ); extern void vTaskSwitchContext( void );
#define portYIELD() __asm volatile ( "ecall" ); #define portYIELD() __asm volatile( "ecall" );
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext() #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vTaskSwitchContext()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section management. */ /* Critical section management. */
#define portCRITICAL_NESTING_IN_TCB 1 #define portCRITICAL_NESTING_IN_TCB 1
extern void vTaskEnterCritical( void ); extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void ); extern void vTaskExitCritical( void );
#define portSET_INTERRUPT_MASK_FROM_ISR() 0 #define portSET_INTERRUPT_MASK_FROM_ISR() 0
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue
#define portDISABLE_INTERRUPTS() __disable_interrupt() #define portDISABLE_INTERRUPTS() __disable_interrupt()
#define portENABLE_INTERRUPTS() __enable_interrupt() #define portENABLE_INTERRUPTS() __enable_interrupt()
#define portENTER_CRITICAL() vTaskEnterCritical() #define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical() #define portEXIT_CRITICAL() vTaskExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) #if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION cannot yet be used in the IAR RISC-V port, the CLZ instruction needs to be emulated. #error configUSE_PORT_OPTIMISED_TASK_SELECTION cannot yet be used in the IAR RISC-V port, the CLZ instruction needs to be emulated.
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#define portNOP() __asm volatile ( " nop " ) #define portNOP() __asm volatile ( " nop " )
#define portINLINE __inline #define portINLINE __inline
#ifndef portFORCE_INLINE #ifndef portFORCE_INLINE
#define portFORCE_INLINE inline __attribute__( ( always_inline ) ) #define portFORCE_INLINE inline __attribute__(( always_inline))
#endif #endif
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
/* 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
the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses
/* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of from the CLINT address. */
* the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses #define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL )
* from the CLINT address. */ #define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL )
#define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL ) #elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS )
#define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL ) #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
#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS ) #endif
#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 ) */
#ifdef __cplusplus #ifdef __cplusplus
} }
#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 usCriticalNesting
EXTERN pxCurrentTCB
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 ; Save CS register.
MOV A, CS; XCH A, X
Save CS register. MOV A, ES ; Save ES register.
XCH A, X PUSH AX
MOV A, ES; PUSH DE ; Save the remaining general purpose registers.
Save ES register. PUSH BC
PUSH AX MOVW AX, usCriticalNesting ; Save the usCriticalNesting value.
PUSH DE; PUSH AX
Save the remaining general purpose registers. MOVW AX, pxCurrentTCB ; Save the Stack pointer.
PUSH BC MOVW HL, AX
MOVW AX, usCriticalNesting; MOVW AX, SP
Save the usCriticalNesting value. MOVW [HL], AX
PUSH AX ENDM
MOVW AX, pxCurrentTCB; ;------------------------------------------------------------------------------
Save the Stack pointer.
MOVW HL, AX
MOVW AX, SP
MOVW[ HL ], AX
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, MOVW HL, AX
; MOVW AX, [HL]
general purpose registers and the CS and ES( only in far memory mode ) MOVW SP, AX
; POP AX ; Restore usCriticalNesting value.
of the selected task from the task stack MOVW usCriticalNesting, AX
; POP BC ; Restore the necessary general purpose registers.
------------------------------------------------------------------------------ POP DE
portRESTORE_CONTEXT MACRO POP AX ; Restore the ES register.
MOVW AX, pxCurrentTCB; MOV ES, A
Restore the Stack pointer. XCH A, X ; Restore the CS register.
MOVW HL, AX MOV CS, A
MOVW AX, [ HL ] POP HL ; Restore general purpose register HL.
MOVW SP, AX POP AX ; Restore AX.
POP AX; ENDM
Restore usCriticalNesting value. ;------------------------------------------------------------------------------
MOVW usCriticalNesting, AX
POP BC;
Restore the necessary general purpose registers.
POP DE
POP AX;
Restore the ES register.
MOV ES, A
XCH A, X;
Restore the CS register.
MOV CS, A
POP HL;
Restore general purpose register HL.
POP AX;
Restore AX.
ENDM
;
------------------------------------------------------------------------------

View file

@ -30,8 +30,8 @@
#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.
* 1100011000000000 * 1100011000000000
@ -44,21 +44,21 @@
* |--------------------- Zero Flag set * |--------------------- Zero Flag set
* ---------------------- Global Interrupt Flag set (enabled) * ---------------------- Global Interrupt Flag set (enabled)
*/ */
#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,10 +71,9 @@ 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,190 +95,186 @@ 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. */
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( uint32_t ) pvParameters; *pulLocal = ( uint32_t ) pvParameters;
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. */
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) ); *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--; pxTopOfStack--;
/* An initial value for the AX register. */ /* An initial value for the AX register. */
*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. */
pulLocal = ( uint32_t * ) pxTopOfStack; pulLocal = ( uint32_t * ) pxTopOfStack;
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) ); *pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
pxTopOfStack--; pxTopOfStack--;
/* The parameter is passed in AX. */ /* The parameter is passed in AX. */
*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;
pxTopOfStack--; pxTopOfStack--;
/* CS and ES registers. */ /* CS and ES registers. */
*pxTopOfStack = ( StackType_t ) 0x0F00; *pxTopOfStack = ( StackType_t ) 0x0F00;
pxTopOfStack--; pxTopOfStack--;
/* The remaining general purpose registers DE and BC */ /* The remaining general purpose registers DE and BC */
*pxTopOfStack = ( StackType_t ) 0xDEDE; *pxTopOfStack = ( StackType_t ) 0xDEDE;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBCBC; *pxTopOfStack = ( StackType_t ) 0xBCBC;
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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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
* defined, then stop here so application writers can catch the error. */
configASSERT( usCriticalNesting == ~0U );
portDISABLE_INTERRUPTS();
for( ; ; ) Artificially force an assert() to be triggered if configASSERT() is
{ defined, then stop here so application writers can catch the error. */
} configASSERT( usCriticalNesting == ~0U );
portDISABLE_INTERRUPTS();
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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the RL78 port will get stopped. */ /* It is unlikely that the RL78 port will get stopped. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
const uint16_t usClockHz = 15000UL; /* Internal clock. */ const uint16_t usClockHz = 15000UL; /* Internal clock. */
const uint16_t usCompareMatch = ( usClockHz / configTICK_RATE_HZ ) + 1UL; const uint16_t usCompareMatch = ( usClockHz / configTICK_RATE_HZ ) + 1UL;
/* Use the internal 15K clock. */ /* Use the internal 15K clock. */
OSMC = ( uint8_t ) 0x16; OSMC = ( uint8_t ) 0x16;
#ifdef RTCEN #ifdef RTCEN
{ {
/* Supply the interval timer clock. */ /* Supply the interval timer clock. */
RTCEN = ( uint8_t ) 1U; RTCEN = ( uint8_t ) 1U;
/* Disable INTIT interrupt. */ /* Disable INTIT interrupt. */
ITMK = ( uint8_t ) 1; ITMK = ( uint8_t ) 1;
/* Disable ITMC operation. */ /* Disable ITMC operation. */
ITMC = ( uint8_t ) 0x0000; ITMC = ( uint8_t ) 0x0000;
/* Clear INIT interrupt. */ /* Clear INIT interrupt. */
ITIF = ( uint8_t ) 0; ITIF = ( uint8_t ) 0;
/* Set interval and enable interrupt operation. */ /* Set interval and enable interrupt operation. */
ITMC = usCompareMatch | 0x8000U; ITMC = usCompareMatch | 0x8000U;
/* Enable INTIT interrupt. */ /* Enable INTIT interrupt. */
ITMK = ( uint8_t ) 0; ITMK = ( uint8_t ) 0;
} }
#endif /* ifdef RTCEN */ #endif
#ifdef TMKAEN #ifdef TMKAEN
{ {
/* Supply the interval timer clock. */ /* Supply the interval timer clock. */
TMKAEN = ( uint8_t ) 1U; TMKAEN = ( uint8_t ) 1U;
/* Disable INTIT interrupt. */ /* Disable INTIT interrupt. */
TMKAMK = ( uint8_t ) 1; TMKAMK = ( uint8_t ) 1;
/* Disable ITMC operation. */ /* Disable ITMC operation. */
ITMC = ( uint8_t ) 0x0000; ITMC = ( uint8_t ) 0x0000;
/* Clear INIT interrupt. */ /* Clear INIT interrupt. */
TMKAIF = ( uint8_t ) 0; TMKAIF = ( uint8_t ) 0;
/* Set interval and enable interrupt operation. */ /* Set interval and enable interrupt operation. */
ITMC = usCompareMatch | 0x8000U; ITMC = usCompareMatch | 0x8000U;
/* Enable INTIT interrupt. */ /* Enable INTIT interrupt. */
TMKAMK = ( uint8_t ) 0; TMKAMK = ( uint8_t ) 0;
} }
#endif /* ifdef TMKAEN */ #endif
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,11 +26,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -42,102 +42,103 @@
*----------------------------------------------------------- *-----------------------------------------------------------
*/ */
#if __DATA_MODEL__ == __DATA_MODEL_FAR__ && __CODE_MODEL__ == __CODE_MODEL_NEAR__ #if __DATA_MODEL__ == __DATA_MODEL_FAR__ && __CODE_MODEL__ == __CODE_MODEL_NEAR__
#warning This port has not been tested with your selected memory model combination. If a far data model is required it is recommended to also use a far code model. #warning This port has not been tested with your selected memory model combination. If a far data model is required it is recommended to also use a far code model.
#endif #endif
#if __DATA_MODEL__ == __DATA_MODEL_NEAR__ && __CODE_MODEL__ == __CODE_MODEL_FAR__ #if __DATA_MODEL__ == __DATA_MODEL_NEAR__ && __CODE_MODEL__ == __CODE_MODEL_FAR__
#warning This port has not been tested with your selected memory model combination. If a far code model is required it is recommended to also use a far data model. #warning This port has not been tested with your selected memory model combination. If a far code model is required it is recommended to also use a far data model.
#endif #endif
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint16_t #define portSTACK_TYPE uint16_t
#define portBASE_TYPE short #define portBASE_TYPE short
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef short BaseType_t; typedef short BaseType_t;
typedef unsigned short UBaseType_t; typedef unsigned short UBaseType_t;
#if __DATA_MODEL__ == __DATA_MODEL_FAR__ #if __DATA_MODEL__ == __DATA_MODEL_FAR__
#define portPOINTER_SIZE_TYPE uint32_t #define portPOINTER_SIZE_TYPE uint32_t
#else #else
#define portPOINTER_SIZE_TYPE uint16_t #define portPOINTER_SIZE_TYPE uint16_t
#endif #endif
#if ( configUSE_16_BIT_TICKS == 1 ) #if ( configUSE_16_BIT_TICKS == 1 )
typedef unsigned int TickType_t; typedef unsigned int TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Interrupt control macros. */ /* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() __asm( "DI" ) #define portDISABLE_INTERRUPTS() __asm ( "DI" )
#define portENABLE_INTERRUPTS() __asm( "EI" ) #define portENABLE_INTERRUPTS() __asm ( "EI" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section control macros. */ /* Critical section control macros. */
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
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 */ \ /* directly. Increment ulCriticalNesting to keep a count of how many */ \
/* times portENTER_CRITICAL() has been called. */ \ /* times portENTER_CRITICAL() has been called. */ \
usCriticalNesting++; \ usCriticalNesting++; \
} }
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile uint16_t usCriticalNesting; \ extern volatile uint16_t usCriticalNesting; \
\ \
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
/* Decrement the nesting count as we are leaving a critical section. */ \ /* Decrement the nesting count as we are leaving a critical section. */ \
usCriticalNesting--; \ usCriticalNesting--; \
\ \
/* 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( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portYIELD() __asm( "BRK" ) #define portYIELD() __asm( "BRK" )
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext() #define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
#define portNOP() __asm( "NOP" ) #define portNOP() __asm( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardwware specifics. */ /* Hardwware specifics. */
#define portBYTE_ALIGNMENT 2 #define portBYTE_ALIGNMENT 2
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -26,8 +26,8 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the SH2A port. * Implementation of functions defined in portable.h for the SH2A port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Standard C includes. */ /* Standard C includes. */
#include "limits.h" #include "limits.h"
@ -45,29 +45,29 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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
#elif ( configPERIPHERAL_CLOCK_HZ >= 12000000 ) #elif ( configPERIPHERAL_CLOCK_HZ >= 12000000 )
#define portCLOCK_DIVISOR 512UL #define portCLOCK_DIVISOR 512UL
#elif ( configPERIPHERAL_CLOCK_HZ >= 6000000 ) #elif ( configPERIPHERAL_CLOCK_HZ >= 6000000 )
#define portCLOCK_DIVISOR 128UL #define portCLOCK_DIVISOR 128UL
#elif ( configPERIPHERAL_CLOCK_HZ >= 1000000 ) #elif ( configPERIPHERAL_CLOCK_HZ >= 1000000 )
#define portCLOCK_DIVISOR 32UL #define portCLOCK_DIVISOR 32UL
#else #else
#define portCLOCK_DIVISOR 8UL #define portCLOCK_DIVISOR 8UL
#endif #endif
/* 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,10 +91,9 @@ __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 */
/* /*
@ -103,12 +102,12 @@ static void prvSetupTimerInterrupt( void );
* instruction. * instruction.
*/ */
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
static void prvSleep( TickType_t xExpectedIdleTime ); static void prvSleep( TickType_t xExpectedIdleTime );
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
extern void * pxCurrentTCB; extern void *pxCurrentTCB;
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -117,406 +116,401 @@ 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--;
/* R0 is not included as it is the stack pointer. */ /* R0 is not included as it is the stack pointer. */
*pxTopOfStack = 0x00;
pxTopOfStack--;
*pxTopOfStack = 0x00; *pxTopOfStack = 0x00;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x00; *pxTopOfStack = portINITIAL_PSW;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSW; *pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
*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--;
*pxTopOfStack = 0x12345678; /* r15. */ *pxTopOfStack = 0x12345678; /* r15. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xaaaabbbb; *pxTopOfStack = 0xaaaabbbb;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xdddddddd; *pxTopOfStack = 0xdddddddd;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xcccccccc; *pxTopOfStack = 0xcccccccc;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xbbbbbbbb; *pxTopOfStack = 0xbbbbbbbb;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xaaaaaaaa; *pxTopOfStack = 0xaaaaaaaa;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x99999999; *pxTopOfStack = 0x99999999;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x88888888; *pxTopOfStack = 0x88888888;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x77777777; *pxTopOfStack = 0x77777777;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x66666666; *pxTopOfStack = 0x66666666;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x55555555; *pxTopOfStack = 0x55555555;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x44444444; *pxTopOfStack = 0x44444444;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x33333333; *pxTopOfStack = 0x33333333;
pxTopOfStack--; 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--;
*pxTopOfStack = 0x12345678; /* Accumulator. */ *pxTopOfStack = 0x12345678; /* Accumulator. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x87654321; /* Accumulator. */ *pxTopOfStack = 0x87654321; /* Accumulator. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
/* Use pxCurrentTCB just so it does not get optimised away. */ /* Use pxCurrentTCB just so it does not get optimised away. */
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. */
_IEN( _ICU_SWINT ) = 1; _IEN( _ICU_SWINT ) = 1;
/* Ensure the software interrupt is clear. */ /* Ensure the software interrupt is clear. */
_IR( _ICU_SWINT ) = 0; _IR( _ICU_SWINT ) = 0;
/* Ensure the software interrupt is set to the kernel priority. */ /* Ensure the software interrupt is set to the kernel priority. */
_IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY; _IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
/* Start the first task. */ /* Start the first task. */
prvStartFirstTask(); prvStartFirstTask();
} }
/* 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. */
return pdFAIL; return pdFAIL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#pragma vector = configTICK_VECTOR #pragma vector = configTICK_VECTOR
__interrupt static void prvTickISR( void ) __interrupt static void prvTickISR( void )
{ {
/* Re-enable interrupts. */ /* Re-enable interrupts. */
__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 )
{ {
taskYIELD(); taskYIELD();
} }
} }
__set_interrupt_level( configKERNEL_INTERRUPT_PRIORITY ); __set_interrupt_level( configKERNEL_INTERRUPT_PRIORITY );
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
{ {
/* The CPU woke because of a tick. */ /* The CPU woke because of a tick. */
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
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
/* Unlock. */ /* Unlock. */
SYSTEM.PRCR.WORD = portUNLOCK_KEY; SYSTEM.PRCR.WORD = portUNLOCK_KEY;
/* Enable CMT0. */ /* Enable CMT0. */
MSTP( CMT0 ) = 0; MSTP( CMT0 ) = 0;
/* Lock again. */ /* Lock again. */
SYSTEM.PRCR.WORD = portLOCK_KEY; SYSTEM.PRCR.WORD = portLOCK_KEY;
/* Interrupt on compare match. */ /* Interrupt on compare match. */
CMT0.CMCR.BIT.CMIE = 1; CMT0.CMCR.BIT.CMIE = 1;
/* Set the compare match value. */ /* Set the compare match value. */
CMT0.CMCOR = ( uint16_t ) ulMatchValueForOneTick; CMT0.CMCOR = ( uint16_t ) ulMatchValueForOneTick;
/* Divide the PCLK. */ /* Divide the PCLK. */
#if portCLOCK_DIVISOR == 512 #if portCLOCK_DIVISOR == 512
{ {
CMT0.CMCR.BIT.CKS = 3; CMT0.CMCR.BIT.CKS = 3;
} }
#elif portCLOCK_DIVISOR == 128 #elif portCLOCK_DIVISOR == 128
{ {
CMT0.CMCR.BIT.CKS = 2; CMT0.CMCR.BIT.CKS = 2;
} }
#elif portCLOCK_DIVISOR == 32 #elif portCLOCK_DIVISOR == 32
{ {
CMT0.CMCR.BIT.CKS = 1; CMT0.CMCR.BIT.CKS = 1;
} }
#elif portCLOCK_DIVISOR == 8 #elif portCLOCK_DIVISOR == 8
{ {
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... */
_IEN( _CMT0_CMI0 ) = 1; _IEN( _CMT0_CMI0 ) = 1;
/* ...and set its priority to the application defined kernel priority. */ /* ...and set its priority to the application defined kernel priority. */
_IPR( _CMT0_CMI0 ) = configKERNEL_INTERRUPT_PRIORITY; _IPR( _CMT0_CMI0 ) = configKERNEL_INTERRUPT_PRIORITY;
/* Start the timer. */ /* Start the timer. */
CMT.CMSTR0.BIT.STR0 = 1; CMT.CMSTR0.BIT.STR0 = 1;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
static void prvSleep( TickType_t xExpectedIdleTime ) static void prvSleep( TickType_t xExpectedIdleTime )
{ {
/* Allow the application to define some pre-sleep processing. */ /* Allow the application to define some pre-sleep processing. */
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();
} }
/* Allow the application to define some post sleep processing. */ /* Allow the application to define some post sleep processing. */
configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
} }
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
{ {
uint32_t ulMatchValue, ulCompleteTickPeriods, ulCurrentCount; uint32_t ulMatchValue, ulCompleteTickPeriods, ulCurrentCount;
eSleepModeStatus eSleepAction; eSleepModeStatus eSleepAction;
/* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */ /* THIS FUNCTION IS CALLED WITH THE SCHEDULER SUSPENDED. */
/* Make sure the CMT reload value does not overflow the counter. */ /* Make sure the CMT reload value does not overflow the counter. */
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
{ {
xExpectedIdleTime = xMaximumPossibleSuppressedTicks; xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
} }
/* 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 )
{
/* Compensate for the fact that the CMT is going to be stopped
momentarily. */
ulMatchValue -= ulStoppedTimerCompensation;
}
if( ulMatchValue > ulStoppedTimerCompensation ) /* 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
/* Compensate for the fact that the CMT is going to be stopped inevitably result in some tiny drift of the time maintained by the
* momentarily. */ kernel with respect to calendar time. */
ulMatchValue -= ulStoppedTimerCompensation; CMT.CMSTR0.BIT.STR0 = 0;
} while( CMT.CMSTR0.BIT.STR0 == 1 )
{
/* Nothing to do here. */
}
/* Stop the CMT momentarily. The time the CMT is stopped for is /* Critical section using the global interrupt bit as the i bit is
* accounted for as best it can be, but using the tickless mode will automatically reset by the WAIT instruction. */
* inevitably result in some tiny drift of the time maintained by the __disable_interrupt();
* kernel with respect to calendar time. */
CMT.CMSTR0.BIT.STR0 = 0;
while( CMT.CMSTR0.BIT.STR0 == 1 ) /* 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
/* Nothing to do here. */ tick was suppressed for the entire xExpectedIdleTime period. */
} ulTickFlag = pdFALSE;
/* Critical section using the global interrupt bit as the i bit is /* If a context switch is pending then abandon the low power entry as
* automatically reset by the WAIT instruction. */ the context switch might have been pended by an external interrupt that
__disable_interrupt(); requires processing. */
eSleepAction = eTaskConfirmSleepModeStatus();
if( eSleepAction == eAbortSleep )
{
/* Restart tick. */
CMT.CMSTR0.BIT.STR0 = 1;
__enable_interrupt();
}
else if( eSleepAction == eNoTasksWaitingTimeout )
{
/* Protection off. */
SYSTEM.PRCR.WORD = portUNLOCK_KEY;
/* The tick flag is set to false before sleeping. If it is true when /* Ready for software standby with all clocks stopped. */
* sleep mode is exited then sleep mode was probably exited because the SYSTEM.SBYCR.BIT.SSBY = 1;
* tick was suppressed for the entire xExpectedIdleTime period. */
ulTickFlag = pdFALSE;
/* If a context switch is pending then abandon the low power entry as /* Protection on. */
* the context switch might have been pended by an external interrupt that SYSTEM.PRCR.WORD = portLOCK_KEY;
* requires processing. */
eSleepAction = eTaskConfirmSleepModeStatus();
if( eSleepAction == eAbortSleep ) /* Sleep until something happens. Calling prvSleep() will
{ automatically reset the i bit in the PSW. */
/* Restart tick. */ prvSleep( xExpectedIdleTime );
CMT.CMSTR0.BIT.STR0 = 1;
__enable_interrupt();
}
else if( eSleepAction == eNoTasksWaitingTimeout )
{
/* Protection off. */
SYSTEM.PRCR.WORD = portUNLOCK_KEY;
/* Ready for software standby with all clocks stopped. */ /* Restart the CMT. */
SYSTEM.SBYCR.BIT.SSBY = 1; CMT.CMSTR0.BIT.STR0 = 1;
}
else
{
/* Protection off. */
SYSTEM.PRCR.WORD = portUNLOCK_KEY;
/* Protection on. */ /* Ready for deep sleep mode. */
SYSTEM.PRCR.WORD = portLOCK_KEY; SYSTEM.MSTPCRC.BIT.DSLPE = 1;
SYSTEM.MSTPCRA.BIT.MSTPA28 = 1;
SYSTEM.SBYCR.BIT.SSBY = 0;
/* Sleep until something happens. Calling prvSleep() will /* Protection on. */
* automatically reset the i bit in the PSW. */ SYSTEM.PRCR.WORD = portLOCK_KEY;
prvSleep( xExpectedIdleTime );
/* Restart the CMT. */ /* Adjust the match value to take into account that the current
CMT.CMSTR0.BIT.STR0 = 1; time slice is already partially complete. */
} ulMatchValue -= ( uint32_t ) CMT0.CMCNT;
else CMT0.CMCOR = ( uint16_t ) ulMatchValue;
{
/* Protection off. */
SYSTEM.PRCR.WORD = portUNLOCK_KEY;
/* Ready for deep sleep mode. */ /* Restart the CMT to count up to the new match value. */
SYSTEM.MSTPCRC.BIT.DSLPE = 1; CMT0.CMCNT = 0;
SYSTEM.MSTPCRA.BIT.MSTPA28 = 1; CMT.CMSTR0.BIT.STR0 = 1;
SYSTEM.SBYCR.BIT.SSBY = 0;
/* Protection on. */ /* Sleep until something happens. Calling prvSleep() will
SYSTEM.PRCR.WORD = portLOCK_KEY; automatically reset the i bit in the PSW. */
prvSleep( xExpectedIdleTime );
/* Adjust the match value to take into account that the current /* Stop CMT. Again, the time the SysTick is stopped for is
* time slice is already partially complete. */ accounted for as best it can be, but using the tickless mode will
ulMatchValue -= ( uint32_t ) CMT0.CMCNT; inevitably result in some tiny drift of the time maintained by the
CMT0.CMCOR = ( uint16_t ) ulMatchValue; kernel with respect to calendar time. */
CMT.CMSTR0.BIT.STR0 = 0;
while( CMT.CMSTR0.BIT.STR0 == 1 )
{
/* Nothing to do here. */
}
/* Restart the CMT to count up to the new match value. */ ulCurrentCount = ( uint32_t ) CMT0.CMCNT;
CMT0.CMCNT = 0;
CMT.CMSTR0.BIT.STR0 = 1;
/* Sleep until something happens. Calling prvSleep() will if( ulTickFlag != pdFALSE )
* automatically reset the i bit in the PSW. */ {
prvSleep( xExpectedIdleTime ); /* The tick interrupt has already executed, although because
this function is called with the scheduler suspended the actual
tick processing will not occur until after this function has
exited. Reset the match value with whatever remains of this
tick period. */
ulMatchValue = ulMatchValueForOneTick - ulCurrentCount;
CMT0.CMCOR = ( uint16_t ) ulMatchValue;
/* Stop CMT. Again, the time the SysTick is stopped for is /* The tick interrupt handler will already have pended the tick
* accounted for as best it can be, but using the tickless mode will processing in the kernel. As the pending tick will be
* inevitably result in some tiny drift of the time maintained by the processed as soon as this function exits, the tick value
* kernel with respect to calendar time. */ maintained by the tick is stepped forward by one less than the
CMT.CMSTR0.BIT.STR0 = 0; time spent sleeping. The actual stepping of the tick appears
later in this function. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
How many complete tick periods passed while the processor was
sleeping? */
ulCompleteTickPeriods = ulCurrentCount / ulMatchValueForOneTick;
while( CMT.CMSTR0.BIT.STR0 == 1 ) /* The match value is set to whatever fraction of a single tick
{ period remains. */
/* Nothing to do here. */ ulMatchValue = ulCurrentCount - ( ulCompleteTickPeriods * ulMatchValueForOneTick );
} CMT0.CMCOR = ( uint16_t ) ulMatchValue;
}
ulCurrentCount = ( uint32_t ) CMT0.CMCNT; /* 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
the next time the CMT interrupt executes. */
CMT0.CMCNT = 0;
CMT.CMSTR0.BIT.STR0 = 1;
if( ulTickFlag != pdFALSE ) /* Wind the tick forward by the number of tick periods that the CPU
{ remained in a low power state. */
/* The tick interrupt has already executed, although because vTaskStepTick( ulCompleteTickPeriods );
* this function is called with the scheduler suspended the actual }
* tick processing will not occur until after this function has }
* exited. Reset the match value with whatever remains of this
* tick period. */
ulMatchValue = ulMatchValueForOneTick - ulCurrentCount;
CMT0.CMCOR = ( uint16_t ) ulMatchValue;
/* The tick interrupt handler will already have pended the tick
* processing in the kernel. As the pending tick will be
* processed as soon as this function exits, the tick value
* maintained by the tick is stepped forward by one less than the
* time spent sleeping. The actual stepping of the tick appears
* later in this function. */
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
}
else
{
/* Something other than the tick interrupt ended the sleep.
* How many complete tick periods passed while the processor was
* sleeping? */
ulCompleteTickPeriods = ulCurrentCount / ulMatchValueForOneTick;
/* The match value is set to whatever fraction of a single tick
* period remains. */
ulMatchValue = ulCurrentCount - ( ulCompleteTickPeriods * ulMatchValueForOneTick );
CMT0.CMCOR = ( uint16_t ) ulMatchValue;
}
/* 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
* the next time the CMT interrupt executes. */
CMT0.CMCNT = 0;
CMT.CMSTR0.BIT.STR0 = 1;
/* Wind the tick forward by the number of tick periods that the CPU
* remained in a low power state. */
vTaskStepTick( ulCompleteTickPeriods );
}
}
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */

View file

@ -27,16 +27,16 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Hardware specifics. */ /* Hardware specifics. */
#include "machine.h" #include "machine.h"
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -49,101 +49,102 @@
*/ */
/* 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
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */ #define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portNOP() __no_operation() #define portNOP() __no_operation()
#define portYIELD() \ #define portYIELD() \
__asm volatile \ __asm volatile \
( \ ( \
"MOV.L #0x872E0, R15 \n"\ "MOV.L #0x872E0, R15 \n" \
"MOV.B #1, [R15] \n"\ "MOV.B #1, [R15] \n" \
"MOV.L [R15], R15 \n"\ "MOV.L [R15], R15 \n" \
::: "R15" \ ::: "R15" \
) )
#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 ) )
#define portDISABLE_INTERRUPTS() if( __get_interrupt_level() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() if( __get_interrupt_level() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY )
#else #else
#define portDISABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY )
#endif #endif
/* Critical nesting counts are stored in the TCB. */ /* Critical nesting counts are stored in the TCB. */
#define portCRITICAL_NESTING_IN_TCB ( 1 ) #define portCRITICAL_NESTING_IN_TCB ( 1 )
/* The critical nesting functions defined within tasks.c. */ /* The critical nesting functions defined within tasks.c. */
extern void vTaskEnterCritical( void ); extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void ); extern void vTaskExitCritical( void );
#define portENTER_CRITICAL() vTaskEnterCritical() #define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical() #define portEXIT_CRITICAL() vTaskExitCritical()
/* As this port allows interrupt nesting... */ /* As this port allows interrupt nesting... */
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_level(); portDISABLE_INTERRUPTS() #define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_level(); portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) __set_interrupt_level( ( uint8_t ) ( uxSavedInterruptStatus ) ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) __set_interrupt_level( ( uint8_t ) ( uxSavedInterruptStatus ) )
/* Tickless idle/low power functionality. */ /* Tickless idle/low power functionality. */
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
#ifndef portSUPPRESS_TICKS_AND_SLEEP #ifndef portSUPPRESS_TICKS_AND_SLEEP
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
#endif #endif
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
/* 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
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -26,8 +26,8 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the SH2A port. * Implementation of functions defined in portable.h for the SH2A port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -42,9 +42,9 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -62,131 +62,132 @@ __interrupt void vTickISR( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
extern void * pxCurrentTCB; 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. */
*pxTopOfStack = 0x00; *pxTopOfStack = 0x00;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSW; *pxTopOfStack = portINITIAL_PSW;
pxTopOfStack--; 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--;
*pxTopOfStack = 0xffffffff; /* r15. */ *pxTopOfStack = 0xffffffff; /* r15. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee; *pxTopOfStack = 0xeeeeeeee;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xdddddddd; *pxTopOfStack = 0xdddddddd;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xcccccccc; *pxTopOfStack = 0xcccccccc;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xbbbbbbbb; *pxTopOfStack = 0xbbbbbbbb;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xaaaaaaaa; *pxTopOfStack = 0xaaaaaaaa;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x99999999; *pxTopOfStack = 0x99999999;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x88888888; *pxTopOfStack = 0x88888888;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x77777777; *pxTopOfStack = 0x77777777;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x66666666; *pxTopOfStack = 0x66666666;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x55555555; *pxTopOfStack = 0x55555555;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x44444444; *pxTopOfStack = 0x44444444;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x33333333; *pxTopOfStack = 0x33333333;
pxTopOfStack--; 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--;
*pxTopOfStack = portINITIAL_FPSW; *pxTopOfStack = portINITIAL_FPSW;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x12345678; /* Accumulator. */ *pxTopOfStack = 0x12345678; /* Accumulator. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x87654321; /* Accumulator. */ *pxTopOfStack = 0x87654321; /* Accumulator. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void vApplicationSetupTimerInterrupt( void ); extern void vApplicationSetupTimerInterrupt( void );
/* Use pxCurrentTCB just so it does not get optimised away. */ /* Use pxCurrentTCB just so it does not get optimised away. */
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. */
_IEN( _ICU_SWINT ) = 1; _IEN( _ICU_SWINT ) = 1;
/* Ensure the software interrupt is clear. */ /* Ensure the software interrupt is clear. */
_IR( _ICU_SWINT ) = 0; _IR( _ICU_SWINT ) = 0;
/* Ensure the software interrupt is set to the kernel priority. */ /* Ensure the software interrupt is set to the kernel priority. */
_IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY; _IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
/* Start the first task. */ /* Start the first task. */
prvStartFirstTask(); prvStartFirstTask();
} }
/* Should not get here. */ /* Should not get here. */
return pdFAIL; return pdFAIL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#pragma vector = configTICK_VECTOR #pragma vector = configTICK_VECTOR
__interrupt void vTickISR( void ) __interrupt void vTickISR( void )
{ {
/* Re-enable interrupts. */ /* Re-enable interrupts. */
__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 )
{ {
taskYIELD(); taskYIELD();
} }
} }
__set_interrupt_level( configKERNEL_INTERRUPT_PRIORITY ); __set_interrupt_level( configKERNEL_INTERRUPT_PRIORITY );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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

@ -27,13 +27,13 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -46,93 +46,94 @@
*/ */
/* 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
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */ #define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#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 \
( \ ( \
"PUSH.L R10 \n"\ "PUSH.L R10 \n" \
"MOV.L #0x872E0, R10 \n"\ "MOV.L #0x872E0, R10 \n" \
"MOV.B #0x1, [R10] \n"\ "MOV.B #0x1, [R10] \n" \
"MOV.L [R10], R10 \n"\ "MOV.L [R10], R10 \n" \
"POP R10 \n"\ "POP R10 \n" \
) )
#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 ) )
#define portDISABLE_INTERRUPTS() if( __get_interrupt_level() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() if( __get_interrupt_level() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY )
#else #else
#define portDISABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY )
#endif #endif
/* Critical nesting counts are stored in the TCB. */ /* Critical nesting counts are stored in the TCB. */
#define portCRITICAL_NESTING_IN_TCB ( 1 ) #define portCRITICAL_NESTING_IN_TCB ( 1 )
/* The critical nesting functions defined within tasks.c. */ /* The critical nesting functions defined within tasks.c. */
extern void vTaskEnterCritical( void ); extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void ); extern void vTaskExitCritical( void );
#define portENTER_CRITICAL() vTaskEnterCritical() #define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical() #define portEXIT_CRITICAL() vTaskExitCritical()
/* As this port allows interrupt nesting... */ /* As this port allows interrupt nesting... */
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_level(); portDISABLE_INTERRUPTS() #define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_level(); portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) __set_interrupt_level( ( uint8_t ) ( uxSavedInterruptStatus ) ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) __set_interrupt_level( ( uint8_t ) ( uxSavedInterruptStatus ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -26,8 +26,8 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the SH2A port. * Implementation of functions defined in portable.h for the SH2A port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Scheduler includes. */ /* Scheduler includes. */
#include "FreeRTOS.h" #include "FreeRTOS.h"
@ -42,9 +42,9 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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 )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -62,139 +62,140 @@ __interrupt void vTickISR( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
extern void * pxCurrentTCB; 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. */
*pxTopOfStack = 0x00; *pxTopOfStack = 0x00;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_PSW; *pxTopOfStack = portINITIAL_PSW;
pxTopOfStack--; 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--;
*pxTopOfStack = 0xffffffff; /* r15. */ *pxTopOfStack = 0xffffffff; /* r15. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee; *pxTopOfStack = 0xeeeeeeee;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xdddddddd; *pxTopOfStack = 0xdddddddd;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xcccccccc; *pxTopOfStack = 0xcccccccc;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xbbbbbbbb; *pxTopOfStack = 0xbbbbbbbb;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0xaaaaaaaa; *pxTopOfStack = 0xaaaaaaaa;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x99999999; *pxTopOfStack = 0x99999999;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x88888888; *pxTopOfStack = 0x88888888;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x77777777; *pxTopOfStack = 0x77777777;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x66666666; *pxTopOfStack = 0x66666666;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x55555555; *pxTopOfStack = 0x55555555;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x44444444; *pxTopOfStack = 0x44444444;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x33333333; *pxTopOfStack = 0x33333333;
pxTopOfStack--; 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--;
*pxTopOfStack = portINITIAL_FPSW; *pxTopOfStack = portINITIAL_FPSW;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x11111111; /* Accumulator 0. */ *pxTopOfStack = 0x11111111; /* Accumulator 0. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x22222222; /* Accumulator 0. */ *pxTopOfStack = 0x22222222; /* Accumulator 0. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x33333333; /* Accumulator 0. */ *pxTopOfStack = 0x33333333; /* Accumulator 0. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x44444444; /* Accumulator 1. */ *pxTopOfStack = 0x44444444; /* Accumulator 1. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x55555555; /* Accumulator 1. */ *pxTopOfStack = 0x55555555; /* Accumulator 1. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0x66666666; /* Accumulator 1. */ *pxTopOfStack = 0x66666666; /* Accumulator 1. */
return pxTopOfStack; return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
{ {
extern void vApplicationSetupTimerInterrupt( void ); extern void vApplicationSetupTimerInterrupt( void );
/* Use pxCurrentTCB just so it does not get optimised away. */ /* Use pxCurrentTCB just so it does not get optimised away. */
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. */
_IEN( _ICU_SWINT ) = 1; _IEN( _ICU_SWINT ) = 1;
/* Ensure the software interrupt is clear. */ /* Ensure the software interrupt is clear. */
_IR( _ICU_SWINT ) = 0; _IR( _ICU_SWINT ) = 0;
/* Ensure the software interrupt is set to the kernel priority. */ /* Ensure the software interrupt is set to the kernel priority. */
_IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY; _IPR( _ICU_SWINT ) = configKERNEL_INTERRUPT_PRIORITY;
/* Start the first task. */ /* Start the first task. */
prvStartFirstTask(); prvStartFirstTask();
} }
/* Should not get here. */ /* Should not get here. */
return pdFAIL; return pdFAIL;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#pragma vector = configTICK_VECTOR #pragma vector = configTICK_VECTOR
__interrupt void vTickISR( void ) __interrupt void vTickISR( void )
{ {
/* Re-enable interrupts. */ /* Re-enable interrupts. */
__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 )
{ {
taskYIELD(); taskYIELD();
} }
} }
__set_interrupt_level( configKERNEL_INTERRUPT_PRIORITY ); __set_interrupt_level( configKERNEL_INTERRUPT_PRIORITY );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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

@ -27,13 +27,13 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -46,98 +46,99 @@
*/ */
/* 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
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#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
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */ #define portBYTE_ALIGNMENT 8 /* Could make four, according to manual. */
#define portSTACK_GROWTH -1 #define portSTACK_GROWTH -1
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#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 \
( \ ( \
"PUSH.L R10 \n"\ "PUSH.L R10 \n" \
"MOV.L #0x872E0, R10 \n"\ "MOV.L #0x872E0, R10 \n" \
"MOV.B #0x1, [R10] \n"\ "MOV.B #0x1, [R10] \n" \
"MOV.L [R10], R10 \n"\ "MOV.L [R10], R10 \n" \
"POP R10 \n"\ "POP R10 \n" \
) )
#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 ) )
#define portDISABLE_INTERRUPTS() if( __get_interrupt_level() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() if( __get_interrupt_level() < configMAX_SYSCALL_INTERRUPT_PRIORITY ) __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY )
#else #else
#define portDISABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY ) #define portDISABLE_INTERRUPTS() __set_interrupt_level( ( uint8_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY )
#endif #endif
/* Critical nesting counts are stored in the TCB. */ /* Critical nesting counts are stored in the TCB. */
#define portCRITICAL_NESTING_IN_TCB ( 1 ) #define portCRITICAL_NESTING_IN_TCB ( 1 )
/* The critical nesting functions defined within tasks.c. */ /* The critical nesting functions defined within tasks.c. */
extern void vTaskEnterCritical( void ); extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void ); extern void vTaskExitCritical( void );
#define portENTER_CRITICAL() vTaskEnterCritical() #define portENTER_CRITICAL() vTaskEnterCritical()
#define portEXIT_CRITICAL() vTaskExitCritical() #define portEXIT_CRITICAL() vTaskExitCritical()
/* As this port allows interrupt nesting... */ /* As this port allows interrupt nesting... */
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_level(); portDISABLE_INTERRUPTS() #define portSET_INTERRUPT_MASK_FROM_ISR() __get_interrupt_level(); portDISABLE_INTERRUPTS()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) __set_interrupt_level( ( uint8_t ) ( uxSavedInterruptStatus ) ) #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ) __set_interrupt_level( ( uint8_t ) ( uxSavedInterruptStatus ) )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
/* 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
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,123 +1,105 @@
; /* ;/*
* ; * 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.
MOV LR, R0
Now we have saved LR we can use it instead of R0. ; Pop R0 so we can save it onto the system mode stack.
MOV LR, R0 LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Pop R0 so we can save it onto the system mode stack. STMDB LR, {R0-LR}^
LDMIA SP !, { R0 } NOP
SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push all the system mode registers onto the task stack. MRS R0, SPSR
STMDB LR, { R0 - LR } ^ STMDB LR!, {R0}
NOP
SUB LR, LR, # 60
; LDR R0, =ulCriticalNesting
Push the SPSR onto the task stack. LDR R0, [R0]
MRS R0, SPSR STMDB LR!, {R0}
STMDB LR !, { R0 }
LDR R0, = ulCriticalNesting ; Store the new top of stack for the task.
LDR R0, [ R0 ] LDR R1, =pxCurrentTCB
STMDB LR !, { R0 } LDR R0, [R1]
STR LR, [R0]
; ENDM
Store the new top of stack for the task.
LDR R1, = pxCurrentTCB
LDR R0, [ R1 ]
STR LR, [ R0 ]
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.
; LDR R0, =ulCriticalNesting
Load it into the ulCriticalNesting variable. LDMFD LR!, {R1}
LDR R0, = ulCriticalNesting STR R1, [R0]
LDMFD LR !, { R1 }
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.
SUBS PC, LR, #4
And return -correcting the offset in the LR to obtain the ENDM
;
correct address.
SUBS PC, LR, # 4
ENDM

View file

@ -26,9 +26,9 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ST STR71x ARM7 * Implementation of functions defined in portable.h for the ST STR71x ARM7
* port. * port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Library includes. */ /* Library includes. */
#include "wdg.h" #include "wdg.h"
@ -42,14 +42,14 @@
#include "task.h" #include "task.h"
/* Constants required to setup the initial stack. */ /* Constants required to setup the initial stack. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) #define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
#define portMICROS_PER_SECOND 1000000 #define portMICROS_PER_SECOND 1000000
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -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,180 +75,184 @@ 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--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
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--;
/* The status register is set for system mode, with interrupts enabled. */ /* The status register is set for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL )
{
/* We want the task to start in thumb mode. */
*pxTopOfStack |= portTHUMB_MODE_BIT;
}
pxTopOfStack--;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL ) /* 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
/* We want the task to start in thumb mode. */ tasks context. */
*pxTopOfStack |= portTHUMB_MODE_BIT; *pxTopOfStack = portNO_CRITICAL_NESTING;
}
pxTopOfStack--; return pxTopOfStack;
/* 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
* tasks context. */
*pxTopOfStack = portNO_CRITICAL_NESTING;
return pxTopOfStack;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
WDG->SR = 0x0000; WDG->SR = 0x0000;
portCLEAR_EIC(); portCLEAR_EIC();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* 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. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* Select a new task to execute. */ /* Select a new task to execute. */
vTaskSwitchContext(); vTaskSwitchContext();
} }
/* Clear the interrupt in the watchdog and EIC. */ /* Clear the interrupt in the watchdog and EIC. */
WDG->SR = 0x0000; WDG->SR = 0x0000;
portCLEAR_EIC(); portCLEAR_EIC();
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
/* Set the watchdog up to generate a periodic tick. */ /* Set the watchdog up to generate a periodic tick. */
WDG_ECITConfig( DISABLE ); WDG_ECITConfig( DISABLE );
WDG_CntOnOffConfig( DISABLE ); WDG_CntOnOffConfig( DISABLE );
WDG_PeriodValueConfig( portMICROS_PER_SECOND / configTICK_RATE_HZ ); WDG_PeriodValueConfig( portMICROS_PER_SECOND / configTICK_RATE_HZ );
/* Setup the tick interrupt in the EIC. */ /* Setup the tick interrupt in the EIC. */
EIC_IRQChannelPriorityConfig( WDG_IRQChannel, 1 ); EIC_IRQChannelPriorityConfig( WDG_IRQChannel, 1 );
EIC_IRQChannelConfig( WDG_IRQChannel, ENABLE ); EIC_IRQChannelConfig( WDG_IRQChannel, ENABLE );
EIC_IRQConfig( ENABLE ); EIC_IRQConfig( ENABLE );
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 );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__arm __interwork void vPortEnterCritical( void ) __arm __interwork void vPortEnterCritical( void )
{ {
/* Disable interrupts first! */ /* Disable interrupts first! */
__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++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__arm __interwork void vPortExitCritical( void ) __arm __interwork void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -27,7 +27,7 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -39,81 +39,83 @@
*----------------------------------------------------------- *-----------------------------------------------------------
*/ */
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm ( "SWI 0" ) #define portYIELD() asm ( "SWI 0" )
#define portNOP() asm ( "NOP" ) #define portNOP() asm ( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
__arm __interwork void vPortDisableInterruptsFromThumb( void ); __arm __interwork void vPortDisableInterruptsFromThumb( void );
__arm __interwork void vPortEnableInterruptsFromThumb( void ); __arm __interwork void vPortEnableInterruptsFromThumb( void );
__arm __interwork void vPortEnterCritical( void ); __arm __interwork void vPortEnterCritical( void );
__arm __interwork void vPortExitCritical( void ); __arm __interwork void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() __disable_interrupt() #define portDISABLE_INTERRUPTS() __disable_interrupt()
#define portENABLE_INTERRUPTS() __enable_interrupt() #define portENABLE_INTERRUPTS() __enable_interrupt()
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern void vTaskSwitchContext( void ); \ extern void vTaskSwitchContext( void ); \
\ \
if( xSwitchRequired ) \ if( xSwitchRequired ) \
{ \ { \
vTaskSwitchContext(); \ vTaskSwitchContext(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* EIC utilities. */ /* EIC utilities. */
#define portEIC_CICR_ADDR *( ( uint32_t * ) 0xFFFFF804 ) #define portEIC_CICR_ADDR *( ( uint32_t * ) 0xFFFFF804 )
#define portEIC_IPR_ADDR *( ( uint32_t * ) 0xFFFFF840 ) #define portEIC_IPR_ADDR *( ( uint32_t * ) 0xFFFFF840 )
#define portCLEAR_EIC() portEIC_IPR_ADDR = 0x01 << portEIC_CICR_ADDR #define portCLEAR_EIC() portEIC_IPR_ADDR = 0x01 << portEIC_CICR_ADDR
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -1,123 +1,105 @@
; /* ;/*
* ; * 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.
MOV LR, R0
Now we have saved LR we can use it instead of R0. ; Pop R0 so we can save it onto the system mode stack.
MOV LR, R0 LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Pop R0 so we can save it onto the system mode stack. STMDB LR, {R0-LR}^
LDMIA SP !, { R0 } NOP
SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push all the system mode registers onto the task stack. MRS R0, SPSR
STMDB LR, { R0 - LR } ^ STMDB LR!, {R0}
NOP
SUB LR, LR, # 60
; LDR R0, =ulCriticalNesting
Push the SPSR onto the task stack. LDR R0, [R0]
MRS R0, SPSR STMDB LR!, {R0}
STMDB LR !, { R0 }
LDR R0, = ulCriticalNesting ; Store the new top of stack for the task.
LDR R0, [ R0 ] LDR R1, =pxCurrentTCB
STMDB LR !, { R0 } LDR R0, [R1]
STR LR, [R0]
; ENDM
Store the new top of stack for the task.
LDR R1, = pxCurrentTCB
LDR R0, [ R1 ]
STR LR, [ R0 ]
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.
; LDR R0, =ulCriticalNesting
Load it into the ulCriticalNesting variable. LDMFD LR!, {R1}
LDR R0, = ulCriticalNesting STR R1, [R0]
LDMFD LR !, { R1 }
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.
SUBS PC, LR, #4
And return -correcting the offset in the LR to obtain the ENDM
;
correct address.
SUBS PC, LR, # 4
ENDM

View file

@ -26,9 +26,9 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ST STR75x ARM7 * Implementation of functions defined in portable.h for the ST STR75x ARM7
* port. * port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Library includes. */ /* Library includes. */
#include "75x_tb.h" #include "75x_tb.h"
@ -39,14 +39,14 @@
#include "task.h" #include "task.h"
/* Constants required to setup the initial stack. */ /* Constants required to setup the initial stack. */
#define portINITIAL_SPSR ( ( StackType_t ) 0x3f ) /* System mode, THUMB mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x3f ) /* System mode, THUMB mode, interrupts enabled. */
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* Prescale used on the timer clock when calculating the tick period. */ /* Prescale used on the timer clock when calculating the tick period. */
#define portPRESCALE 20 #define portPRESCALE 20
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -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,164 +70,168 @@ __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--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
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--;
/* The status register is set for system mode, with interrupts enabled. */ /* The status register is set for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__arm void vPortPreemptiveTick( void ) __arm void vPortPreemptiveTick( void )
{ {
/* Increment the tick counter. */ /* Increment the tick counter. */
if( xTaskIncrementTick() != pdFALSE ) if( xTaskIncrementTick() != pdFALSE )
{ {
/* Select a new task to execute. */ /* Select a new task to execute. */
vTaskSwitchContext(); vTaskSwitchContext();
} }
TB_ClearITPendingBit( TB_IT_Update ); TB_ClearITPendingBit( TB_IT_Update );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
EIC_IRQInitTypeDef EIC_IRQInitStructure; EIC_IRQInitTypeDef EIC_IRQInitStructure;
TB_InitTypeDef TB_InitStructure; TB_InitTypeDef TB_InitStructure;
/* Setup the EIC for the TB. */ /* Setup the EIC for the TB. */
EIC_IRQInitStructure.EIC_IRQChannelCmd = ENABLE; EIC_IRQInitStructure.EIC_IRQChannelCmd = ENABLE;
EIC_IRQInitStructure.EIC_IRQChannel = TB_IRQChannel; EIC_IRQInitStructure.EIC_IRQChannel = TB_IRQChannel;
EIC_IRQInitStructure.EIC_IRQChannelPriority = 1; EIC_IRQInitStructure.EIC_IRQChannelPriority = 1;
EIC_IRQInit( &EIC_IRQInitStructure ); EIC_IRQInit(&EIC_IRQInitStructure);
/* Setup the TB for the generation of the tick interrupt. */
TB_InitStructure.TB_Mode = TB_Mode_Timing;
TB_InitStructure.TB_CounterMode = TB_CounterMode_Down;
TB_InitStructure.TB_Prescaler = portPRESCALE - 1;
TB_InitStructure.TB_AutoReload = ( ( configCPU_CLOCK_HZ / portPRESCALE ) / configTICK_RATE_HZ );
TB_Init(&TB_InitStructure);
/* Enable TB Update interrupt */
TB_ITConfig(TB_IT_Update, ENABLE);
/* Setup the TB for the generation of the tick interrupt. */ /* Clear TB Update interrupt pending bit */
TB_InitStructure.TB_Mode = TB_Mode_Timing; TB_ClearITPendingBit(TB_IT_Update);
TB_InitStructure.TB_CounterMode = TB_CounterMode_Down;
TB_InitStructure.TB_Prescaler = portPRESCALE - 1;
TB_InitStructure.TB_AutoReload = ( ( configCPU_CLOCK_HZ / portPRESCALE ) / configTICK_RATE_HZ );
TB_Init( &TB_InitStructure );
/* Enable TB Update interrupt */ /* Enable TB */
TB_ITConfig( TB_IT_Update, ENABLE ); TB_Cmd(ENABLE);
/* Clear TB Update interrupt pending bit */
TB_ClearITPendingBit( TB_IT_Update );
/* Enable TB */
TB_Cmd( ENABLE );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__arm __interwork void vPortEnterCritical( void ) __arm __interwork void vPortEnterCritical( void )
{ {
/* Disable interrupts first! */ /* Disable interrupts first! */
__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++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__arm __interwork void vPortExitCritical( void ) __arm __interwork void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -27,7 +27,7 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -39,72 +39,74 @@
*----------------------------------------------------------- *-----------------------------------------------------------
*/ */
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm ( "SWI 0" ) #define portYIELD() asm ( "SWI 0" )
#define portNOP() asm ( "NOP" ) #define portNOP() asm ( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
__arm __interwork void vPortEnterCritical( void ); __arm __interwork void vPortEnterCritical( void );
__arm __interwork void vPortExitCritical( void ); __arm __interwork void vPortExitCritical( void );
#define portDISABLE_INTERRUPTS() __disable_interrupt() #define portDISABLE_INTERRUPTS() __disable_interrupt()
#define portENABLE_INTERRUPTS() __enable_interrupt() #define portENABLE_INTERRUPTS() __enable_interrupt()
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern void vTaskSwitchContext( void ); \ extern void vTaskSwitchContext( void ); \
\ \
if( xSwitchRequired ) \ if( xSwitchRequired ) \
{ \ { \
vTaskSwitchContext(); \ vTaskSwitchContext(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,99 +25,81 @@
* 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.
MOV LR, R0
Now we have saved LR we can use it instead of R0. ; Pop R0 so we can save it onto the system mode stack.
MOV LR, R0 LDMIA SP!, {R0}
; ; Push all the system mode registers onto the task stack.
Pop R0 so we can save it onto the system mode stack. STMDB LR, {R0-LR}^
LDMIA SP !, { R0 } NOP
SUB LR, LR, #60
; ; Push the SPSR onto the task stack.
Push all the system mode registers onto the task stack. MRS R0, SPSR
STMDB LR, { R0 - LR } ^ STMDB LR!, {R0}
NOP
SUB LR, LR, # 60
; LDR R0, =ulCriticalNesting
Push the SPSR onto the task stack. LDR R0, [R0]
MRS R0, SPSR STMDB LR!, {R0}
STMDB LR !, { R0 }
LDR R0, = ulCriticalNesting ; Store the new top of stack for the task.
LDR R0, [ R0 ] LDR R1, =pxCurrentTCB
STMDB LR !, { R0 } LDR R0, [R1]
STR LR, [R0]
; ENDM
Store the new top of stack for the task.
LDR R1, = pxCurrentTCB
LDR R0, [ R1 ]
STR LR, [ R0 ]
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.
; LDR R0, =ulCriticalNesting
Load it into the ulCriticalNesting variable. LDMFD LR!, {R1}
LDR R0, = ulCriticalNesting STR R1, [R0]
LDMFD LR !, { R1 }
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.
SUBS PC, LR, #4
And return -correcting the offset in the LR to obtain the ENDM
;
correct address.
SUBS PC, LR, # 4
ENDM

View file

@ -26,9 +26,9 @@
*/ */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Implementation of functions defined in portable.h for the ST STR91x ARM9 * Implementation of functions defined in portable.h for the ST STR91x ARM9
* port. * port.
*----------------------------------------------------------*/ *----------------------------------------------------------*/
/* Library includes. */ /* Library includes. */
#include "91x_lib.h" #include "91x_lib.h"
@ -42,23 +42,23 @@
#include "task.h" #include "task.h"
#ifndef configUSE_WATCHDOG_TICK #ifndef configUSE_WATCHDOG_TICK
#error configUSE_WATCHDOG_TICK must be set to either 1 or 0 in FreeRTOSConfig.h to use either the Watchdog or timer 2 to generate the tick interrupt respectively. #error configUSE_WATCHDOG_TICK must be set to either 1 or 0 in FreeRTOSConfig.h to use either the Watchdog or timer 2 to generate the tick interrupt respectively.
#endif #endif
/* Constants required to setup the initial stack. */ /* Constants required to setup the initial stack. */
#ifndef _RUN_TASK_IN_ARM_MODE_ #ifndef _RUN_TASK_IN_ARM_MODE_
#define portINITIAL_SPSR ( ( StackType_t ) 0x3f ) /* System mode, THUMB mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x3f ) /* System mode, THUMB mode, interrupts enabled. */
#else #else
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */ #define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
#endif #endif
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) #define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
/* Constants required to handle critical sections. */ /* Constants required to handle critical sections. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
#ifndef abs #ifndef abs
#define abs( x ) ( ( x ) > 0 ? ( x ) : -( x ) ) #define abs(x) ((x)>0 ? (x) : -(x))
#endif #endif
/** /**
@ -73,15 +73,15 @@
* } * }
* *
*/ */
#define TOGGLE_LED( port, pin ) \ #define TOGGLE_LED(port,pin) \
if( ( ( ( ( port )->DR[ ( pin ) << 2 ] ) ) & ( pin ) ) != Bit_RESET ) \ if ( ((((port)->DR[(pin)<<2])) & (pin)) != Bit_RESET ) \
{ \ { \
( port )->DR[ ( pin ) << 2 ] = 0x00; \ (port)->DR[(pin) <<2] = 0x00; \
} \ } \
else \ else \
{ \ { \
( port )->DR[ ( pin ) << 2 ] = ( pin ); \ (port)->DR[(pin) <<2] = (pin); \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -90,21 +90,21 @@
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. */
static void prvDefaultHandler( void ); static void prvDefaultHandler( void );
#if configUSE_WATCHDOG_TICK == 0 #if configUSE_WATCHDOG_TICK == 0
/* Used to update the OCR timer register */ /* Used to update the OCR timer register */
static u16 s_nPulseLength; static u16 s_nPulseLength;
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -115,286 +115,268 @@ 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--;
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */ *pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */ *pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */ *pxTopOfStack = ( StackType_t ) 0x09090909; /* R9 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */ *pxTopOfStack = ( StackType_t ) 0x08080808; /* R8 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */ *pxTopOfStack = ( StackType_t ) 0x07070707; /* R7 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */ *pxTopOfStack = ( StackType_t ) 0x06060606; /* R6 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */ *pxTopOfStack = ( StackType_t ) 0x05050505; /* R5 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */ *pxTopOfStack = ( StackType_t ) 0x04040404; /* R4 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */ *pxTopOfStack = ( StackType_t ) 0x03030303; /* R3 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */ *pxTopOfStack = ( StackType_t ) 0x02020202; /* R2 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
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--;
/* The status register is set for system mode, with interrupts enabled. */ /* The status register is set for system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) 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. */
vPortStartFirstTask(); vPortStartFirstTask();
/* Should not get here! */ /* Should not get here! */
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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
{ copyright STMicroelectronics. Reproduced with permission. */
/* This function is copied from the ST STR7 library and is
* copyright STMicroelectronics. Reproduced with permission. */ u32 b0;
u16 a0;
int32_t err, err_min=n;
*a = a0 = ((n-1)/65536ul) + 1;
*b = b0 = n / *a;
for (; *a <= 256; (*a)++)
{
*b = n / *a;
err = (int32_t)*a * (int32_t)*b - (int32_t)n;
if (abs(err) > (*a / 2))
{
(*b)++;
err = (int32_t)*a * (int32_t)*b - (int32_t)n;
}
if (abs(err) < abs(err_min))
{
err_min = err;
a0 = *a;
b0 = *b;
if (err == 0) break;
}
}
*a = a0;
*b = b0;
}
/*-----------------------------------------------------------*/
u32 b0; static void prvSetupTimerInterrupt( void )
u16 a0; {
int32_t err, err_min = n; WDG_InitTypeDef xWdg;
uint16_t a;
uint32_t n = configCPU_PERIPH_HZ / configTICK_RATE_HZ, b;
/* Configure the watchdog as a free running timer that generates a
periodic interrupt. */
SCU_APBPeriphClockConfig( __WDG, ENABLE );
WDG_DeInit();
WDG_StructInit(&xWdg);
prvFindFactors( n, &a, &b );
xWdg.WDG_Prescaler = a - 1;
xWdg.WDG_Preload = b - 1;
WDG_Init( &xWdg );
WDG_ITConfig(ENABLE);
/* Configure the VIC for the WDG interrupt. */
VIC_Config( WDG_ITLine, VIC_IRQ, 10 );
VIC_ITCmd( WDG_ITLine, ENABLE );
/* Install the default handlers for both VIC's. */
VIC0->DVAR = ( uint32_t ) prvDefaultHandler;
VIC1->DVAR = ( uint32_t ) prvDefaultHandler;
WDG_Cmd(ENABLE);
}
/*-----------------------------------------------------------*/
*a = a0 = ( ( n - 1 ) / 65536ul ) + 1; void WDG_IRQHandler( void )
*b = b0 = n / *a; {
{
/* Increment the tick counter. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Select a new task to execute. */
vTaskSwitchContext();
}
/* Clear the interrupt in the watchdog. */
WDG->SR &= ~0x0001;
}
}
for( ; *a <= 256; ( *a )++ ) #else
{
*b = n / *a;
err = ( int32_t ) *a * ( int32_t ) *b - ( int32_t ) n;
if( abs( err ) > ( *a / 2 ) ) static void prvFindFactors(u32 n, u8 *a, u16 *b)
{ {
( *b )++; /* This function is copied from the ST STR7 library and is
err = ( int32_t ) *a * ( int32_t ) *b - ( int32_t ) n; copyright STMicroelectronics. Reproduced with permission. */
}
u16 b0;
u8 a0;
int32_t err, err_min=n;
*a = a0 = ((n-1)/256) + 1;
*b = b0 = n / *a;
for (; *a <= 256; (*a)++)
{
*b = n / *a;
err = (int32_t)*a * (int32_t)*b - (int32_t)n;
if (abs(err) > (*a / 2))
{
(*b)++;
err = (int32_t)*a * (int32_t)*b - (int32_t)n;
}
if (abs(err) < abs(err_min))
{
err_min = err;
a0 = *a;
b0 = *b;
if (err == 0) break;
}
}
*a = a0;
*b = b0;
}
/*-----------------------------------------------------------*/
if( abs( err ) < abs( err_min ) ) static void prvSetupTimerInterrupt( void )
{ {
err_min = err; uint8_t a;
a0 = *a; uint16_t b;
b0 = *b; uint32_t n = configCPU_PERIPH_HZ / configTICK_RATE_HZ;
TIM_InitTypeDef timer;
SCU_APBPeriphClockConfig( __TIM23, ENABLE );
TIM_DeInit(TIM2);
TIM_StructInit(&timer);
prvFindFactors( n, &a, &b );
timer.TIM_Mode = TIM_OCM_CHANNEL_1;
timer.TIM_OC1_Modes = TIM_TIMING;
timer.TIM_Clock_Source = TIM_CLK_APB;
timer.TIM_Clock_Edge = TIM_CLK_EDGE_RISING;
timer.TIM_Prescaler = a-1;
timer.TIM_Pulse_Level_1 = TIM_HIGH;
timer.TIM_Pulse_Length_1 = s_nPulseLength = b-1;
TIM_Init (TIM2, &timer);
TIM_ITConfig(TIM2, TIM_IT_OC1, ENABLE);
/* Configure the VIC for the WDG interrupt. */
VIC_Config( TIM2_ITLine, VIC_IRQ, 10 );
VIC_ITCmd( TIM2_ITLine, ENABLE );
/* Install the default handlers for both VIC's. */
VIC0->DVAR = ( uint32_t ) prvDefaultHandler;
VIC1->DVAR = ( uint32_t ) prvDefaultHandler;
TIM_CounterCmd(TIM2, TIM_CLEAR);
TIM_CounterCmd(TIM2, TIM_START);
}
/*-----------------------------------------------------------*/
if( err == 0 ) void TIM2_IRQHandler( void )
{ {
break; /* Reset the timer counter to avioid overflow. */
} TIM2->OC1R += s_nPulseLength;
}
} /* Increment the tick counter. */
if( xTaskIncrementTick() != pdFALSE )
*a = a0; {
*b = b0; /* Select a new task to run. */
} vTaskSwitchContext();
/*-----------------------------------------------------------*/ }
static void prvSetupTimerInterrupt( void ) /* Clear the interrupt in the watchdog. */
{ TIM2->SR &= ~TIM_FLAG_OC1;
WDG_InitTypeDef xWdg; }
uint16_t a;
uint32_t n = configCPU_PERIPH_HZ / configTICK_RATE_HZ, b;
/* Configure the watchdog as a free running timer that generates a
* periodic interrupt. */
SCU_APBPeriphClockConfig( __WDG, ENABLE );
WDG_DeInit();
WDG_StructInit( &xWdg );
prvFindFactors( n, &a, &b );
xWdg.WDG_Prescaler = a - 1;
xWdg.WDG_Preload = b - 1;
WDG_Init( &xWdg );
WDG_ITConfig( ENABLE );
/* Configure the VIC for the WDG interrupt. */
VIC_Config( WDG_ITLine, VIC_IRQ, 10 );
VIC_ITCmd( WDG_ITLine, ENABLE );
/* Install the default handlers for both VIC's. */
VIC0->DVAR = ( uint32_t ) prvDefaultHandler;
VIC1->DVAR = ( uint32_t ) prvDefaultHandler;
WDG_Cmd( ENABLE );
}
/*-----------------------------------------------------------*/
void WDG_IRQHandler( void )
{
{
/* Increment the tick counter. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Select a new task to execute. */
vTaskSwitchContext();
}
/* Clear the interrupt in the watchdog. */
WDG->SR &= ~0x0001;
}
}
#else /* if configUSE_WATCHDOG_TICK == 1 */
static void prvFindFactors( u32 n,
u8 * a,
u16 * b )
{
/* This function is copied from the ST STR7 library and is
* copyright STMicroelectronics. Reproduced with permission. */
u16 b0;
u8 a0;
int32_t err, err_min = n;
*a = a0 = ( ( n - 1 ) / 256 ) + 1;
*b = b0 = n / *a;
for( ; *a <= 256; ( *a )++ )
{
*b = n / *a;
err = ( int32_t ) *a * ( int32_t ) *b - ( int32_t ) n;
if( abs( err ) > ( *a / 2 ) )
{
( *b )++;
err = ( int32_t ) *a * ( int32_t ) *b - ( int32_t ) n;
}
if( abs( err ) < abs( err_min ) )
{
err_min = err;
a0 = *a;
b0 = *b;
if( err == 0 )
{
break;
}
}
}
*a = a0;
*b = b0;
}
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void )
{
uint8_t a;
uint16_t b;
uint32_t n = configCPU_PERIPH_HZ / configTICK_RATE_HZ;
TIM_InitTypeDef timer;
SCU_APBPeriphClockConfig( __TIM23, ENABLE );
TIM_DeInit( TIM2 );
TIM_StructInit( &timer );
prvFindFactors( n, &a, &b );
timer.TIM_Mode = TIM_OCM_CHANNEL_1;
timer.TIM_OC1_Modes = TIM_TIMING;
timer.TIM_Clock_Source = TIM_CLK_APB;
timer.TIM_Clock_Edge = TIM_CLK_EDGE_RISING;
timer.TIM_Prescaler = a - 1;
timer.TIM_Pulse_Level_1 = TIM_HIGH;
timer.TIM_Pulse_Length_1 = s_nPulseLength = b - 1;
TIM_Init( TIM2, &timer );
TIM_ITConfig( TIM2, TIM_IT_OC1, ENABLE );
/* Configure the VIC for the WDG interrupt. */
VIC_Config( TIM2_ITLine, VIC_IRQ, 10 );
VIC_ITCmd( TIM2_ITLine, ENABLE );
/* Install the default handlers for both VIC's. */
VIC0->DVAR = ( uint32_t ) prvDefaultHandler;
VIC1->DVAR = ( uint32_t ) prvDefaultHandler;
TIM_CounterCmd( TIM2, TIM_CLEAR );
TIM_CounterCmd( TIM2, TIM_START );
}
/*-----------------------------------------------------------*/
void TIM2_IRQHandler( void )
{
/* Reset the timer counter to avioid overflow. */
TIM2->OC1R += s_nPulseLength;
/* Increment the tick counter. */
if( xTaskIncrementTick() != pdFALSE )
{
/* Select a new task to run. */
vTaskSwitchContext();
}
/* Clear the interrupt in the watchdog. */
TIM2->SR &= ~TIM_FLAG_OC1;
}
#endif /* USE_WATCHDOG_TICK */ #endif /* USE_WATCHDOG_TICK */
@ -402,33 +384,38 @@ void vPortEndScheduler( void )
__arm __interwork void vPortEnterCritical( void ) __arm __interwork void vPortEnterCritical( void )
{ {
/* Disable interrupts first! */ /* Disable interrupts first! */
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++;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__arm __interwork void vPortExitCritical( void ) __arm __interwork void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as we are leaving a critical section. */ /* Decrement the nesting count as we are leaving a critical section. */
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();
} }
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvDefaultHandler( void ) static void prvDefaultHandler( void )
{ {
} }

View file

@ -27,7 +27,7 @@
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -39,74 +39,76 @@
*----------------------------------------------------------- *-----------------------------------------------------------
*/ */
#include <intrinsics.h> #include <intrinsics.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
#define portYIELD() asm ( "SWI 0" ) #define portYIELD() asm ( "SWI 0" )
#define portNOP() asm ( "NOP" ) #define portNOP() asm ( "NOP" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */
__arm __interwork void vPortEnterCritical( void ); __arm __interwork void vPortEnterCritical( void );
__arm __interwork void vPortExitCritical( void ); __arm __interwork void vPortExitCritical( void );
#define portENTER_CRITICAL() vPortEnterCritical() #define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical() #define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() __disable_interrupt() #define portDISABLE_INTERRUPTS() __disable_interrupt()
#define portENABLE_INTERRUPTS() __enable_interrupt() #define portENABLE_INTERRUPTS() __enable_interrupt()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern void vTaskSwitchContext( void ); \ extern void vTaskSwitchContext( void ); \
\ \
if( xSwitchRequired ) \ if( xSwitchRequired ) \
{ \ { \
vTaskSwitchContext(); \ vTaskSwitchContext(); \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */

View file

@ -25,142 +25,125 @@
* 1 tab == 4 spaces! * 1 tab == 4 spaces!
*/ */
EXTERN pxCurrentTCB EXTERN pxCurrentTCB
EXTERN usCriticalNesting 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 ]; stsr 0,r31
store LP to stack st.w lp,4[sp] ; store EIPC to stack
stsr 0, r31 stsr 1,lp
st.w lp, 4[ sp ]; st.w lp,0[sp] ; store EIPSW to stack
store EIPC to stack #if configDATA_MODE == 1 ; Using the Tiny data model
stsr 1, lp prepare {r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30},76,sp ; save general purpose registers
st.w lp, 0[ sp ]; sst.w r19,72[ep]
store EIPSW to stack sst.w r18,68[ep]
#if configDATA_MODE == 1; Using the Tiny data model sst.w r17,64[ep]
prepare { r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30 }, 76, sp; sst.w r16,60[ep]
save general purpose registers sst.w r15,56[ep]
sst.w r19, 72[ ep ] sst.w r14,52[ep]
sst.w r18, 68[ ep ] sst.w r13,48[ep]
sst.w r17, 64[ ep ] sst.w r12,44[ep]
sst.w r16, 60[ ep ] sst.w r11,40[ep]
sst.w r15, 56[ ep ] sst.w r10,36[ep]
sst.w r14, 52[ ep ] sst.w r9,32[ep]
sst.w r13, 48[ ep ] sst.w r8,28[ep]
sst.w r12, 44[ ep ] sst.w r7,24[ep]
sst.w r11, 40[ ep ] sst.w r6,20[ep]
sst.w r10, 36[ ep ] sst.w r5,16[ep]
sst.w r9, 32[ ep ] sst.w r4,12[ep]
sst.w r8, 28[ ep ] #else ; Using the Small/Large data model
sst.w r7, 24[ ep ] prepare {r20,r21,r22,r23,r24,r26,r27,r28,r29,r30},72,sp ; save general purpose registers
sst.w r6, 20[ ep ] sst.w r19,68[ep]
sst.w r5, 16[ ep ] sst.w r18,64[ep]
sst.w r4, 12[ ep ] sst.w r17,60[ep]
#else; Using the Small / Large data model sst.w r16,56[ep]
prepare { r20, r21, r22, r23, r24, r26, r27, r28, r29, r30 }, 72, sp; sst.w r15,52[ep]
save general purpose registers sst.w r14,48[ep]
sst.w r19, 68[ ep ] sst.w r13,44[ep]
sst.w r18, 64[ ep ] sst.w r12,40[ep]
sst.w r17, 60[ ep ] sst.w r11,36[ep]
sst.w r16, 56[ ep ] sst.w r10,32[ep]
sst.w r15, 52[ ep ] sst.w r9,28[ep]
sst.w r14, 48[ ep ] sst.w r8,24[ep]
sst.w r13, 44[ ep ] sst.w r7,20[ep]
sst.w r12, 40[ ep ] sst.w r6,16[ep]
sst.w r11, 36[ ep ] sst.w r5,12[ep]
sst.w r10, 32[ ep ]
sst.w r9, 28[ ep ]
sst.w r8, 24[ ep ]
sst.w r7, 20[ ep ]
sst.w r6, 16[ ep ]
sst.w r5, 12[ ep ]
#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 ; save SP to top of current TCB
MOVHI hi1( pxCurrentTCB ), r0, r1; ld.w lw1(pxCurrentTCB)[r1],r2
save SP to top of current TCB st.w sp,0[r2]
ld.w lw1( pxCurrentTCB )[ r1 ], r2 ENDM
st.w sp, 0[ r2 ]
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 ; load stackpointer
ld.w 0[ r1 ], sp; MOV sp,ep ; set stack pointer to element pointer
load stackpointer sld.w 0[ep],r1 ; load usCriticalNesting value from stack
MOV sp, ep; MOVHI hi1(usCriticalNesting),r0,r2
set stack pointer to element pointer st.w r1,lw1(usCriticalNesting)[r2]
sld.w 0[ ep ], r1; sld.w 4[ep],r1 ; restore general purpose registers
load usCriticalNesting value from stack sld.w 8[ep],r2
MOVHI hi1( usCriticalNesting ), r0, r2 #if configDATA_MODE == 1 ; Using Tiny data model
st.w r1, lw1( usCriticalNesting )[ r2 ] sld.w 12[ep],r4
sld.w 4[ ep ], r1; sld.w 16[ep],r5
restore general purpose registers sld.w 20[ep],r6
sld.w 8[ ep ], r2 sld.w 24[ep],r7
#if configDATA_MODE == 1; Using Tiny data model sld.w 28[ep],r8
sld.w 12[ ep ], r4 sld.w 32[ep],r9
sld.w 16[ ep ], r5 sld.w 36[ep],r10
sld.w 20[ ep ], r6 sld.w 40[ep],r11
sld.w 24[ ep ], r7 sld.w 44[ep],r12
sld.w 28[ ep ], r8 sld.w 48[ep],r13
sld.w 32[ ep ], r9 sld.w 52[ep],r14
sld.w 36[ ep ], r10 sld.w 56[ep],r15
sld.w 40[ ep ], r11 sld.w 60[ep],r16
sld.w 44[ ep ], r12 sld.w 64[ep],r17
sld.w 48[ ep ], r13 sld.w 68[ep],r18
sld.w 52[ ep ], r14 sld.w 72[ep],r19
sld.w 56[ ep ], r15 dispose 76,{r20,r21,r22,r23,r24,r25,r26,r27,r28,r29,r30}
sld.w 60[ ep ], r16 #else ; Using Small/Large data model
sld.w 64[ ep ], r17 sld.w 12[ep],r5
sld.w 68[ ep ], r18 sld.w 16[ep],r6
sld.w 72[ ep ], r19 sld.w 20[ep],r7
dispose 76, { r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, r30 } sld.w 24[ep],r8
#else; Using Small / Large data model sld.w 28[ep],r9
sld.w 12[ ep ], r5 sld.w 32[ep],r10
sld.w 16[ ep ], r6 sld.w 36[ep],r11
sld.w 20[ ep ], r7 sld.w 40[ep],r12
sld.w 24[ ep ], r8 sld.w 44[ep],r13
sld.w 28[ ep ], r9 sld.w 48[ep],r14
sld.w 32[ ep ], r10 sld.w 52[ep],r15
sld.w 36[ ep ], r11 sld.w 56[ep],r16
sld.w 40[ ep ], r12 sld.w 60[ep],r17
sld.w 44[ ep ], r13 sld.w 64[ep],r18
sld.w 48[ ep ], r14 sld.w 68[ep],r19
sld.w 52[ ep ], r15 dispose 72,{r20,r21,r22,r23,r24,r26,r27,r28,r29,r30}
sld.w 56[ ep ], r16
sld.w 60[ ep ], r17
sld.w 64[ ep ], r18
sld.w 68[ ep ], r19
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 ; restore EIPC from stack
ld.w 4[ sp ], lp; ldsr lp,0
restore EIPC from stack ld.w 8[sp],lp ; restore LP from stack
ldsr lp, 0 add 0x0C,sp ; set SP to right position
ld.w 8[ sp ], lp;
restore LP from stack
add 0x0C, sp;
set SP to right position
RETI RETI
ENDM ENDM

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,106 +52,104 @@ 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--;
*pxTopOfStack = ( StackType_t ) pxCode; /* Task function start address */ *pxTopOfStack = ( StackType_t ) pxCode; /* Task function start address */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portPSW; /* Initial PSW value */ *pxTopOfStack = portPSW; /* Initial PSW value */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x20202020; /* Initial Value of R20 */ *pxTopOfStack = ( StackType_t ) 0x20202020; /* Initial Value of R20 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x21212121; /* Initial Value of R21 */ *pxTopOfStack = ( StackType_t ) 0x21212121; /* Initial Value of R21 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x22222222; /* Initial Value of R22 */ *pxTopOfStack = ( StackType_t ) 0x22222222; /* Initial Value of R22 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x23232323; /* Initial Value of R23 */ *pxTopOfStack = ( StackType_t ) 0x23232323; /* Initial Value of R23 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x24242424; /* Initial Value of R24 */ *pxTopOfStack = ( StackType_t ) 0x24242424; /* Initial Value of R24 */
pxTopOfStack--; pxTopOfStack--;
#if ( __DATA_MODEL__ == 0 ) || ( __DATA_MODEL__ == 1 ) #if (__DATA_MODEL__ == 0) || (__DATA_MODEL__ == 1)
*pxTopOfStack = ( StackType_t ) 0x25252525; /* Initial Value of R25 */ *pxTopOfStack = ( StackType_t ) 0x25252525; /* Initial Value of R25 */
pxTopOfStack--; pxTopOfStack--;
#endif /* configDATA_MODE */ #endif /* configDATA_MODE */
*pxTopOfStack = ( StackType_t ) 0x26262626; /* Initial Value of R26 */ *pxTopOfStack = ( StackType_t ) 0x26262626; /* Initial Value of R26 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x27272727; /* Initial Value of R27 */ *pxTopOfStack = ( StackType_t ) 0x27272727; /* Initial Value of R27 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x28282828; /* Initial Value of R28 */ *pxTopOfStack = ( StackType_t ) 0x28282828; /* Initial Value of R28 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x29292929; /* Initial Value of R29 */ *pxTopOfStack = ( StackType_t ) 0x29292929; /* Initial Value of R29 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x30303030; /* Initial Value of R30 */ *pxTopOfStack = ( StackType_t ) 0x30303030; /* Initial Value of R30 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x19191919; /* Initial Value of R19 */ *pxTopOfStack = ( StackType_t ) 0x19191919; /* Initial Value of R19 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x18181818; /* Initial Value of R18 */ *pxTopOfStack = ( StackType_t ) 0x18181818; /* Initial Value of R18 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x17171717; /* Initial Value of R17 */ *pxTopOfStack = ( StackType_t ) 0x17171717; /* Initial Value of R17 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x16161616; /* Initial Value of R16 */ *pxTopOfStack = ( StackType_t ) 0x16161616; /* Initial Value of R16 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x15151515; /* Initial Value of R15 */ *pxTopOfStack = ( StackType_t ) 0x15151515; /* Initial Value of R15 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x14141414; /* Initial Value of R14 */ *pxTopOfStack = ( StackType_t ) 0x14141414; /* Initial Value of R14 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x13131313; /* Initial Value of R13 */ *pxTopOfStack = ( StackType_t ) 0x13131313; /* Initial Value of R13 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x12121212; /* Initial Value of R12 */ *pxTopOfStack = ( StackType_t ) 0x12121212; /* Initial Value of R12 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x11111111; /* Initial Value of R11 */ *pxTopOfStack = ( StackType_t ) 0x11111111; /* Initial Value of R11 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x10101010; /* Initial Value of R10 */ *pxTopOfStack = ( StackType_t ) 0x10101010; /* Initial Value of R10 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x99999999; /* Initial Value of R09 */ *pxTopOfStack = ( StackType_t ) 0x99999999; /* Initial Value of R09 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x88888888; /* Initial Value of R08 */ *pxTopOfStack = ( StackType_t ) 0x88888888; /* Initial Value of R08 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x77777777; /* Initial Value of R07 */ *pxTopOfStack = ( StackType_t ) 0x77777777; /* Initial Value of R07 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x66666666; /* Initial Value of R06 */ *pxTopOfStack = ( StackType_t ) 0x66666666; /* Initial Value of R06 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0x55555555; /* Initial Value of R05 */ *pxTopOfStack = ( StackType_t ) 0x55555555; /* Initial Value of R05 */
pxTopOfStack--; pxTopOfStack--;
#if __DATA_MODEL__ == 0 || __DATA_MODEL__ == 1 #if __DATA_MODEL__ == 0 || __DATA_MODEL__ == 1
*pxTopOfStack = ( StackType_t ) 0x44444444; /* Initial Value of R04 */ *pxTopOfStack = ( StackType_t ) 0x44444444; /* Initial Value of R04 */
pxTopOfStack--; pxTopOfStack--;
#endif /* configDATA_MODE */ #endif /* configDATA_MODE */
*pxTopOfStack = ( StackType_t ) 0x22222222; /* Initial Value of R02 */ *pxTopOfStack = ( StackType_t ) 0x22222222; /* Initial Value of R02 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R1 is expected to hold the function parameter*/ *pxTopOfStack = ( StackType_t ) pvParameters; /* R1 is expected to hold the function parameter*/
pxTopOfStack--; pxTopOfStack--;
*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;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
vPortStart(); vPortStart();
/* Should not get here as the tasks are now running! */ /* Should not get here as the tasks are now running! */
return pdTRUE; return pdTRUE;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
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. */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -160,24 +158,26 @@ void vPortEndScheduler( void )
*/ */
static void prvSetupTimerInterrupt( void ) static void prvSetupTimerInterrupt( void )
{ {
TM0CE = 0; /* TMM0 operation disable */ TM0CE = 0; /* TMM0 operation disable */
TM0EQMK0 = 1; /* INTTM0EQ0 interrupt disable */ TM0EQMK0 = 1; /* INTTM0EQ0 interrupt disable */
TM0EQIF0 = 0; /* clear INTTM0EQ0 interrupt flag */ TM0EQIF0 = 0; /* clear INTTM0EQ0 interrupt flag */
#ifdef __IAR_V850ES_Fx3__ #ifdef __IAR_V850ES_Fx3__
{ {
TM0CMP0 = ( ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) / 2 ) - 1 ); /* divided by 2 because peripherals only run at CPU_CLOCK/2 */ TM0CMP0 = (((configCPU_CLOCK_HZ / configTICK_RATE_HZ) / 2)-1); /* divided by 2 because peripherals only run at CPU_CLOCK/2 */
} }
#else #else
{ {
TM0CMP0 = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ); TM0CMP0 = (configCPU_CLOCK_HZ / configTICK_RATE_HZ);
} }
#endif #endif
TM0EQIC0 &= 0xF8; TM0EQIC0 &= 0xF8;
TM0CTL0 = 0x00; TM0CTL0 = 0x00;
TM0EQIF0 = 0; /* clear INTTM0EQ0 interrupt flag */ TM0EQIF0 = 0; /* clear INTTM0EQ0 interrupt flag */
TM0EQMK0 = 0; /* INTTM0EQ0 interrupt enable */ TM0EQMK0 = 0; /* INTTM0EQ0 interrupt enable */
TM0CE = 1; /* TMM0 operation enable */ TM0CE = 1; /* TMM0 operation enable */
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -26,11 +26,11 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -43,92 +43,93 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE unsigned int #define portSTACK_TYPE unsigned int
#define portBASE_TYPE int #define portBASE_TYPE int
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
#if ( configUSE_16_BIT_TICKS == 1 ) #if (configUSE_16_BIT_TICKS==1)
typedef uint16_t TickType_t; typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff #define portMAX_DELAY ( TickType_t ) 0xffff
#else #else
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
#endif #endif
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Interrupt control macros. */ /* Interrupt control macros. */
#define portDISABLE_INTERRUPTS() __asm( "DI" ) #define portDISABLE_INTERRUPTS() __asm ( "DI" )
#define portENABLE_INTERRUPTS() __asm( "EI" ) #define portENABLE_INTERRUPTS() __asm ( "EI" )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Critical section control macros. */ /* Critical section control macros. */
#define portNO_CRITICAL_SECTION_NESTING ( ( UBaseType_t ) 0 ) #define portNO_CRITICAL_SECTION_NESTING ( ( UBaseType_t ) 0 )
#define portENTER_CRITICAL() \ #define portENTER_CRITICAL() \
{ \ { \
extern volatile /*uint16_t*/ portSTACK_TYPE usCriticalNesting; \ extern volatile /*uint16_t*/ portSTACK_TYPE usCriticalNesting; \
\ \
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 */ \ /* directly. Increment ulCriticalNesting to keep a count of how many */ \
/* times portENTER_CRITICAL() has been called. */ \ /* times portENTER_CRITICAL() has been called. */ \
usCriticalNesting++; \ usCriticalNesting++; \
} }
#define portEXIT_CRITICAL() \ #define portEXIT_CRITICAL() \
{ \ { \
extern volatile /*uint16_t*/ portSTACK_TYPE usCriticalNesting; \ extern volatile /*uint16_t*/ portSTACK_TYPE usCriticalNesting; \
\ \
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
/* Decrement the nesting count as we are leaving a critical section. */ \ /* Decrement the nesting count as we are leaving a critical section. */ \
usCriticalNesting--; \ usCriticalNesting--; \
\ \
/* 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( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \ if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
{ \ { \
portENABLE_INTERRUPTS(); \ portENABLE_INTERRUPTS(); \
} \ } \
} \ } \
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
extern void vPortYield( void ); extern void vPortYield( void );
extern void vPortStart( void ); extern void vPortStart( void );
extern void portSAVE_CONTEXT( void ); extern void portSAVE_CONTEXT( void );
extern void portRESTORE_CONTEXT( void ); extern void portRESTORE_CONTEXT( void );
#define portYIELD() __asm( "trap 0" ) #define portYIELD() __asm ( "trap 0" )
#define portNOP() __asm( "NOP" ) #define portNOP() __asm ( "NOP" )
extern void vTaskSwitchContext( void ); extern void vTaskSwitchContext( void );
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext() #define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardwware specifics. */ /* Hardwware specifics. */
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. */ /* Task function macros as described on the FreeRTOS.org WEB site. */
#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 )
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */