mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2026-01-16 23:00:34 -05:00
Re-sync with upstream and stripping away none kernel related.
This commit is contained in:
parent
9c0c37ab9b
commit
210b1ffcc8
13732 changed files with 49 additions and 7054697 deletions
82
portable/IAR/78K0R/ISR_Support.h
Normal file
82
portable/IAR/78K0R/ISR_Support.h
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
; Variables used by scheduler
|
||||
;------------------------------------------------------------------------------
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN usCriticalNesting
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; portSAVE_CONTEXT MACRO
|
||||
; 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
|
||||
|
||||
PUSH AX ; Save AX Register to stack.
|
||||
PUSH HL
|
||||
MOV A, CS ; Save CS register.
|
||||
XCH A, X
|
||||
MOV A, ES ; Save ES register.
|
||||
PUSH AX
|
||||
PUSH DE ; Save the remaining general purpose registers.
|
||||
PUSH BC
|
||||
MOVW AX, usCriticalNesting ; Save the usCriticalNesting value.
|
||||
PUSH AX
|
||||
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
|
||||
MOVW AX, pxCurrentTCB ; Restore the Stack pointer.
|
||||
MOVW HL, AX
|
||||
MOVW AX, [HL]
|
||||
MOVW SP, AX
|
||||
POP AX ; 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
|
||||
;------------------------------------------------------------------------------
|
||||
225
portable/IAR/78K0R/port.c
Normal file
225
portable/IAR/78K0R/port.c
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* The critical nesting value is initialised to a non zero value to ensure
|
||||
interrupts don't accidentally become enabled before the scheduler is started. */
|
||||
#define portINITIAL_CRITICAL_NESTING (( uint16_t ) 10)
|
||||
|
||||
/* Initial PSW value allocated to a newly created task.
|
||||
* 1100011000000000
|
||||
* ||||||||-------------- Fill byte
|
||||
* |||||||--------------- Carry Flag cleared
|
||||
* |||||----------------- In-service priority Flags set to low level
|
||||
* ||||------------------ Register bank Select 0 Flag cleared
|
||||
* |||------------------- Auxiliary Carry Flag cleared
|
||||
* ||-------------------- Register bank Select 1 Flag cleared
|
||||
* |--------------------- Zero Flag set
|
||||
* ---------------------- Global Interrupt Flag set (enabled)
|
||||
*/
|
||||
#define portPSW (0xc6UL)
|
||||
|
||||
/* We require the address of the pxCurrentTCB variable, but don't want to know
|
||||
any details of its type. */
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
|
||||
/* Most ports implement critical sections by placing the interrupt flags on
|
||||
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
|
||||
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
|
||||
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 -
|
||||
with interrupts only being re-enabled if the count is zero.
|
||||
|
||||
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
|
||||
sequence. */
|
||||
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Sets up the periodic ISR used for the RTOS tick.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint32_t *pulLocal;
|
||||
|
||||
#if configMEMORY_MODE == 1
|
||||
{
|
||||
/* Parameters are passed in on the stack, and written using a 32bit value
|
||||
hence a space is left for the second two bytes. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Write in the parameter value. */
|
||||
pulLocal = ( uint32_t * ) pxTopOfStack;
|
||||
*pulLocal = ( uint32_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* These values are just spacers. The return address of the function
|
||||
would normally be written here. */
|
||||
*pxTopOfStack = ( StackType_t ) 0xcdcd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xcdcd;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The start address / PSW value is also written in as a 32bit value,
|
||||
so leave a space for the second two bytes. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Task function start address combined with the PSW. */
|
||||
pulLocal = ( uint32_t * ) pxTopOfStack;
|
||||
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* An initial value for the AX register. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x1111;
|
||||
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--;
|
||||
|
||||
/* Task function start address combined with the PSW. */
|
||||
pulLocal = ( uint32_t * ) pxTopOfStack;
|
||||
*pulLocal = ( ( ( uint32_t ) pxCode ) | ( portPSW << 24UL ) );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The parameter is passed in AX. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* An initial value for the HL register. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x2222;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* CS and ES registers. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x0F00;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Finally the remaining general purpose registers DE and BC */
|
||||
*pxTopOfStack = ( StackType_t ) 0xDEDE;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xBCBC;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Finally the critical section nesting count is set to zero when the task
|
||||
first starts. */
|
||||
*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;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled when
|
||||
this function is called. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
vPortStart();
|
||||
|
||||
/* Should not get here as the tasks are now running! */
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the 78K0R port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Setup channel 5 of the TAU to generate the tick interrupt. */
|
||||
|
||||
/* First the Timer Array Unit has to be enabled. */
|
||||
TAU0EN = 1;
|
||||
|
||||
/* To configure the Timer Array Unit all Channels have to first be stopped. */
|
||||
TT0 = 0xff;
|
||||
|
||||
/* Interrupt of Timer Array Unit Channel 5 is disabled to set the interrupt
|
||||
priority. */
|
||||
TMMK05 = 1;
|
||||
|
||||
/* Clear Timer Array Unit Channel 5 interrupt flag. */
|
||||
TMIF05 = 0;
|
||||
|
||||
/* Set Timer Array Unit Channel 5 interrupt priority */
|
||||
TMPR005 = 0;
|
||||
TMPR105 = 0;
|
||||
|
||||
/* Set Timer Array Unit Channel 5 Mode as interval timer. */
|
||||
TMR05 = 0x0000;
|
||||
|
||||
/* Set the compare match value according to the tick rate we want. */
|
||||
TDR05 = ( TickType_t ) ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
|
||||
/* Set Timer Array Unit Channel 5 output mode */
|
||||
TOM0 &= ~0x0020;
|
||||
|
||||
/* Set Timer Array Unit Channel 5 output level */
|
||||
TOL0 &= ~0x0020;
|
||||
|
||||
/* Set Timer Array Unit Channel 5 output enable */
|
||||
TOE0 &= ~0x0020;
|
||||
|
||||
/* Interrupt of Timer Array Unit Channel 5 enabled */
|
||||
TMMK05 = 0;
|
||||
|
||||
/* Start Timer Array Unit Channel 5.*/
|
||||
TS0 |= 0x0020;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
138
portable/IAR/78K0R/portasm.s26
Normal file
138
portable/IAR/78K0R/portasm.s26
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
#include "ISR_Support.h"
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
#if __CORE__ != __78K0R__
|
||||
#error "This file is only for 78K0R Devices"
|
||||
#endif
|
||||
|
||||
#define CS 0xFFFFC
|
||||
#define ES 0xFFFFD
|
||||
|
||||
; Functions implemented in this file
|
||||
;------------------------------------------------------------------------------
|
||||
PUBLIC vPortYield
|
||||
PUBLIC vPortStart
|
||||
|
||||
; Functions used by scheduler
|
||||
;------------------------------------------------------------------------------
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN xTaskIncrementTick
|
||||
|
||||
; Tick ISR Prototype
|
||||
;------------------------------------------------------------------------------
|
||||
; EXTERN ?CL78K0R_V2_L00
|
||||
|
||||
PUBWEAK `??MD_INTTM05??INTVEC 68`
|
||||
PUBLIC MD_INTTM05
|
||||
|
||||
MD_INTTM05 SYMBOL "MD_INTTM05"
|
||||
`??MD_INTTM05??INTVEC 68` SYMBOL "??INTVEC 68", MD_INTTM05
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Yield to another task. Implemented as a software interrupt. The return
|
||||
; address and PSW will have been saved to the stack automatically before
|
||||
; this code runs.
|
||||
;
|
||||
; Input: NONE
|
||||
;
|
||||
; Call: CALL vPortYield
|
||||
;
|
||||
; Output: NONE
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
RSEG CODE:CODE
|
||||
vPortYield:
|
||||
portSAVE_CONTEXT ; Save the context of the current task.
|
||||
call vTaskSwitchContext ; Call the scheduler to select the next task.
|
||||
portRESTORE_CONTEXT ; Restore the context of the next task to run.
|
||||
retb
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Restore the context of the first task that is going to run.
|
||||
;
|
||||
; Input: NONE
|
||||
;
|
||||
; Call: CALL vPortStart
|
||||
;
|
||||
; Output: NONE
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
RSEG CODE:CODE
|
||||
vPortStart:
|
||||
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
|
||||
reti ; An interrupt stack frame is used so the task
|
||||
; is started using a RETI instruction.
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Perform the necessary steps of the Tick Count Increment and Task Switch
|
||||
; depending on the chosen kernel configuration
|
||||
;
|
||||
; Input: NONE
|
||||
;
|
||||
; Call: ISR
|
||||
;
|
||||
; Output: NONE
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
MD_INTTM05:
|
||||
|
||||
portSAVE_CONTEXT ; Save the context of the current task.
|
||||
call xTaskIncrementTick ; Call the timer tick function.
|
||||
#if configUSE_PREEMPTION == 1
|
||||
call vTaskSwitchContext ; Call the scheduler to select the next task.
|
||||
#endif
|
||||
portRESTORE_CONTEXT ; Restore the context of the next task to run.
|
||||
reti
|
||||
|
||||
|
||||
|
||||
; REQUIRE ?CL78K0R_V2_L00
|
||||
COMMON INTVEC:CODE:ROOT(1) ; Set ISR location to the Interrupt vector table.
|
||||
ORG 68
|
||||
`??MD_INTTM05??INTVEC 68`:
|
||||
DW MD_INTTM05
|
||||
|
||||
COMMON INTVEC:CODE:ROOT(1) ; Set ISR location to the Interrupt vector table.
|
||||
ORG 126
|
||||
`??vPortYield??INTVEC 126`:
|
||||
DW vPortYield
|
||||
|
||||
; Set value for the usCriticalNesting.
|
||||
RSEG NEAR_ID:CONST:SORT:NOROOT(1)
|
||||
`?<Initializer for usCriticalNesting>`:
|
||||
DW 10
|
||||
|
||||
;#endif
|
||||
|
||||
END
|
||||
145
portable/IAR/78K0R/portmacro.h
Normal file
145
portable/IAR/78K0R/portmacro.h
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE short
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
#if (configUSE_16_BIT_TICKS==1)
|
||||
typedef unsigned int TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros. */
|
||||
#define portDISABLE_INTERRUPTS() __asm ( "DI" )
|
||||
#define portENABLE_INTERRUPTS() __asm ( "EI" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section control macros. */
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
\
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed */ \
|
||||
/* directly. Increment ulCriticalNesting to keep a count of how many */ \
|
||||
/* times portENTER_CRITICAL() has been called. */ \
|
||||
usCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
/* Decrement the nesting count as we are leaving a critical section. */ \
|
||||
usCriticalNesting--; \
|
||||
\
|
||||
/* If the nesting level has reached zero then interrupts should be */ \
|
||||
/* re-enabled. */ \
|
||||
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
extern void vPortStart( void );
|
||||
#define portYIELD() __asm( "BRK" )
|
||||
#define portYIELD_FROM_ISR( xHigherPriorityTaskWoken ) if( xHigherPriorityTaskWoken ) vTaskSwitchContext()
|
||||
#define portNOP() __asm( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardwware specifics. */
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
|
||||
static __interrupt void P0_isr (void);
|
||||
|
||||
/* --------------------------------------------------------------------------*/
|
||||
/* Option-bytes and security ID */
|
||||
/* --------------------------------------------------------------------------*/
|
||||
#define OPT_BYTES_SIZE 4
|
||||
#define SECU_ID_SIZE 10
|
||||
#define WATCHDOG_DISABLED 0x00
|
||||
#define LVI_ENABLED 0xFE
|
||||
#define LVI_DISABLED 0xFF
|
||||
#define RESERVED_FF 0xFF
|
||||
#define OCD_DISABLED 0x04
|
||||
#define OCD_ENABLED 0x81
|
||||
#define OCD_ENABLED_ERASE 0x80
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
300
portable/IAR/ARM_CA5_No_GIC/port.c
Normal file
300
portable/IAR/ARM_CA5_No_GIC/port.c
Normal file
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* Check the configuration. */
|
||||
#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.
|
||||
#endif
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#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.
|
||||
#endif
|
||||
|
||||
#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.
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
/* 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
|
||||
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
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
|
||||
/* The value of the mode bits in the APSR when the CPU is executing in user
|
||||
mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Starts the first task executing. This function is necessarily written in
|
||||
* assembly code so is implemented in portASM.s.
|
||||
*/
|
||||
extern void vPortRestoreTaskContext( void );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
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
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/* 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. */
|
||||
uint32_t ulPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
uint32_t ulPortYieldRequired = pdFALSE;
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
uint32_t ulPortInterruptNesting = 0UL;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
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 task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* R14 */
|
||||
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
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
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 )
|
||||
{
|
||||
/* 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
|
||||
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( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR;
|
||||
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
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 )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
portENABLE_INTERRUPTS();
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
|
||||
/* 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). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
__asm( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
113
portable/IAR/ARM_CA5_No_GIC/portASM.h
Normal file
113
portable/IAR/ARM_CA5_No_GIC/portASM.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN ulCriticalNesting
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN ulPortTaskHasFPUContext
|
||||
EXTERN ulAsmAPIPriorityMask
|
||||
|
||||
portSAVE_CONTEXT macro
|
||||
|
||||
; 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
|
||||
CPS #SYS_MODE
|
||||
PUSH {R0-R12, R14}
|
||||
|
||||
; Push the critical nesting count
|
||||
LDR R2, =ulCriticalNesting
|
||||
LDR R1, [R2]
|
||||
PUSH {R1}
|
||||
|
||||
; Does the task have a floating point context that needs saving? If
|
||||
; ulPortTaskHasFPUContext is 0 then no.
|
||||
LDR R2, =ulPortTaskHasFPUContext
|
||||
LDR R3, [R2]
|
||||
CMP R3, #0
|
||||
|
||||
; Save the floating point context, if any
|
||||
FMRXNE R1, FPSCR
|
||||
VPUSHNE {D0-D15}
|
||||
#if configFPU_D32 == 1
|
||||
VPUSHNE {D16-D31}
|
||||
#endif ; configFPU_D32
|
||||
PUSHNE {R1}
|
||||
|
||||
; Save ulPortTaskHasFPUContext itself
|
||||
PUSH {R3}
|
||||
|
||||
; Save the stack pointer in the TCB
|
||||
LDR R0, =pxCurrentTCB
|
||||
LDR R1, [R0]
|
||||
STR SP, [R1]
|
||||
|
||||
endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
portRESTORE_CONTEXT macro
|
||||
|
||||
; Set the SP to point to the stack of the task being restored.
|
||||
LDR R0, =pxCurrentTCB
|
||||
LDR R1, [R0]
|
||||
LDR SP, [R1]
|
||||
|
||||
; Is there a floating point context to restore? If the restored
|
||||
; ulPortTaskHasFPUContext is zero then no.
|
||||
LDR R0, =ulPortTaskHasFPUContext
|
||||
POP {R1}
|
||||
STR R1, [R0]
|
||||
CMP R1, #0
|
||||
|
||||
; Restore the floating point context, if any
|
||||
POPNE {R0}
|
||||
#if configFPU_D32 == 1
|
||||
VPOPNE {D16-D31}
|
||||
#endif ; configFPU_D32
|
||||
VPOPNE {D0-D15}
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
176
portable/IAR/ARM_CA5_No_GIC/portASM.s
Normal file
176
portable/IAR/ARM_CA5_No_GIC/portASM.s
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
INCLUDE FreeRTOSConfig.h
|
||||
INCLUDE portmacro.h
|
||||
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN ulPortYieldRequired
|
||||
EXTERN ulPortInterruptNesting
|
||||
EXTERN vApplicationIRQHandler
|
||||
|
||||
PUBLIC FreeRTOS_SWI_Handler
|
||||
PUBLIC FreeRTOS_IRQ_Handler
|
||||
PUBLIC vPortRestoreTaskContext
|
||||
|
||||
SYS_MODE EQU 0x1f
|
||||
SVC_MODE EQU 0x13
|
||||
IRQ_MODE EQU 0x12
|
||||
|
||||
SECTION .text:CODE:ROOT(2)
|
||||
ARM
|
||||
|
||||
INCLUDE portASM.h
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; SVC handler is used to yield a task.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
FreeRTOS_SWI_Handler
|
||||
|
||||
PRESERVE8
|
||||
|
||||
; Save the context of the current task and select a new task to run.
|
||||
portSAVE_CONTEXT
|
||||
LDR R0, =vTaskSwitchContext
|
||||
BLX R0
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; vPortRestoreTaskContext is used to start the scheduler.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortRestoreTaskContext
|
||||
|
||||
PRESERVE8
|
||||
|
||||
; Switch to system mode
|
||||
CPS #SYS_MODE
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; IRQ interrupt handler used when individual priorities cannot be masked
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
FreeRTOS_IRQ_Handler
|
||||
|
||||
PRESERVE8
|
||||
|
||||
; Return to the interrupted instruction.
|
||||
SUB lr, lr, #4
|
||||
|
||||
; Push the return address and SPSR
|
||||
PUSH {lr}
|
||||
MRS lr, SPSR
|
||||
PUSH {lr}
|
||||
|
||||
; Change to supervisor mode to allow reentry.
|
||||
CPS #SVC_MODE
|
||||
|
||||
; Push used registers.
|
||||
PUSH {r0-r4, r12}
|
||||
|
||||
; Increment nesting count. r3 holds the address of ulPortInterruptNesting
|
||||
; for future use. r1 holds the original ulPortInterruptNesting value for
|
||||
; future use.
|
||||
LDR r3, =ulPortInterruptNesting
|
||||
LDR r1, [r3]
|
||||
ADD r4, r1, #1
|
||||
STR r4, [r3]
|
||||
|
||||
; Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
|
||||
; future use.
|
||||
MOV r2, sp
|
||||
AND r2, r2, #4
|
||||
SUB sp, sp, r2
|
||||
|
||||
PUSH {r0-r4, lr}
|
||||
|
||||
; Call the port part specific handler.
|
||||
LDR r0, =vApplicationIRQHandler
|
||||
BLX r0
|
||||
POP {r0-r4, lr}
|
||||
ADD sp, sp, r2
|
||||
|
||||
CPSID i
|
||||
|
||||
; Write to the EOI register.
|
||||
LDR r4, =configEOI_ADDRESS
|
||||
STR r0, [r4]
|
||||
|
||||
; Restore the old nesting count
|
||||
STR r1, [r3]
|
||||
|
||||
; A context switch is never performed if the nesting count is not 0.
|
||||
CMP r1, #0
|
||||
BNE exit_without_switch
|
||||
|
||||
; Did the interrupt request a context switch? r1 holds the address of
|
||||
; ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
|
||||
; use.
|
||||
LDR r1, =ulPortYieldRequired
|
||||
LDR r0, [r1]
|
||||
CMP r0, #0
|
||||
BNE switch_before_exit
|
||||
|
||||
exit_without_switch
|
||||
; No context switch. Restore used registers, LR_irq and SPSR before
|
||||
; returning.
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
MOVS PC, LR
|
||||
|
||||
switch_before_exit
|
||||
; A context switch is to be performed. Clear the context switch pending
|
||||
; flag.
|
||||
MOV r0, #0
|
||||
STR r0, [r1]
|
||||
|
||||
; Restore used registers, LR-irq and SPSR before saving the context
|
||||
; to the task stack.
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Call the function that selects the new task to execute.
|
||||
; vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
|
||||
; instructions, or 8 byte aligned stack allocated data. LR does not need
|
||||
; saving as a new LR will be loaded by portRESTORE_CONTEXT anyway.
|
||||
LDR r0, =vTaskSwitchContext
|
||||
BLX r0
|
||||
|
||||
; Restore the context of, and branch to, the task selected to execute next.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
END
|
||||
|
||||
|
||||
|
||||
|
||||
162
portable/IAR/ARM_CA5_No_GIC/portmacro.h
Normal file
162
portable/IAR/ARM_CA5_No_GIC/portmacro.h
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/* IAR includes. */
|
||||
#ifdef __ICCARM__
|
||||
|
||||
#include <intrinsics.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0" ); __ISB()
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() __disable_irq(); __DSB(); __ISB() /* No priority mask register so global disable is used. */
|
||||
#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 portCLEAR_INTERRUPT_MASK_FROM_ISR(x) __set_interrupt_state(x)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( 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
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_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 ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
/* 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 warnings. */
|
||||
#pragma diag_suppress=Pe191
|
||||
#pragma diag_suppress=Pa082
|
||||
|
||||
#endif /* __ICCARM__ */
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
439
portable/IAR/ARM_CA9/port.c
Normal file
439
portable/IAR/ARM_CA9/port.c
Normal file
|
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#ifndef configUNIQUE_INTERRUPT_PRIORITIES
|
||||
#error configUNIQUE_INTERRUPT_PRIORITIES must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined. See http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html
|
||||
#endif /* configSETUP_TICK_INTERRUPT */
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY == 0
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must not be set to 0
|
||||
#endif
|
||||
|
||||
#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
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* Check the configuration. */
|
||||
#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.
|
||||
#endif
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
/* In case security extensions are implemented. */
|
||||
#if configMAX_API_CALL_INTERRUPT_PRIORITY <= ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
|
||||
#endif
|
||||
|
||||
#ifndef configCLEAR_TICK_INTERRUPT
|
||||
#define configCLEAR_TICK_INTERRUPT()
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
/* In all GICs 255 can be written to the priority mask register to unmask all
|
||||
(but the lowest) interrupt priority. */
|
||||
#define portUNMASK_VALUE ( 0xFFUL )
|
||||
|
||||
/* 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
|
||||
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
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
|
||||
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
|
||||
point is zero. */
|
||||
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
|
||||
/* The value of the mode bits in the APSR when the CPU is executing in user
|
||||
mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
|
||||
/* Macro to unmask all interrupt priorities. */
|
||||
#define portCLEAR_INTERRUPT_MASK() \
|
||||
{ \
|
||||
__disable_irq(); \
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \
|
||||
__asm( "DSB \n" \
|
||||
"ISB \n" ); \
|
||||
__enable_irq(); \
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Starts the first task executing. This function is necessarily written in
|
||||
* assembly code so is implemented in portASM.s.
|
||||
*/
|
||||
extern void vPortRestoreTaskContext( void );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
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
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/* 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. */
|
||||
uint32_t ulPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
uint32_t ulPortYieldRequired = pdFALSE;
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
uint32_t ulPortInterruptNesting = 0UL;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
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 task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* R14 */
|
||||
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
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
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 )
|
||||
{
|
||||
/* 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
|
||||
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( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR;
|
||||
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
|
||||
if( 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( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
__enable_irq();
|
||||
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 )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts as per portDISABLE_INTERRUPTS(); */
|
||||
ulPortSetInterruptMask();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
/* Set interrupt mask before altering scheduler structures. The tick
|
||||
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. */
|
||||
__disable_irq();
|
||||
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
|
||||
__asm( "DSB \n"
|
||||
"ISB \n" );
|
||||
__enable_irq();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
/* Ensure all interrupt priorities are active again. */
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
|
||||
/* 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). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
__asm( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortClearInterruptMask( uint32_t ulNewMaskValue )
|
||||
{
|
||||
if( ulNewMaskValue == pdFALSE )
|
||||
{
|
||||
portCLEAR_INTERRUPT_MASK();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
uint32_t ulPortSetInterruptMask( void )
|
||||
{
|
||||
uint32_t ulReturn;
|
||||
|
||||
__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();
|
||||
|
||||
return ulReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
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
|
||||
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 */
|
||||
|
||||
|
||||
115
portable/IAR/ARM_CA9/portASM.h
Normal file
115
portable/IAR/ARM_CA9/portASM.h
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN ulCriticalNesting
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN ulPortTaskHasFPUContext
|
||||
EXTERN ulAsmAPIPriorityMask
|
||||
|
||||
portSAVE_CONTEXT macro
|
||||
|
||||
; 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
|
||||
CPS #SYS_MODE
|
||||
PUSH {R0-R12, R14}
|
||||
|
||||
; Push the critical nesting count
|
||||
LDR R2, =ulCriticalNesting
|
||||
LDR R1, [R2]
|
||||
PUSH {R1}
|
||||
|
||||
; Does the task have a floating point context that needs saving? If
|
||||
; ulPortTaskHasFPUContext is 0 then no.
|
||||
LDR R2, =ulPortTaskHasFPUContext
|
||||
LDR R3, [R2]
|
||||
CMP R3, #0
|
||||
|
||||
; Save the floating point context, if any
|
||||
FMRXNE R1, FPSCR
|
||||
VPUSHNE {D0-D15}
|
||||
VPUSHNE {D16-D31}
|
||||
PUSHNE {R1}
|
||||
|
||||
; Save ulPortTaskHasFPUContext itself
|
||||
PUSH {R3}
|
||||
|
||||
; Save the stack pointer in the TCB
|
||||
LDR R0, =pxCurrentTCB
|
||||
LDR R1, [R0]
|
||||
STR SP, [R1]
|
||||
|
||||
endm
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
portRESTORE_CONTEXT macro
|
||||
|
||||
; Set the SP to point to the stack of the task being restored.
|
||||
LDR R0, =pxCurrentTCB
|
||||
LDR R1, [R0]
|
||||
LDR SP, [R1]
|
||||
|
||||
; Is there a floating point context to restore? If the restored
|
||||
; ulPortTaskHasFPUContext is zero then no.
|
||||
LDR R0, =ulPortTaskHasFPUContext
|
||||
POP {R1}
|
||||
STR R1, [R0]
|
||||
CMP R1, #0
|
||||
|
||||
; Restore the floating point context, if any
|
||||
POPNE {R0}
|
||||
VPOPNE {D16-D31}
|
||||
VPOPNE {D0-D15}
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
177
portable/IAR/ARM_CA9/portASM.s
Normal file
177
portable/IAR/ARM_CA9/portASM.s
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
INCLUDE FreeRTOSConfig.h
|
||||
INCLUDE portmacro.h
|
||||
|
||||
EXTERN vApplicationIRQHandler
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN ulPortYieldRequired
|
||||
EXTERN ulPortInterruptNesting
|
||||
|
||||
PUBLIC FreeRTOS_SWI_Handler
|
||||
PUBLIC FreeRTOS_IRQ_Handler
|
||||
PUBLIC vPortRestoreTaskContext
|
||||
|
||||
SYS_MODE EQU 0x1f
|
||||
SVC_MODE EQU 0x13
|
||||
IRQ_MODE EQU 0x12
|
||||
|
||||
|
||||
SECTION .text:CODE:ROOT(2)
|
||||
ARM
|
||||
|
||||
INCLUDE portASM.h
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; SVC handler is used to yield a task.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
FreeRTOS_SWI_Handler
|
||||
|
||||
PRESERVE8
|
||||
|
||||
; Save the context of the current task and select a new task to run.
|
||||
portSAVE_CONTEXT
|
||||
LDR R0, =vTaskSwitchContext
|
||||
BLX R0
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; vPortRestoreTaskContext is used to start the scheduler.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortRestoreTaskContext
|
||||
; Switch to system mode
|
||||
CPS #SYS_MODE
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; PL390 GIC interrupt handler
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
FreeRTOS_IRQ_Handler
|
||||
|
||||
; Return to the interrupted instruction.
|
||||
SUB lr, lr, #4
|
||||
|
||||
; Push the return address and SPSR
|
||||
PUSH {lr}
|
||||
MRS lr, SPSR
|
||||
PUSH {lr}
|
||||
|
||||
; Change to supervisor mode to allow reentry.
|
||||
CPS #SVC_MODE
|
||||
|
||||
; Push used registers.
|
||||
PUSH {r0-r4, r12}
|
||||
|
||||
; Increment nesting count. r3 holds the address of ulPortInterruptNesting
|
||||
; for future use. r1 holds the original ulPortInterruptNesting value for
|
||||
; future use.
|
||||
LDR r3, =ulPortInterruptNesting
|
||||
LDR r1, [r3]
|
||||
ADD r4, r1, #1
|
||||
STR r4, [r3]
|
||||
|
||||
; Read value from the interrupt acknowledge register, which is stored in r0
|
||||
; for future parameter and interrupt clearing use.
|
||||
LDR r2, =portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS
|
||||
LDR r0, [r2]
|
||||
|
||||
; Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
|
||||
; future use. _RB_ Is this ever necessary if start of stack is 8-byte aligned?
|
||||
MOV r2, sp
|
||||
AND r2, r2, #4
|
||||
SUB sp, sp, r2
|
||||
|
||||
; Call the interrupt handler. r4 is pushed to maintain alignment.
|
||||
PUSH {r0-r4, lr}
|
||||
LDR r1, =vApplicationIRQHandler
|
||||
BLX r1
|
||||
POP {r0-r4, lr}
|
||||
ADD sp, sp, r2
|
||||
|
||||
CPSID i
|
||||
|
||||
; Write the value read from ICCIAR to ICCEOIR
|
||||
LDR r4, =portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS
|
||||
STR r0, [r4]
|
||||
|
||||
; Restore the old nesting count
|
||||
STR r1, [r3]
|
||||
|
||||
; A context switch is never performed if the nesting count is not 0
|
||||
CMP r1, #0
|
||||
BNE exit_without_switch
|
||||
|
||||
; Did the interrupt request a context switch? r1 holds the address of
|
||||
; ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
|
||||
; use.
|
||||
LDR r1, =ulPortYieldRequired
|
||||
LDR r0, [r1]
|
||||
CMP r0, #0
|
||||
BNE switch_before_exit
|
||||
|
||||
exit_without_switch
|
||||
; No context switch. Restore used registers, LR_irq and SPSR before
|
||||
; returning.
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
MOVS PC, LR
|
||||
|
||||
switch_before_exit
|
||||
; A context switch is to be performed. Clear the context switch pending
|
||||
; flag.
|
||||
MOV r0, #0
|
||||
STR r0, [r1]
|
||||
|
||||
; Restore used registers, LR-irq and SPSR before saving the context
|
||||
; to the task stack.
|
||||
POP {r0-r4, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
portSAVE_CONTEXT
|
||||
|
||||
; Call the function that selects the new task to execute.
|
||||
; vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
|
||||
; instructions, or 8 byte aligned stack allocated data. LR does not need
|
||||
; saving as a new LR will be loaded by portRESTORE_CONTEXT anyway.
|
||||
LDR r0, =vTaskSwitchContext
|
||||
BLX r0
|
||||
|
||||
; Restore the context of, and branch to, the task selected to execute next.
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
END
|
||||
|
||||
|
||||
|
||||
|
||||
209
portable/IAR/ARM_CA9/portmacro.h
Normal file
209
portable/IAR/ARM_CA9/portmacro.h
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/* IAR includes. */
|
||||
#ifdef __ICCARM__
|
||||
|
||||
#include <intrinsics.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm( "SWI 0" );
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
|
||||
/* These macros do not globally disable/enable interrupts. They do mask off
|
||||
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortClearInterruptMask(x)
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( 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
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_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 ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif /* configASSERT */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
/* 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 warnings. */
|
||||
#pragma diag_suppress=Pe191
|
||||
#pragma diag_suppress=Pa082
|
||||
|
||||
#endif /* __ICCARM__ */
|
||||
|
||||
|
||||
/* The number of bits to shift for an interrupt priority is dependent on the
|
||||
number of bits implemented by the interrupt controller. */
|
||||
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
|
||||
#define portPRIORITY_SHIFT 4
|
||||
#define portMAX_BINARY_POINT_VALUE 3
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32
|
||||
#define portPRIORITY_SHIFT 3
|
||||
#define portMAX_BINARY_POINT_VALUE 2
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64
|
||||
#define portPRIORITY_SHIFT 2
|
||||
#define portMAX_BINARY_POINT_VALUE 1
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128
|
||||
#define portPRIORITY_SHIFT 1
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
|
||||
#define portPRIORITY_SHIFT 0
|
||||
#define portMAX_BINARY_POINT_VALUE 0
|
||||
#else
|
||||
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
|
||||
#endif
|
||||
|
||||
/* Interrupt controller access addresses. */
|
||||
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
|
||||
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
|
||||
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
|
||||
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
|
||||
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
|
||||
|
||||
#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 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 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 portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
424
portable/IAR/ARM_CM0/port.c
Normal file
424
portable/IAR/ARM_CM0/port.c
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM0 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include "intrinsics.h"
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to manipulate the NVIC. */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t *) 0xe000ed20 ) )
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
|
||||
defined. The value 255 should also ensure backward compatibility.
|
||||
FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
|
||||
#ifndef configKERNEL_INTERRUPT_PRIORITY
|
||||
#define configKERNEL_INTERRUPT_PRIORITY 0
|
||||
#endif
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/* The systick is a 24-bit counter. */
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
|
||||
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||
occurred while the SysTick counter is stopped during tickless idle
|
||||
calculations. */
|
||||
#ifndef portMISSED_COUNTS_FACTOR
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
#endif
|
||||
|
||||
/* The number of SysTick increments that make up one tick period. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulTimerCountsForOneTick = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* The maximum number of tick periods that can be suppressed is limited by the
|
||||
24 bit resolution of the SysTick timer. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||
power functionality only. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulStoppedTimerCompensation = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
#pragma weak vPortSetupTimerInterrupt
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortSysTickHandler( void );
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 8; /* R11..R4. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* 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
|
||||
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( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void )
|
||||
{
|
||||
/* Set a PendSV to request a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is completely
|
||||
within the specified behaviour for the architecture. */
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
uint32_t ulPreviousMask;
|
||||
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR;
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Stop and reset the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
|
||||
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||
TickType_t xModifiableIdleTime;
|
||||
|
||||
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
|
||||
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||
is accounted for as best it can be, but using the tickless mode will
|
||||
inevitably result in some tiny drift of the time maintained by the
|
||||
kernel with respect to calendar time. */
|
||||
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||
tick periods. -1 is used because this code will execute part way
|
||||
through one of the tick periods. */
|
||||
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
ulReloadValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||
method as that will mask interrupts that should exit sleep mode. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* If a context switch is pending or a task is waiting for the scheduler
|
||||
to be unsuspended then abandon the low power entry. */
|
||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||
{
|
||||
/* Restart from whatever is left in the count register to complete
|
||||
this tick period. */
|
||||
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Reset the reload register to the value required for normal tick
|
||||
periods. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||
call above. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new reload value. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||
|
||||
/* Clear the SysTick count flag and set the count value back to
|
||||
zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||
set its parameter to 0 to indicate that its implementation contains
|
||||
its own wait for interrupt or wait for event instruction, and so wfi
|
||||
should not be executed again. However, the original expected idle
|
||||
time variable must remain unmodified, so a copy is taken. */
|
||||
xModifiableIdleTime = xExpectedIdleTime;
|
||||
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
}
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||
out of sleep mode to execute immediately. see comments above
|
||||
__disable_interrupt() call above. */
|
||||
__enable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable interrupts again because the clock is about to be stopped
|
||||
and interrupts that execute while the clock is stopped will increase
|
||||
any slippage between the time maintained by the RTOS and calendar
|
||||
time. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable the SysTick clock without reading the
|
||||
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
|
||||
the time the SysTick is stopped for is accounted for as best it can
|
||||
be, but using the tickless mode will inevitably result in some tiny
|
||||
drift of the time maintained by the kernel with respect to calendar
|
||||
time*/
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||
|
||||
/* Determine if the SysTick clock has already counted to zero and
|
||||
been set back to the current reload value (the reload back being
|
||||
correct for the entire expected idle time) or if the SysTick is yet
|
||||
to count to zero (in which case an interrupt other than the SysTick
|
||||
must have brought the system out of sleep mode). */
|
||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
|
||||
/* The tick interrupt is already pending, and the SysTick count
|
||||
reloaded with ulReloadValue. Reset the
|
||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||
period. */
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||
|
||||
/* Don't allow a tiny value, or values that have somehow
|
||||
underflowed because the post sleep hook did something
|
||||
that took too long. */
|
||||
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||
{
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||
}
|
||||
|
||||
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||
|
||||
/* 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 waiting. */
|
||||
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something other than the tick interrupt ended the sleep.
|
||||
Work out how long the sleep lasted rounded to complete tick
|
||||
periods (not the ulReload value which accounted for part
|
||||
ticks). */
|
||||
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG ;
|
||||
|
||||
/* How many complete tick periods passed while the processor
|
||||
was waiting? */
|
||||
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||
|
||||
/* The reload value is set to whatever fraction of a single tick
|
||||
period remains. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||
}
|
||||
|
||||
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||
value. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Exit with interrpts enabled. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
131
portable/IAR/ARM_CM0/portasm.s
Normal file
131
portable/IAR/ARM_CM0/portasm.s
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#include <FreeRTOSConfig.h>
|
||||
|
||||
RSEG CODE:CODE(2)
|
||||
thumb
|
||||
|
||||
EXTERN vPortYieldFromISR
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
|
||||
PUBLIC vSetMSP
|
||||
PUBLIC xPortPendSVHandler
|
||||
PUBLIC vPortSVCHandler
|
||||
PUBLIC vPortStartFirstTask
|
||||
PUBLIC ulSetInterruptMaskFromISR
|
||||
PUBLIC vClearInterruptMaskFromISR
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vSetMSP
|
||||
msr msp, r0
|
||||
bx lr
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xPortPendSVHandler:
|
||||
mrs r0, psp
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
|
||||
ldr r2, [r3]
|
||||
|
||||
subs r0, r0, #32 /* Make space for the remaining low registers. */
|
||||
str r0, [r2] /* Save the new top of stack. */
|
||||
stmia r0!, {r4-r7} /* Store the low registers that are not saved automatically. */
|
||||
mov r4, r8 /* Store the high registers. */
|
||||
mov r5, r9
|
||||
mov r6, r10
|
||||
mov r7, r11
|
||||
stmia r0!, {r4-r7}
|
||||
|
||||
push {r3, r14}
|
||||
cpsid i
|
||||
bl vTaskSwitchContext
|
||||
cpsie i
|
||||
pop {r2, r3} /* lr goes in r3. r2 now holds tcb pointer. */
|
||||
|
||||
ldr r1, [r2]
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
adds r0, r0, #16 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Pop the high registers. */
|
||||
mov r8, r4
|
||||
mov r9, r5
|
||||
mov r10, r6
|
||||
mov r11, r7
|
||||
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
|
||||
subs r0, r0, #32 /* Go back for the low registers that are not automatically restored. */
|
||||
ldmia r0!, {r4-r7} /* Pop low registers. */
|
||||
|
||||
bx r3
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortSVCHandler;
|
||||
/* This function is no longer used, but retained for backward
|
||||
compatibility. */
|
||||
bx lr
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortStartFirstTask
|
||||
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
|
||||
table offset register that can be used to locate the initial stack value.
|
||||
Not all M0 parts have the application vector table at address 0. */
|
||||
|
||||
ldr r3, =pxCurrentTCB /* Obtain location of pxCurrentTCB. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
movs r0, #2 /* Switch to the psp stack. */
|
||||
msr CONTROL, r0
|
||||
isb
|
||||
pop {r0-r5} /* Pop the registers that are saved automatically. */
|
||||
mov lr, r5 /* lr is now in r5. */
|
||||
pop {r3} /* The return address is now in r3. */
|
||||
pop {r2} /* Pop and discard the XPSR. */
|
||||
cpsie i /* The first task has its context and interrupts can be enabled. */
|
||||
bx r3 /* Jump to the user defined task code. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMaskFromISR
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMaskFromISR
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
|
||||
END
|
||||
129
portable/IAR/ARM_CM0/portmacro.h
Normal file
129
portable/IAR/ARM_CM0/portmacro.h
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
extern void vPortYield( void );
|
||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 )
|
||||
#define portNVIC_PENDSVSET 0x10000000
|
||||
#define portYIELD() vPortYield()
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) *(portNVIC_INT_CTRL) = portNVIC_PENDSVSET
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulSetInterruptMaskFromISR( void );
|
||||
extern void vClearInterruptMaskFromISR( uint32_t ulMask );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile( "cpsid i" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile( "cpsie i" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#define portNOP()
|
||||
|
||||
/* 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
|
||||
warnings. */
|
||||
#pragma diag_suppress=Pa082
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
933
portable/IAR/ARM_CM23/non_secure/port.c
Normal file
933
portable/IAR/ARM_CM23/non_secure/port.c
Normal file
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/* Secure components includes. */
|
||||
#include "secure_context.h"
|
||||
#include "secure_init.h"
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/**
|
||||
* The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
|
||||
* i.e. the processor boots as secure and never jumps to the non-secure side.
|
||||
* The Trust Zone support in the port must be disabled in order to run FreeRTOS
|
||||
* on the secure side. The following are the valid configuration seetings:
|
||||
*
|
||||
* 1. Run FreeRTOS on the Secure Side:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
|
||||
*
|
||||
* 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
|
||||
*
|
||||
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
|
||||
*/
|
||||
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
|
||||
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the NVIC.
|
||||
*/
|
||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
|
||||
#define portCPACR_CP10_VALUE ( 3UL )
|
||||
#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE
|
||||
#define portCPACR_CP10_POS ( 20UL )
|
||||
#define portCPACR_CP11_POS ( 22UL )
|
||||
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define portFPCCR_ASPEN_POS ( 31UL )
|
||||
#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS )
|
||||
#define portFPCCR_LSPEN_POS ( 30UL )
|
||||
#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the MPU.
|
||||
*/
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) )
|
||||
|
||||
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) )
|
||||
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) )
|
||||
|
||||
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) )
|
||||
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) )
|
||||
|
||||
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) )
|
||||
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) )
|
||||
|
||||
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) )
|
||||
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) )
|
||||
|
||||
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) )
|
||||
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) )
|
||||
|
||||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR1_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR2_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR3_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR4_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR5_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR6_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR7_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
|
||||
|
||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||
|
||||
/* Enable privileged access to unmapped region. */
|
||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
|
||||
/* Enable MPU. */
|
||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
||||
|
||||
/* Expected value of the portMPU_TYPE register. */
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to set up the initial stack.
|
||||
*/
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
#if( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF FD
|
||||
* 1111 1111 1111 1111 1111 1111 1111 1101
|
||||
*
|
||||
* Bit[6] - 1 --> The exception was taken from the Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 1 --> The exception was taken to the Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
#else
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF BC
|
||||
* 1111 1111 1111 1111 1111 1111 1011 1100
|
||||
*
|
||||
* Bit[6] - 0 --> The exception was taken from the Non-Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 0 --> The exception was taken to the Non-Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xffffffbc )
|
||||
#endif /* configRUN_FREERTOS_SECURE_ONLY */
|
||||
|
||||
/**
|
||||
* @brief CONTROL register privileged bit mask.
|
||||
*
|
||||
* Bit[0] in CONTROL register tells the privilege:
|
||||
* Bit[0] = 0 ==> The task is privileged.
|
||||
* Bit[0] = 1 ==> The task is not privileged.
|
||||
*/
|
||||
#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL )
|
||||
|
||||
/**
|
||||
* @brief Initial CONTROL register values.
|
||||
*/
|
||||
#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 )
|
||||
#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 )
|
||||
|
||||
/**
|
||||
* @brief 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 debugger.
|
||||
*/
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief If portPRELOAD_REGISTERS then registers will be given an initial value
|
||||
* when a task is created. This helps in debugging at the cost of code size.
|
||||
*/
|
||||
#define portPRELOAD_REGISTERS 1
|
||||
|
||||
/**
|
||||
* @brief A task is created without a secure context, and must call
|
||||
* portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
|
||||
* any secure calls.
|
||||
*/
|
||||
#define portNO_SECURE_CONTEXT 0
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Used to catch tasks that attempt to return from their implementing
|
||||
* function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Memory Protection Unit (MPU).
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Floating Point Unit (FPU).
|
||||
*/
|
||||
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/**
|
||||
* @brief Setup the timer to generate the tick interrupts.
|
||||
*
|
||||
* The implementation in this file is weak to allow application writers to
|
||||
* change the timer used to generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether the current execution context is interrupt.
|
||||
*
|
||||
* @return pdTRUE if the current execution context is interrupt, pdFALSE
|
||||
* otherwise.
|
||||
*/
|
||||
BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
/**
|
||||
* @brief Yield the processor.
|
||||
*/
|
||||
void vPortYield( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enter critical section.
|
||||
*/
|
||||
void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Exit from critical section.
|
||||
*/
|
||||
void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SysTick handler.
|
||||
*/
|
||||
void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief C part of SVC handler.
|
||||
*/
|
||||
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Each task maintains its own interrupt status in the critical nesting
|
||||
* variable.
|
||||
*/
|
||||
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Saved as part of the task context to indicate which context the
|
||||
* task is using on the secure side.
|
||||
*/
|
||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Stop and reset the SysTick. */
|
||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
volatile uint32_t ulDummy = 0UL;
|
||||
|
||||
/* 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
|
||||
* 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( ulCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
while( ulDummy == 0 )
|
||||
{
|
||||
/* This file calls prvTaskExitError() after the scheduler has been
|
||||
* started to remove a compiler warning about the function being
|
||||
* defined but never called. ulDummy is used purely to quieten other
|
||||
* warnings about code appearing after this function is called - making
|
||||
* ulDummy volatile makes the compiler think the function could return
|
||||
* and therefore not output an 'unreachable code' warning for code that
|
||||
* appears after it. */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __privileged_functions_start__;
|
||||
extern uint32_t * __privileged_functions_end__;
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
extern uint32_t * __unprivileged_flash_start__;
|
||||
extern uint32_t * __unprivileged_flash_end__;
|
||||
extern uint32_t * __privileged_sram_start__;
|
||||
extern uint32_t * __privileged_sram_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __privileged_functions_start__[];
|
||||
extern uint32_t __privileged_functions_end__[];
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
extern uint32_t __unprivileged_flash_start__[];
|
||||
extern uint32_t __unprivileged_flash_end__[];
|
||||
extern uint32_t __privileged_sram_start__[];
|
||||
extern uint32_t __privileged_sram_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
|
||||
/* Check that the MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* MAIR0 - Index 0. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
/* MAIR0 - Index 1. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* Setup privileged flash as Read Only so that privileged tasks can
|
||||
* read it but not modify. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged flash as Read Only by both privileged and
|
||||
* unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged syscalls flash as Read Only by both privileged
|
||||
* and unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup RAM containing kernel data for privileged access only. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Enable mem fault. */
|
||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable MPU with privileged background access i.e. unmapped
|
||||
* regions have privileged access. */
|
||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* Enable non-secure access to the FPU. */
|
||||
SecureInit_EnableNSFPUAccess();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/* CP10 = 11 ==> Full access to FPU i.e. both privileged and
|
||||
* unprivileged code should be able to access FPU. CP11 should be
|
||||
* programmed to the same value as CP10. */
|
||||
*( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
|
||||
( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
|
||||
);
|
||||
|
||||
/* ASPEN = 1 ==> Hardware should automatically preserve floating point
|
||||
* context on exception entry and restore on exception return.
|
||||
* LSPEN = 1 ==> Enable lazy context save of FP state. */
|
||||
*( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Set a PendSV to request a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
configASSERT( ulCriticalNesting );
|
||||
ulCriticalNesting--;
|
||||
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulPreviousMask;
|
||||
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
|
||||
{
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
uint32_t ulPC;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
uint32_t ulR0;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t ulControl, ulIsTaskPrivileged;
|
||||
#endif /* configENABLE_MPU */
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
uint8_t ucSVCNumber;
|
||||
|
||||
/* Register are stored on the stack in the following order - R0, R1, R2, R3,
|
||||
* R12, LR, PC, xPSR. */
|
||||
ulPC = pulCallerStackAddress[ 6 ];
|
||||
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ];
|
||||
|
||||
switch( ucSVCNumber )
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
case portSVC_ALLOCATE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the stack size passed as parameter to the
|
||||
* vPortAllocateSecureContext function. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Read the CONTROL register value. */
|
||||
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
|
||||
|
||||
/* The task that raised the SVC is privileged if Bit[0]
|
||||
* in the CONTROL register is 0. */
|
||||
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
|
||||
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0 );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
configASSERT( xSecureContext != NULL );
|
||||
SecureContext_LoadContext( xSecureContext );
|
||||
}
|
||||
break;
|
||||
|
||||
case portSVC_FREE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the secure context handle to be freed. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
/* Free the secure context. */
|
||||
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
case portSVC_START_SCHEDULER:
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* De-prioritize the non-secure exceptions so that the
|
||||
* non-secure pendSV runs at the lowest priority. */
|
||||
SecureInit_DePrioritizeNSExceptions();
|
||||
|
||||
/* Initialize the secure context management system. */
|
||||
SecureContext_Init();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
{
|
||||
/* Setup the Floating Point Unit (FPU). */
|
||||
prvSetupFPU();
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/* Setup the context of the first task so that the first task starts
|
||||
* executing. */
|
||||
vRestoreContextOfFirstTask();
|
||||
}
|
||||
break;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
case portSVC_RAISE_PRIVILEGE:
|
||||
{
|
||||
/* Only raise the privilege, if the svc was raised from any of
|
||||
* the system calls. */
|
||||
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||
{
|
||||
vRaisePrivilege();
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
default:
|
||||
{
|
||||
/* Incorrect SVC call. */
|
||||
configASSERT( pdFALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
|
||||
#else
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
#if( portPRELOAD_REGISTERS == 0 )
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#else /* portPRELOAD_REGISTERS */
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#endif /* portPRELOAD_REGISTERS */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Setup the Memory Protection Unit (MPU). */
|
||||
prvSetupMPU();
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialize the critical nesting count ready for the first task. */
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing. Call the task
|
||||
* exit error function to prevent compiler warnings about a static function
|
||||
* not being called in the case that the application writer overrides this
|
||||
* functionality by defining configTASK_RETURN_ADDRESS. Call
|
||||
* vTaskSwitchContext() so link time optimization does not remove the
|
||||
* symbol. */
|
||||
vTaskSwitchContext();
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
|
||||
int32_t lIndex = 0;
|
||||
|
||||
/* Setup MAIR0. */
|
||||
xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* This function is called automatically when the task is created - in
|
||||
* which case the stack region parameters will be valid. At all other
|
||||
* times the stack parameters will not be valid and it is assumed that
|
||||
* the stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) pxBottomOfStack ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
}
|
||||
|
||||
/* User supplied configurable regions. */
|
||||
for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
|
||||
{
|
||||
/* If xRegions is NULL i.e. the task has not specified any MPU
|
||||
* region, the else part ensures that all the configurable MPU
|
||||
* regions are invalidated. */
|
||||
if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
|
||||
{
|
||||
/* Translate the generic region definition contained in xRegions
|
||||
* into the ARMv8 specific MPU settings that are then stored in
|
||||
* xMPUSettings. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
/* Start address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE );
|
||||
|
||||
/* RO/RW. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
|
||||
}
|
||||
else
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
|
||||
}
|
||||
|
||||
/* XN. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
|
||||
}
|
||||
|
||||
/* End Address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Normal memory/ Device memory. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as device memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as normal memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. Interrupt Program
|
||||
* Status Register (IPSR) holds the exception number of the currently-executing
|
||||
* exception or zero for Thread mode.*/
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
113
portable/IAR/ARM_CM23/non_secure/portasm.h
Normal file
113
portable/IAR/ARM_CM23/non_secure/portasm.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
377
portable/IAR/ARM_CM23/non_secure/portasm.s
Normal file
377
portable/IAR/ARM_CM23/non_secure/portasm.s
Normal file
|
|
@ -0,0 +1,377 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xSecureContext
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
EXTERN SecureContext_SaveContext
|
||||
EXTERN SecureContext_LoadContext
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vPortAllocateSecureContext
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
PUBLIC vPortFreeSecureContext
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
running_privileged:
|
||||
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
orrs r0, r1 /* r0 = r0 | r1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortAllocateSecureContext:
|
||||
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
movs r5, #4 /* r5 = 4. */
|
||||
str r5, [r2] /* Program RNR = 4. */
|
||||
ldmia r3!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r5, #5 /* r5 = 5. */
|
||||
str r5, [r2] /* Program RNR = 5. */
|
||||
ldmia r3!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r5, #6 /* r5 = 6. */
|
||||
str r5, [r2] /* Program RNR = 6. */
|
||||
ldmia r3!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r5, #7 /* r5 = 7. */
|
||||
str r5, [r2] /* Program RNR = 7. */
|
||||
ldmia r3!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
ldr r5, =xSecureContext
|
||||
str r1, [r5] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
msr control, r3 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r4 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
ldr r4, =xSecureContext
|
||||
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
bics r0, r1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r1, psp /* Read PSP in r1. */
|
||||
ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r2] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
|
||||
cbz r0, save_ns_context /* No secure context to save. */
|
||||
push {r0-r2, r14}
|
||||
bl SecureContext_SaveContext
|
||||
pop {r0-r3} /* LR is now in r3. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r2, r3, #25 /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl save_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r1, r1, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
stmia r1!, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r1, r1, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r1!, {r0, r2-r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
b select_next_task
|
||||
|
||||
save_ns_context:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r1, r1, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
adds r1, r1, #16 /* r1 = r1 + 16. */
|
||||
stmia r1!, {r4-r7} /* Store the low registers that are not saved automatically. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r1!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
subs r1, r1, #48 /* r1 = r1 - 48. */
|
||||
stmia r1!, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r1, r1, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r1!, {r0, r2-r7} /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r1!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
select_next_task:
|
||||
cpsid i
|
||||
bl vTaskSwitchContext
|
||||
cpsie i
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r1, [r3] /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
bics r4, r5 /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
movs r5, #4 /* r5 = 4. */
|
||||
str r5, [r2] /* Program RNR = 4. */
|
||||
ldmia r3!, {r6,r7} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r5, #5 /* r5 = 5. */
|
||||
str r5, [r2] /* Program RNR = 5. */
|
||||
ldmia r3!, {r6,r7} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r5, #6 /* r5 = 6. */
|
||||
str r5, [r2] /* Program RNR = 6. */
|
||||
ldmia r3!, {r6,r7} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r5, #7 /* r5 = 7. */
|
||||
str r5, [r2] /* Program RNR = 7. */
|
||||
ldmia r3!, {r6,r7} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r4, =0xe000ed9c /* r4 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r4!, {r6,r7} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r5, #1 /* r5 = 1. */
|
||||
orrs r4, r5 /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r0, r2-r4} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r3 /* Restore the CONTROL register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r2] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
push {r1,r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. */
|
||||
pop {r1,r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r2, r4, #25 /* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r1 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r1!, {r0, r2-r3} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r2] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
push {r1,r3}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. */
|
||||
pop {r1,r3}
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r2, r3, #25 /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r1 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
restore_ns_context:
|
||||
adds r1, r1, #16 /* Move to the high registers. */
|
||||
ldmia r1!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r1 /* Remember the new top of stack for the task. */
|
||||
subs r1, r1, #32 /* Go back to the low registers. */
|
||||
ldmia r1!, {r4-r7} /* Restore the low registers that are not automatically restored. */
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
movs r0, #4
|
||||
mov r1, lr
|
||||
tst r0, r1
|
||||
beq stacking_used_msp
|
||||
mrs r0, psp
|
||||
b vPortSVCHandler_C
|
||||
stacking_used_msp:
|
||||
mrs r0, msp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortFreeSecureContext:
|
||||
ldr r1, [r0] /* The first item in the TCB is the top of the stack. */
|
||||
ldr r0, [r1] /* The first item on the stack is the task's xSecureContext. */
|
||||
cmp r0, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||
beq free_secure_context
|
||||
bx lr /* There is no secure context (xSecureContext is NULL). */
|
||||
free_secure_context:
|
||||
svc 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
308
portable/IAR/ARM_CM23/non_secure/portmacro.h
Normal file
308
portable/IAR/ARM_CM23/non_secure/portmacro.h
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
204
portable/IAR/ARM_CM23/secure/secure_context.c
Normal file
204
portable/IAR/ARM_CM23/secure/secure_context.c
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for privileged tasks.
|
||||
*
|
||||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
*
|
||||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to represent secure context.
|
||||
*
|
||||
* @note Since stack grows down, pucStackStart is the highest address while
|
||||
* pucStackLimit is the first addess of the allocated memory.
|
||||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t *pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t *pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t *pucStackStart; /**< First location of the stack memory. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged.. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t *pucStackMemory = NULL;
|
||||
uint32_t ulIPSR;
|
||||
SecureContextHandle_t xSecureContextHandle = NULL;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t *pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Allocate the context structure. */
|
||||
xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
|
||||
|
||||
if( xSecureContextHandle != NULL )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte because the hardware decrements the stack
|
||||
* pointer before writing i.e. if stack pointer is 0x2, a push
|
||||
* operation will decrement the stack pointer to 0x1 and then
|
||||
* write at 0x1. */
|
||||
xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContextHandle->pucStackLimit = pucStackMemory;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
|
||||
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the context to avoid memory leak and make sure to return
|
||||
* NULL to indicate failure. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
xSecureContextHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Ensure that valid parameters are passed. */
|
||||
secureportASSERT( xSecureContextHandle != NULL );
|
||||
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContextHandle->pucStackLimit );
|
||||
|
||||
/* Free the context itself. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
111
portable/IAR/ARM_CM23/secure/secure_context.h
Normal file
111
portable/IAR/ARM_CM23/secure/secure_context.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_CONTEXT_H__
|
||||
#define __SECURE_CONTEXT_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/**
|
||||
* @brief PSP value when no task's context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Opaque handle.
|
||||
*/
|
||||
struct SecureContext;
|
||||
typedef struct SecureContext* SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the secure context management system.
|
||||
*
|
||||
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||
* before calling any secure side function in the thread mode.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureContext_Init( void );
|
||||
|
||||
/**
|
||||
* @brief Allocates a context on the secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||
*
|
||||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief Frees the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||
* context to be freed.
|
||||
*/
|
||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
/**
|
||||
* @brief Loads the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be loaded.
|
||||
*/
|
||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
/**
|
||||
* @brief Saves the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be saved.
|
||||
*/
|
||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
#endif /* __SECURE_CONTEXT_H__ */
|
||||
48
portable/IAR/ARM_CM23/secure/secure_context_port.c
Normal file
48
portable/IAR/ARM_CM23/secure/secure_context_port.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/* Functions implemented in assembler file. */
|
||||
extern void SecureContext_LoadContextAsm( SecureContextHandle_t xSecureContextHandle );
|
||||
extern void SecureContext_SaveContextAsm( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
SecureContext_LoadContextAsm( xSecureContextHandle );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
SecureContext_SaveContextAsm( xSecureContextHandle );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
76
portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
Normal file
76
portable/IAR/ARM_CM23/secure/secure_context_port_asm.s
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
|
||||
PUBLIC SecureContext_LoadContextAsm
|
||||
PUBLIC SecureContext_SaveContextAsm
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_LoadContextAsm:
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
ldmia r0!, {r1, r2} /* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
msr control, r3 /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
msr psplim, r2 /* PSPLIM = r2. */
|
||||
msr psp, r1 /* PSP = r1. */
|
||||
|
||||
load_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_SaveContextAsm:
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
mrs r1, psp /* r1 = PSP. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
subs r1, r1, #4 /* Make space for the CONTROL value on the stack. */
|
||||
str r1, [r0] /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
stmia r1!, {r2} /* Store CONTROL value on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
str r1, [r0] /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
#endif /* configENABLE_MPU */
|
||||
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
|
||||
save_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
450
portable/IAR/ARM_CM23/secure/secure_heap.c
Normal file
450
portable/IAR/ARM_CM23/secure/secure_heap.c
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure context heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
* @brief The linked list structure.
|
||||
*
|
||||
* This is used to link free blocks in order of their memory address.
|
||||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Called automatically to setup the required heap structures the first
|
||||
* time pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void );
|
||||
|
||||
/**
|
||||
* @brief Inserts a block of memory that is being freed into the correct
|
||||
* position in the list of free memory blocks.
|
||||
*
|
||||
* The block being freed will be merged with the block in front it and/or the
|
||||
* block behind it if the memory blocks are adjacent to each other.
|
||||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The size of the structure placed at the beginning of each allocated
|
||||
* memory block must by correctly byte aligned.
|
||||
*/
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
* @brief Gets set to the top bit of an size_t type.
|
||||
*
|
||||
* When this bit in the xBlockSize member of an BlockLink_t structure is set
|
||||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t *pxFirstFreeBlock;
|
||||
uint8_t *pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
#if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void *pv )
|
||||
{
|
||||
uint8_t *puc = ( uint8_t * ) pv;
|
||||
BlockLink_t *pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
51
portable/IAR/ARM_CM23/secure/secure_heap.h
Normal file
51
portable/IAR/ARM_CM23/secure/secure_heap.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_HEAP_H__
|
||||
#define __SECURE_HEAP_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from heap.
|
||||
*
|
||||
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||
*
|
||||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void *pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void *pv );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
105
portable/IAR/ARM_CM23/secure/secure_init.c
Normal file
105
portable/IAR/ARM_CM23/secure/secure_init.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure init includes. */
|
||||
#include "secure_init.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~ ( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
53
portable/IAR/ARM_CM23/secure/secure_init.h
Normal file
53
portable/IAR/ARM_CM23/secure/secure_init.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_INIT_H__
|
||||
#define __SECURE_INIT_H__
|
||||
|
||||
/**
|
||||
* @brief De-prioritizes the non-secure exceptions.
|
||||
*
|
||||
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||
* priority. Context switch is done in the non-secure PendSV handler.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_DePrioritizeNSExceptions( void );
|
||||
|
||||
/**
|
||||
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||
*
|
||||
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||
* Registers are not leaked to the non-secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_EnableNSFPUAccess( void );
|
||||
|
||||
#endif /* __SECURE_INIT_H__ */
|
||||
133
portable/IAR/ARM_CM23/secure/secure_port_macros.h
Normal file
133
portable/IAR/ARM_CM23/secure/secure_port_macros.h
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_PORT_MACROS_H__
|
||||
#define __SECURE_PORT_MACROS_H__
|
||||
|
||||
/**
|
||||
* @brief Byte alignment requirements.
|
||||
*/
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
|
||||
/**
|
||||
* @brief Macro to declare a function as non-secure callable.
|
||||
*/
|
||||
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#else
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Set the non-secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the PSP value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSP to the given value.
|
||||
*/
|
||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSPLIM to the given value.
|
||||
*/
|
||||
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the NonSecure MSP to the given value.
|
||||
*/
|
||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the CONTROL register to the given value.
|
||||
*/
|
||||
#define secureportSET_CONTROL( ulControl ) \
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||
* variable.
|
||||
*/
|
||||
#define secureportREAD_IPSR( ulIPSR ) \
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to enable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to disable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
|
||||
/**
|
||||
* @brief Disable secure interrupts.
|
||||
*/
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Disable non-secure interrupts.
|
||||
*
|
||||
* This effectively disables context switches.
|
||||
*/
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Enable non-secure interrupts.
|
||||
*/
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Assert definition.
|
||||
*/
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ;; ); \
|
||||
}
|
||||
|
||||
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||
933
portable/IAR/ARM_CM23_NTZ/non_secure/port.c
Normal file
933
portable/IAR/ARM_CM23_NTZ/non_secure/port.c
Normal file
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/* Secure components includes. */
|
||||
#include "secure_context.h"
|
||||
#include "secure_init.h"
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/**
|
||||
* The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
|
||||
* i.e. the processor boots as secure and never jumps to the non-secure side.
|
||||
* The Trust Zone support in the port must be disabled in order to run FreeRTOS
|
||||
* on the secure side. The following are the valid configuration seetings:
|
||||
*
|
||||
* 1. Run FreeRTOS on the Secure Side:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
|
||||
*
|
||||
* 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
|
||||
*
|
||||
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
|
||||
*/
|
||||
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
|
||||
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the NVIC.
|
||||
*/
|
||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
|
||||
#define portCPACR_CP10_VALUE ( 3UL )
|
||||
#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE
|
||||
#define portCPACR_CP10_POS ( 20UL )
|
||||
#define portCPACR_CP11_POS ( 22UL )
|
||||
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define portFPCCR_ASPEN_POS ( 31UL )
|
||||
#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS )
|
||||
#define portFPCCR_LSPEN_POS ( 30UL )
|
||||
#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the MPU.
|
||||
*/
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) )
|
||||
|
||||
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) )
|
||||
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) )
|
||||
|
||||
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) )
|
||||
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) )
|
||||
|
||||
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) )
|
||||
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) )
|
||||
|
||||
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) )
|
||||
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) )
|
||||
|
||||
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) )
|
||||
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) )
|
||||
|
||||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR1_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR2_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR3_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR4_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR5_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR6_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR7_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
|
||||
|
||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||
|
||||
/* Enable privileged access to unmapped region. */
|
||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
|
||||
/* Enable MPU. */
|
||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
||||
|
||||
/* Expected value of the portMPU_TYPE register. */
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to set up the initial stack.
|
||||
*/
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
#if( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF FD
|
||||
* 1111 1111 1111 1111 1111 1111 1111 1101
|
||||
*
|
||||
* Bit[6] - 1 --> The exception was taken from the Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 1 --> The exception was taken to the Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
#else
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF BC
|
||||
* 1111 1111 1111 1111 1111 1111 1011 1100
|
||||
*
|
||||
* Bit[6] - 0 --> The exception was taken from the Non-Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 0 --> The exception was taken to the Non-Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xffffffbc )
|
||||
#endif /* configRUN_FREERTOS_SECURE_ONLY */
|
||||
|
||||
/**
|
||||
* @brief CONTROL register privileged bit mask.
|
||||
*
|
||||
* Bit[0] in CONTROL register tells the privilege:
|
||||
* Bit[0] = 0 ==> The task is privileged.
|
||||
* Bit[0] = 1 ==> The task is not privileged.
|
||||
*/
|
||||
#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL )
|
||||
|
||||
/**
|
||||
* @brief Initial CONTROL register values.
|
||||
*/
|
||||
#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 )
|
||||
#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 )
|
||||
|
||||
/**
|
||||
* @brief 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 debugger.
|
||||
*/
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief If portPRELOAD_REGISTERS then registers will be given an initial value
|
||||
* when a task is created. This helps in debugging at the cost of code size.
|
||||
*/
|
||||
#define portPRELOAD_REGISTERS 1
|
||||
|
||||
/**
|
||||
* @brief A task is created without a secure context, and must call
|
||||
* portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
|
||||
* any secure calls.
|
||||
*/
|
||||
#define portNO_SECURE_CONTEXT 0
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Used to catch tasks that attempt to return from their implementing
|
||||
* function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Memory Protection Unit (MPU).
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Floating Point Unit (FPU).
|
||||
*/
|
||||
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/**
|
||||
* @brief Setup the timer to generate the tick interrupts.
|
||||
*
|
||||
* The implementation in this file is weak to allow application writers to
|
||||
* change the timer used to generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether the current execution context is interrupt.
|
||||
*
|
||||
* @return pdTRUE if the current execution context is interrupt, pdFALSE
|
||||
* otherwise.
|
||||
*/
|
||||
BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
/**
|
||||
* @brief Yield the processor.
|
||||
*/
|
||||
void vPortYield( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enter critical section.
|
||||
*/
|
||||
void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Exit from critical section.
|
||||
*/
|
||||
void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SysTick handler.
|
||||
*/
|
||||
void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief C part of SVC handler.
|
||||
*/
|
||||
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Each task maintains its own interrupt status in the critical nesting
|
||||
* variable.
|
||||
*/
|
||||
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Saved as part of the task context to indicate which context the
|
||||
* task is using on the secure side.
|
||||
*/
|
||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Stop and reset the SysTick. */
|
||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
volatile uint32_t ulDummy = 0UL;
|
||||
|
||||
/* 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
|
||||
* 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( ulCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
while( ulDummy == 0 )
|
||||
{
|
||||
/* This file calls prvTaskExitError() after the scheduler has been
|
||||
* started to remove a compiler warning about the function being
|
||||
* defined but never called. ulDummy is used purely to quieten other
|
||||
* warnings about code appearing after this function is called - making
|
||||
* ulDummy volatile makes the compiler think the function could return
|
||||
* and therefore not output an 'unreachable code' warning for code that
|
||||
* appears after it. */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __privileged_functions_start__;
|
||||
extern uint32_t * __privileged_functions_end__;
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
extern uint32_t * __unprivileged_flash_start__;
|
||||
extern uint32_t * __unprivileged_flash_end__;
|
||||
extern uint32_t * __privileged_sram_start__;
|
||||
extern uint32_t * __privileged_sram_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __privileged_functions_start__[];
|
||||
extern uint32_t __privileged_functions_end__[];
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
extern uint32_t __unprivileged_flash_start__[];
|
||||
extern uint32_t __unprivileged_flash_end__[];
|
||||
extern uint32_t __privileged_sram_start__[];
|
||||
extern uint32_t __privileged_sram_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
|
||||
/* Check that the MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* MAIR0 - Index 0. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
/* MAIR0 - Index 1. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* Setup privileged flash as Read Only so that privileged tasks can
|
||||
* read it but not modify. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged flash as Read Only by both privileged and
|
||||
* unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged syscalls flash as Read Only by both privileged
|
||||
* and unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup RAM containing kernel data for privileged access only. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Enable mem fault. */
|
||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable MPU with privileged background access i.e. unmapped
|
||||
* regions have privileged access. */
|
||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* Enable non-secure access to the FPU. */
|
||||
SecureInit_EnableNSFPUAccess();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/* CP10 = 11 ==> Full access to FPU i.e. both privileged and
|
||||
* unprivileged code should be able to access FPU. CP11 should be
|
||||
* programmed to the same value as CP10. */
|
||||
*( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
|
||||
( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
|
||||
);
|
||||
|
||||
/* ASPEN = 1 ==> Hardware should automatically preserve floating point
|
||||
* context on exception entry and restore on exception return.
|
||||
* LSPEN = 1 ==> Enable lazy context save of FP state. */
|
||||
*( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Set a PendSV to request a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
configASSERT( ulCriticalNesting );
|
||||
ulCriticalNesting--;
|
||||
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulPreviousMask;
|
||||
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
|
||||
{
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
uint32_t ulPC;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
uint32_t ulR0;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t ulControl, ulIsTaskPrivileged;
|
||||
#endif /* configENABLE_MPU */
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
uint8_t ucSVCNumber;
|
||||
|
||||
/* Register are stored on the stack in the following order - R0, R1, R2, R3,
|
||||
* R12, LR, PC, xPSR. */
|
||||
ulPC = pulCallerStackAddress[ 6 ];
|
||||
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ];
|
||||
|
||||
switch( ucSVCNumber )
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
case portSVC_ALLOCATE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the stack size passed as parameter to the
|
||||
* vPortAllocateSecureContext function. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Read the CONTROL register value. */
|
||||
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
|
||||
|
||||
/* The task that raised the SVC is privileged if Bit[0]
|
||||
* in the CONTROL register is 0. */
|
||||
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
|
||||
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0 );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
configASSERT( xSecureContext != NULL );
|
||||
SecureContext_LoadContext( xSecureContext );
|
||||
}
|
||||
break;
|
||||
|
||||
case portSVC_FREE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the secure context handle to be freed. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
/* Free the secure context. */
|
||||
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
case portSVC_START_SCHEDULER:
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* De-prioritize the non-secure exceptions so that the
|
||||
* non-secure pendSV runs at the lowest priority. */
|
||||
SecureInit_DePrioritizeNSExceptions();
|
||||
|
||||
/* Initialize the secure context management system. */
|
||||
SecureContext_Init();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
{
|
||||
/* Setup the Floating Point Unit (FPU). */
|
||||
prvSetupFPU();
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/* Setup the context of the first task so that the first task starts
|
||||
* executing. */
|
||||
vRestoreContextOfFirstTask();
|
||||
}
|
||||
break;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
case portSVC_RAISE_PRIVILEGE:
|
||||
{
|
||||
/* Only raise the privilege, if the svc was raised from any of
|
||||
* the system calls. */
|
||||
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||
{
|
||||
vRaisePrivilege();
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
default:
|
||||
{
|
||||
/* Incorrect SVC call. */
|
||||
configASSERT( pdFALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
|
||||
#else
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
#if( portPRELOAD_REGISTERS == 0 )
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#else /* portPRELOAD_REGISTERS */
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#endif /* portPRELOAD_REGISTERS */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Setup the Memory Protection Unit (MPU). */
|
||||
prvSetupMPU();
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialize the critical nesting count ready for the first task. */
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing. Call the task
|
||||
* exit error function to prevent compiler warnings about a static function
|
||||
* not being called in the case that the application writer overrides this
|
||||
* functionality by defining configTASK_RETURN_ADDRESS. Call
|
||||
* vTaskSwitchContext() so link time optimization does not remove the
|
||||
* symbol. */
|
||||
vTaskSwitchContext();
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
|
||||
int32_t lIndex = 0;
|
||||
|
||||
/* Setup MAIR0. */
|
||||
xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* This function is called automatically when the task is created - in
|
||||
* which case the stack region parameters will be valid. At all other
|
||||
* times the stack parameters will not be valid and it is assumed that
|
||||
* the stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) pxBottomOfStack ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
}
|
||||
|
||||
/* User supplied configurable regions. */
|
||||
for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
|
||||
{
|
||||
/* If xRegions is NULL i.e. the task has not specified any MPU
|
||||
* region, the else part ensures that all the configurable MPU
|
||||
* regions are invalidated. */
|
||||
if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
|
||||
{
|
||||
/* Translate the generic region definition contained in xRegions
|
||||
* into the ARMv8 specific MPU settings that are then stored in
|
||||
* xMPUSettings. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
/* Start address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE );
|
||||
|
||||
/* RO/RW. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
|
||||
}
|
||||
else
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
|
||||
}
|
||||
|
||||
/* XN. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
|
||||
}
|
||||
|
||||
/* End Address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Normal memory/ Device memory. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as device memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as normal memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. Interrupt Program
|
||||
* Status Register (IPSR) holds the exception number of the currently-executing
|
||||
* exception or zero for Thread mode.*/
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
113
portable/IAR/ARM_CM23_NTZ/non_secure/portasm.h
Normal file
113
portable/IAR/ARM_CM23_NTZ/non_secure/portasm.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
303
portable/IAR/ARM_CM23_NTZ/non_secure/portasm.s
Normal file
303
portable/IAR/ARM_CM23_NTZ/non_secure/portasm.s
Normal file
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
#error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
tst r0, r1 /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */
|
||||
beq running_privileged /* If the result of previous AND operation was 0, branch. */
|
||||
movs r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
running_privileged:
|
||||
movs r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
bx lr /* Return. */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
orrs r0, r1 /* r0 = r0 | r1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r4, #5 /* r4 = 5. */
|
||||
str r4, [r2] /* Program RNR = 5. */
|
||||
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r4, #6 /* r4 = 6. */
|
||||
str r4, [r2] /* Program RNR = 6. */
|
||||
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r4, #7 /* r4 = 7. */
|
||||
str r4, [r2] /* Program RNR = 7. */
|
||||
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
msr control, r2 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
movs r1, #1 /* r1 = 1. */
|
||||
bics r0, r1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
nop
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, PRIMASK
|
||||
cpsid i
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr PRIMASK, r0
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r0, psp /* Read PSP in r0. */
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r0, r0, #44 /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r0!, {r1-r7} /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r0, r0, #40 /* Make space for PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r0!, {r2-r7} /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */
|
||||
mov r4, r8 /* r4 = r8. */
|
||||
mov r5, r9 /* r5 = r9. */
|
||||
mov r6, r10 /* r6 = r10. */
|
||||
mov r7, r11 /* r7 = r11. */
|
||||
stmia r0!, {r4-r7} /* Store the high registers that are not saved automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
cpsid i
|
||||
bl vTaskSwitchContext
|
||||
cpsie i
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
bics r3, r4 /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r1] /* r4 = *r1 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
ldmia r1!, {r5,r6} /* Read first set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write first set of RBAR/RLAR registers. */
|
||||
movs r4, #5 /* r4 = 5. */
|
||||
str r4, [r2] /* Program RNR = 5. */
|
||||
ldmia r1!, {r5,r6} /* Read second set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write second set of RBAR/RLAR registers. */
|
||||
movs r4, #6 /* r4 = 6. */
|
||||
str r4, [r2] /* Program RNR = 6. */
|
||||
ldmia r1!, {r5,r6} /* Read third set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write third set of RBAR/RLAR registers. */
|
||||
movs r4, #7 /* r4 = 7. */
|
||||
str r4, [r2] /* Program RNR = 7. */
|
||||
ldmia r1!, {r5,r6} /* Read fourth set of RBAR/RLAR from TCB. */
|
||||
ldr r3, =0xe000ed9c /* r3 = 0xe000ed9c [Location of RBAR]. */
|
||||
stmia r3!, {r5,r6} /* Write fourth set of RBAR/RLAR registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
movs r4, #1 /* r4 = 1. */
|
||||
orrs r3, r4 /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
adds r0, r0, #28 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
subs r0, r0, #44 /* Move to the starting of the saved context. */
|
||||
ldmia r0!, {r1-r7} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r2 /* Restore the CONTROL register value for the task. */
|
||||
bx r3
|
||||
#else /* configENABLE_MPU */
|
||||
adds r0, r0, #24 /* Move to the high registers. */
|
||||
ldmia r0!, {r4-r7} /* Restore the high registers that are not automatically restored. */
|
||||
mov r8, r4 /* r8 = r4. */
|
||||
mov r9, r5 /* r9 = r5. */
|
||||
mov r10, r6 /* r10 = r6. */
|
||||
mov r11, r7 /* r11 = r7. */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
subs r0, r0, #40 /* Move to the starting of the saved context. */
|
||||
ldmia r0!, {r2-r7} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
bx r3
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
movs r0, #4
|
||||
mov r1, lr
|
||||
tst r0, r1
|
||||
beq stacking_used_msp
|
||||
mrs r0, psp
|
||||
b vPortSVCHandler_C
|
||||
stacking_used_msp:
|
||||
mrs r0, msp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
308
portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h
Normal file
308
portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M23"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" )
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
619
portable/IAR/ARM_CM3/port.c
Normal file
619
portable/IAR/ARM_CM3/port.c
Normal file
|
|
@ -0,0 +1,619 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM3 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
|
||||
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||
#endif
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#else
|
||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||
as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to manipulate the core. Registers first... */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
/* The systick is a 24-bit counter. */
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
|
||||
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||
occurred while the SysTick counter is stopped during tickless idle
|
||||
calculations. */
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
|
||||
/* For strict compliance with the Cortex-M spec the task start address should
|
||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is
|
||||
defined. The value 255 should also ensure backward compatibility.
|
||||
FreeRTOS.org versions prior to V4.3.0 did not include this definition. */
|
||||
#ifndef configKERNEL_INTERRUPT_PRIORITY
|
||||
#define configKERNEL_INTERRUPT_PRIORITY 255
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortSysTickHandler( void );
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* The number of SysTick increments that make up one tick period.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulTimerCountsForOneTick = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* The maximum number of tick periods that can be suppressed is limited by the
|
||||
* 24 bit resolution of the SysTick timer.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||
* power functionality only.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulStoppedTimerCompensation = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
interrupt. */
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* 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
|
||||
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( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
functions can be called. ISR safe functions are those that end in
|
||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
{
|
||||
/* Check the CMSIS configuration that defines the number of
|
||||
priority bits matches the number of priority bits actually queried
|
||||
from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef configPRIO_BITS
|
||||
{
|
||||
/* Check the FreeRTOS configuration that defines the number of
|
||||
priority bits matches the number of priority bits actually queried
|
||||
from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( uxCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||
executes all interrupts must be unmasked. There is therefore no need to
|
||||
save and then restore the interrupt mask value as its value is already
|
||||
known. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is required. Context switching is performed in
|
||||
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
|
||||
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||
TickType_t xModifiableIdleTime;
|
||||
|
||||
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
|
||||
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||
is accounted for as best it can be, but using the tickless mode will
|
||||
inevitably result in some tiny drift of the time maintained by the
|
||||
kernel with respect to calendar time. */
|
||||
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||
tick periods. -1 is used because this code will execute part way
|
||||
through one of the tick periods. */
|
||||
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
ulReloadValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||
method as that will mask interrupts that should exit sleep mode. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* If a context switch is pending or a task is waiting for the scheduler
|
||||
to be unsuspended then abandon the low power entry. */
|
||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||
{
|
||||
/* Restart from whatever is left in the count register to complete
|
||||
this tick period. */
|
||||
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Reset the reload register to the value required for normal tick
|
||||
periods. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||
call above. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new reload value. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||
|
||||
/* Clear the SysTick count flag and set the count value back to
|
||||
zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||
set its parameter to 0 to indicate that its implementation contains
|
||||
its own wait for interrupt or wait for event instruction, and so wfi
|
||||
should not be executed again. However, the original expected idle
|
||||
time variable must remain unmodified, so a copy is taken. */
|
||||
xModifiableIdleTime = xExpectedIdleTime;
|
||||
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
}
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||
out of sleep mode to execute immediately. see comments above
|
||||
__disable_interrupt() call above. */
|
||||
__enable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable interrupts again because the clock is about to be stopped
|
||||
and interrupts that execute while the clock is stopped will increase
|
||||
any slippage between the time maintained by the RTOS and calendar
|
||||
time. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable the SysTick clock without reading the
|
||||
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
|
||||
the time the SysTick is stopped for is accounted for as best it can
|
||||
be, but using the tickless mode will inevitably result in some tiny
|
||||
drift of the time maintained by the kernel with respect to calendar
|
||||
time*/
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||
|
||||
/* Determine if the SysTick clock has already counted to zero and
|
||||
been set back to the current reload value (the reload back being
|
||||
correct for the entire expected idle time) or if the SysTick is yet
|
||||
to count to zero (in which case an interrupt other than the SysTick
|
||||
must have brought the system out of sleep mode). */
|
||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
|
||||
/* The tick interrupt is already pending, and the SysTick count
|
||||
reloaded with ulReloadValue. Reset the
|
||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||
period. */
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||
|
||||
/* Don't allow a tiny value, or values that have somehow
|
||||
underflowed because the post sleep hook did something
|
||||
that took too long. */
|
||||
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||
{
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||
}
|
||||
|
||||
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||
|
||||
/* 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 waiting. */
|
||||
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something other than the tick interrupt ended the sleep.
|
||||
Work out how long the sleep lasted rounded to complete tick
|
||||
periods (not the ulReload value which accounted for part
|
||||
ticks). */
|
||||
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* How many complete tick periods passed while the processor
|
||||
was waiting? */
|
||||
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||
|
||||
/* The reload value is set to whatever fraction of a single tick
|
||||
period remains. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||
}
|
||||
|
||||
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||
value. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Exit with interrupts enabled. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
__weak void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Stop and clear the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
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.
|
||||
|
||||
Interrupts that use the FreeRTOS API must not be left at their
|
||||
default priority of zero as that is the highest possible priority,
|
||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
and therefore also guaranteed to be invalid.
|
||||
|
||||
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( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) 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).
|
||||
|
||||
If the application only uses CMSIS libraries for interrupt
|
||||
configuration then the correct setting can be achieved on all Cortex-M
|
||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
scheduler. Note however that some vendor specific peripheral libraries
|
||||
assume a non-zero priority group setting, in which cases using a value
|
||||
of zero will result in unpredictable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
103
portable/IAR/ARM_CM3/portasm.s
Normal file
103
portable/IAR/ARM_CM3/portasm.s
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#include <FreeRTOSConfig.h>
|
||||
|
||||
RSEG CODE:CODE(2)
|
||||
thumb
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
|
||||
PUBLIC xPortPendSVHandler
|
||||
PUBLIC vPortSVCHandler
|
||||
PUBLIC vPortStartFirstTask
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xPortPendSVHandler:
|
||||
mrs r0, psp
|
||||
isb
|
||||
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
|
||||
ldr r2, [r3]
|
||||
|
||||
stmdb r0!, {r4-r11} /* Save the remaining registers. */
|
||||
str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
|
||||
|
||||
stmdb sp!, {r3, r14}
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r3, r14}
|
||||
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldmia r0!, {r4-r11} /* Pop the registers. */
|
||||
msr psp, r0
|
||||
isb
|
||||
bx r14
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortSVCHandler:
|
||||
/* Get the location of the current TCB. */
|
||||
ldr r3, =pxCurrentTCB
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11}
|
||||
msr psp, r0
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
orr r14, r14, #13
|
||||
bx r14
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortStartFirstTask
|
||||
/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, =0xE000ED08
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
/* Call SVC to start the first task, ensuring interrupts are enabled. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 0
|
||||
|
||||
END
|
||||
208
portable/IAR/ARM_CM3/portmacro.h
Normal file
208
portable/IAR/ARM_CM3/portmacro.h
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler directives. */
|
||||
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/* Check the configuration. */
|
||||
#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.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_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 ) ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
__set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() __set_BASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_BASEPRI(); portDISABLE_INTERRUPTS()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) __set_BASEPRI( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
warnings. */
|
||||
#pragma diag_suppress=Pe191
|
||||
#pragma diag_suppress=Pa082
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
933
portable/IAR/ARM_CM33/non_secure/port.c
Normal file
933
portable/IAR/ARM_CM33/non_secure/port.c
Normal file
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/* Secure components includes. */
|
||||
#include "secure_context.h"
|
||||
#include "secure_init.h"
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/**
|
||||
* The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
|
||||
* i.e. the processor boots as secure and never jumps to the non-secure side.
|
||||
* The Trust Zone support in the port must be disabled in order to run FreeRTOS
|
||||
* on the secure side. The following are the valid configuration seetings:
|
||||
*
|
||||
* 1. Run FreeRTOS on the Secure Side:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
|
||||
*
|
||||
* 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
|
||||
*
|
||||
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
|
||||
*/
|
||||
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
|
||||
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the NVIC.
|
||||
*/
|
||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
|
||||
#define portCPACR_CP10_VALUE ( 3UL )
|
||||
#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE
|
||||
#define portCPACR_CP10_POS ( 20UL )
|
||||
#define portCPACR_CP11_POS ( 22UL )
|
||||
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define portFPCCR_ASPEN_POS ( 31UL )
|
||||
#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS )
|
||||
#define portFPCCR_LSPEN_POS ( 30UL )
|
||||
#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the MPU.
|
||||
*/
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) )
|
||||
|
||||
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) )
|
||||
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) )
|
||||
|
||||
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) )
|
||||
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) )
|
||||
|
||||
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) )
|
||||
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) )
|
||||
|
||||
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) )
|
||||
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) )
|
||||
|
||||
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) )
|
||||
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) )
|
||||
|
||||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR1_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR2_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR3_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR4_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR5_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR6_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR7_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
|
||||
|
||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||
|
||||
/* Enable privileged access to unmapped region. */
|
||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
|
||||
/* Enable MPU. */
|
||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
||||
|
||||
/* Expected value of the portMPU_TYPE register. */
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to set up the initial stack.
|
||||
*/
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
#if( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF FD
|
||||
* 1111 1111 1111 1111 1111 1111 1111 1101
|
||||
*
|
||||
* Bit[6] - 1 --> The exception was taken from the Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 1 --> The exception was taken to the Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
#else
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF BC
|
||||
* 1111 1111 1111 1111 1111 1111 1011 1100
|
||||
*
|
||||
* Bit[6] - 0 --> The exception was taken from the Non-Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 0 --> The exception was taken to the Non-Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xffffffbc )
|
||||
#endif /* configRUN_FREERTOS_SECURE_ONLY */
|
||||
|
||||
/**
|
||||
* @brief CONTROL register privileged bit mask.
|
||||
*
|
||||
* Bit[0] in CONTROL register tells the privilege:
|
||||
* Bit[0] = 0 ==> The task is privileged.
|
||||
* Bit[0] = 1 ==> The task is not privileged.
|
||||
*/
|
||||
#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL )
|
||||
|
||||
/**
|
||||
* @brief Initial CONTROL register values.
|
||||
*/
|
||||
#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 )
|
||||
#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 )
|
||||
|
||||
/**
|
||||
* @brief 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 debugger.
|
||||
*/
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief If portPRELOAD_REGISTERS then registers will be given an initial value
|
||||
* when a task is created. This helps in debugging at the cost of code size.
|
||||
*/
|
||||
#define portPRELOAD_REGISTERS 1
|
||||
|
||||
/**
|
||||
* @brief A task is created without a secure context, and must call
|
||||
* portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
|
||||
* any secure calls.
|
||||
*/
|
||||
#define portNO_SECURE_CONTEXT 0
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Used to catch tasks that attempt to return from their implementing
|
||||
* function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Memory Protection Unit (MPU).
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Floating Point Unit (FPU).
|
||||
*/
|
||||
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/**
|
||||
* @brief Setup the timer to generate the tick interrupts.
|
||||
*
|
||||
* The implementation in this file is weak to allow application writers to
|
||||
* change the timer used to generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether the current execution context is interrupt.
|
||||
*
|
||||
* @return pdTRUE if the current execution context is interrupt, pdFALSE
|
||||
* otherwise.
|
||||
*/
|
||||
BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
/**
|
||||
* @brief Yield the processor.
|
||||
*/
|
||||
void vPortYield( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enter critical section.
|
||||
*/
|
||||
void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Exit from critical section.
|
||||
*/
|
||||
void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SysTick handler.
|
||||
*/
|
||||
void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief C part of SVC handler.
|
||||
*/
|
||||
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Each task maintains its own interrupt status in the critical nesting
|
||||
* variable.
|
||||
*/
|
||||
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Saved as part of the task context to indicate which context the
|
||||
* task is using on the secure side.
|
||||
*/
|
||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Stop and reset the SysTick. */
|
||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
volatile uint32_t ulDummy = 0UL;
|
||||
|
||||
/* 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
|
||||
* 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( ulCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
while( ulDummy == 0 )
|
||||
{
|
||||
/* This file calls prvTaskExitError() after the scheduler has been
|
||||
* started to remove a compiler warning about the function being
|
||||
* defined but never called. ulDummy is used purely to quieten other
|
||||
* warnings about code appearing after this function is called - making
|
||||
* ulDummy volatile makes the compiler think the function could return
|
||||
* and therefore not output an 'unreachable code' warning for code that
|
||||
* appears after it. */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __privileged_functions_start__;
|
||||
extern uint32_t * __privileged_functions_end__;
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
extern uint32_t * __unprivileged_flash_start__;
|
||||
extern uint32_t * __unprivileged_flash_end__;
|
||||
extern uint32_t * __privileged_sram_start__;
|
||||
extern uint32_t * __privileged_sram_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __privileged_functions_start__[];
|
||||
extern uint32_t __privileged_functions_end__[];
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
extern uint32_t __unprivileged_flash_start__[];
|
||||
extern uint32_t __unprivileged_flash_end__[];
|
||||
extern uint32_t __privileged_sram_start__[];
|
||||
extern uint32_t __privileged_sram_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
|
||||
/* Check that the MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* MAIR0 - Index 0. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
/* MAIR0 - Index 1. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* Setup privileged flash as Read Only so that privileged tasks can
|
||||
* read it but not modify. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged flash as Read Only by both privileged and
|
||||
* unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged syscalls flash as Read Only by both privileged
|
||||
* and unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup RAM containing kernel data for privileged access only. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Enable mem fault. */
|
||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable MPU with privileged background access i.e. unmapped
|
||||
* regions have privileged access. */
|
||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* Enable non-secure access to the FPU. */
|
||||
SecureInit_EnableNSFPUAccess();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/* CP10 = 11 ==> Full access to FPU i.e. both privileged and
|
||||
* unprivileged code should be able to access FPU. CP11 should be
|
||||
* programmed to the same value as CP10. */
|
||||
*( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
|
||||
( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
|
||||
);
|
||||
|
||||
/* ASPEN = 1 ==> Hardware should automatically preserve floating point
|
||||
* context on exception entry and restore on exception return.
|
||||
* LSPEN = 1 ==> Enable lazy context save of FP state. */
|
||||
*( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Set a PendSV to request a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
configASSERT( ulCriticalNesting );
|
||||
ulCriticalNesting--;
|
||||
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulPreviousMask;
|
||||
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
|
||||
{
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
uint32_t ulPC;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
uint32_t ulR0;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t ulControl, ulIsTaskPrivileged;
|
||||
#endif /* configENABLE_MPU */
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
uint8_t ucSVCNumber;
|
||||
|
||||
/* Register are stored on the stack in the following order - R0, R1, R2, R3,
|
||||
* R12, LR, PC, xPSR. */
|
||||
ulPC = pulCallerStackAddress[ 6 ];
|
||||
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ];
|
||||
|
||||
switch( ucSVCNumber )
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
case portSVC_ALLOCATE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the stack size passed as parameter to the
|
||||
* vPortAllocateSecureContext function. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Read the CONTROL register value. */
|
||||
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
|
||||
|
||||
/* The task that raised the SVC is privileged if Bit[0]
|
||||
* in the CONTROL register is 0. */
|
||||
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
|
||||
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0 );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
configASSERT( xSecureContext != NULL );
|
||||
SecureContext_LoadContext( xSecureContext );
|
||||
}
|
||||
break;
|
||||
|
||||
case portSVC_FREE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the secure context handle to be freed. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
/* Free the secure context. */
|
||||
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
case portSVC_START_SCHEDULER:
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* De-prioritize the non-secure exceptions so that the
|
||||
* non-secure pendSV runs at the lowest priority. */
|
||||
SecureInit_DePrioritizeNSExceptions();
|
||||
|
||||
/* Initialize the secure context management system. */
|
||||
SecureContext_Init();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
{
|
||||
/* Setup the Floating Point Unit (FPU). */
|
||||
prvSetupFPU();
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/* Setup the context of the first task so that the first task starts
|
||||
* executing. */
|
||||
vRestoreContextOfFirstTask();
|
||||
}
|
||||
break;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
case portSVC_RAISE_PRIVILEGE:
|
||||
{
|
||||
/* Only raise the privilege, if the svc was raised from any of
|
||||
* the system calls. */
|
||||
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||
{
|
||||
vRaisePrivilege();
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
default:
|
||||
{
|
||||
/* Incorrect SVC call. */
|
||||
configASSERT( pdFALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
|
||||
#else
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
#if( portPRELOAD_REGISTERS == 0 )
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#else /* portPRELOAD_REGISTERS */
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#endif /* portPRELOAD_REGISTERS */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Setup the Memory Protection Unit (MPU). */
|
||||
prvSetupMPU();
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialize the critical nesting count ready for the first task. */
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing. Call the task
|
||||
* exit error function to prevent compiler warnings about a static function
|
||||
* not being called in the case that the application writer overrides this
|
||||
* functionality by defining configTASK_RETURN_ADDRESS. Call
|
||||
* vTaskSwitchContext() so link time optimization does not remove the
|
||||
* symbol. */
|
||||
vTaskSwitchContext();
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
|
||||
int32_t lIndex = 0;
|
||||
|
||||
/* Setup MAIR0. */
|
||||
xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* This function is called automatically when the task is created - in
|
||||
* which case the stack region parameters will be valid. At all other
|
||||
* times the stack parameters will not be valid and it is assumed that
|
||||
* the stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) pxBottomOfStack ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
}
|
||||
|
||||
/* User supplied configurable regions. */
|
||||
for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
|
||||
{
|
||||
/* If xRegions is NULL i.e. the task has not specified any MPU
|
||||
* region, the else part ensures that all the configurable MPU
|
||||
* regions are invalidated. */
|
||||
if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
|
||||
{
|
||||
/* Translate the generic region definition contained in xRegions
|
||||
* into the ARMv8 specific MPU settings that are then stored in
|
||||
* xMPUSettings. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
/* Start address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE );
|
||||
|
||||
/* RO/RW. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
|
||||
}
|
||||
else
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
|
||||
}
|
||||
|
||||
/* XN. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
|
||||
}
|
||||
|
||||
/* End Address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Normal memory/ Device memory. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as device memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as normal memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. Interrupt Program
|
||||
* Status Register (IPSR) holds the exception number of the currently-executing
|
||||
* exception or zero for Thread mode.*/
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
113
portable/IAR/ARM_CM33/non_secure/portasm.h
Normal file
113
portable/IAR/ARM_CM33/non_secure/portasm.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
342
portable/IAR/ARM_CM33/non_secure/portasm.s
Normal file
342
portable/IAR/ARM_CM33/non_secure/portasm.s
Normal file
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xSecureContext
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
EXTERN SecureContext_SaveContext
|
||||
EXTERN SecureContext_LoadContext
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vPortAllocateSecureContext
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
PUBLIC vPortFreeSecureContext
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
ite ne
|
||||
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortAllocateSecureContext:
|
||||
svc 0 /* Secure context is allocated in the supervisor call. portSVC_ALLOCATE_SECURE_CONTEXT = 0. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r3] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r3!, {r4-r11} /* Read 4 set of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r4} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */
|
||||
ldr r5, =xSecureContext
|
||||
str r1, [r5] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
msr control, r3 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r4 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */
|
||||
ldr r4, =xSecureContext
|
||||
str r1, [r4] /* Set xSecureContext to this task's value for the same. */
|
||||
msr psplim, r2 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
bic r0, r0, #1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr basepri, r0 /* basepri = ulMask. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r1, psp /* Read PSP in r1. */
|
||||
ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
ldr r0, [r2] /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */
|
||||
|
||||
cbz r0, save_ns_context /* No secure context to save. */
|
||||
push {r0-r2, r14}
|
||||
bl SecureContext_SaveContext
|
||||
pop {r0-r3} /* LR is now in r3. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r2, r3, #25 /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl save_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r1, r1, #16 /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
stmia r1!, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r1, r1, #12 /* Make space for xSecureContext, PSPLIM and LR on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmia r1!, {r0, r2-r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
b select_next_task
|
||||
|
||||
save_ns_context:
|
||||
ldr r3, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r2, [r3] /* Read pxCurrentTCB. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
it eq
|
||||
vstmdbeq r1!, {s16-s31} /* Store the FPU registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
subs r1, r1, #48 /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
adds r1, r1, #16 /* r1 = r1 + 16. */
|
||||
stm r1, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mrs r3, control /* r3 = CONTROL. */
|
||||
mov r4, lr /* r4 = LR/EXC_RETURN. */
|
||||
subs r1, r1, #16 /* r1 = r1 - 16. */
|
||||
stm r1, {r0, r2-r4} /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */
|
||||
#else /* configENABLE_MPU */
|
||||
subs r1, r1, #44 /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */
|
||||
str r1, [r2] /* Save the new top of stack in TCB. */
|
||||
adds r1, r1, #12 /* r1 = r1 + 12. */
|
||||
stm r1, {r4-r11} /* Store the registers that are not saved automatically. */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
subs r1, r1, #12 /* r1 = r1 - 12. */
|
||||
stmia r1!, {r0, r2-r3} /* Store xSecureContext, PSPLIM and LR on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
select_next_task:
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0 /* r0 = 0. */
|
||||
msr basepri, r0 /* Enable interrupts. */
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r3, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r1, [r3] /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */
|
||||
ldr r4, [r3] /* r4 = *r3 i.e. r4 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r4, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r4, #4 /* r4 = 4. */
|
||||
str r4, [r2] /* Program RNR = 4. */
|
||||
adds r3, #4 /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r3!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r0, r2-r4} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r3 /* Restore the CONTROL register value for the task. */
|
||||
mov lr, r4 /* LR = r4. */
|
||||
ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r2] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
push {r1,r4}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. */
|
||||
pop {r1,r4}
|
||||
mov lr, r4 /* LR = r4. */
|
||||
lsls r2, r4, #25 /* r2 = r4 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r1 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r1!, {r0, r2-r3} /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
mov lr, r3 /* LR = r3. */
|
||||
ldr r2, =xSecureContext /* Read the location of xSecureContext i.e. &( xSecureContext ). */
|
||||
str r0, [r2] /* Restore the task's xSecureContext. */
|
||||
cbz r0, restore_ns_context /* If there is no secure context for the task, restore the non-secure context. */
|
||||
push {r1,r3}
|
||||
bl SecureContext_LoadContext /* Restore the secure context. */
|
||||
pop {r1,r3}
|
||||
mov lr, r3 /* LR = r3. */
|
||||
lsls r2, r3, #25 /* r2 = r3 << 25. Bit[6] of EXC_RETURN is 1 if secure stack was used, 0 if non-secure stack was used to store stack frame. */
|
||||
bpl restore_ns_context /* bpl - branch if positive or zero. If r2 >= 0 ==> Bit[6] in EXC_RETURN is 0 i.e. non-secure stack was used. */
|
||||
msr psp, r1 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
restore_ns_context:
|
||||
ldmia r1!, {r4-r11} /* Restore the registers that are not automatically restored. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
it eq
|
||||
vldmiaeq r1!, {s16-s31} /* Restore the FPU registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
msr psp, r1 /* Remember the new top of stack for the task. */
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortFreeSecureContext:
|
||||
/* r0 = uint32_t *pulTCB. */
|
||||
ldr r1, [r0] /* The first item in the TCB is the top of the stack. */
|
||||
ldr r0, [r1] /* The first item on the stack is the task's xSecureContext. */
|
||||
cmp r0, #0 /* Raise svc if task's xSecureContext is not NULL. */
|
||||
it ne
|
||||
svcne 1 /* Secure context is freed in the supervisor call. portSVC_FREE_SECURE_CONTEXT = 1. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
308
portable/IAR/ARM_CM33/non_secure/portmacro.h
Normal file
308
portable/IAR/ARM_CM33/non_secure/portmacro.h
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
204
portable/IAR/ARM_CM33/secure/secure_context.c
Normal file
204
portable/IAR/ARM_CM33/secure/secure_context.c
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for privileged tasks.
|
||||
*
|
||||
* Bit[0] - 0 --> Thread mode is privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_PRIVILEGED 0x02
|
||||
|
||||
/**
|
||||
* @brief CONTROL value for un-privileged tasks.
|
||||
*
|
||||
* Bit[0] - 1 --> Thread mode is un-privileged.
|
||||
* Bit[1] - 1 --> Thread mode uses PSP.
|
||||
*/
|
||||
#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Structure to represent secure context.
|
||||
*
|
||||
* @note Since stack grows down, pucStackStart is the highest address while
|
||||
* pucStackLimit is the first addess of the allocated memory.
|
||||
*/
|
||||
typedef struct SecureContext
|
||||
{
|
||||
uint8_t *pucCurrentStackPointer; /**< Current value of stack pointer (PSP). */
|
||||
uint8_t *pucStackLimit; /**< Last location of the stack memory (PSPLIM). */
|
||||
uint8_t *pucStackStart; /**< First location of the stack memory. */
|
||||
} SecureContext_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* No stack for thread mode until a task's context is loaded. */
|
||||
secureportSET_PSPLIM( securecontextNO_STACK );
|
||||
secureportSET_PSP( securecontextNO_STACK );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be unprivileged. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_UNPRIVILEGED );
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Configure thread mode to use PSP and to be privileged.. */
|
||||
secureportSET_CONTROL( securecontextCONTROL_VALUE_PRIVILEGED );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )
|
||||
#else /* configENABLE_MPU */
|
||||
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
uint8_t *pucStackMemory = NULL;
|
||||
uint32_t ulIPSR;
|
||||
SecureContextHandle_t xSecureContextHandle = NULL;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t *pulCurrentStackPointer = NULL;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Allocate the context structure. */
|
||||
xSecureContextHandle = ( SecureContextHandle_t ) pvPortMalloc( sizeof( SecureContext_t ) );
|
||||
|
||||
if( xSecureContextHandle != NULL )
|
||||
{
|
||||
/* Allocate the stack space. */
|
||||
pucStackMemory = pvPortMalloc( ulSecureStackSize );
|
||||
|
||||
if( pucStackMemory != NULL )
|
||||
{
|
||||
/* Since stack grows down, the starting point will be the last
|
||||
* location. Note that this location is next to the last
|
||||
* allocated byte because the hardware decrements the stack
|
||||
* pointer before writing i.e. if stack pointer is 0x2, a push
|
||||
* operation will decrement the stack pointer to 0x1 and then
|
||||
* write at 0x1. */
|
||||
xSecureContextHandle->pucStackStart = pucStackMemory + ulSecureStackSize;
|
||||
|
||||
/* The stack cannot go beyond this location. This value is
|
||||
* programmed in the PSPLIM register on context switch.*/
|
||||
xSecureContextHandle->pucStackLimit = pucStackMemory;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Store the correct CONTROL value for the task on the stack.
|
||||
* This value is programmed in the CONTROL register on
|
||||
* context switch. */
|
||||
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
|
||||
pulCurrentStackPointer--;
|
||||
if( ulIsTaskPrivileged )
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
/* Store the current stack pointer. This value is programmed in
|
||||
* the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = ( uint8_t * ) pulCurrentStackPointer;
|
||||
}
|
||||
#else /* configENABLE_MPU */
|
||||
{
|
||||
/* Current SP is set to the starting of the stack. This
|
||||
* value programmed in the PSP register on context switch. */
|
||||
xSecureContextHandle->pucCurrentStackPointer = xSecureContextHandle->pucStackStart;
|
||||
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free the context to avoid memory leak and make sure to return
|
||||
* NULL to indicate failure. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
xSecureContextHandle = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xSecureContextHandle;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* Ensure that valid parameters are passed. */
|
||||
secureportASSERT( xSecureContextHandle != NULL );
|
||||
|
||||
/* Free the stack space. */
|
||||
vPortFree( xSecureContextHandle->pucStackLimit );
|
||||
|
||||
/* Free the context itself. */
|
||||
vPortFree( xSecureContextHandle );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
111
portable/IAR/ARM_CM33/secure/secure_context.h
Normal file
111
portable/IAR/ARM_CM33/secure/secure_context.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_CONTEXT_H__
|
||||
#define __SECURE_CONTEXT_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* FreeRTOS includes. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
/**
|
||||
* @brief PSP value when no task's context is loaded.
|
||||
*/
|
||||
#define securecontextNO_STACK 0x0
|
||||
|
||||
/**
|
||||
* @brief Opaque handle.
|
||||
*/
|
||||
struct SecureContext;
|
||||
typedef struct SecureContext* SecureContextHandle_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the secure context management system.
|
||||
*
|
||||
* PSP is set to NULL and therefore a task must allocate and load a context
|
||||
* before calling any secure side function in the thread mode.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureContext_Init( void );
|
||||
|
||||
/**
|
||||
* @brief Allocates a context on the secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] ulSecureStackSize Size of the stack to allocate on secure side.
|
||||
* @param[in] ulIsTaskPrivileged 1 if the calling task is privileged, 0 otherwise.
|
||||
*
|
||||
* @return Opaque context handle if context is successfully allocated, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged );
|
||||
#else /* configENABLE_MPU */
|
||||
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/**
|
||||
* @brief Frees the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the
|
||||
* context to be freed.
|
||||
*/
|
||||
void SecureContext_FreeContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
/**
|
||||
* @brief Loads the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be loaded.
|
||||
*/
|
||||
void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
/**
|
||||
* @brief Saves the given context.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*
|
||||
* @param[in] xSecureContextHandle Context handle corresponding to the context
|
||||
* to be saved.
|
||||
*/
|
||||
void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
#endif /* __SECURE_CONTEXT_H__ */
|
||||
48
portable/IAR/ARM_CM33/secure/secure_context_port.c
Normal file
48
portable/IAR/ARM_CM33/secure/secure_context_port.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Secure context includes. */
|
||||
#include "secure_context.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/* Functions implemented in assembler file. */
|
||||
extern void SecureContext_LoadContextAsm( SecureContextHandle_t xSecureContextHandle );
|
||||
extern void SecureContext_SaveContextAsm( SecureContextHandle_t xSecureContextHandle );
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
SecureContext_LoadContextAsm( xSecureContextHandle );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle )
|
||||
{
|
||||
SecureContext_SaveContextAsm( xSecureContextHandle );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
73
portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
Normal file
73
portable/IAR/ARM_CM33/secure/secure_context_port_asm.s
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
|
||||
PUBLIC SecureContext_LoadContextAsm
|
||||
PUBLIC SecureContext_SaveContextAsm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_LoadContextAsm:
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, load_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
ldmia r0!, {r1, r2} /* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r1!, {r3} /* Read CONTROL register value from task's stack. r3 = CONTROL. */
|
||||
msr control, r3 /* CONTROL = r3. */
|
||||
#endif /* configENABLE_MPU */
|
||||
msr psplim, r2 /* PSPLIM = r2. */
|
||||
msr psp, r1 /* PSP = r1. */
|
||||
|
||||
load_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SecureContext_SaveContextAsm:
|
||||
/* xSecureContextHandle value is in r0. */
|
||||
mrs r1, ipsr /* r1 = IPSR. */
|
||||
cbz r1, save_ctx_therad_mode /* Do nothing if the processor is running in the Thread Mode. */
|
||||
mrs r1, psp /* r1 = PSP. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
vstmdb r1!, {s0} /* Trigger the defferred stacking of FPU registers. */
|
||||
vldmia r1!, {s0} /* Nullify the effect of the pervious statement. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
stmdb r1!, {r2} /* Store CONTROL value on the stack. */
|
||||
#endif /* configENABLE_MPU */
|
||||
str r1, [r0] /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */
|
||||
movs r1, #0 /* r1 = securecontextNO_STACK. */
|
||||
msr psplim, r1 /* PSPLIM = securecontextNO_STACK. */
|
||||
msr psp, r1 /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */
|
||||
|
||||
save_ctx_therad_mode:
|
||||
bx lr
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
450
portable/IAR/ARM_CM33/secure/secure_heap.c
Normal file
450
portable/IAR/ARM_CM33/secure/secure_heap.c
Normal file
|
|
@ -0,0 +1,450 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure context heap includes. */
|
||||
#include "secure_heap.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Total heap size.
|
||||
*/
|
||||
#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) )
|
||||
|
||||
/* No test marker by default. */
|
||||
#ifndef mtCOVERAGE_TEST_MARKER
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceMALLOC
|
||||
#define traceMALLOC( pvReturn, xWantedSize )
|
||||
#endif
|
||||
|
||||
/* No tracing by default. */
|
||||
#ifndef traceFREE
|
||||
#define traceFREE( pv, xBlockSize )
|
||||
#endif
|
||||
|
||||
/* Block sizes must not get too small. */
|
||||
#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) )
|
||||
|
||||
/* Assumes 8bit bytes! */
|
||||
#define secureheapBITS_PER_BYTE ( ( size_t ) 8 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Allocate the memory for the heap. */
|
||||
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
|
||||
/* The application writer has already defined the array used for the RTOS
|
||||
* heap - probably so it can be placed in a special segment or address. */
|
||||
extern uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#else /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ];
|
||||
#endif /* configAPPLICATION_ALLOCATED_HEAP */
|
||||
|
||||
/**
|
||||
* @brief The linked list structure.
|
||||
*
|
||||
* This is used to link free blocks in order of their memory address.
|
||||
*/
|
||||
typedef struct A_BLOCK_LINK
|
||||
{
|
||||
struct A_BLOCK_LINK *pxNextFreeBlock; /**< The next free block in the list. */
|
||||
size_t xBlockSize; /**< The size of the free block. */
|
||||
} BlockLink_t;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Called automatically to setup the required heap structures the first
|
||||
* time pvPortMalloc() is called.
|
||||
*/
|
||||
static void prvHeapInit( void );
|
||||
|
||||
/**
|
||||
* @brief Inserts a block of memory that is being freed into the correct
|
||||
* position in the list of free memory blocks.
|
||||
*
|
||||
* The block being freed will be merged with the block in front it and/or the
|
||||
* block behind it if the memory blocks are adjacent to each other.
|
||||
*
|
||||
* @param[in] pxBlockToInsert The block being freed.
|
||||
*/
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief The size of the structure placed at the beginning of each allocated
|
||||
* memory block must by correctly byte aligned.
|
||||
*/
|
||||
static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( secureportBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
|
||||
/**
|
||||
* @brief Create a couple of list links to mark the start and end of the list.
|
||||
*/
|
||||
static BlockLink_t xStart, *pxEnd = NULL;
|
||||
|
||||
/**
|
||||
* @brief Keeps track of the number of free bytes remaining, but says nothing
|
||||
* about fragmentation.
|
||||
*/
|
||||
static size_t xFreeBytesRemaining = 0U;
|
||||
static size_t xMinimumEverFreeBytesRemaining = 0U;
|
||||
|
||||
/**
|
||||
* @brief Gets set to the top bit of an size_t type.
|
||||
*
|
||||
* When this bit in the xBlockSize member of an BlockLink_t structure is set
|
||||
* then the block belongs to the application. When the bit is free the block is
|
||||
* still part of the free heap space.
|
||||
*/
|
||||
static size_t xBlockAllocatedBit = 0;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvHeapInit( void )
|
||||
{
|
||||
BlockLink_t *pxFirstFreeBlock;
|
||||
uint8_t *pucAlignedHeap;
|
||||
size_t uxAddress;
|
||||
size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE;
|
||||
|
||||
/* Ensure the heap starts on a correctly aligned boundary. */
|
||||
uxAddress = ( size_t ) ucHeap;
|
||||
|
||||
if( ( uxAddress & secureportBYTE_ALIGNMENT_MASK ) != 0 )
|
||||
{
|
||||
uxAddress += ( secureportBYTE_ALIGNMENT - 1 );
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;
|
||||
}
|
||||
|
||||
pucAlignedHeap = ( uint8_t * ) uxAddress;
|
||||
|
||||
/* xStart is used to hold a pointer to the first item in the list of free
|
||||
* blocks. The void cast is used to prevent compiler warnings. */
|
||||
xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap;
|
||||
xStart.xBlockSize = ( size_t ) 0;
|
||||
|
||||
/* pxEnd is used to mark the end of the list of free blocks and is inserted
|
||||
* at the end of the heap space. */
|
||||
uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
|
||||
uxAddress -= xHeapStructSize;
|
||||
uxAddress &= ~( ( size_t ) secureportBYTE_ALIGNMENT_MASK );
|
||||
pxEnd = ( void * ) uxAddress;
|
||||
pxEnd->xBlockSize = 0;
|
||||
pxEnd->pxNextFreeBlock = NULL;
|
||||
|
||||
/* To start with there is a single free block that is sized to take up the
|
||||
* entire heap space, minus the space taken by pxEnd. */
|
||||
pxFirstFreeBlock = ( void * ) pucAlignedHeap;
|
||||
pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
|
||||
pxFirstFreeBlock->pxNextFreeBlock = pxEnd;
|
||||
|
||||
/* Only one block exists - and it covers the entire usable heap space. */
|
||||
xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;
|
||||
|
||||
/* Work out the position of the top bit in a size_t variable. */
|
||||
xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * secureheapBITS_PER_BYTE ) - 1 );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert )
|
||||
{
|
||||
BlockLink_t *pxIterator;
|
||||
uint8_t *puc;
|
||||
|
||||
/* Iterate through the list until a block is found that has a higher address
|
||||
* than the block being inserted. */
|
||||
for( pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
/* Nothing to do here, just iterate to the right position. */
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted after
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxIterator;
|
||||
if( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert )
|
||||
{
|
||||
pxIterator->xBlockSize += pxBlockToInsert->xBlockSize;
|
||||
pxBlockToInsert = pxIterator;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Do the block being inserted, and the block it is being inserted before
|
||||
* make a contiguous block of memory? */
|
||||
puc = ( uint8_t * ) pxBlockToInsert;
|
||||
if( ( puc + pxBlockToInsert->xBlockSize ) == ( uint8_t * ) pxIterator->pxNextFreeBlock )
|
||||
{
|
||||
if( pxIterator->pxNextFreeBlock != pxEnd )
|
||||
{
|
||||
/* Form one big block from the two blocks. */
|
||||
pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize;
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock;
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxEnd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the block being inserted plugged a gab, so was merged with the block
|
||||
* before and the block after, then it's pxNextFreeBlock pointer will have
|
||||
* already been set, and should not be set here as that would make it point
|
||||
* to itself. */
|
||||
if( pxIterator != pxBlockToInsert )
|
||||
{
|
||||
pxIterator->pxNextFreeBlock = pxBlockToInsert;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void *pvPortMalloc( size_t xWantedSize )
|
||||
{
|
||||
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
|
||||
void *pvReturn = NULL;
|
||||
|
||||
/* If this is the first call to malloc then the heap will require
|
||||
* initialisation to setup the list of free blocks. */
|
||||
if( pxEnd == NULL )
|
||||
{
|
||||
prvHeapInit();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* Check the requested block size is not so large that the top bit is set.
|
||||
* The top bit of the block size member of the BlockLink_t structure is used
|
||||
* to determine who owns the block - the application or the kernel, so it
|
||||
* must be free. */
|
||||
if( ( xWantedSize & xBlockAllocatedBit ) == 0 )
|
||||
{
|
||||
/* The wanted size is increased so it can contain a BlockLink_t
|
||||
* structure in addition to the requested amount of bytes. */
|
||||
if( xWantedSize > 0 )
|
||||
{
|
||||
xWantedSize += xHeapStructSize;
|
||||
|
||||
/* Ensure that blocks are always aligned to the required number of
|
||||
* bytes. */
|
||||
if( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) != 0x00 )
|
||||
{
|
||||
/* Byte alignment required. */
|
||||
xWantedSize += ( secureportBYTE_ALIGNMENT - ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) );
|
||||
secureportASSERT( ( xWantedSize & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) )
|
||||
{
|
||||
/* Traverse the list from the start (lowest address) block until
|
||||
* one of adequate size is found. */
|
||||
pxPreviousBlock = &xStart;
|
||||
pxBlock = xStart.pxNextFreeBlock;
|
||||
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
|
||||
{
|
||||
pxPreviousBlock = pxBlock;
|
||||
pxBlock = pxBlock->pxNextFreeBlock;
|
||||
}
|
||||
|
||||
/* If the end marker was reached then a block of adequate size was
|
||||
* not found. */
|
||||
if( pxBlock != pxEnd )
|
||||
{
|
||||
/* Return the memory space pointed to - jumping over the
|
||||
* BlockLink_t structure at its start. */
|
||||
pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + xHeapStructSize );
|
||||
|
||||
/* This block is being returned for use so must be taken out
|
||||
* of the list of free blocks. */
|
||||
pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;
|
||||
|
||||
/* If the block is larger than required it can be split into
|
||||
* two. */
|
||||
if( ( pxBlock->xBlockSize - xWantedSize ) > secureheapMINIMUM_BLOCK_SIZE )
|
||||
{
|
||||
/* This block is to be split into two. Create a new
|
||||
* block following the number of bytes requested. The void
|
||||
* cast is used to prevent byte alignment warnings from the
|
||||
* compiler. */
|
||||
pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );
|
||||
secureportASSERT( ( ( ( size_t ) pxNewBlockLink ) & secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
|
||||
/* Calculate the sizes of two blocks split from the single
|
||||
* block. */
|
||||
pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
|
||||
pxBlock->xBlockSize = xWantedSize;
|
||||
|
||||
/* Insert the new block into the list of free blocks. */
|
||||
prvInsertBlockIntoFreeList( pxNewBlockLink );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xFreeBytesRemaining -= pxBlock->xBlockSize;
|
||||
|
||||
if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining )
|
||||
{
|
||||
xMinimumEverFreeBytesRemaining = xFreeBytesRemaining;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
/* The block is being returned - it is allocated and owned by
|
||||
* the application and has no "next" block. */
|
||||
pxBlock->xBlockSize |= xBlockAllocatedBit;
|
||||
pxBlock->pxNextFreeBlock = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
traceMALLOC( pvReturn, xWantedSize );
|
||||
|
||||
#if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 )
|
||||
{
|
||||
if( pvReturn == NULL )
|
||||
{
|
||||
extern void vApplicationMallocFailedHook( void );
|
||||
vApplicationMallocFailedHook();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortFree( void *pv )
|
||||
{
|
||||
uint8_t *puc = ( uint8_t * ) pv;
|
||||
BlockLink_t *pxLink;
|
||||
|
||||
if( pv != NULL )
|
||||
{
|
||||
/* The memory being freed will have an BlockLink_t structure immediately
|
||||
* before it. */
|
||||
puc -= xHeapStructSize;
|
||||
|
||||
/* This casting is to keep the compiler from issuing warnings. */
|
||||
pxLink = ( void * ) puc;
|
||||
|
||||
/* Check the block is actually allocated. */
|
||||
secureportASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 );
|
||||
secureportASSERT( pxLink->pxNextFreeBlock == NULL );
|
||||
|
||||
if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 )
|
||||
{
|
||||
if( pxLink->pxNextFreeBlock == NULL )
|
||||
{
|
||||
/* The block is being returned to the heap - it is no longer
|
||||
* allocated. */
|
||||
pxLink->xBlockSize &= ~xBlockAllocatedBit;
|
||||
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS();
|
||||
{
|
||||
/* Add this block to the list of free blocks. */
|
||||
xFreeBytesRemaining += pxLink->xBlockSize;
|
||||
traceFREE( pv, pxLink->xBlockSize );
|
||||
prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) );
|
||||
}
|
||||
secureportENABLE_NON_SECURE_INTERRUPTS();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetFreeHeapSize( void )
|
||||
{
|
||||
return xFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
size_t xPortGetMinimumEverFreeHeapSize( void )
|
||||
{
|
||||
return xMinimumEverFreeBytesRemaining;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortInitialiseBlocks( void )
|
||||
{
|
||||
/* This just exists to keep the linker quiet. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
51
portable/IAR/ARM_CM33/secure/secure_heap.h
Normal file
51
portable/IAR/ARM_CM33/secure/secure_heap.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_HEAP_H__
|
||||
#define __SECURE_HEAP_H__
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief Allocates memory from heap.
|
||||
*
|
||||
* @param[in] xWantedSize The size of the memory to be allocated.
|
||||
*
|
||||
* @return Pointer to the memory region if the allocation is successful, NULL
|
||||
* otherwise.
|
||||
*/
|
||||
void *pvPortMalloc( size_t xWantedSize );
|
||||
|
||||
/**
|
||||
* @brief Frees the previously allocated memory.
|
||||
*
|
||||
* @param[in] pv Pointer to the memory to be freed.
|
||||
*/
|
||||
void vPortFree( void *pv );
|
||||
|
||||
#endif /* __SECURE_HEAP_H__ */
|
||||
105
portable/IAR/ARM_CM33/secure/secure_init.c
Normal file
105
portable/IAR/ARM_CM33/secure/secure_init.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdint.h>
|
||||
|
||||
/* Secure init includes. */
|
||||
#include "secure_init.h"
|
||||
|
||||
/* Secure port macros. */
|
||||
#include "secure_port_macros.h"
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define secureinitSCB_AIRCR ( ( volatile uint32_t * ) 0xe000ed0c ) /* Application Interrupt and Reset Control Register. */
|
||||
#define secureinitSCB_AIRCR_VECTKEY_POS ( 16UL )
|
||||
#define secureinitSCB_AIRCR_VECTKEY_MASK ( 0xFFFFUL << secureinitSCB_AIRCR_VECTKEY_POS )
|
||||
#define secureinitSCB_AIRCR_PRIS_POS ( 14UL )
|
||||
#define secureinitSCB_AIRCR_PRIS_MASK ( 1UL << secureinitSCB_AIRCR_PRIS_POS )
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define secureinitFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define secureinitFPCCR_LSPENS_POS ( 29UL )
|
||||
#define secureinitFPCCR_LSPENS_MASK ( 1UL << secureinitFPCCR_LSPENS_POS )
|
||||
#define secureinitFPCCR_TS_POS ( 26UL )
|
||||
#define secureinitFPCCR_TS_MASK ( 1UL << secureinitFPCCR_TS_POS )
|
||||
|
||||
#define secureinitNSACR ( ( volatile uint32_t * ) 0xe000ed8c ) /* Non-secure Access Control Register. */
|
||||
#define secureinitNSACR_CP10_POS ( 10UL )
|
||||
#define secureinitNSACR_CP10_MASK ( 1UL << secureinitNSACR_CP10_POS )
|
||||
#define secureinitNSACR_CP11_POS ( 11UL )
|
||||
#define secureinitNSACR_CP11_MASK ( 1UL << secureinitNSACR_CP11_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_DePrioritizeNSExceptions( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
*( secureinitSCB_AIRCR ) = ( *( secureinitSCB_AIRCR ) & ~( secureinitSCB_AIRCR_VECTKEY_MASK | secureinitSCB_AIRCR_PRIS_MASK ) ) |
|
||||
( ( 0x05FAUL << secureinitSCB_AIRCR_VECTKEY_POS ) & secureinitSCB_AIRCR_VECTKEY_MASK ) |
|
||||
( ( 0x1UL << secureinitSCB_AIRCR_PRIS_POS ) & secureinitSCB_AIRCR_PRIS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
secureportNON_SECURE_CALLABLE void SecureInit_EnableNSFPUAccess( void )
|
||||
{
|
||||
uint32_t ulIPSR;
|
||||
|
||||
/* Read the Interrupt Program Status Register (IPSR) value. */
|
||||
secureportREAD_IPSR( ulIPSR );
|
||||
|
||||
/* Do nothing if the processor is running in the Thread Mode. IPSR is zero
|
||||
* when the processor is running in the Thread Mode. */
|
||||
if( ulIPSR != 0 )
|
||||
{
|
||||
/* CP10 = 1 ==> Non-secure access to the Floating Point Unit is
|
||||
* permitted. CP11 should be programmed to the same value as CP10. */
|
||||
*( secureinitNSACR ) |= ( secureinitNSACR_CP10_MASK | secureinitNSACR_CP11_MASK );
|
||||
|
||||
/* LSPENS = 0 ==> LSPEN is writable fron non-secure state. This ensures
|
||||
* that we can enable/disable lazy stacking in port.c file. */
|
||||
*( secureinitFPCCR ) &= ~ ( secureinitFPCCR_LSPENS_MASK );
|
||||
|
||||
/* TS = 1 ==> Treat FP registers as secure i.e. callee saved FP
|
||||
* registers (S16-S31) are also pushed to stack on exception entry and
|
||||
* restored on exception return. */
|
||||
*( secureinitFPCCR ) |= ( secureinitFPCCR_TS_MASK );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
53
portable/IAR/ARM_CM33/secure/secure_init.h
Normal file
53
portable/IAR/ARM_CM33/secure/secure_init.h
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_INIT_H__
|
||||
#define __SECURE_INIT_H__
|
||||
|
||||
/**
|
||||
* @brief De-prioritizes the non-secure exceptions.
|
||||
*
|
||||
* This is needed to ensure that the non-secure PendSV runs at the lowest
|
||||
* priority. Context switch is done in the non-secure PendSV handler.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_DePrioritizeNSExceptions( void );
|
||||
|
||||
/**
|
||||
* @brief Sets up the Floating Point Unit (FPU) for Non-Secure access.
|
||||
*
|
||||
* Also sets FPCCR.TS=1 to ensure that the content of the Floating Point
|
||||
* Registers are not leaked to the non-secure side.
|
||||
*
|
||||
* @note This function must be called in the handler mode. It is no-op if called
|
||||
* in the thread mode.
|
||||
*/
|
||||
void SecureInit_EnableNSFPUAccess( void );
|
||||
|
||||
#endif /* __SECURE_INIT_H__ */
|
||||
133
portable/IAR/ARM_CM33/secure/secure_port_macros.h
Normal file
133
portable/IAR/ARM_CM33/secure/secure_port_macros.h
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __SECURE_PORT_MACROS_H__
|
||||
#define __SECURE_PORT_MACROS_H__
|
||||
|
||||
/**
|
||||
* @brief Byte alignment requirements.
|
||||
*/
|
||||
#define secureportBYTE_ALIGNMENT 8
|
||||
#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 )
|
||||
|
||||
/**
|
||||
* @brief Macro to declare a function as non-secure callable.
|
||||
*/
|
||||
#if defined( __IAR_SYSTEMS_ICC__ )
|
||||
#define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root
|
||||
#else
|
||||
#define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set the secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Set the non-secure PRIMASK value.
|
||||
*/
|
||||
#define secureportSET_NON_SECURE_PRIMASK( ulPrimaskValue ) \
|
||||
__asm volatile ( "msr primask_ns, %0" : : "r" ( ulPrimaskValue ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the PSP value in the given variable.
|
||||
*/
|
||||
#define secureportREAD_PSP( pucOutCurrentStackPointer ) \
|
||||
__asm volatile ( "mrs %0, psp" : "=r" ( pucOutCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSP to the given value.
|
||||
*/
|
||||
#define secureportSET_PSP( pucCurrentStackPointer ) \
|
||||
__asm volatile ( "msr psp, %0" : : "r" ( pucCurrentStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the PSPLIM to the given value.
|
||||
*/
|
||||
#define secureportSET_PSPLIM( pucStackLimit ) \
|
||||
__asm volatile ( "msr psplim, %0" : : "r" ( pucStackLimit ) )
|
||||
|
||||
/**
|
||||
* @brief Set the NonSecure MSP to the given value.
|
||||
*/
|
||||
#define secureportSET_MSP_NS( pucMainStackPointer ) \
|
||||
__asm volatile ( "msr msp_ns, %0" : : "r" ( pucMainStackPointer ) )
|
||||
|
||||
/**
|
||||
* @brief Set the CONTROL register to the given value.
|
||||
*/
|
||||
#define secureportSET_CONTROL( ulControl ) \
|
||||
__asm volatile ( "msr control, %0" : : "r" ( ulControl ) : "memory" )
|
||||
|
||||
/**
|
||||
* @brief Read the Interrupt Program Status Register (IPSR) value in the given
|
||||
* variable.
|
||||
*/
|
||||
#define secureportREAD_IPSR( ulIPSR ) \
|
||||
__asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) )
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to enable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0
|
||||
|
||||
/**
|
||||
* @brief PRIMASK value to disable interrupts.
|
||||
*/
|
||||
#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1
|
||||
|
||||
/**
|
||||
* @brief Disable secure interrupts.
|
||||
*/
|
||||
#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Disable non-secure interrupts.
|
||||
*
|
||||
* This effectively disables context switches.
|
||||
*/
|
||||
#define secureportDISABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Enable non-secure interrupts.
|
||||
*/
|
||||
#define secureportENABLE_NON_SECURE_INTERRUPTS() secureportSET_NON_SECURE_PRIMASK( secureportPRIMASK_ENABLE_INTERRUPTS_VAL )
|
||||
|
||||
/**
|
||||
* @brief Assert definition.
|
||||
*/
|
||||
#define secureportASSERT( x ) \
|
||||
if( ( x ) == 0 ) \
|
||||
{ \
|
||||
secureportDISABLE_SECURE_INTERRUPTS(); \
|
||||
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
|
||||
for( ;; ); \
|
||||
}
|
||||
|
||||
#endif /* __SECURE_PORT_MACROS_H__ */
|
||||
933
portable/IAR/ARM_CM33_NTZ/non_secure/port.c
Normal file
933
portable/IAR/ARM_CM33_NTZ/non_secure/port.c
Normal file
|
|
@ -0,0 +1,933 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/* Portasm includes. */
|
||||
#include "portasm.h"
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/* Secure components includes. */
|
||||
#include "secure_context.h"
|
||||
#include "secure_init.h"
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/**
|
||||
* The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
|
||||
* i.e. the processor boots as secure and never jumps to the non-secure side.
|
||||
* The Trust Zone support in the port must be disabled in order to run FreeRTOS
|
||||
* on the secure side. The following are the valid configuration seetings:
|
||||
*
|
||||
* 1. Run FreeRTOS on the Secure Side:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
|
||||
*
|
||||
* 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
|
||||
*
|
||||
* 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
|
||||
* configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
|
||||
*/
|
||||
#if( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
|
||||
#error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the NVIC.
|
||||
*/
|
||||
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
|
||||
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 )
|
||||
#define portNVIC_INT_CTRL ( ( volatile uint32_t * ) 0xe000ed04 )
|
||||
#define portNVIC_SYSPRI2 ( ( volatile uint32_t * ) 0xe000ed20 )
|
||||
#define portNVIC_SYSTICK_CLK ( 0x00000004 )
|
||||
#define portNVIC_SYSTICK_INT ( 0x00000002 )
|
||||
#define portNVIC_SYSTICK_ENABLE ( 0x00000001 )
|
||||
#define portNVIC_PENDSVSET ( 0x10000000 )
|
||||
#define portMIN_INTERRUPT_PRIORITY ( 255UL )
|
||||
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the SCB.
|
||||
*/
|
||||
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 )
|
||||
#define portSCB_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the FPU.
|
||||
*/
|
||||
#define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
|
||||
#define portCPACR_CP10_VALUE ( 3UL )
|
||||
#define portCPACR_CP11_VALUE portCPACR_CP10_VALUE
|
||||
#define portCPACR_CP10_POS ( 20UL )
|
||||
#define portCPACR_CP11_POS ( 22UL )
|
||||
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
|
||||
#define portFPCCR_ASPEN_POS ( 31UL )
|
||||
#define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS )
|
||||
#define portFPCCR_LSPEN_POS ( 30UL )
|
||||
#define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to manipulate the MPU.
|
||||
*/
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portMPU_RNR_REG ( * ( ( volatile uint32_t * ) 0xe000ed98 ) )
|
||||
|
||||
#define portMPU_RBAR_REG ( * ( ( volatile uint32_t * ) 0xe000ed9c ) )
|
||||
#define portMPU_RLAR_REG ( * ( ( volatile uint32_t * ) 0xe000eda0 ) )
|
||||
|
||||
#define portMPU_RBAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda4 ) )
|
||||
#define portMPU_RLAR_A1_REG ( * ( ( volatile uint32_t * ) 0xe000eda8 ) )
|
||||
|
||||
#define portMPU_RBAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edac ) )
|
||||
#define portMPU_RLAR_A2_REG ( * ( ( volatile uint32_t * ) 0xe000edb0 ) )
|
||||
|
||||
#define portMPU_RBAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb4 ) )
|
||||
#define portMPU_RLAR_A3_REG ( * ( ( volatile uint32_t * ) 0xe000edb8 ) )
|
||||
|
||||
#define portMPU_MAIR0_REG ( * ( ( volatile uint32_t * ) 0xe000edc0 ) )
|
||||
#define portMPU_MAIR1_REG ( * ( ( volatile uint32_t * ) 0xe000edc4 ) )
|
||||
|
||||
#define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
#define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
|
||||
|
||||
#define portMPU_MAIR_ATTR0_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR1_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR2_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR3_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR4_POS ( 0UL )
|
||||
#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
|
||||
|
||||
#define portMPU_MAIR_ATTR5_POS ( 8UL )
|
||||
#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
|
||||
|
||||
#define portMPU_MAIR_ATTR6_POS ( 16UL )
|
||||
#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
|
||||
|
||||
#define portMPU_MAIR_ATTR7_POS ( 24UL )
|
||||
#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
|
||||
|
||||
#define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
|
||||
#define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
|
||||
|
||||
#define portMPU_RLAR_REGION_ENABLE ( 1UL )
|
||||
|
||||
/* Enable privileged access to unmapped region. */
|
||||
#define portMPU_PRIV_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
|
||||
/* Enable MPU. */
|
||||
#define portMPU_ENABLE ( 1UL << 0UL )
|
||||
|
||||
/* Expected value of the portMPU_TYPE register. */
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Constants required to set up the initial stack.
|
||||
*/
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
|
||||
#if( configRUN_FREERTOS_SECURE_ONLY == 1 )
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF FD
|
||||
* 1111 1111 1111 1111 1111 1111 1111 1101
|
||||
*
|
||||
* Bit[6] - 1 --> The exception was taken from the Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 1 --> The exception was taken to the Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
#else
|
||||
/**
|
||||
* @brief Initial EXC_RETURN value.
|
||||
*
|
||||
* FF FF FF BC
|
||||
* 1111 1111 1111 1111 1111 1111 1011 1100
|
||||
*
|
||||
* Bit[6] - 0 --> The exception was taken from the Non-Secure state.
|
||||
* Bit[5] - 1 --> Do not skip stacking of additional state context.
|
||||
* Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
|
||||
* Bit[3] - 1 --> Return to the Thread mode.
|
||||
* Bit[2] - 1 --> Restore registers from the process stack.
|
||||
* Bit[1] - 0 --> Reserved, 0.
|
||||
* Bit[0] - 0 --> The exception was taken to the Non-Secure state.
|
||||
*/
|
||||
#define portINITIAL_EXC_RETURN ( 0xffffffbc )
|
||||
#endif /* configRUN_FREERTOS_SECURE_ONLY */
|
||||
|
||||
/**
|
||||
* @brief CONTROL register privileged bit mask.
|
||||
*
|
||||
* Bit[0] in CONTROL register tells the privilege:
|
||||
* Bit[0] = 0 ==> The task is privileged.
|
||||
* Bit[0] = 1 ==> The task is not privileged.
|
||||
*/
|
||||
#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL )
|
||||
|
||||
/**
|
||||
* @brief Initial CONTROL register values.
|
||||
*/
|
||||
#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 )
|
||||
#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 )
|
||||
|
||||
/**
|
||||
* @brief 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 debugger.
|
||||
*/
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief If portPRELOAD_REGISTERS then registers will be given an initial value
|
||||
* when a task is created. This helps in debugging at the cost of code size.
|
||||
*/
|
||||
#define portPRELOAD_REGISTERS 1
|
||||
|
||||
/**
|
||||
* @brief A task is created without a secure context, and must call
|
||||
* portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
|
||||
* any secure calls.
|
||||
*/
|
||||
#define portNO_SECURE_CONTEXT 0
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Used to catch tasks that attempt to return from their implementing
|
||||
* function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Memory Protection Unit (MPU).
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
/**
|
||||
* @brief Setup the Floating Point Unit (FPU).
|
||||
*/
|
||||
static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/**
|
||||
* @brief Setup the timer to generate the tick interrupts.
|
||||
*
|
||||
* The implementation in this file is weak to allow application writers to
|
||||
* change the timer used to generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether the current execution context is interrupt.
|
||||
*
|
||||
* @return pdTRUE if the current execution context is interrupt, pdFALSE
|
||||
* otherwise.
|
||||
*/
|
||||
BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
/**
|
||||
* @brief Yield the processor.
|
||||
*/
|
||||
void vPortYield( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enter critical section.
|
||||
*/
|
||||
void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Exit from critical section.
|
||||
*/
|
||||
void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SysTick handler.
|
||||
*/
|
||||
void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief C part of SVC handler.
|
||||
*/
|
||||
portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Each task maintains its own interrupt status in the critical nesting
|
||||
* variable.
|
||||
*/
|
||||
static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Saved as part of the task context to indicate which context the
|
||||
* task is using on the secure side.
|
||||
*/
|
||||
portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Stop and reset the SysTick. */
|
||||
*( portNVIC_SYSTICK_CTRL ) = 0UL;
|
||||
*( portNVIC_SYSTICK_CURRENT_VALUE ) = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
*( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
*( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
volatile uint32_t ulDummy = 0UL;
|
||||
|
||||
/* 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
|
||||
* 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( ulCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
while( ulDummy == 0 )
|
||||
{
|
||||
/* This file calls prvTaskExitError() after the scheduler has been
|
||||
* started to remove a compiler warning about the function being
|
||||
* defined but never called. ulDummy is used purely to quieten other
|
||||
* warnings about code appearing after this function is called - making
|
||||
* ulDummy volatile makes the compiler think the function could return
|
||||
* and therefore not output an 'unreachable code' warning for code that
|
||||
* appears after it. */
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __privileged_functions_start__;
|
||||
extern uint32_t * __privileged_functions_end__;
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
extern uint32_t * __unprivileged_flash_start__;
|
||||
extern uint32_t * __unprivileged_flash_end__;
|
||||
extern uint32_t * __privileged_sram_start__;
|
||||
extern uint32_t * __privileged_sram_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __privileged_functions_start__[];
|
||||
extern uint32_t __privileged_functions_end__[];
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
extern uint32_t __unprivileged_flash_start__[];
|
||||
extern uint32_t __unprivileged_flash_end__[];
|
||||
extern uint32_t __privileged_sram_start__[];
|
||||
extern uint32_t __privileged_sram_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
|
||||
/* Check that the MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* MAIR0 - Index 0. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
/* MAIR0 - Index 1. */
|
||||
portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* Setup privileged flash as Read Only so that privileged tasks can
|
||||
* read it but not modify. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged flash as Read Only by both privileged and
|
||||
* unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup unprivileged syscalls flash as Read Only by both privileged
|
||||
* and unprivileged tasks. All tasks can read it but no-one can modify. */
|
||||
portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_ONLY );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Setup RAM containing kernel data for privileged access only. */
|
||||
portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
|
||||
portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Enable mem fault. */
|
||||
portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable MPU with privileged background access i.e. unmapped
|
||||
* regions have privileged access. */
|
||||
portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE | portMPU_ENABLE );
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* Enable non-secure access to the FPU. */
|
||||
SecureInit_EnableNSFPUAccess();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/* CP10 = 11 ==> Full access to FPU i.e. both privileged and
|
||||
* unprivileged code should be able to access FPU. CP11 should be
|
||||
* programmed to the same value as CP10. */
|
||||
*( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
|
||||
( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
|
||||
);
|
||||
|
||||
/* ASPEN = 1 ==> Hardware should automatically preserve floating point
|
||||
* context on exception entry and restore on exception return.
|
||||
* LSPEN = 1 ==> Enable lazy context save of FP state. */
|
||||
*( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortYield( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Set a PendSV to request a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* Barriers are normally not required but do ensure the code is
|
||||
* completely within the specified behaviour for the architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
configASSERT( ulCriticalNesting );
|
||||
ulCriticalNesting--;
|
||||
|
||||
if( ulCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
uint32_t ulPreviousMask;
|
||||
|
||||
ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* Pend a context switch. */
|
||||
*( portNVIC_INT_CTRL ) = portNVIC_PENDSVSET;
|
||||
}
|
||||
}
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
|
||||
{
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#if defined( __ARMCC_VERSION )
|
||||
/* Declaration when these variable are defined in code instead of being
|
||||
* exported from linker scripts. */
|
||||
extern uint32_t * __syscalls_flash_start__;
|
||||
extern uint32_t * __syscalls_flash_end__;
|
||||
#else
|
||||
/* Declaration when these variable are exported from linker scripts. */
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* defined( __ARMCC_VERSION ) */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
uint32_t ulPC;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
uint32_t ulR0;
|
||||
#if( configENABLE_MPU == 1 )
|
||||
uint32_t ulControl, ulIsTaskPrivileged;
|
||||
#endif /* configENABLE_MPU */
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
uint8_t ucSVCNumber;
|
||||
|
||||
/* Register are stored on the stack in the following order - R0, R1, R2, R3,
|
||||
* R12, LR, PC, xPSR. */
|
||||
ulPC = pulCallerStackAddress[ 6 ];
|
||||
ucSVCNumber = ( ( uint8_t *) ulPC )[ -2 ];
|
||||
|
||||
switch( ucSVCNumber )
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
case portSVC_ALLOCATE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the stack size passed as parameter to the
|
||||
* vPortAllocateSecureContext function. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Read the CONTROL register value. */
|
||||
__asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
|
||||
|
||||
/* The task that raised the SVC is privileged if Bit[0]
|
||||
* in the CONTROL register is 0. */
|
||||
ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
|
||||
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Allocate and load a context for the secure task. */
|
||||
xSecureContext = SecureContext_AllocateContext( ulR0 );
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
configASSERT( xSecureContext != NULL );
|
||||
SecureContext_LoadContext( xSecureContext );
|
||||
}
|
||||
break;
|
||||
|
||||
case portSVC_FREE_SECURE_CONTEXT:
|
||||
{
|
||||
/* R0 contains the secure context handle to be freed. */
|
||||
ulR0 = pulCallerStackAddress[ 0 ];
|
||||
|
||||
/* Free the secure context. */
|
||||
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
case portSVC_START_SCHEDULER:
|
||||
{
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
/* De-prioritize the non-secure exceptions so that the
|
||||
* non-secure pendSV runs at the lowest priority. */
|
||||
SecureInit_DePrioritizeNSExceptions();
|
||||
|
||||
/* Initialize the secure context management system. */
|
||||
SecureContext_Init();
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_FPU == 1 )
|
||||
{
|
||||
/* Setup the Floating Point Unit (FPU). */
|
||||
prvSetupFPU();
|
||||
}
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
/* Setup the context of the first task so that the first task starts
|
||||
* executing. */
|
||||
vRestoreContextOfFirstTask();
|
||||
}
|
||||
break;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
case portSVC_RAISE_PRIVILEGE:
|
||||
{
|
||||
/* Only raise the privilege, if the svc was raised from any of
|
||||
* the system calls. */
|
||||
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||
{
|
||||
vRaisePrivilege();
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
default:
|
||||
{
|
||||
/* Incorrect SVC call. */
|
||||
configASSERT( pdFALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
|
||||
#else
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, StackType_t *pxEndOfStack, TaskFunction_t pxCode, void *pvParameters ) /* PRIVILEGED_FUNCTION */
|
||||
#endif /* configENABLE_MPU */
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
#if( portPRELOAD_REGISTERS == 0 )
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#else /* portPRELOAD_REGISTERS */
|
||||
{
|
||||
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxCode; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
{
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
|
||||
}
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
}
|
||||
#endif /* portPRELOAD_REGISTERS */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_PENDSV_PRI;
|
||||
*( portNVIC_SYSPRI2 ) |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
{
|
||||
/* Setup the Memory Protection Unit (MPU). */
|
||||
prvSetupMPU();
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialize the critical nesting count ready for the first task. */
|
||||
ulCriticalNesting = 0;
|
||||
|
||||
/* Start the first task. */
|
||||
vStartFirstTask();
|
||||
|
||||
/* Should never get here as the tasks will now be executing. Call the task
|
||||
* exit error function to prevent compiler warnings about a static function
|
||||
* not being called in the case that the application writer overrides this
|
||||
* functionality by defining configTASK_RETURN_ADDRESS. Call
|
||||
* vTaskSwitchContext() so link time optimization does not remove the
|
||||
* symbol. */
|
||||
vTaskSwitchContext();
|
||||
prvTaskExitError();
|
||||
|
||||
/* Should not get here. */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
|
||||
int32_t lIndex = 0;
|
||||
|
||||
/* Setup MAIR0. */
|
||||
xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
|
||||
xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
|
||||
|
||||
/* This function is called automatically when the task is created - in
|
||||
* which case the stack region parameters will be valid. At all other
|
||||
* times the stack parameters will not be valid and it is assumed that
|
||||
* the stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) pxBottomOfStack ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE ) |
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_EXECUTE_NEVER );
|
||||
|
||||
xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_ATTR_INDEX0 ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
}
|
||||
|
||||
/* User supplied configurable regions. */
|
||||
for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
|
||||
{
|
||||
/* If xRegions is NULL i.e. the task has not specified any MPU
|
||||
* region, the else part ensures that all the configurable MPU
|
||||
* regions are invalidated. */
|
||||
if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
|
||||
{
|
||||
/* Translate the generic region definition contained in xRegions
|
||||
* into the ARMv8 specific MPU settings that are then stored in
|
||||
* xMPUSettings. */
|
||||
ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
|
||||
ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
|
||||
ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
|
||||
|
||||
/* Start address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
|
||||
( portMPU_REGION_NON_SHAREABLE );
|
||||
|
||||
/* RO/RW. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
|
||||
}
|
||||
else
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
|
||||
}
|
||||
|
||||
/* XN. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
|
||||
{
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
|
||||
}
|
||||
|
||||
/* End Address. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
|
||||
( portMPU_RLAR_REGION_ENABLE );
|
||||
|
||||
/* Normal memory/ Device memory. */
|
||||
if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as device memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Attr1 in MAIR0 is configured as normal memory. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
|
||||
xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. Interrupt Program
|
||||
* Status Register (IPSR) holds the exception number of the currently-executing
|
||||
* exception or zero for Thread mode.*/
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
113
portable/IAR/ARM_CM33_NTZ/non_secure/portasm.h
Normal file
113
portable/IAR/ARM_CM33_NTZ/non_secure/portasm.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef __PORT_ASM_H__
|
||||
#define __PORT_ASM_H__
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
/* MPU wrappers includes. */
|
||||
#include "mpu_wrappers.h"
|
||||
|
||||
/**
|
||||
* @brief Restore the context of the first task so that the first task starts
|
||||
* executing.
|
||||
*/
|
||||
void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
BaseType_t xIsPrivileged( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Raises the privilege level by clearing the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* @note This is a privileged function and should only be called from the kenrel
|
||||
* code.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*
|
||||
* Bit 0 of the CONTROL register defines the privilege level of Thread Mode.
|
||||
* Bit[0] = 0 --> The processor is running privileged
|
||||
* Bit[0] = 1 --> The processor is running unprivileged.
|
||||
*/
|
||||
void vResetPrivilege( void ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Starts the first task.
|
||||
*/
|
||||
void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts.
|
||||
*/
|
||||
uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts.
|
||||
*/
|
||||
void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief PendSV Exception handler.
|
||||
*/
|
||||
void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief SVC Handler.
|
||||
*/
|
||||
void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Allocate a Secure context for the calling task.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the stack to be allocated on the
|
||||
* secure side for the calling task.
|
||||
*/
|
||||
void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) __attribute__ (( naked ));
|
||||
|
||||
/**
|
||||
* @brief Free the task's secure context.
|
||||
*
|
||||
* @param[in] pulTCB Pointer to the Task Control Block (TCB) of the task.
|
||||
*/
|
||||
void vPortFreeSecureContext( uint32_t *pulTCB ) __attribute__ (( naked )) PRIVILEGED_FUNCTION;
|
||||
|
||||
#endif /* __PORT_ASM_H__ */
|
||||
258
portable/IAR/ARM_CM33_NTZ/non_secure/portasm.s
Normal file
258
portable/IAR/ARM_CM33_NTZ/non_secure/portasm.s
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
PUBLIC vRestoreContextOfFirstTask
|
||||
PUBLIC vRaisePrivilege
|
||||
PUBLIC vStartFirstTask
|
||||
PUBLIC ulSetInterruptMask
|
||||
PUBLIC vClearInterruptMask
|
||||
PUBLIC PendSV_Handler
|
||||
PUBLIC SVC_Handler
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*---------------- Unprivileged Functions -------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
ite ne
|
||||
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is not privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*----------------- Privileged Functions --------------------*/
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SECTION privileged_functions:CODE:NOROOT(2)
|
||||
THUMB
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRestoreContextOfFirstTask:
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r3, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r2] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldm r0!, {r1-r3} /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
msr control, r2 /* Set this task's CONTROL value. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r3 /* Finally, branch to EXC_RETURN. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldm r0!, {r1-r2} /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */
|
||||
msr psplim, r1 /* Set this task's PSPLIM value. */
|
||||
movs r1, #2 /* r1 = 2. */
|
||||
msr CONTROL, r1 /* Switch to use PSP in the thread mode. */
|
||||
adds r0, #32 /* Discard everything up to r0. */
|
||||
msr psp, r0 /* This is now the new top of stack to use in the task. */
|
||||
isb
|
||||
bx r2 /* Finally, branch to EXC_RETURN. */
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vRaisePrivilege:
|
||||
mrs r0, control /* Read the CONTROL register. */
|
||||
bic r0, r0, #1 /* Clear the bit 0. */
|
||||
msr control, r0 /* Write back the new CONTROL value. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vStartFirstTask:
|
||||
ldr r0, =0xe000ed08 /* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, [r0] /* Read the VTOR register which gives the address of vector table. */
|
||||
ldr r0, [r0] /* The first entry in vector table is stack pointer. */
|
||||
msr msp, r0 /* Set the MSP back to the start of the stack. */
|
||||
cpsie i /* Globally enable interrupts. */
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 2 /* System call to start the first task. portSVC_START_SCHEDULER = 2. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
ulSetInterruptMask:
|
||||
mrs r0, basepri /* r0 = basepri. Return original basepri value. */
|
||||
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r1 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vClearInterruptMask:
|
||||
msr basepri, r0 /* basepri = ulMask. */
|
||||
dsb
|
||||
isb
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
PendSV_Handler:
|
||||
mrs r0, psp /* Read PSP in r0. */
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
tst lr, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31} /* Store the FPU registers which are not saved automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
mrs r1, psplim /* r1 = PSPLIM. */
|
||||
mrs r2, control /* r2 = CONTROL. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmdb r0!, {r1-r11} /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */
|
||||
#else /* configENABLE_MPU */
|
||||
mrs r2, psplim /* r2 = PSPLIM. */
|
||||
mov r3, lr /* r3 = LR/EXC_RETURN. */
|
||||
stmdb r0!, {r2-r11} /* Store on the stack - PSPLIM, LR and registers that are not automatically. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
str r0, [r1] /* Save the new top of stack in TCB. */
|
||||
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0 /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0 /* r0 = 0. */
|
||||
msr basepri, r0 /* Enable interrupts. */
|
||||
|
||||
ldr r2, =pxCurrentTCB /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */
|
||||
ldr r1, [r2] /* Read pxCurrentTCB. */
|
||||
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r4, r4, #1 /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */
|
||||
str r4, [r2] /* Disable MPU. */
|
||||
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */
|
||||
ldr r3, [r1] /* r3 = *r1 i.e. r3 = MAIR0. */
|
||||
ldr r2, =0xe000edc0 /* r2 = 0xe000edc0 [Location of MAIR0]. */
|
||||
str r3, [r2] /* Program MAIR0. */
|
||||
ldr r2, =0xe000ed98 /* r2 = 0xe000ed98 [Location of RNR]. */
|
||||
movs r3, #4 /* r3 = 4. */
|
||||
str r3, [r2] /* Program RNR = 4. */
|
||||
adds r1, #4 /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */
|
||||
ldr r2, =0xe000ed9c /* r2 = 0xe000ed9c [Location of RBAR]. */
|
||||
ldmia r1!, {r4-r11} /* Read 4 sets of RBAR/RLAR registers from TCB. */
|
||||
stmia r2!, {r4-r11} /* Write 4 set of RBAR/RLAR registers using alias registers. */
|
||||
|
||||
ldr r2, =0xe000ed94 /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */
|
||||
ldr r4, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r4, r4, #1 /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */
|
||||
str r4, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
ldmia r0!, {r1-r11} /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */
|
||||
#else /* configENABLE_MPU */
|
||||
ldmia r0!, {r2-r11} /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#if ( configENABLE_FPU == 1 )
|
||||
tst r3, #0x10 /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31} /* Restore the FPU registers which are not restored automatically. */
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#if ( configENABLE_MPU == 1 )
|
||||
msr psplim, r1 /* Restore the PSPLIM register value for the task. */
|
||||
msr control, r2 /* Restore the CONTROL register value for the task. */
|
||||
#else /* configENABLE_MPU */
|
||||
msr psplim, r2 /* Restore the PSPLIM register value for the task. */
|
||||
#endif /* configENABLE_MPU */
|
||||
msr psp, r0 /* Remember the new top of stack for the task. */
|
||||
bx r3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
SVC_Handler:
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
b vPortSVCHandler_C
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
308
portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h
Normal file
308
portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef configENABLE_FPU
|
||||
#error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU.
|
||||
#endif /* configENABLE_FPU */
|
||||
|
||||
#ifndef configENABLE_MPU
|
||||
#error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU.
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
#ifndef configENABLE_TRUSTZONE
|
||||
#error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone.
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Type definitions.
|
||||
*/
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Architecture specifics.
|
||||
*/
|
||||
#define portARCH_NAME "Cortex-M33"
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portNOP()
|
||||
#define portINLINE __inline
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline ))
|
||||
#endif
|
||||
#define portHAS_STACK_OVERFLOW_CHECKING 1
|
||||
#define portDONT_DISCARD __root
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Extern declarations.
|
||||
*/
|
||||
extern BaseType_t xPortIsInsideInterrupt( void );
|
||||
|
||||
extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */;
|
||||
|
||||
extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */;
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */
|
||||
extern void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */;
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */;
|
||||
extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */;
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief MPU specific constants.
|
||||
*/
|
||||
#if( configENABLE_MPU == 1 )
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
#else
|
||||
#define portPRIVILEGE_BIT ( 0x0UL )
|
||||
#endif /* configENABLE_MPU */
|
||||
|
||||
|
||||
/* MPU regions. */
|
||||
#define portPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
/* Device memory attributes used in MPU_MAIR registers.
|
||||
*
|
||||
* 8-bit values encoded as follows:
|
||||
* Bit[7:4] - 0000 - Device Memory
|
||||
* Bit[3:2] - 00 --> Device-nGnRnE
|
||||
* 01 --> Device-nGnRE
|
||||
* 10 --> Device-nGRE
|
||||
* 11 --> Device-GRE
|
||||
* Bit[1:0] - 00, Reserved.
|
||||
*/
|
||||
#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */
|
||||
#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */
|
||||
#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */
|
||||
#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */
|
||||
|
||||
/* Normal memory attributes used in MPU_MAIR registers. */
|
||||
#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */
|
||||
#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */
|
||||
|
||||
/* Attributes used in MPU_RBAR registers. */
|
||||
#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL )
|
||||
#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL )
|
||||
#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL )
|
||||
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL )
|
||||
#define portMPU_REGION_READ_WRITE ( 1UL << 1UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 3UL << 1UL )
|
||||
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 1UL )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Settings to define an MPU region.
|
||||
*/
|
||||
typedef struct MPURegionSettings
|
||||
{
|
||||
uint32_t ulRBAR; /**< RBAR for the region. */
|
||||
uint32_t ulRLAR; /**< RLAR for the region. */
|
||||
} MPURegionSettings_t;
|
||||
|
||||
/**
|
||||
* @brief MPU settings as stored in the TCB.
|
||||
*/
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */
|
||||
MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */
|
||||
} xMPU_SETTINGS;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief SVC numbers.
|
||||
*/
|
||||
#define portSVC_ALLOCATE_SECURE_CONTEXT 0
|
||||
#define portSVC_FREE_SECURE_CONTEXT 1
|
||||
#define portSVC_START_SCHEDULER 2
|
||||
#define portSVC_RAISE_PRIVILEGE 3
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Scheduler utilities.
|
||||
*/
|
||||
#define portYIELD() vPortYield()
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Critical section management.
|
||||
*/
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMask( x )
|
||||
#define portDISABLE_INTERRUPTS() ulSetInterruptMask()
|
||||
#define portENABLE_INTERRUPTS() vClearInterruptMask( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Task function macros as described on the FreeRTOS.org WEB site.
|
||||
*/
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_TRUSTZONE == 1 )
|
||||
/**
|
||||
* @brief Allocate a secure context for the task.
|
||||
*
|
||||
* Tasks are not created with a secure context. Any task that is going to call
|
||||
* secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a
|
||||
* secure context before it calls any secure function.
|
||||
*
|
||||
* @param[in] ulSecureStackSize The size of the secure stack to be allocated.
|
||||
*/
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize )
|
||||
|
||||
/**
|
||||
* @brief Called when a task is deleted to delete the task's secure context,
|
||||
* if it has one.
|
||||
*
|
||||
* @param[in] pxTCB The TCB of the task being deleted.
|
||||
*/
|
||||
#define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB )
|
||||
#else
|
||||
#define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize )
|
||||
#define portCLEAN_UP_TCB( pxTCB )
|
||||
#endif /* configENABLE_TRUSTZONE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configENABLE_MPU == 1 )
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*
|
||||
* The SVC handler checks that the SVC was raised from a system call and only
|
||||
* then it raises the privilege. If this is called from any other place,
|
||||
* the privilege is not raised.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
#else
|
||||
#define portIS_PRIVILEGED()
|
||||
#define portRAISE_PRIVILEGE()
|
||||
#define portRESET_PRIVILEGE()
|
||||
#endif /* configENABLE_MPU */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Barriers.
|
||||
*/
|
||||
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
* warnings. */
|
||||
#pragma diag_suppress=Be006
|
||||
#pragma diag_suppress=Pa082
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
656
portable/IAR/ARM_CM4F/port.c
Normal file
656
portable/IAR/ARM_CM4F/port.c
Normal file
|
|
@ -0,0 +1,656 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#ifndef __ARMVFP__
|
||||
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||
#endif
|
||||
|
||||
#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
|
||||
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||
#endif
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#else
|
||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||
as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to manipulate the core. Registers first... */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||
|
||||
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
|
||||
r0p1 port. */
|
||||
#define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
|
||||
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )
|
||||
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )
|
||||
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||
|
||||
/* Constants required to manipulate the VFP. */
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
|
||||
/* The systick is a 24-bit counter. */
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
|
||||
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||
occurred while the SysTick counter is stopped during tickless idle
|
||||
calculations. */
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
|
||||
/* For strict compliance with the Cortex-M spec the task start address should
|
||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortSysTickHandler( void );
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/*
|
||||
* Turn the VFP on.
|
||||
*/
|
||||
extern void vPortEnableVFP( void );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* The number of SysTick increments that make up one tick period.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulTimerCountsForOneTick = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* The maximum number of tick periods that can be suppressed is limited by the
|
||||
* 24 bit resolution of the SysTick timer.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||
* power functionality only.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulStoppedTimerCompensation = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
interrupt. */
|
||||
|
||||
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||
of interrupts, and to ensure alignment. */
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||
|
||||
/* Save code space by skipping register initialisation. */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
|
||||
/* A save method is being used that requires each task to maintain its
|
||||
own exec return value. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* 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
|
||||
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( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
|
||||
/* This port can be used on all revisions of the Cortex-M7 core other than
|
||||
the r0p1 parts. r0p1 parts should use the port from the
|
||||
/source/portable/GCC/ARM_CM7/r0p1 directory. */
|
||||
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
|
||||
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
functions can be called. ISR safe functions are those that end in
|
||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
{
|
||||
/* Check the CMSIS configuration that defines the number of
|
||||
priority bits matches the number of priority bits actually queried
|
||||
from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef configPRIO_BITS
|
||||
{
|
||||
/* Check the FreeRTOS configuration that defines the number of
|
||||
priority bits matches the number of priority bits actually queried
|
||||
from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Ensure the VFP is enabled - it should be anyway. */
|
||||
vPortEnableVFP();
|
||||
|
||||
/* Lazy save always. */
|
||||
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( uxCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||
executes all interrupts must be unmasked. There is therefore no need to
|
||||
save and then restore the interrupt mask value as its value is already
|
||||
known. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is required. Context switching is performed in
|
||||
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
|
||||
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||
TickType_t xModifiableIdleTime;
|
||||
|
||||
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
|
||||
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||
is accounted for as best it can be, but using the tickless mode will
|
||||
inevitably result in some tiny drift of the time maintained by the
|
||||
kernel with respect to calendar time. */
|
||||
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||
tick periods. -1 is used because this code will execute part way
|
||||
through one of the tick periods. */
|
||||
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
ulReloadValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||
method as that will mask interrupts that should exit sleep mode. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* If a context switch is pending or a task is waiting for the scheduler
|
||||
to be unsuspended then abandon the low power entry. */
|
||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||
{
|
||||
/* Restart from whatever is left in the count register to complete
|
||||
this tick period. */
|
||||
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Reset the reload register to the value required for normal tick
|
||||
periods. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||
call above. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new reload value. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||
|
||||
/* Clear the SysTick count flag and set the count value back to
|
||||
zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||
set its parameter to 0 to indicate that its implementation contains
|
||||
its own wait for interrupt or wait for event instruction, and so wfi
|
||||
should not be executed again. However, the original expected idle
|
||||
time variable must remain unmodified, so a copy is taken. */
|
||||
xModifiableIdleTime = xExpectedIdleTime;
|
||||
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
}
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||
out of sleep mode to execute immediately. see comments above
|
||||
__disable_interrupt() call above. */
|
||||
__enable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable interrupts again because the clock is about to be stopped
|
||||
and interrupts that execute while the clock is stopped will increase
|
||||
any slippage between the time maintained by the RTOS and calendar
|
||||
time. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable the SysTick clock without reading the
|
||||
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
|
||||
the time the SysTick is stopped for is accounted for as best it can
|
||||
be, but using the tickless mode will inevitably result in some tiny
|
||||
drift of the time maintained by the kernel with respect to calendar
|
||||
time*/
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||
|
||||
/* Determine if the SysTick clock has already counted to zero and
|
||||
been set back to the current reload value (the reload back being
|
||||
correct for the entire expected idle time) or if the SysTick is yet
|
||||
to count to zero (in which case an interrupt other than the SysTick
|
||||
must have brought the system out of sleep mode). */
|
||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
|
||||
/* The tick interrupt is already pending, and the SysTick count
|
||||
reloaded with ulReloadValue. Reset the
|
||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||
period. */
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||
|
||||
/* Don't allow a tiny value, or values that have somehow
|
||||
underflowed because the post sleep hook did something
|
||||
that took too long. */
|
||||
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||
{
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||
}
|
||||
|
||||
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||
|
||||
/* 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 waiting. */
|
||||
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something other than the tick interrupt ended the sleep.
|
||||
Work out how long the sleep lasted rounded to complete tick
|
||||
periods (not the ulReload value which accounted for part
|
||||
ticks). */
|
||||
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* How many complete tick periods passed while the processor
|
||||
was waiting? */
|
||||
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||
|
||||
/* The reload value is set to whatever fraction of a single tick
|
||||
period remains. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||
}
|
||||
|
||||
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||
value. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Exit with interrupts enabled. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
__weak void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Stop and clear the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
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.
|
||||
|
||||
Interrupts that use the FreeRTOS API must not be left at their
|
||||
default priority of zero as that is the highest possible priority,
|
||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
and therefore also guaranteed to be invalid.
|
||||
|
||||
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( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) 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).
|
||||
|
||||
If the application only uses CMSIS libraries for interrupt
|
||||
configuration then the correct setting can be achieved on all Cortex-M
|
||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
scheduler. Note however that some vendor specific peripheral libraries
|
||||
assume a non-zero priority group setting, in which cases using a value
|
||||
of zero will result in unpredictable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
149
portable/IAR/ARM_CM4F/portasm.s
Normal file
149
portable/IAR/ARM_CM4F/portasm.s
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#include <FreeRTOSConfig.h>
|
||||
|
||||
RSEG CODE:CODE(2)
|
||||
thumb
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
|
||||
PUBLIC xPortPendSVHandler
|
||||
PUBLIC vPortSVCHandler
|
||||
PUBLIC vPortStartFirstTask
|
||||
PUBLIC vPortEnableVFP
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xPortPendSVHandler:
|
||||
mrs r0, psp
|
||||
isb
|
||||
/* Get the location of the current TCB. */
|
||||
ldr r3, =pxCurrentTCB
|
||||
ldr r2, [r3]
|
||||
|
||||
/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31}
|
||||
|
||||
/* Save the core registers. */
|
||||
stmdb r0!, {r4-r11, r14}
|
||||
|
||||
/* Save the new top of stack into the first member of the TCB. */
|
||||
str r0, [r2]
|
||||
|
||||
stmdb sp!, {r0, r3}
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r0, r3}
|
||||
|
||||
/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
|
||||
/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
|
||||
/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||
too. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31}
|
||||
|
||||
msr psp, r0
|
||||
isb
|
||||
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
|
||||
#if WORKAROUND_PMU_CM001 == 1
|
||||
push { r14 }
|
||||
pop { pc }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bx r14
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortSVCHandler:
|
||||
/* Get the location of the current TCB. */
|
||||
ldr r3, =pxCurrentTCB
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
msr psp, r0
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
bx r14
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortStartFirstTask
|
||||
/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, =0xE000ED08
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||
before the scheduler was started - which would otherwise result in the
|
||||
unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||
registers. */
|
||||
mov r0, #0
|
||||
msr control, r0
|
||||
/* Call SVC to start the first task. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 0
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortEnableVFP:
|
||||
/* The FPU enable bits are in the CPACR. */
|
||||
ldr.w r0, =0xE000ED88
|
||||
ldr r1, [r0]
|
||||
|
||||
/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||
orr r1, r1, #( 0xf << 20 )
|
||||
str r1, [r0]
|
||||
bx r14
|
||||
|
||||
|
||||
|
||||
END
|
||||
|
||||
207
portable/IAR/ARM_CM4F/portmacro.h
Normal file
207
portable/IAR/ARM_CM4F/portmacro.h
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler directives. */
|
||||
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/* Check the configuration. */
|
||||
#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.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_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 ) ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
__set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() __set_BASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_BASEPRI(); portDISABLE_INTERRUPTS()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) __set_BASEPRI( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
warnings. */
|
||||
#pragma diag_suppress=Pe191
|
||||
#pragma diag_suppress=Pa082
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
749
portable/IAR/ARM_CM4F_MPU/port.c
Normal file
749
portable/IAR/ARM_CM4F_MPU/port.c
Normal file
|
|
@ -0,0 +1,749 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
* all the API functions to use the MPU wrappers. That should only be done when
|
||||
* task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#ifndef __ARMVFP__
|
||||
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||
#endif
|
||||
|
||||
#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
|
||||
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||
#endif
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#else
|
||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||
as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to manipulate the core. Registers first... */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
#define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) )
|
||||
#define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) )
|
||||
#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL )
|
||||
|
||||
/* Constants required to access and manipulate the MPU. */
|
||||
#define portMPU_TYPE_REG ( * ( ( volatile uint32_t * ) 0xe000ed90 ) )
|
||||
#define portMPU_REGION_BASE_ADDRESS_REG ( * ( ( volatile uint32_t * ) 0xe000ed9C ) )
|
||||
#define portMPU_REGION_ATTRIBUTE_REG ( * ( ( volatile uint32_t * ) 0xe000edA0 ) )
|
||||
#define portMPU_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed94 ) )
|
||||
#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */
|
||||
#define portMPU_ENABLE ( 0x01UL )
|
||||
#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL )
|
||||
#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL )
|
||||
#define portMPU_REGION_VALID ( 0x10UL )
|
||||
#define portMPU_REGION_ENABLE ( 0x01UL )
|
||||
#define portPERIPHERALS_START_ADDRESS 0x40000000UL
|
||||
#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL
|
||||
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||
|
||||
/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7
|
||||
* r0p1 port. */
|
||||
#define portCPUID ( * ( ( volatile uint32_t * ) 0xE000ed00 ) )
|
||||
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )
|
||||
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )
|
||||
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||
|
||||
/* Constants required to manipulate the VFP. */
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 )
|
||||
#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 )
|
||||
|
||||
/* Offsets in the stack to the parameters when inside the SVC handler. */
|
||||
#define portOFFSET_TO_PC ( 6 )
|
||||
|
||||
/* The systick is a 24-bit counter. */
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
|
||||
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||
occurred while the SysTick counter is stopped during tickless idle
|
||||
calculations. */
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
|
||||
/* For strict compliance with the Cortex-M spec the task start address should
|
||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/*
|
||||
* Configure a number of standard MPU regions that are used by all tasks.
|
||||
*/
|
||||
static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Return the smallest MPU region size that a given number of bytes will fit
|
||||
* into. The region size is returned as the value that should be programmed
|
||||
* into the region attribute register for that region.
|
||||
*/
|
||||
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortSysTickHandler( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
extern void vPortStartFirstTask( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Turn the VFP on.
|
||||
*/
|
||||
extern void vPortEnableVFP( void );
|
||||
|
||||
/*
|
||||
* The C portion of the SVC handler.
|
||||
*/
|
||||
void vPortSVCHandler_C( uint32_t *pulParam );
|
||||
|
||||
/*
|
||||
* Called from the SVC handler used to start the scheduler.
|
||||
*/
|
||||
extern void vPortRestoreContextOfFirstTask( void ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/**
|
||||
* @brief Calls the port specific code to raise the privilege.
|
||||
*
|
||||
* @return pdFALSE if privilege was raised, pdTRUE otherwise.
|
||||
*/
|
||||
extern BaseType_t xPortRaisePrivilege( void );
|
||||
|
||||
/**
|
||||
* @brief If xRunningPrivileged is not pdTRUE, calls the port specific
|
||||
* code to reset the privilege, otherwise does nothing.
|
||||
*/
|
||||
extern void vPortResetPrivilege( BaseType_t xRunningPrivileged );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
* interrupt. */
|
||||
|
||||
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||
* of interrupts, and to ensure alignment. */
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0; /* LR */
|
||||
|
||||
/* Save code space by skipping register initialisation. */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
|
||||
/* A save method is being used that requires each task to maintain its
|
||||
* own exec return value. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
if( xRunPrivileged == pdTRUE )
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED;
|
||||
}
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortSVCHandler_C( uint32_t *pulParam )
|
||||
{
|
||||
uint8_t ucSVCNumber;
|
||||
uint32_t ulPC;
|
||||
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||
extern uint32_t __syscalls_flash_start__[];
|
||||
extern uint32_t __syscalls_flash_end__[];
|
||||
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||
|
||||
/* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
|
||||
* argument (r0) is pulParam[ 0 ]. */
|
||||
ulPC = pulParam[ portOFFSET_TO_PC ];
|
||||
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
|
||||
switch( ucSVCNumber )
|
||||
{
|
||||
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
|
||||
vPortRestoreContextOfFirstTask();
|
||||
break;
|
||||
|
||||
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
/* Barriers are normally not required
|
||||
* but do ensure the code is completely
|
||||
* within the specified behaviour for the
|
||||
* architecture. */
|
||||
__asm volatile( "dsb" ::: "memory" );
|
||||
__asm volatile( "isb" );
|
||||
|
||||
break;
|
||||
|
||||
#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 )
|
||||
case portSVC_RAISE_PRIVILEGE : /* Only raise the privilege, if the
|
||||
* svc was raised from any of the
|
||||
* system calls. */
|
||||
if( ulPC >= ( uint32_t ) __syscalls_flash_start__ &&
|
||||
ulPC <= ( uint32_t ) __syscalls_flash_end__ )
|
||||
{
|
||||
__asm volatile
|
||||
(
|
||||
" mrs r1, control \n" /* Obtain current control value. */
|
||||
" bic r1, r1, #1 \n" /* Set privilege bit. */
|
||||
" msr control, r1 \n" /* Write back new control value. */
|
||||
::: "r1", "memory"
|
||||
);
|
||||
}
|
||||
break;
|
||||
#else
|
||||
case portSVC_RAISE_PRIVILEGE : __asm volatile
|
||||
(
|
||||
" mrs r1, control \n" /* Obtain current control value. */
|
||||
" bic r1, r1, #1 \n" /* Set privilege bit. */
|
||||
" msr control, r1 \n" /* Write back new control value. */
|
||||
::: "r1", "memory"
|
||||
);
|
||||
break;
|
||||
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
|
||||
|
||||
default : /* Unknown SVC call. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||
* See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
|
||||
/* This port can be used on all revisions of the Cortex-M7 core other than
|
||||
* the r0p1 parts. r0p1 parts should use the port from the
|
||||
* /source/portable/GCC/ARM_CM7/r0p1 directory. */
|
||||
configASSERT( portCPUID != portCORTEX_M7_r0p1_ID );
|
||||
configASSERT( portCPUID != portCORTEX_M7_r0p0_ID );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
* functions can be called. ISR safe functions are those that end in
|
||||
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
* ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
* possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
* of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
{
|
||||
/* Check the CMSIS configuration that defines the number of
|
||||
* priority bits matches the number of priority bits actually queried
|
||||
* from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef configPRIO_BITS
|
||||
{
|
||||
/* Check the FreeRTOS configuration that defines the number of
|
||||
* priority bits matches the number of priority bits actually queried
|
||||
* from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
* register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
* value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Configure the regions in the MPU that are common to all tasks. */
|
||||
prvSetupMPU();
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
* here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Ensure the VFP is enabled - it should be anyway. */
|
||||
vPortEnableVFP();
|
||||
|
||||
/* Lazy save always. */
|
||||
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
* Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
vPortResetPrivilege( xRunningPrivileged );
|
||||
|
||||
/* 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
|
||||
* 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
|
||||
* assert function also uses a critical section. */
|
||||
if( uxCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
BaseType_t xRunningPrivileged = xPortRaisePrivilege();
|
||||
|
||||
configASSERT( uxCriticalNesting );
|
||||
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
|
||||
vPortResetPrivilege( xRunningPrivileged );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||
* executes all interrupts must be unmasked. There is therefore no need to
|
||||
* save and then restore the interrupt mask value as its value is already
|
||||
* known. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is required. Context switching is performed in
|
||||
* the PendSV interrupt. Pend the PendSV interrupt. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
__weak void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Stop and clear the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupMPU( void )
|
||||
{
|
||||
extern uint32_t __privileged_functions_end__[];
|
||||
extern uint32_t __FLASH_segment_start__[];
|
||||
extern uint32_t __FLASH_segment_end__[];
|
||||
extern uint32_t __privileged_data_start__[];
|
||||
extern uint32_t __privileged_data_end__[];
|
||||
|
||||
/* Check the expected MPU is present. */
|
||||
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
|
||||
{
|
||||
/* First setup the entire flash for unprivileged read only access. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portUNPRIVILEGED_FLASH_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Setup the first 16K for privileged only access (even though less
|
||||
* than 10K is actually being used). This is where the kernel code is
|
||||
* placed. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portPRIVILEGED_FLASH_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Setup the privileged data RAM region. This is where the kernel data
|
||||
* is placed. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portPRIVILEGED_RAM_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* By default allow everything to access the general peripherals. The
|
||||
* system peripherals and registers are protected. */
|
||||
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portGENERAL_PERIPHERALS_REGION );
|
||||
|
||||
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) |
|
||||
( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Enable the memory fault exception. */
|
||||
portNVIC_SYS_CTRL_STATE_REG |= portNVIC_MEM_FAULT_ENABLE;
|
||||
|
||||
/* Enable the MPU with the background region configured. */
|
||||
portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
|
||||
{
|
||||
uint32_t ulRegionSize, ulReturnValue = 4;
|
||||
|
||||
/* 32 is the smallest region size, 31 is the largest valid value for
|
||||
* ulReturnValue. */
|
||||
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
|
||||
{
|
||||
if( ulActualSizeInBytes <= ulRegionSize )
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ulReturnValue++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Shift the code by one before returning so it can be written directly
|
||||
* into the the correct bit position of the attribute register. */
|
||||
return ( ulReturnValue << 1UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth )
|
||||
{
|
||||
extern uint32_t __SRAM_segment_start__[];
|
||||
extern uint32_t __SRAM_segment_end__[];
|
||||
extern uint32_t __privileged_data_start__[];
|
||||
extern uint32_t __privileged_data_end__[];
|
||||
int32_t lIndex;
|
||||
uint32_t ul;
|
||||
|
||||
if( xRegions == NULL )
|
||||
{
|
||||
/* No MPU regions are specified so allow access to all RAM. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION );
|
||||
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
( portMPU_REGION_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
|
||||
* just removed the privileged only parameters. */
|
||||
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION + 1 );
|
||||
|
||||
xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
|
||||
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
|
||||
/* Invalidate all other regions. */
|
||||
for( ul = 2; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This function is called automatically when the task is created - in
|
||||
* which case the stack region parameters will be valid. At all other
|
||||
* times the stack parameters will not be valid and it is assumed that the
|
||||
* stack region has already been configured. */
|
||||
if( ulStackDepth > 0 )
|
||||
{
|
||||
/* Define the region that allows access to the stack. */
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) pxBottomOfStack ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION ); /* Region number. */
|
||||
|
||||
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
|
||||
( portMPU_REGION_READ_WRITE ) | /* Read and write. */
|
||||
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
|
||||
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
}
|
||||
|
||||
lIndex = 0;
|
||||
|
||||
for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ )
|
||||
{
|
||||
if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL )
|
||||
{
|
||||
/* Translate the generic region definition contained in
|
||||
* xRegions into the CM3 specific MPU settings that are then
|
||||
* stored in xMPUSettings. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress =
|
||||
( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) |
|
||||
( portMPU_REGION_VALID ) |
|
||||
( portSTACK_REGION + ul ); /* Region number. */
|
||||
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute =
|
||||
( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) |
|
||||
( xRegions[ lIndex ].ulParameters ) |
|
||||
( portMPU_REGION_ENABLE );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalidate the region. */
|
||||
xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( portSTACK_REGION + ul ) | portMPU_REGION_VALID;
|
||||
xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL;
|
||||
}
|
||||
|
||||
lIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
* an interrupt that has been assigned a priority above
|
||||
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
* function. ISR safe FreeRTOS API functions must *only* be called
|
||||
* from interrupts that have been assigned a priority at or below
|
||||
* 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.
|
||||
|
||||
* Interrupts that use the FreeRTOS API must not be left at their
|
||||
* default priority of zero as that is the highest possible priority,
|
||||
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
* and therefore also guaranteed to be invalid.
|
||||
|
||||
* 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( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) 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).
|
||||
|
||||
* If the application only uses CMSIS libraries for interrupt
|
||||
* configuration then the correct setting can be achieved on all Cortex-M
|
||||
* devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
* scheduler. Note however that some vendor specific peripheral libraries
|
||||
* assume a non-zero priority group setting, in which cases using a value
|
||||
* of zero will result in unpredictable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
/*-----------------------------------------------------------*/
|
||||
231
portable/IAR/ARM_CM4F_MPU/portasm.s
Normal file
231
portable/IAR/ARM_CM4F_MPU/portasm.s
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
/* Including FreeRTOSConfig.h here will cause build errors if the header file
|
||||
contains code not understood by the assembler - for example the 'extern' keyword.
|
||||
To avoid errors place any such code inside a #ifdef __ICCARM__/#endif block so
|
||||
the code is included in C files but excluded by the preprocessor in assembly
|
||||
files (__ICCARM__ is defined by the IAR C compiler but not by the IAR assembler. */
|
||||
#include <FreeRTOSConfig.h>
|
||||
|
||||
RSEG CODE:CODE(2)
|
||||
thumb
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortSVCHandler_C
|
||||
|
||||
PUBLIC xPortPendSVHandler
|
||||
PUBLIC vPortSVCHandler
|
||||
PUBLIC vPortStartFirstTask
|
||||
PUBLIC vPortEnableVFP
|
||||
PUBLIC vPortRestoreContextOfFirstTask
|
||||
PUBLIC xIsPrivileged
|
||||
PUBLIC vResetPrivilege
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xPortPendSVHandler:
|
||||
mrs r0, psp
|
||||
isb
|
||||
/* Get the location of the current TCB. */
|
||||
ldr r3, =pxCurrentTCB
|
||||
ldr r2, [r3]
|
||||
|
||||
/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31}
|
||||
|
||||
/* Save the core registers. */
|
||||
mrs r1, control
|
||||
stmdb r0!, {r1, r4-r11, r14}
|
||||
|
||||
/* Save the new top of stack into the first member of the TCB. */
|
||||
str r0, [r2]
|
||||
|
||||
stmdb sp!, {r0, r3}
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
msr basepri, r0
|
||||
dsb
|
||||
isb
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r0, r3}
|
||||
|
||||
/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
/* Move onto the second item in the TCB... */
|
||||
add r1, r1, #4
|
||||
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
/* Region Base Address register. */
|
||||
ldr r2, =0xe000ed9c
|
||||
/* Read 4 sets of MPU registers. */
|
||||
ldmia r1!, {r4-r11}
|
||||
/* Write 4 sets of MPU registers. */
|
||||
stmia r2!, {r4-r11}
|
||||
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
|
||||
/* Pop the registers that are not automatically saved on exception entry. */
|
||||
ldmia r0!, {r3-r11, r14}
|
||||
msr control, r3
|
||||
|
||||
/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||
too. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31}
|
||||
|
||||
msr psp, r0
|
||||
isb
|
||||
|
||||
bx r14
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortSVCHandler:
|
||||
#ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */
|
||||
tst lr, #4
|
||||
ite eq
|
||||
mrseq r0, msp
|
||||
mrsne r0, psp
|
||||
#else
|
||||
mrs r0, psp
|
||||
#endif
|
||||
b vPortSVCHandler_C
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortStartFirstTask:
|
||||
/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, =0xE000ED08
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||
before the scheduler was started - which would otherwise result in the
|
||||
unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||
registers. */
|
||||
mov r0, #0
|
||||
msr control, r0
|
||||
/* Call SVC to start the first task. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 0
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortRestoreContextOfFirstTask:
|
||||
/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, =0xE000ED08
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
/* Restore the context. */
|
||||
ldr r3, =pxCurrentTCB
|
||||
ldr r1, [r3]
|
||||
/* The first item in the TCB is the task top of stack. */
|
||||
ldr r0, [r1]
|
||||
/* Move onto the second item in the TCB... */
|
||||
add r1, r1, #4
|
||||
|
||||
dmb /* Complete outstanding transfers before disabling MPU. */
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
bic r3, r3, #1 /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */
|
||||
str r3, [r2] /* Disable MPU. */
|
||||
|
||||
/* Region Base Address register. */
|
||||
ldr r2, =0xe000ed9c
|
||||
/* Read 4 sets of MPU registers. */
|
||||
ldmia r1!, {r4-r11}
|
||||
/* Write 4 sets of MPU registers. */
|
||||
stmia r2!, {r4-r11}
|
||||
|
||||
ldr r2, =0xe000ed94 /* MPU_CTRL register. */
|
||||
ldr r3, [r2] /* Read the value of MPU_CTRL. */
|
||||
orr r3, r3, #1 /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */
|
||||
str r3, [r2] /* Enable MPU. */
|
||||
dsb /* Force memory writes before continuing. */
|
||||
|
||||
/* Pop the registers that are not automatically saved on exception entry. */
|
||||
ldmia r0!, {r3-r11, r14}
|
||||
msr control, r3
|
||||
/* Restore the task stack pointer. */
|
||||
msr psp, r0
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
bx r14
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortEnableVFP:
|
||||
/* The FPU enable bits are in the CPACR. */
|
||||
ldr.w r0, =0xE000ED88
|
||||
ldr r1, [r0]
|
||||
|
||||
/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||
orr r1, r1, #( 0xf << 20 )
|
||||
str r1, [r0]
|
||||
bx r14
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xIsPrivileged:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
tst r0, #1 /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */
|
||||
ite ne
|
||||
movne r0, #0 /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */
|
||||
moveq r0, #1 /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */
|
||||
bx lr /* Return. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vResetPrivilege:
|
||||
mrs r0, control /* r0 = CONTROL. */
|
||||
orr r0, r0, #1 /* r0 = r0 | 1. */
|
||||
msr control, r0 /* CONTROL = r0. */
|
||||
bx lr /* Return to the caller. */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
END
|
||||
267
portable/IAR/ARM_CM4F_MPU/portmacro.h
Normal file
267
portable/IAR/ARM_CM4F_MPU/portmacro.h
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* MPU specific constants. */
|
||||
#define portUSING_MPU_WRAPPERS 1
|
||||
#define portPRIVILEGE_BIT ( 0x80000000UL )
|
||||
|
||||
#define portMPU_REGION_READ_WRITE ( 0x03UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 0x05UL << 24UL )
|
||||
#define portMPU_REGION_READ_ONLY ( 0x06UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0x01UL << 24UL )
|
||||
#define portMPU_REGION_PRIVILEGED_READ_WRITE_UNPRIV_READ_ONLY ( 0x02UL << 24UL )
|
||||
#define portMPU_REGION_CACHEABLE_BUFFERABLE ( 0x07UL << 16UL )
|
||||
#define portMPU_REGION_EXECUTE_NEVER ( 0x01UL << 28UL )
|
||||
|
||||
#define portUNPRIVILEGED_FLASH_REGION ( 0UL )
|
||||
#define portPRIVILEGED_FLASH_REGION ( 1UL )
|
||||
#define portPRIVILEGED_RAM_REGION ( 2UL )
|
||||
#define portGENERAL_PERIPHERALS_REGION ( 3UL )
|
||||
#define portSTACK_REGION ( 4UL )
|
||||
#define portFIRST_CONFIGURABLE_REGION ( 5UL )
|
||||
#define portLAST_CONFIGURABLE_REGION ( 7UL )
|
||||
#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 )
|
||||
#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */
|
||||
|
||||
#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, r0, #1 \n msr control, r0 " ::: "r0", "memory" )
|
||||
|
||||
typedef struct MPU_REGION_REGISTERS
|
||||
{
|
||||
uint32_t ulRegionBaseAddress;
|
||||
uint32_t ulRegionAttribute;
|
||||
} xMPU_REGION_REGISTERS;
|
||||
|
||||
/* Plus 1 to create space for the stack region. */
|
||||
typedef struct MPU_SETTINGS
|
||||
{
|
||||
xMPU_REGION_REGISTERS xRegion[ portTOTAL_NUM_REGIONS ];
|
||||
} xMPU_SETTINGS;
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* SVC numbers for various services. */
|
||||
#define portSVC_START_SCHEDULER 0
|
||||
#define portSVC_YIELD 1
|
||||
#define portSVC_RAISE_PRIVILEGE 2
|
||||
|
||||
/* Scheduler utilities. */
|
||||
|
||||
#define portYIELD() __asm volatile ( " SVC %0 \n" :: "i" (portSVC_YIELD) : "memory" )
|
||||
#define portYIELD_WITHIN_API() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD_WITHIN_API()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/* Check the configuration. */
|
||||
#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.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_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 ) ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
__set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() __set_BASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_BASEPRI(); portDISABLE_INTERRUPTS()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) __set_BASEPRI( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
extern BaseType_t xIsPrivileged( void );
|
||||
extern void vResetPrivilege( void );
|
||||
|
||||
/**
|
||||
* @brief Checks whether or not the processor is privileged.
|
||||
*
|
||||
* @return 1 if the processor is already privileged, 0 otherwise.
|
||||
*/
|
||||
#define portIS_PRIVILEGED() xIsPrivileged()
|
||||
|
||||
/**
|
||||
* @brief Raise an SVC request to raise privilege.
|
||||
*/
|
||||
#define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" :: "i" ( portSVC_RAISE_PRIVILEGE ) : "memory" );
|
||||
|
||||
/**
|
||||
* @brief Lowers the privilege level by setting the bit 0 of the CONTROL
|
||||
* register.
|
||||
*/
|
||||
#define portRESET_PRIVILEGE() vResetPrivilege()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY
|
||||
#warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security. https://www.freertos.org/FreeRTOS-V10.3.x.html"
|
||||
#define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
warnings. */
|
||||
#pragma diag_suppress=Pe191
|
||||
#pragma diag_suppress=Pa082
|
||||
#pragma diag_suppress=Be006
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
18
portable/IAR/ARM_CM7/ReadMe.txt
Normal file
18
portable/IAR/ARM_CM7/ReadMe.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
There are two options for running FreeRTOS on ARM Cortex-M7 microcontrollers.
|
||||
The best option depends on the revision of the ARM Cortex-M7 core in use. The
|
||||
revision is specified by an 'r' number, and a 'p' number, so will look something
|
||||
like 'r0p1'. Check the documentation for the microcontroller in use to find the
|
||||
revision of the Cortex-M7 core used in that microcontroller. If in doubt, use
|
||||
the FreeRTOS port provided specifically for r0p1 revisions, as that can be used
|
||||
with all core revisions.
|
||||
|
||||
The first option is to use the ARM Cortex-M4F port, and the second option is to
|
||||
use the Cortex-M7 r0p1 port - the latter containing a minor errata workaround.
|
||||
|
||||
If the revision of the ARM Cortex-M7 core is not r0p1 then either option can be
|
||||
used, but it is recommended to use the FreeRTOS ARM Cortex-M4F port located in
|
||||
the /FreeRTOS/Source/portable/IAR/ARM_CM4F directory.
|
||||
|
||||
If the revision of the ARM Cortex-M7 core is r0p1 then use the FreeRTOS ARM
|
||||
Cortex-M7 r0p1 port located in the /FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1
|
||||
directory.
|
||||
644
portable/IAR/ARM_CM7/r0p1/port.c
Normal file
644
portable/IAR/ARM_CM7/r0p1/port.c
Normal file
|
|
@ -0,0 +1,644 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the ARM CM4F port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#ifndef __ARMVFP__
|
||||
#error This port can only be used when the project options are configured to enable hardware floating point support.
|
||||
#endif
|
||||
|
||||
#if( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 )
|
||||
#error configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0. See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
|
||||
#endif
|
||||
|
||||
#ifndef configSYSTICK_CLOCK_HZ
|
||||
#define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ
|
||||
/* Ensure the SysTick is clocked at the same frequency as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
|
||||
#else
|
||||
/* The way the SysTick is clocked is not modified in case it is not the same
|
||||
as the core. */
|
||||
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
|
||||
#endif
|
||||
|
||||
/* Constants required to manipulate the core. Registers first... */
|
||||
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
|
||||
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
|
||||
/* ...then bits in the registers. */
|
||||
#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
|
||||
#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
|
||||
#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
|
||||
#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL )
|
||||
#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
|
||||
|
||||
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||
|
||||
/* Constants required to check the validity of an interrupt priority. */
|
||||
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||
#define portAIRCR_REG ( * ( ( volatile uint32_t * ) 0xE000ED0C ) )
|
||||
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
|
||||
#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
|
||||
#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
|
||||
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||
#define portPRIGROUP_SHIFT ( 8UL )
|
||||
|
||||
/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */
|
||||
#define portVECTACTIVE_MASK ( 0xFFUL )
|
||||
|
||||
/* Constants required to manipulate the VFP. */
|
||||
#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||
|
||||
/* Constants required to set up the initial stack. */
|
||||
#define portINITIAL_XPSR ( 0x01000000 )
|
||||
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
|
||||
|
||||
/* The systick is a 24-bit counter. */
|
||||
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
|
||||
|
||||
/* A fiddle factor to estimate the number of SysTick counts that would have
|
||||
occurred while the SysTick counter is stopped during tickless idle
|
||||
calculations. */
|
||||
#define portMISSED_COUNTS_FACTOR ( 45UL )
|
||||
|
||||
/* For strict compliance with the Cortex-M spec the task start address should
|
||||
have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
|
||||
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
|
||||
|
||||
/*
|
||||
* Setup the timer to generate the tick interrupts. The implementation in this
|
||||
* file is weak to allow application writers to change the timer used to
|
||||
* generate the tick interrupt.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* Exception handlers.
|
||||
*/
|
||||
void xPortSysTickHandler( void );
|
||||
|
||||
/*
|
||||
* Start first task is a separate function so it can be tested in isolation.
|
||||
*/
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/*
|
||||
* Turn the VFP on.
|
||||
*/
|
||||
extern void vPortEnableVFP( void );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Each task maintains its own interrupt status in the critical nesting
|
||||
variable. */
|
||||
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
|
||||
|
||||
/*
|
||||
* The number of SysTick increments that make up one tick period.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulTimerCountsForOneTick = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* The maximum number of tick periods that can be suppressed is limited by the
|
||||
* 24 bit resolution of the SysTick timer.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t xMaximumPossibleSuppressedTicks = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Compensate for the CPU cycles that pass while the SysTick is stopped (low
|
||||
* power functionality only.
|
||||
*/
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
static uint32_t ulStoppedTimerCompensation = 0;
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/*
|
||||
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||
*/
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
static uint8_t ucMaxSysCallPriority = 0;
|
||||
static uint32_t ulMaxPRIGROUPValue = 0;
|
||||
static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Simulate the stack frame as it would be created by a context switch
|
||||
interrupt. */
|
||||
|
||||
/* Offset added to account for the way the MCU uses the stack on entry/exit
|
||||
of interrupts, and to ensure alignment. */
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
|
||||
|
||||
/* Save code space by skipping register initialisation. */
|
||||
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
|
||||
/* A save method is being used that requires each task to maintain its
|
||||
own exec return value. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portINITIAL_EXC_RETURN;
|
||||
|
||||
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvTaskExitError( void )
|
||||
{
|
||||
/* 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
|
||||
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( uxCriticalNesting == ~0UL );
|
||||
portDISABLE_INTERRUPTS();
|
||||
for( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to 0.
|
||||
See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
|
||||
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
{
|
||||
volatile uint32_t ulOriginalPriority;
|
||||
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||
volatile uint8_t ucMaxPriorityValue;
|
||||
|
||||
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||
functions can be called. ISR safe functions are those that end in
|
||||
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||
ensure interrupt entry is as fast and simple as possible.
|
||||
|
||||
Save the interrupt priority value that is about to be clobbered. */
|
||||
ulOriginalPriority = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Determine the number of priority bits available. First write to all
|
||||
possible bits. */
|
||||
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
|
||||
|
||||
/* Read the value back to see how many bits stuck. */
|
||||
ucMaxPriorityValue = *pucFirstUserPriorityRegister;
|
||||
|
||||
/* Use the same mask on the maximum system call priority. */
|
||||
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
|
||||
|
||||
/* Calculate the maximum acceptable priority group value for the number
|
||||
of bits read back. */
|
||||
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
|
||||
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
|
||||
{
|
||||
ulMaxPRIGROUPValue--;
|
||||
ucMaxPriorityValue <<= ( uint8_t ) 0x01;
|
||||
}
|
||||
|
||||
#ifdef __NVIC_PRIO_BITS
|
||||
{
|
||||
/* Check the CMSIS configuration that defines the number of
|
||||
priority bits matches the number of priority bits actually queried
|
||||
from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef configPRIO_BITS
|
||||
{
|
||||
/* Check the FreeRTOS configuration that defines the number of
|
||||
priority bits matches the number of priority bits actually queried
|
||||
from the hardware. */
|
||||
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Shift the priority group value back to its position within the AIRCR
|
||||
register. */
|
||||
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
|
||||
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
|
||||
|
||||
/* Restore the clobbered interrupt priority register to its original
|
||||
value. */
|
||||
*pucFirstUserPriorityRegister = ulOriginalPriority;
|
||||
}
|
||||
#endif /* conifgASSERT_DEFINED */
|
||||
|
||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
vPortSetupTimerInterrupt();
|
||||
|
||||
/* Initialise the critical nesting count ready for the first task. */
|
||||
uxCriticalNesting = 0;
|
||||
|
||||
/* Ensure the VFP is enabled - it should be anyway. */
|
||||
vPortEnableVFP();
|
||||
|
||||
/* Lazy save always. */
|
||||
*( portFPCCR ) |= portASPEN_AND_LSPEN_BITS;
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( uxCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( uxCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
configASSERT( uxCriticalNesting );
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == 0 )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void xPortSysTickHandler( void )
|
||||
{
|
||||
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
|
||||
executes all interrupts must be unmasked. There is therefore no need to
|
||||
save and then restore the interrupt mask value as its value is already
|
||||
known. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
{
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
/* A context switch is required. Context switching is performed in
|
||||
the PendSV interrupt. Pend the PendSV interrupt. */
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
|
||||
}
|
||||
}
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
|
||||
__weak void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
|
||||
{
|
||||
uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
|
||||
TickType_t xModifiableIdleTime;
|
||||
|
||||
/* Make sure the SysTick reload value does not overflow the counter. */
|
||||
if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
|
||||
{
|
||||
xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
|
||||
}
|
||||
|
||||
/* Stop the SysTick momentarily. The time the SysTick is stopped for
|
||||
is accounted for as best it can be, but using the tickless mode will
|
||||
inevitably result in some tiny drift of the time maintained by the
|
||||
kernel with respect to calendar time. */
|
||||
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Calculate the reload value required to wait xExpectedIdleTime
|
||||
tick periods. -1 is used because this code will execute part way
|
||||
through one of the tick periods. */
|
||||
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
|
||||
if( ulReloadValue > ulStoppedTimerCompensation )
|
||||
{
|
||||
ulReloadValue -= ulStoppedTimerCompensation;
|
||||
}
|
||||
|
||||
/* Enter a critical section but don't use the taskENTER_CRITICAL()
|
||||
method as that will mask interrupts that should exit sleep mode. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* If a context switch is pending or a task is waiting for the scheduler
|
||||
to be unsuspended then abandon the low power entry. */
|
||||
if( eTaskConfirmSleepModeStatus() == eAbortSleep )
|
||||
{
|
||||
/* Restart from whatever is left in the count register to complete
|
||||
this tick period. */
|
||||
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Reset the reload register to the value required for normal tick
|
||||
periods. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Re-enable interrupts - see comments above __disable_interrupt()
|
||||
call above. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new reload value. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
|
||||
|
||||
/* Clear the SysTick count flag and set the count value back to
|
||||
zero. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Restart SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
|
||||
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
|
||||
set its parameter to 0 to indicate that its implementation contains
|
||||
its own wait for interrupt or wait for event instruction, and so wfi
|
||||
should not be executed again. However, the original expected idle
|
||||
time variable must remain unmodified, so a copy is taken. */
|
||||
xModifiableIdleTime = xExpectedIdleTime;
|
||||
configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
|
||||
if( xModifiableIdleTime > 0 )
|
||||
{
|
||||
__DSB();
|
||||
__WFI();
|
||||
__ISB();
|
||||
}
|
||||
configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
|
||||
|
||||
/* Re-enable interrupts to allow the interrupt that brought the MCU
|
||||
out of sleep mode to execute immediately. see comments above
|
||||
__disable_interrupt() call above. */
|
||||
__enable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable interrupts again because the clock is about to be stopped
|
||||
and interrupts that execute while the clock is stopped will increase
|
||||
any slippage between the time maintained by the RTOS and calendar
|
||||
time. */
|
||||
__disable_interrupt();
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
/* Disable the SysTick clock without reading the
|
||||
portNVIC_SYSTICK_CTRL_REG register to ensure the
|
||||
portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
|
||||
the time the SysTick is stopped for is accounted for as best it can
|
||||
be, but using the tickless mode will inevitably result in some tiny
|
||||
drift of the time maintained by the kernel with respect to calendar
|
||||
time*/
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
|
||||
|
||||
/* Determine if the SysTick clock has already counted to zero and
|
||||
been set back to the current reload value (the reload back being
|
||||
correct for the entire expected idle time) or if the SysTick is yet
|
||||
to count to zero (in which case an interrupt other than the SysTick
|
||||
must have brought the system out of sleep mode). */
|
||||
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
|
||||
{
|
||||
uint32_t ulCalculatedLoadValue;
|
||||
|
||||
/* The tick interrupt is already pending, and the SysTick count
|
||||
reloaded with ulReloadValue. Reset the
|
||||
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
|
||||
period. */
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
|
||||
|
||||
/* Don't allow a tiny value, or values that have somehow
|
||||
underflowed because the post sleep hook did something
|
||||
that took too long. */
|
||||
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
|
||||
{
|
||||
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
|
||||
}
|
||||
|
||||
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
|
||||
|
||||
/* 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 waiting. */
|
||||
ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Something other than the tick interrupt ended the sleep.
|
||||
Work out how long the sleep lasted rounded to complete tick
|
||||
periods (not the ulReload value which accounted for part
|
||||
ticks). */
|
||||
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
|
||||
/* How many complete tick periods passed while the processor
|
||||
was waiting? */
|
||||
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
|
||||
|
||||
/* The reload value is set to whatever fraction of a single tick
|
||||
period remains. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
|
||||
}
|
||||
|
||||
/* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
|
||||
again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
|
||||
value. */
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
|
||||
vTaskStepTick( ulCompleteTickPeriods );
|
||||
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
|
||||
|
||||
/* Exit with interrupts enabled. */
|
||||
__enable_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup the systick timer to generate the tick interrupts at the required
|
||||
* frequency.
|
||||
*/
|
||||
__weak void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Calculate the constants required to configure the tick interrupt. */
|
||||
#if( configUSE_TICKLESS_IDLE == 1 )
|
||||
{
|
||||
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
|
||||
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
|
||||
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
|
||||
}
|
||||
#endif /* configUSE_TICKLESS_IDLE */
|
||||
|
||||
/* Stop and clear the SysTick. */
|
||||
portNVIC_SYSTICK_CTRL_REG = 0UL;
|
||||
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
|
||||
|
||||
/* Configure SysTick to interrupt at the requested rate. */
|
||||
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
|
||||
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if( configASSERT_DEFINED == 1 )
|
||||
|
||||
void vPortValidateInterruptPriority( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
uint8_t ucCurrentPriority;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
/* Is the interrupt number a user defined interrupt? */
|
||||
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||
{
|
||||
/* Look up the interrupt's priority. */
|
||||
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||
|
||||
/* The following assertion will fail if a service routine (ISR) for
|
||||
an interrupt that has been assigned a priority above
|
||||
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||
function. ISR safe FreeRTOS API functions must *only* be called
|
||||
from interrupts that have been assigned a priority at or below
|
||||
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.
|
||||
|
||||
Interrupts that use the FreeRTOS API must not be left at their
|
||||
default priority of zero as that is the highest possible priority,
|
||||
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||
and therefore also guaranteed to be invalid.
|
||||
|
||||
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( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||
}
|
||||
|
||||
/* Priority grouping: The interrupt controller (NVIC) 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).
|
||||
|
||||
If the application only uses CMSIS libraries for interrupt
|
||||
configuration then the correct setting can be achieved on all Cortex-M
|
||||
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||
scheduler. Note however that some vendor specific peripheral libraries
|
||||
assume a non-zero priority group setting, in which cases using a value
|
||||
of zero will result in unpredictable behaviour. */
|
||||
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
|
||||
}
|
||||
|
||||
#endif /* configASSERT_DEFINED */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
151
portable/IAR/ARM_CM7/r0p1/portasm.s
Normal file
151
portable/IAR/ARM_CM7/r0p1/portasm.s
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#include <FreeRTOSConfig.h>
|
||||
|
||||
RSEG CODE:CODE(2)
|
||||
thumb
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
|
||||
PUBLIC xPortPendSVHandler
|
||||
PUBLIC vPortSVCHandler
|
||||
PUBLIC vPortStartFirstTask
|
||||
PUBLIC vPortEnableVFP
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
xPortPendSVHandler:
|
||||
mrs r0, psp
|
||||
isb
|
||||
/* Get the location of the current TCB. */
|
||||
ldr r3, =pxCurrentTCB
|
||||
ldr r2, [r3]
|
||||
|
||||
/* Is the task using the FPU context? If so, push high vfp registers. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vstmdbeq r0!, {s16-s31}
|
||||
|
||||
/* Save the core registers. */
|
||||
stmdb r0!, {r4-r11, r14}
|
||||
|
||||
/* Save the new top of stack into the first member of the TCB. */
|
||||
str r0, [r2]
|
||||
|
||||
stmdb sp!, {r0, r3}
|
||||
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
|
||||
cpsid i
|
||||
msr basepri, r0
|
||||
dsb
|
||||
isb
|
||||
cpsie i
|
||||
bl vTaskSwitchContext
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
ldmia sp!, {r0, r3}
|
||||
|
||||
/* The first item in pxCurrentTCB is the task top of stack. */
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
|
||||
/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
|
||||
/* Is the task using the FPU context? If so, pop the high vfp registers
|
||||
too. */
|
||||
tst r14, #0x10
|
||||
it eq
|
||||
vldmiaeq r0!, {s16-s31}
|
||||
|
||||
msr psp, r0
|
||||
isb
|
||||
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
|
||||
#if WORKAROUND_PMU_CM001 == 1
|
||||
push { r14 }
|
||||
pop { pc }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bx r14
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortSVCHandler:
|
||||
/* Get the location of the current TCB. */
|
||||
ldr r3, =pxCurrentTCB
|
||||
ldr r1, [r3]
|
||||
ldr r0, [r1]
|
||||
/* Pop the core registers. */
|
||||
ldmia r0!, {r4-r11, r14}
|
||||
msr psp, r0
|
||||
isb
|
||||
mov r0, #0
|
||||
msr basepri, r0
|
||||
bx r14
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortStartFirstTask
|
||||
/* Use the NVIC offset register to locate the stack. */
|
||||
ldr r0, =0xE000ED08
|
||||
ldr r0, [r0]
|
||||
ldr r0, [r0]
|
||||
/* Set the msp back to the start of the stack. */
|
||||
msr msp, r0
|
||||
/* Clear the bit that indicates the FPU is in use in case the FPU was used
|
||||
before the scheduler was started - which would otherwise result in the
|
||||
unnecessary leaving of space in the SVC stack for lazy saving of FPU
|
||||
registers. */
|
||||
mov r0, #0
|
||||
msr control, r0
|
||||
/* Call SVC to start the first task. */
|
||||
cpsie i
|
||||
cpsie f
|
||||
dsb
|
||||
isb
|
||||
svc 0
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
vPortEnableVFP:
|
||||
/* The FPU enable bits are in the CPACR. */
|
||||
ldr.w r0, =0xE000ED88
|
||||
ldr r1, [r0]
|
||||
|
||||
/* Enable CP10 and CP11 coprocessors, then save back. */
|
||||
orr r1, r1, #( 0xf << 20 )
|
||||
str r1, [r0]
|
||||
bx r14
|
||||
|
||||
|
||||
|
||||
END
|
||||
|
||||
210
portable/IAR/ARM_CM7/r0p1/portmacro.h
Normal file
210
portable/IAR/ARM_CM7/r0p1/portmacro.h
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* IAR includes. */
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Compiler directives. */
|
||||
#define portWEAK_SYMBOL __attribute__( ( weak ) )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Scheduler utilities. */
|
||||
#define portYIELD() \
|
||||
{ \
|
||||
/* Set a PendSV to request a context switch. */ \
|
||||
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
}
|
||||
|
||||
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
|
||||
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
|
||||
|
||||
/* Check the configuration. */
|
||||
#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.
|
||||
#endif
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_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 ) ) ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() \
|
||||
{ \
|
||||
/* Errata work around. */ \
|
||||
__disable_interrupt(); \
|
||||
__set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \
|
||||
__DSB(); \
|
||||
__ISB(); \
|
||||
__enable_interrupt(); \
|
||||
}
|
||||
|
||||
#define portENABLE_INTERRUPTS() __set_BASEPRI( 0 )
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
#define portSET_INTERRUPT_MASK_FROM_ISR() __get_BASEPRI(); portDISABLE_INTERRUPTS()
|
||||
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) __set_BASEPRI( x )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Tickless idle/low power functionality. */
|
||||
#ifndef portSUPPRESS_TICKS_AND_SLEEP
|
||||
extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
|
||||
#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime )
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
(which build with all the ports) will build. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#ifdef configASSERT
|
||||
void vPortValidateInterruptPriority( void );
|
||||
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||
#endif
|
||||
|
||||
/* portNOP() is not required by this port. */
|
||||
#define portNOP()
|
||||
|
||||
#define portINLINE __inline
|
||||
|
||||
#ifndef portFORCE_INLINE
|
||||
#define portFORCE_INLINE inline __attribute__(( always_inline))
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
|
||||
{
|
||||
uint32_t ulCurrentInterrupt;
|
||||
BaseType_t xReturn;
|
||||
|
||||
/* Obtain the number of the currently executing interrupt. */
|
||||
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) :: "memory" );
|
||||
|
||||
if( ulCurrentInterrupt == 0 )
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
warnings. */
|
||||
#pragma diag_suppress=Pe191
|
||||
#pragma diag_suppress=Pa082
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
316
portable/IAR/ARM_CRx_No_GIC/port.c
Normal file
316
portable/IAR/ARM_CRx_No_GIC/port.c
Normal file
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
/* Check the configuration. */
|
||||
#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.
|
||||
#endif
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#ifndef configSETUP_TICK_INTERRUPT
|
||||
#error configSETUP_TICK_INTERRUPT() must be defined in FreeRTOSConfig.h to call the function that sets up the tick interrupt.
|
||||
#endif
|
||||
|
||||
#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.
|
||||
#endif
|
||||
|
||||
/* A critical section is exited when the critical section nesting count reaches
|
||||
this value. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
/* 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
|
||||
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
|
||||
context. */
|
||||
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
|
||||
|
||||
/* Constants required to setup the initial task context. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
|
||||
|
||||
/* Masks all bits in the APSR other than the mode bits. */
|
||||
#define portAPSR_MODE_BITS_MASK ( 0x1F )
|
||||
|
||||
/* The value of the mode bits in the APSR when the CPU is executing in user
|
||||
mode. */
|
||||
#define portAPSR_USER_MODE ( 0x10 )
|
||||
|
||||
/* 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
|
||||
debugger. */
|
||||
#ifdef configTASK_RETURN_ADDRESS
|
||||
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
|
||||
#else
|
||||
#define portTASK_RETURN_ADDRESS prvTaskExitError
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Starts the first task executing. This function is necessarily written in
|
||||
* assembly code so is implemented in portASM.s.
|
||||
*/
|
||||
extern void vPortRestoreTaskContext( void );
|
||||
|
||||
/*
|
||||
* Used to catch tasks that attempt to return from their implementing function.
|
||||
*/
|
||||
static void prvTaskExitError( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* 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
|
||||
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
|
||||
automatically be set to 0 when the first task is started. */
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
/* 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. */
|
||||
volatile uint32_t ulPortTaskHasFPUContext = pdFALSE;
|
||||
|
||||
/* Set to 1 to pend a context switch from an ISR. */
|
||||
volatile uint32_t ulPortYieldRequired = pdFALSE;
|
||||
|
||||
/* Counts the interrupt nesting depth. A context switch is only performed if
|
||||
if the nesting depth is 0. */
|
||||
volatile uint32_t ulPortInterruptNesting = 0UL;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
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 task will start in THUMB mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the return address, which in this case is the start of the task. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next all the registers other than the stack pointer. */
|
||||
*pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* R14 */
|
||||
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
|
||||
enabled. */
|
||||
*pxTopOfStack = portNO_CRITICAL_NESTING;
|
||||
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 )
|
||||
{
|
||||
/* 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
|
||||
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( ;; );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
uint32_t ulAPSR;
|
||||
|
||||
/* Only continue if the CPU is not in User mode. The CPU must be in a
|
||||
Privileged mode for the scheduler to start. */
|
||||
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR ) );
|
||||
ulAPSR &= portAPSR_MODE_BITS_MASK;
|
||||
configASSERT( ulAPSR != portAPSR_USER_MODE );
|
||||
|
||||
if( ulAPSR != portAPSR_USER_MODE )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
configSETUP_TICK_INTERRUPT();
|
||||
|
||||
/* Start the first task executing. */
|
||||
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. prvTaskExitError() is referenced to prevent a compiler
|
||||
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 )
|
||||
{
|
||||
/* Not implemented in ports where there is nothing to return to.
|
||||
Artificially force an assert. */
|
||||
configASSERT( ulCriticalNesting == 1000UL );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
|
||||
/* 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
|
||||
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
|
||||
assert function also uses a critical section. */
|
||||
if( ulCriticalNesting == 1 )
|
||||
{
|
||||
configASSERT( ulPortInterruptNesting == 0 );
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as the critical section is being
|
||||
exited. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then all interrupt
|
||||
priorities must be re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Critical nesting has reached zero so all interrupt priorities
|
||||
should be unmasked. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void FreeRTOS_Tick_Handler( void )
|
||||
{
|
||||
uint32_t ulInterruptStatus;
|
||||
|
||||
ulInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||
|
||||
/* Increment the RTOS tick. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
ulPortYieldRequired = pdTRUE;
|
||||
}
|
||||
|
||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( ulInterruptStatus );
|
||||
|
||||
configCLEAR_TICK_INTERRUPT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortTaskUsesFPU( void )
|
||||
{
|
||||
uint32_t ulInitialFPSCR = 0;
|
||||
|
||||
/* 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). */
|
||||
ulPortTaskHasFPUContext = pdTRUE;
|
||||
|
||||
/* Initialise the floating point status register. */
|
||||
__asm volatile ( "FMXR FPSCR, %0" :: "r" (ulInitialFPSCR) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
247
portable/IAR/ARM_CRx_No_GIC/portASM.s
Normal file
247
portable/IAR/ARM_CRx_No_GIC/portASM.s
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
|
||||
SECTION .text:CODE:ROOT(2)
|
||||
arm
|
||||
|
||||
/* Variables and functions. */
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vApplicationIRQHandler
|
||||
EXTERN ulPortInterruptNesting
|
||||
EXTERN ulPortTaskHasFPUContext
|
||||
EXTERN ulPortYieldRequired
|
||||
EXTERN ulCriticalNesting
|
||||
|
||||
PUBLIC FreeRTOS_IRQ_Handler
|
||||
PUBLIC FreeRTOS_SVC_Handler
|
||||
PUBLIC vPortRestoreTaskContext
|
||||
|
||||
SYS_MODE EQU 0x1f
|
||||
SVC_MODE EQU 0x13
|
||||
IRQ_MODE EQU 0x12
|
||||
|
||||
portSAVE_CONTEXT MACRO
|
||||
|
||||
/* 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
|
||||
CPS #SYS_MODE
|
||||
PUSH {R0-R12, R14}
|
||||
|
||||
/* Push the critical nesting count. */
|
||||
LDR R2, =ulCriticalNesting
|
||||
LDR R1, [R2]
|
||||
PUSH {R1}
|
||||
|
||||
/* Does the task have a floating point context that needs saving? If
|
||||
ulPortTaskHasFPUContext is 0 then no. */
|
||||
LDR R2, =ulPortTaskHasFPUContext
|
||||
LDR R3, [R2]
|
||||
CMP R3, #0
|
||||
|
||||
/* Save the floating point context, if any. */
|
||||
FMRXNE R1, FPSCR
|
||||
VPUSHNE {D0-D15}
|
||||
#if configFPU_D32 == 1
|
||||
VPUSHNE {D16-D31}
|
||||
#endif /* configFPU_D32 */
|
||||
PUSHNE {R1}
|
||||
|
||||
/* Save ulPortTaskHasFPUContext itself. */
|
||||
PUSH {R3}
|
||||
|
||||
/* Save the stack pointer in the TCB. */
|
||||
LDR R0, =pxCurrentTCB
|
||||
LDR R1, [R0]
|
||||
STR SP, [R1]
|
||||
|
||||
ENDM
|
||||
|
||||
; /**********************************************************************/
|
||||
|
||||
portRESTORE_CONTEXT MACRO
|
||||
|
||||
/* Set the SP to point to the stack of the task being restored. */
|
||||
LDR R0, =pxCurrentTCB
|
||||
LDR R1, [R0]
|
||||
LDR SP, [R1]
|
||||
|
||||
/* Is there a floating point context to restore? If the restored
|
||||
ulPortTaskHasFPUContext is zero then no. */
|
||||
LDR R0, =ulPortTaskHasFPUContext
|
||||
POP {R1}
|
||||
STR R1, [R0]
|
||||
CMP R1, #0
|
||||
|
||||
/* Restore the floating point context, if any. */
|
||||
POPNE {R0}
|
||||
#if configFPU_D32 == 1
|
||||
VPOPNE {D16-D31}
|
||||
#endif /* configFPU_D32 */
|
||||
VPOPNE {D0-D15}
|
||||
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. */
|
||||
RFEIA sp!
|
||||
|
||||
ENDM
|
||||
|
||||
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* SVC handler is used to yield.
|
||||
*****************************************************************************/
|
||||
FreeRTOS_SVC_Handler:
|
||||
/* Save the context of the current task and select a new task to run. */
|
||||
portSAVE_CONTEXT
|
||||
LDR R0, =vTaskSwitchContext
|
||||
BLX R0
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* vPortRestoreTaskContext is used to start the scheduler.
|
||||
*****************************************************************************/
|
||||
vPortRestoreTaskContext:
|
||||
/* Switch to system mode. */
|
||||
CPS #SYS_MODE
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
FreeRTOS_IRQ_Handler:
|
||||
/* Return to the interrupted instruction. */
|
||||
SUB lr, lr, #4
|
||||
|
||||
/* Push the return address and SPSR. */
|
||||
PUSH {lr}
|
||||
MRS lr, SPSR
|
||||
PUSH {lr}
|
||||
|
||||
/* Change to supervisor mode to allow reentry. */
|
||||
CPS #SVC_MODE
|
||||
|
||||
/* Push used registers. */
|
||||
PUSH {r0-r3, r12}
|
||||
|
||||
/* Increment nesting count. r3 holds the address of ulPortInterruptNesting
|
||||
for future use. r1 holds the original ulPortInterruptNesting value for
|
||||
future use. */
|
||||
LDR r3, =ulPortInterruptNesting
|
||||
LDR r1, [r3]
|
||||
ADD r0, r1, #1
|
||||
STR r0, [r3]
|
||||
|
||||
/* Ensure bit 2 of the stack pointer is clear. r2 holds the bit 2 value for
|
||||
future use. */
|
||||
MOV r0, sp
|
||||
AND r2, r0, #4
|
||||
SUB sp, sp, r2
|
||||
|
||||
/* Call the interrupt handler. */
|
||||
PUSH {r0-r3, lr}
|
||||
LDR r1, =vApplicationIRQHandler
|
||||
BLX r1
|
||||
POP {r0-r3, lr}
|
||||
ADD sp, sp, r2
|
||||
|
||||
CPSID i
|
||||
DSB
|
||||
ISB
|
||||
|
||||
/* Write to the EOI register. */
|
||||
LDR r2, =configEOI_ADDRESS
|
||||
STR r0, [r2]
|
||||
|
||||
/* Restore the old nesting count. */
|
||||
STR r1, [r3]
|
||||
|
||||
/* A context switch is never performed if the nesting count is not 0. */
|
||||
CMP r1, #0
|
||||
BNE exit_without_switch
|
||||
|
||||
/* Did the interrupt request a context switch? r1 holds the address of
|
||||
ulPortYieldRequired and r0 the value of ulPortYieldRequired for future
|
||||
use. */
|
||||
LDR r1, =ulPortYieldRequired
|
||||
LDR r0, [r1]
|
||||
CMP r0, #0
|
||||
BNE switch_before_exit
|
||||
|
||||
exit_without_switch:
|
||||
/* No context switch. Restore used registers, LR_irq and SPSR before
|
||||
returning. */
|
||||
POP {r0-r3, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
MOVS PC, LR
|
||||
|
||||
switch_before_exit:
|
||||
/* A context swtich is to be performed. Clear the context switch pending
|
||||
flag. */
|
||||
MOV r0, #0
|
||||
STR r0, [r1]
|
||||
|
||||
/* Restore used registers, LR-irq and SPSR before saving the context
|
||||
to the task stack. */
|
||||
POP {r0-r3, r12}
|
||||
CPS #IRQ_MODE
|
||||
POP {LR}
|
||||
MSR SPSR_cxsf, LR
|
||||
POP {LR}
|
||||
portSAVE_CONTEXT
|
||||
|
||||
/* Call the function that selects the new task to execute.
|
||||
vTaskSwitchContext() if vTaskSwitchContext() uses LDRD or STRD
|
||||
instructions, or 8 byte aligned stack allocated data. LR does not need
|
||||
saving as a new LR will be loaded by portRESTORE_CONTEXT anyway. */
|
||||
LDR R0, =vTaskSwitchContext
|
||||
BLX R0
|
||||
|
||||
/* Restore the context of, and branch to, the task selected to execute
|
||||
next. */
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
END
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
181
portable/IAR/ARM_CRx_No_GIC/portmacro.h
Normal file
181
portable/IAR/ARM_CRx_No_GIC/portmacro.h
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include <intrinsics.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the given hardware
|
||||
* and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
|
||||
/* 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. */
|
||||
#define portTICK_TYPE_IS_ATOMIC 1
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/* Called at the end of an ISR that can cause a context switch. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired )\
|
||||
{ \
|
||||
extern volatile uint32_t ulPortYieldRequired; \
|
||||
\
|
||||
if( xSwitchRequired != pdFALSE ) \
|
||||
{ \
|
||||
ulPortYieldRequired = pdTRUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
|
||||
#define portYIELD() __asm volatile ( "SWI 0 \n" \
|
||||
"ISB " );
|
||||
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Critical section control
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
|
||||
extern void vPortInstallFreeRTOSVectorTable( void );
|
||||
|
||||
/* The I bit within the CPSR. */
|
||||
#define portINTERRUPT_ENABLE_BIT ( 1 << 7 )
|
||||
|
||||
/* In the absence of a priority mask register, these functions and macros
|
||||
globally enable and disable interrupts. */
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
#define portENABLE_INTERRUPTS() __asm volatile ( "CPSIE i \n" );
|
||||
#define portDISABLE_INTERRUPTS() __asm volatile ( "CPSID i \n" \
|
||||
"DSB \n" \
|
||||
"ISB " );
|
||||
#pragma inline
|
||||
static inline uint32_t portINLINE_SET_INTERRUPT_MASK_FROM_ISR( void )
|
||||
{
|
||||
volatile uint32_t ulCPSR;
|
||||
|
||||
__asm volatile ( "MRS %0, CPSR" : "=r" (ulCPSR) );
|
||||
ulCPSR &= portINTERRUPT_ENABLE_BIT;
|
||||
portDISABLE_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
|
||||
not required for this port but included in case common demo code that uses these
|
||||
macros is used. */
|
||||
#define portTASK_FUNCTION_PROTO( 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
|
||||
handler for whichever peripheral is used to generate the RTOS tick. */
|
||||
void FreeRTOS_Tick_Handler( void );
|
||||
|
||||
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
|
||||
before any floating point instructions are executed. */
|
||||
void vPortTaskUsesFPU( void );
|
||||
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
|
||||
|
||||
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
|
||||
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
|
||||
|
||||
/* Architecture specific optimisations. */
|
||||
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
|
||||
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
|
||||
#endif
|
||||
|
||||
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
|
||||
|
||||
/* Store/clear the ready priorities in a bit map. */
|
||||
#define portRECORD_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 ) )
|
||||
|
||||
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
|
||||
|
||||
#define portNOP() __asm volatile( "NOP" )
|
||||
#define portINLINE inline
|
||||
|
||||
/* 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
|
||||
warnings. */
|
||||
#pragma diag_suppress=Pe191
|
||||
#pragma diag_suppress=Pa082
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
339
portable/IAR/ATMega323/port.c
Normal file
339
portable/IAR/ATMega323/port.c
Normal file
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the AVR/IAR port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Start tasks with interrupts enables. */
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x80 )
|
||||
|
||||
/* Hardware constants for timer 1. */
|
||||
#define portCLEAR_COUNTER_ON_MATCH ( ( uint8_t ) 0x08 )
|
||||
#define portPRESCALE_64 ( ( uint8_t ) 0x03 )
|
||||
#define portCLOCK_PRESCALER ( ( uint32_t ) 64 )
|
||||
#define portCOMPARE_MATCH_A_INTERRUPT_ENABLE ( ( uint8_t ) 0x10 )
|
||||
|
||||
/* The number of bytes used on the hardware stack by the task start address. */
|
||||
#define portBYTES_USED_BY_RETURN_ADDRESS ( 2 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Stores the critical section nesting. This must not be initialised to 0.
|
||||
It will be initialised when a task starts. */
|
||||
#define portNO_CRITICAL_NESTING ( ( UBaseType_t ) 0 )
|
||||
UBaseType_t uxCriticalNesting = 0x50;
|
||||
|
||||
|
||||
/*
|
||||
* Perform hardware setup to enable ticks from timer 1, compare match A.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*
|
||||
* The IAR compiler does not have full support for inline assembler, so
|
||||
* these are defined in the portmacro assembler file.
|
||||
*/
|
||||
extern void vPortYieldFromTick( void );
|
||||
extern void vPortStart( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint16_t usAddress;
|
||||
StackType_t *pxTopOfHardwareStack;
|
||||
|
||||
/* Place a few bytes of known values on the bottom of the stack.
|
||||
This is just useful for debugging. */
|
||||
|
||||
*pxTopOfStack = 0x11;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x22;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = 0x33;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Remember where the top of the hardware stack is - this is required
|
||||
below. */
|
||||
pxTopOfHardwareStack = pxTopOfStack;
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
|
||||
|
||||
/* 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
|
||||
software stack (local variables, parameter passing, etc.) which uses the
|
||||
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;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
|
||||
/* 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().
|
||||
portSAVE_CONTEXT places the flags on the stack immediately after r0
|
||||
to ensure the interrupts get disabled as soon as possible, and so ensuring
|
||||
the stack use is minimal should a context switch interrupt occur. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x00; /* R0 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next place the address of the hardware stack. This is required so
|
||||
the AVR stack pointer can be restored to point to the hardware stack. */
|
||||
pxTopOfHardwareStack -= portBYTES_USED_BY_RETURN_ADDRESS;
|
||||
usAddress = ( uint16_t ) pxTopOfHardwareStack;
|
||||
|
||||
/* SPL */
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
/* SPH */
|
||||
usAddress >>= 8;
|
||||
*pxTopOfStack = ( StackType_t ) ( usAddress & ( uint16_t ) 0x00ff );
|
||||
pxTopOfStack--;
|
||||
|
||||
|
||||
|
||||
|
||||
/* 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--;
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
/* Setup the hardware to generate the tick. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Restore the context of the first task that is going to run.
|
||||
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.*/
|
||||
vPortStart();
|
||||
|
||||
/* Should not get here! */
|
||||
return pdTRUE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the AVR port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Setup timer 1 compare match A to generate a tick interrupt.
|
||||
*/
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
uint8_t ucHighByte, ucLowByte;
|
||||
|
||||
/* Using 16bit timer 1 to generate the tick. Correct fuses must be
|
||||
selected for the configCPU_CLOCK_HZ clock. */
|
||||
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* We only have 16 bits so have to scale to get our required tick rate. */
|
||||
ulCompareMatch /= portCLOCK_PRESCALER;
|
||||
|
||||
/* Adjust for correct value. */
|
||||
ulCompareMatch -= ( uint32_t ) 1;
|
||||
|
||||
/* Setup compare match value for compare match A. Interrupts are disabled
|
||||
before this is called so we need not worry here. */
|
||||
ucLowByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
|
||||
ulCompareMatch >>= 8;
|
||||
ucHighByte = ( uint8_t ) ( ulCompareMatch & ( uint32_t ) 0xff );
|
||||
OCR1AH = ucHighByte;
|
||||
OCR1AL = ucLowByte;
|
||||
|
||||
/* Setup clock source and compare match behaviour. */
|
||||
ucLowByte = portCLEAR_COUNTER_ON_MATCH | portPRESCALE_64;
|
||||
TCCR1B = ucLowByte;
|
||||
|
||||
/* Enable the interrupt - this is okay as interrupt are currently globally
|
||||
disabled. */
|
||||
TIMSK |= portCOMPARE_MATCH_A_INTERRUPT_ENABLE;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_PREEMPTION == 1
|
||||
|
||||
/*
|
||||
* Tick ISR for preemptive scheduler. We can use a __task attribute as
|
||||
* the context is saved at the start of vPortYieldFromTick(). The tick
|
||||
* count is incremented after the context is saved.
|
||||
*/
|
||||
__task void SIG_OUTPUT_COMPARE1A( void )
|
||||
{
|
||||
vPortYieldFromTick();
|
||||
asm( "reti" );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Tick ISR for the cooperative scheduler. All this does is increment the
|
||||
* tick count. We don't need to switch context, this can only be done by
|
||||
* manual calls to taskYIELD();
|
||||
*
|
||||
* THE INTERRUPT VECTOR IS POPULATED IN portmacro.s90. DO NOT INSTALL
|
||||
* IT HERE USING THE USUAL PRAGMA.
|
||||
*/
|
||||
__interrupt void SIG_OUTPUT_COMPARE1A( void )
|
||||
{
|
||||
xTaskIncrementTick();
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
portDISABLE_INTERRUPTS();
|
||||
uxCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
uxCriticalNesting--;
|
||||
if( uxCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
112
portable/IAR/ATMega323/portmacro.h
Normal file
112
portable/IAR/ATMega323/portmacro.h
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*
|
||||
Changes from V1.2.3
|
||||
|
||||
+ portCPU_CLOSK_HZ definition changed to 8MHz base 10, previously it
|
||||
base 16.
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint8_t
|
||||
#define portBASE_TYPE char
|
||||
#define portPOINTER_SIZE_TYPE uint16_t
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef signed char BaseType_t;
|
||||
typedef unsigned char UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section management. */
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
|
||||
#define portDISABLE_INTERRUPTS() asm( "cli" )
|
||||
#define portENABLE_INTERRUPTS() asm( "sei" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 1
|
||||
#define portNOP() asm( "nop" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Kernel utilities. */
|
||||
void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
|
||||
#ifdef IAR_MEGA_AVR
|
||||
#define outb( PORT, VALUE ) PORT = VALUE
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
||||
245
portable/IAR/ATMega323/portmacro.s90
Normal file
245
portable/IAR/ATMega323/portmacro.s90
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
#include <iom323.h>
|
||||
|
||||
; Declare all extern symbols here - including any ISRs that are referenced in
|
||||
; the vector table.
|
||||
|
||||
; ISR functions
|
||||
; -------------
|
||||
EXTERN SIG_OUTPUT_COMPARE1A
|
||||
EXTERN SIG_UART_RECV
|
||||
EXTERN SIG_UART_DATA
|
||||
|
||||
|
||||
; Functions used by scheduler
|
||||
; ---------------------------
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN xTaskIncrementTick
|
||||
EXTERN uxCriticalNesting
|
||||
|
||||
; Functions implemented in this file
|
||||
; ----------------------------------
|
||||
PUBLIC vPortYield
|
||||
PUBLIC vPortYieldFromTick
|
||||
PUBLIC vPortStart
|
||||
|
||||
|
||||
; Interrupt vector table.
|
||||
; -----------------------
|
||||
;
|
||||
; For simplicity the RTOS tick interrupt routine uses the __task keyword.
|
||||
; As the IAR compiler does not permit a function to be declared using both
|
||||
; __task and __interrupt, the use of __task necessitates that the interrupt
|
||||
; vector table be setup manually.
|
||||
;
|
||||
; To write an ISR, implement the ISR function using the __interrupt keyword
|
||||
; but do not install the interrupt using the "#pragma vector=ABC" method.
|
||||
; Instead manually place the name of the ISR in the vector table using an
|
||||
; ORG and jmp instruction as demonstrated below.
|
||||
; You will also have to add an EXTERN statement at the top of the file.
|
||||
|
||||
ASEG
|
||||
|
||||
|
||||
ORG TIMER1_COMPA_vect ; Vector address
|
||||
jmp SIG_OUTPUT_COMPARE1A ; ISR
|
||||
|
||||
ORG USART_RXC_vect ; Vector address
|
||||
jmp SIG_UART_RECV ; ISR
|
||||
|
||||
ORG USART_UDRE_vect ; Vector address
|
||||
jmp SIG_UART_DATA ; ISR
|
||||
|
||||
|
||||
RSEG CODE
|
||||
|
||||
|
||||
|
||||
; Saving and Restoring a Task Context and Task Switching
|
||||
; ------------------------------------------------------
|
||||
;
|
||||
; The IAR compiler does not fully support inline assembler, so saving and
|
||||
; restoring a task context has to be written in an asm file.
|
||||
;
|
||||
; vPortYield() and vPortYieldFromTick() are usually written in C. Doing
|
||||
; so in this case would required calls to be made to portSAVE_CONTEXT() and
|
||||
; portRESTORE_CONTEXT(). This is dis-advantageous as the context switch
|
||||
; function would require two extra jump and return instructions over the
|
||||
; WinAVR equivalent.
|
||||
;
|
||||
; To avoid this I have opted to implement both vPortYield() and
|
||||
; vPortYieldFromTick() in this assembly file. For convenience
|
||||
; portSAVE_CONTEXT and portRESTORE_CONTEXT are implemented as macros.
|
||||
|
||||
portSAVE_CONTEXT MACRO
|
||||
st -y, r0 ; First save the r0 register - we need to use this.
|
||||
in r0, SREG ; Obtain the SREG value so we can disable interrupts...
|
||||
cli ; ... as soon as possible.
|
||||
st -y, r0 ; Store the SREG as it was before we disabled interrupts.
|
||||
|
||||
in r0, SPL ; Next store the hardware stack pointer. The IAR...
|
||||
st -y, r0 ; ... compiler uses the hardware stack as a call stack ...
|
||||
in r0, SPH ; ... only.
|
||||
st -y, r0
|
||||
|
||||
st -y, r1 ; Now store the rest of the registers. Dont store the ...
|
||||
st -y, r2 ; ... the Y register here as it is used as the software
|
||||
st -y, r3 ; stack pointer and will get saved into the TCB.
|
||||
st -y, r4
|
||||
st -y, r5
|
||||
st -y, r6
|
||||
st -y, r7
|
||||
st -y, r8
|
||||
st -y, r9
|
||||
st -y, r10
|
||||
st -y, r11
|
||||
st -y, r12
|
||||
st -y, r13
|
||||
st -y, r14
|
||||
st -y, r15
|
||||
st -y, r16
|
||||
st -y, r17
|
||||
st -y, r18
|
||||
st -y, r19
|
||||
st -y, r20
|
||||
st -y, r21
|
||||
st -y, r22
|
||||
st -y, r23
|
||||
st -y, r24
|
||||
st -y, r25
|
||||
st -y, r26
|
||||
st -y, r27
|
||||
st -y, r30
|
||||
st -y, r31
|
||||
lds r0, uxCriticalNesting
|
||||
st -y, r0 ; Store the critical nesting counter.
|
||||
|
||||
lds r26, pxCurrentTCB ; Finally save the software stack pointer (Y ...
|
||||
lds r27, pxCurrentTCB + 1 ; ... register) into the TCB.
|
||||
st x+, r28
|
||||
st x+, r29
|
||||
|
||||
ENDM
|
||||
|
||||
|
||||
portRESTORE_CONTEXT MACRO
|
||||
lds r26, pxCurrentTCB
|
||||
lds r27, pxCurrentTCB + 1 ; Restore the software stack pointer from ...
|
||||
ld r28, x+ ; the TCB into the software stack pointer (...
|
||||
ld r29, x+ ; ... the Y register).
|
||||
|
||||
ld r0, y+
|
||||
sts uxCriticalNesting, r0
|
||||
ld r31, y+ ; Restore the registers down to R0. The Y
|
||||
ld r30, y+ ; register is missing from this list as it
|
||||
ld r27, y+ ; has already been restored.
|
||||
ld r26, y+
|
||||
ld r25, y+
|
||||
ld r24, y+
|
||||
ld r23, y+
|
||||
ld r22, y+
|
||||
ld r21, y+
|
||||
ld r20, y+
|
||||
ld r19, y+
|
||||
ld r18, y+
|
||||
ld r17, y+
|
||||
ld r16, y+
|
||||
ld r15, y+
|
||||
ld r14, y+
|
||||
ld r13, y+
|
||||
ld r12, y+
|
||||
ld r11, y+
|
||||
ld r10, y+
|
||||
ld r9, y+
|
||||
ld r8, y+
|
||||
ld r7, y+
|
||||
ld r6, y+
|
||||
ld r5, y+
|
||||
ld r4, y+
|
||||
ld r3, y+
|
||||
ld r2, y+
|
||||
ld r1, y+
|
||||
|
||||
ld r0, y+ ; The next thing on the stack is the ...
|
||||
out SPH, r0 ; ... hardware stack pointer.
|
||||
ld r0, y+
|
||||
out SPL, r0
|
||||
|
||||
ld r0, y+ ; Next there is the SREG register.
|
||||
out SREG, r0
|
||||
|
||||
ld r0, y+ ; Finally we have finished with r0, so restore r0.
|
||||
|
||||
ENDM
|
||||
|
||||
|
||||
|
||||
; vPortYield() and vPortYieldFromTick()
|
||||
; -------------------------------------
|
||||
;
|
||||
; Manual and preemptive context switch functions respectively.
|
||||
; The IAR compiler does not fully support inline assembler,
|
||||
; so these are implemented here rather than the more usually
|
||||
; place of within port.c.
|
||||
|
||||
vPortYield:
|
||||
portSAVE_CONTEXT ; Save the context of the current task.
|
||||
call vTaskSwitchContext ; Call the scheduler.
|
||||
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
|
||||
ret ; ... scheduler decided should run.
|
||||
|
||||
vPortYieldFromTick:
|
||||
portSAVE_CONTEXT ; Save the context of the current task.
|
||||
call xTaskIncrementTick ; Call the timer tick function.
|
||||
tst r16
|
||||
breq SkipTaskSwitch
|
||||
call vTaskSwitchContext ; Call the scheduler.
|
||||
SkipTaskSwitch:
|
||||
portRESTORE_CONTEXT ; Restore the context of whichever task the ...
|
||||
ret ; ... scheduler decided should run.
|
||||
|
||||
; vPortStart()
|
||||
; ------------
|
||||
;
|
||||
; Again due to the lack of inline assembler, this is required
|
||||
; to get access to the portRESTORE_CONTEXT macro.
|
||||
|
||||
vPortStart:
|
||||
portRESTORE_CONTEXT
|
||||
ret
|
||||
|
||||
|
||||
; Just a filler for unused interrupt vectors.
|
||||
vNoISR:
|
||||
reti
|
||||
|
||||
|
||||
END
|
||||
|
||||
310
portable/IAR/AVR32_UC3/exception.s82
Normal file
310
portable/IAR/AVR32_UC3/exception.s82
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
/*This file is prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file *********************************************************************
|
||||
*
|
||||
* \brief Exception and interrupt vectors.
|
||||
*
|
||||
* This file maps all events supported by an AVR32UC.
|
||||
*
|
||||
* - Compiler: IAR EWAVR32
|
||||
* - Supported devices: All AVR32UC devices with an INTC module can be used.
|
||||
* - AppNote:
|
||||
*
|
||||
* \author Atmel Corporation: http://www.atmel.com \n
|
||||
* Support and FAQ: http://support.atmel.no/
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of ATMEL may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
|
||||
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <avr32/io.h>
|
||||
#include "intc.h"
|
||||
|
||||
|
||||
//! @{
|
||||
//! \verbatim
|
||||
|
||||
|
||||
// Start of Exception Vector Table.
|
||||
|
||||
// EVBA must be aligned with a power of two strictly greater than the EVBA-
|
||||
// relative offset of the last vector.
|
||||
COMMON EVTAB:CODE:ROOT(9)
|
||||
|
||||
|
||||
// Force EVBA initialization.
|
||||
EXTERN ??init_EVBA
|
||||
REQUIRE ??init_EVBA
|
||||
|
||||
// Export symbol.
|
||||
PUBLIC ??EVBA
|
||||
PUBLIC _evba
|
||||
??EVBA:
|
||||
_evba:
|
||||
|
||||
ORG 0x000
|
||||
// Unrecoverable Exception.
|
||||
_handle_Unrecoverable_Exception:
|
||||
rjmp $
|
||||
|
||||
ORG 0x004
|
||||
// TLB Multiple Hit: UNUSED IN AVR32UC.
|
||||
_handle_TLB_Multiple_Hit:
|
||||
rjmp $
|
||||
|
||||
ORG 0x008
|
||||
// Bus Error Data Fetch.
|
||||
_handle_Bus_Error_Data_Fetch:
|
||||
rjmp $
|
||||
|
||||
ORG 0x00C
|
||||
// Bus Error Instruction Fetch.
|
||||
_handle_Bus_Error_Instruction_Fetch:
|
||||
rjmp $
|
||||
|
||||
ORG 0x010
|
||||
// NMI.
|
||||
_handle_NMI:
|
||||
rjmp $
|
||||
|
||||
ORG 0x014
|
||||
// Instruction Address.
|
||||
_handle_Instruction_Address:
|
||||
rjmp $
|
||||
|
||||
ORG 0x018
|
||||
// ITLB Protection.
|
||||
_handle_ITLB_Protection:
|
||||
rjmp $
|
||||
|
||||
ORG 0x01C
|
||||
// Breakpoint.
|
||||
_handle_Breakpoint:
|
||||
rjmp $
|
||||
|
||||
ORG 0x020
|
||||
// Illegal Opcode.
|
||||
_handle_Illegal_Opcode:
|
||||
rjmp $
|
||||
|
||||
ORG 0x024
|
||||
// Unimplemented Instruction.
|
||||
_handle_Unimplemented_Instruction:
|
||||
rjmp $
|
||||
|
||||
ORG 0x028
|
||||
// Privilege Violation.
|
||||
_handle_Privilege_Violation:
|
||||
rjmp $
|
||||
|
||||
ORG 0x02C
|
||||
// Floating-Point: UNUSED IN AVR32UC.
|
||||
_handle_Floating_Point:
|
||||
rjmp $
|
||||
|
||||
ORG 0x030
|
||||
// Coprocessor Absent: UNUSED IN AVR32UC.
|
||||
_handle_Coprocessor_Absent:
|
||||
rjmp $
|
||||
|
||||
ORG 0x034
|
||||
// Data Address (Read).
|
||||
_handle_Data_Address_Read:
|
||||
rjmp $
|
||||
|
||||
ORG 0x038
|
||||
// Data Address (Write).
|
||||
_handle_Data_Address_Write:
|
||||
rjmp $
|
||||
|
||||
ORG 0x03C
|
||||
// DTLB Protection (Read).
|
||||
_handle_DTLB_Protection_Read:
|
||||
rjmp $
|
||||
|
||||
ORG 0x040
|
||||
// DTLB Protection (Write).
|
||||
_handle_DTLB_Protection_Write:
|
||||
rjmp $
|
||||
|
||||
ORG 0x044
|
||||
// DTLB Modified: UNUSED IN AVR32UC.
|
||||
_handle_DTLB_Modified:
|
||||
rjmp $
|
||||
|
||||
ORG 0x050
|
||||
// ITLB Miss: UNUSED IN AVR32UC.
|
||||
_handle_ITLB_Miss:
|
||||
rjmp $
|
||||
|
||||
ORG 0x060
|
||||
// DTLB Miss (Read): UNUSED IN AVR32UC.
|
||||
_handle_DTLB_Miss_Read:
|
||||
rjmp $
|
||||
|
||||
ORG 0x070
|
||||
// DTLB Miss (Write): UNUSED IN AVR32UC.
|
||||
_handle_DTLB_Miss_Write:
|
||||
rjmp $
|
||||
|
||||
ORG 0x100
|
||||
// Supervisor Call.
|
||||
_handle_Supervisor_Call:
|
||||
lddpc pc, __SCALLYield
|
||||
|
||||
|
||||
// Interrupt support.
|
||||
// The interrupt controller must provide the offset address relative to EVBA.
|
||||
// Important note:
|
||||
// All interrupts call a C function named _get_interrupt_handler.
|
||||
// This function will read group and interrupt line number to then return in
|
||||
// R12 a pointer to a user-provided interrupt handler.
|
||||
|
||||
ALIGN 2
|
||||
|
||||
_int0:
|
||||
// R8-R12, LR, PC and SR are automatically pushed onto the system stack by the
|
||||
// CPU upon interrupt entry.
|
||||
#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.
|
||||
mfsr r12, AVR32_SR
|
||||
bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE
|
||||
cp.w r12, 110b
|
||||
brlo _int0_normal
|
||||
lddsp r12, sp[0 * 4]
|
||||
stdsp sp[6 * 4], r12
|
||||
lddsp r12, sp[1 * 4]
|
||||
stdsp sp[7 * 4], r12
|
||||
lddsp r12, sp[3 * 4]
|
||||
sub sp, -6 * 4
|
||||
rete
|
||||
_int0_normal:
|
||||
#endif
|
||||
mov r12, 0 // Pass the int_lev parameter to the _get_interrupt_handler function.
|
||||
mcall __get_interrupt_handler
|
||||
cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.
|
||||
movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
|
||||
rete // If this was a spurious interrupt (R12 == NULL), return from event handler.
|
||||
|
||||
_int1:
|
||||
// R8-R12, LR, PC and SR are automatically pushed onto the system stack by the
|
||||
// CPU upon interrupt entry.
|
||||
#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.
|
||||
mfsr r12, AVR32_SR
|
||||
bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE
|
||||
cp.w r12, 110b
|
||||
brlo _int1_normal
|
||||
lddsp r12, sp[0 * 4]
|
||||
stdsp sp[6 * 4], r12
|
||||
lddsp r12, sp[1 * 4]
|
||||
stdsp sp[7 * 4], r12
|
||||
lddsp r12, sp[3 * 4]
|
||||
sub sp, -6 * 4
|
||||
rete
|
||||
_int1_normal:
|
||||
#endif
|
||||
mov r12, 1 // Pass the int_lev parameter to the _get_interrupt_handler function.
|
||||
mcall __get_interrupt_handler
|
||||
cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.
|
||||
movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
|
||||
rete // If this was a spurious interrupt (R12 == NULL), return from event handler.
|
||||
|
||||
_int2:
|
||||
// R8-R12, LR, PC and SR are automatically pushed onto the system stack by the
|
||||
// CPU upon interrupt entry.
|
||||
#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.
|
||||
mfsr r12, AVR32_SR
|
||||
bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE
|
||||
cp.w r12, 110b
|
||||
brlo _int2_normal
|
||||
lddsp r12, sp[0 * 4]
|
||||
stdsp sp[6 * 4], r12
|
||||
lddsp r12, sp[1 * 4]
|
||||
stdsp sp[7 * 4], r12
|
||||
lddsp r12, sp[3 * 4]
|
||||
sub sp, -6 * 4
|
||||
rete
|
||||
_int2_normal:
|
||||
#endif
|
||||
mov r12, 2 // Pass the int_lev parameter to the _get_interrupt_handler function.
|
||||
mcall __get_interrupt_handler
|
||||
cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.
|
||||
movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
|
||||
rete // If this was a spurious interrupt (R12 == NULL), return from event handler.
|
||||
|
||||
_int3:
|
||||
// R8-R12, LR, PC and SR are automatically pushed onto the system stack by the
|
||||
// CPU upon interrupt entry.
|
||||
#if 1 // B1832: interrupt stack changed to exception stack if exception is detected.
|
||||
mfsr r12, AVR32_SR
|
||||
bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE
|
||||
cp.w r12, 110b
|
||||
brlo _int3_normal
|
||||
lddsp r12, sp[0 * 4]
|
||||
stdsp sp[6 * 4], r12
|
||||
lddsp r12, sp[1 * 4]
|
||||
stdsp sp[7 * 4], r12
|
||||
lddsp r12, sp[3 * 4]
|
||||
sub sp, -6 * 4
|
||||
rete
|
||||
_int3_normal:
|
||||
#endif
|
||||
mov r12, 3 // Pass the int_lev parameter to the _get_interrupt_handler function.
|
||||
mcall __get_interrupt_handler
|
||||
cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function.
|
||||
movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler.
|
||||
rete // If this was a spurious interrupt (R12 == NULL), return from event handler.
|
||||
|
||||
|
||||
// Constant data area.
|
||||
|
||||
ALIGN 2
|
||||
|
||||
// Import symbols.
|
||||
EXTERN SCALLYield
|
||||
EXTERN _get_interrupt_handler
|
||||
__SCALLYield:
|
||||
DC32 SCALLYield
|
||||
__get_interrupt_handler:
|
||||
DC32 _get_interrupt_handler
|
||||
|
||||
// Values to store in the interrupt priority registers for the various interrupt priority levels.
|
||||
// The interrupt priority registers contain the interrupt priority level and
|
||||
// the EVBA-relative interrupt vector offset.
|
||||
PUBLIC ipr_val
|
||||
ipr_val:
|
||||
DC32 (INT0 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int0 - _evba),\
|
||||
(INT1 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int1 - _evba),\
|
||||
(INT2 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int2 - _evba),\
|
||||
(INT3 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int3 - _evba)
|
||||
|
||||
|
||||
END
|
||||
|
||||
|
||||
//! \endverbatim
|
||||
//! @}
|
||||
406
portable/IAR/AVR32_UC3/port.c
Normal file
406
portable/IAR/AVR32_UC3/port.c
Normal file
|
|
@ -0,0 +1,406 @@
|
|||
/*This file has been prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file *********************************************************************
|
||||
*
|
||||
* \brief FreeRTOS port source for AVR32 UC3.
|
||||
*
|
||||
* - Compiler: IAR EWAVR32
|
||||
* - Supported devices: All AVR32 devices can be used.
|
||||
* - AppNote:
|
||||
*
|
||||
* \author Atmel Corporation: http://www.atmel.com \n
|
||||
* Support and FAQ: http://support.atmel.no/
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* AVR32 UC3 includes. */
|
||||
#include <avr32/io.h>
|
||||
#include <intrinsics.h>
|
||||
#include "gpio.h"
|
||||
|
||||
#if configDBG
|
||||
#include "usart.h"
|
||||
#endif
|
||||
|
||||
#if( configTICK_USE_TC==1 )
|
||||
#include "tc.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* Constants required to setup the task context. */
|
||||
#define portINITIAL_SR ( ( StackType_t ) 0x00400000 ) /* AVR32 : [M2:M0]=001 I1M=0 I0M=0, GM=0 */
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 0 )
|
||||
|
||||
/* Each task maintains its own critical nesting variable. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
volatile uint32_t ulCriticalNesting = 9999UL;
|
||||
|
||||
#if( configTICK_USE_TC==0 )
|
||||
static void prvScheduleNextTick( void );
|
||||
#else
|
||||
static void prvClearTcInt( void );
|
||||
#endif
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Low-level initialization routine called during startup, before the main
|
||||
* function.
|
||||
*/
|
||||
int __low_level_init(void)
|
||||
{
|
||||
#if configHEAP_INIT
|
||||
#pragma segment = "HEAP"
|
||||
BaseType_t *pxMem;
|
||||
#endif
|
||||
|
||||
/* Enable exceptions. */
|
||||
ENABLE_ALL_EXCEPTIONS();
|
||||
|
||||
/* Initialize interrupt handling. */
|
||||
INTC_init_interrupts();
|
||||
|
||||
#if configHEAP_INIT
|
||||
{
|
||||
/* Initialize the heap used by malloc. */
|
||||
for( pxMem = __segment_begin( "HEAP" ); pxMem < ( BaseType_t * ) __segment_end( "HEAP" ); )
|
||||
{
|
||||
*pxMem++ = 0xA5A5A5A5;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Code section present if and only if the debug trace is activated. */
|
||||
#if configDBG
|
||||
{
|
||||
static const gpio_map_t DBG_USART_GPIO_MAP =
|
||||
{
|
||||
{ configDBG_USART_RX_PIN, configDBG_USART_RX_FUNCTION },
|
||||
{ configDBG_USART_TX_PIN, configDBG_USART_TX_FUNCTION }
|
||||
};
|
||||
|
||||
static const usart_options_t DBG_USART_OPTIONS =
|
||||
{
|
||||
.baudrate = configDBG_USART_BAUDRATE,
|
||||
.charlength = 8,
|
||||
.paritytype = USART_NO_PARITY,
|
||||
.stopbits = USART_1_STOPBIT,
|
||||
.channelmode = USART_NORMAL_CHMODE
|
||||
};
|
||||
|
||||
/* Initialize the USART used for the debug trace with the configured parameters. */
|
||||
extern volatile avr32_usart_t *volatile stdio_usart_base;
|
||||
stdio_usart_base = configDBG_USART;
|
||||
gpio_enable_module( DBG_USART_GPIO_MAP,
|
||||
sizeof( DBG_USART_GPIO_MAP ) / sizeof( DBG_USART_GPIO_MAP[0] ) );
|
||||
usart_init_rs232(configDBG_USART, &DBG_USART_OPTIONS, configCPU_CLOCK_HZ);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Request initialization of data segments. */
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Added as there is no such function in FreeRTOS. */
|
||||
void *pvPortRealloc( void *pv, size_t xWantedSize )
|
||||
{
|
||||
void *pvReturn;
|
||||
|
||||
vTaskSuspendAll();
|
||||
{
|
||||
pvReturn = realloc( pv, xWantedSize );
|
||||
}
|
||||
xTaskResumeAll();
|
||||
|
||||
return pvReturn;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
/* The preemptive scheduler is defined as "naked" as the full context is saved
|
||||
on entry as part of the context switch. */
|
||||
#pragma shadow_registers = full // Naked.
|
||||
static void vTick( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT_OS_INT();
|
||||
|
||||
#if( configTICK_USE_TC==1 )
|
||||
/* Clear the interrupt flag. */
|
||||
prvClearTcInt();
|
||||
#else
|
||||
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
|
||||
clock cycles from now. */
|
||||
prvScheduleNextTick();
|
||||
#endif
|
||||
|
||||
/* Because FreeRTOS is not supposed to run with nested interrupts, put all OS
|
||||
calls in a critical section . */
|
||||
portENTER_CRITICAL();
|
||||
xTaskIncrementTick();
|
||||
portEXIT_CRITICAL();
|
||||
|
||||
/* Restore the context of the "elected task". */
|
||||
portRESTORE_CONTEXT_OS_INT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#pragma shadow_registers = full // Naked.
|
||||
void SCALLYield( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT_SCALL();
|
||||
vTaskSwitchContext();
|
||||
portRESTORE_CONTEXT_SCALL();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* The code generated by the GCC compiler uses the stack in different ways at
|
||||
different optimisation levels. The interrupt flags can therefore not always
|
||||
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. */
|
||||
#pragma optimize = no_inline
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#pragma optimize = no_inline
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if(ulCriticalNesting > portNO_CRITICAL_NESTING)
|
||||
{
|
||||
ulCriticalNesting--;
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Enable all interrupt/exception. */
|
||||
portENABLE_INTERRUPTS();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* When the task starts, it will expect to find the function parameter in R12. */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x08080808; /* R8 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x09090909; /* R9 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x0A0A0A0A; /* R10 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x0B0B0B0B; /* R11 */
|
||||
*pxTopOfStack-- = ( StackType_t ) pvParameters; /* R12 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xDEADBEEF; /* R14/LR */
|
||||
*pxTopOfStack-- = ( StackType_t ) pxCode + portINSTRUCTION_SIZE; /* R15/PC */
|
||||
*pxTopOfStack-- = ( StackType_t ) portINITIAL_SR; /* SR */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0xFF0000FF; /* R0 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x01010101; /* R1 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x02020202; /* R2 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x03030303; /* R3 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x04040404; /* R4 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x05050505; /* R5 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x06060606; /* R6 */
|
||||
*pxTopOfStack-- = ( StackType_t ) 0x07070707; /* R7 */
|
||||
*pxTopOfStack = ( StackType_t ) portNO_CRITICAL_NESTING; /* ulCriticalNesting */
|
||||
|
||||
return pxTopOfStack;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
BaseType_t xPortStartScheduler( void )
|
||||
{
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
portRESTORE_CONTEXT();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the AVR32 port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ)
|
||||
clock cycles from now. */
|
||||
#if( configTICK_USE_TC==0 )
|
||||
static void prvScheduleFirstTick(void)
|
||||
{
|
||||
uint32_t lCycles;
|
||||
|
||||
lCycles = Get_system_register(AVR32_COUNT);
|
||||
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;
|
||||
|
||||
lCycles = Get_system_register(AVR32_COMPARE);
|
||||
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++;
|
||||
}
|
||||
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
|
||||
#pragma optimize = no_inline
|
||||
static void prvClearTcInt(void)
|
||||
{
|
||||
AVR32_TC.channel[configTICK_TC_CHANNEL].sr;
|
||||
}
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the timer to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt(void)
|
||||
{
|
||||
#if( configTICK_USE_TC==1 )
|
||||
|
||||
volatile avr32_tc_t *tc = &AVR32_TC;
|
||||
|
||||
// Options for waveform genration.
|
||||
tc_waveform_opt_t waveform_opt =
|
||||
{
|
||||
.channel = configTICK_TC_CHANNEL, /* Channel selection. */
|
||||
|
||||
.bswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOB. */
|
||||
.beevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOB. */
|
||||
.bcpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOB. */
|
||||
.bcpb = TC_EVT_EFFECT_NOOP, /* RB compare effect on TIOB. */
|
||||
|
||||
.aswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOA. */
|
||||
.aeevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOA. */
|
||||
.acpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOA: toggle. */
|
||||
.acpa = TC_EVT_EFFECT_NOOP, /* RA compare effect on TIOA: toggle (other possibilities are none, set and clear). */
|
||||
|
||||
.wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,/* Waveform selection: Up mode without automatic trigger on RC compare. */
|
||||
.enetrg = FALSE, /* External event trigger enable. */
|
||||
.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. */
|
||||
|
||||
.burst = FALSE, /* Burst signal selection. */
|
||||
.clki = FALSE, /* Clock inversion. */
|
||||
.tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */
|
||||
};
|
||||
|
||||
tc_interrupt_t tc_interrupt =
|
||||
{
|
||||
.etrgs=0,
|
||||
.ldrbs=0,
|
||||
.ldras=0,
|
||||
.cpcs =1,
|
||||
.cpbs =0,
|
||||
.cpas =0,
|
||||
.lovrs=0,
|
||||
.covfs=0,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/* Disable all interrupt/exception. */
|
||||
portDISABLE_INTERRUPTS();
|
||||
|
||||
/* Register the compare interrupt handler to the interrupt controller and
|
||||
enable the compare interrupt. */
|
||||
|
||||
#if( configTICK_USE_TC==1 )
|
||||
{
|
||||
INTC_register_interrupt((__int_handler)&vTick, configTICK_TC_IRQ, INT0);
|
||||
|
||||
/* Initialize the timer/counter. */
|
||||
tc_init_waveform(tc, &waveform_opt);
|
||||
|
||||
/* Set the compare triggers.
|
||||
Remember TC counter is 16-bits, so counting second is not possible!
|
||||
That's why we configure it to count ms. */
|
||||
tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4) / configTICK_RATE_HZ );
|
||||
|
||||
tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt );
|
||||
|
||||
/* Start the timer/counter. */
|
||||
tc_start(tc, configTICK_TC_CHANNEL);
|
||||
}
|
||||
#else
|
||||
{
|
||||
INTC_register_interrupt((__int_handler)&vTick, AVR32_CORE_COMPARE_IRQ, INT0);
|
||||
prvScheduleFirstTick();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
654
portable/IAR/AVR32_UC3/portmacro.h
Normal file
654
portable/IAR/AVR32_UC3/portmacro.h
Normal file
|
|
@ -0,0 +1,654 @@
|
|||
/*This file has been prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file *********************************************************************
|
||||
*
|
||||
* \brief FreeRTOS port header for AVR32 UC3.
|
||||
*
|
||||
* - Compiler: IAR EWAVR32
|
||||
* - Supported devices: All AVR32 devices can be used.
|
||||
* - AppNote:
|
||||
*
|
||||
* \author Atmel Corporation: http://www.atmel.com \n
|
||||
* Support and FAQ: http://support.atmel.no/
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
#include <avr32/io.h>
|
||||
#include "intc.h"
|
||||
#include "compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
|
||||
#define TASK_DELAY_MS(x) ( (x) /portTICK_PERIOD_MS )
|
||||
#define TASK_DELAY_S(x) ( (x)*1000 /portTICK_PERIOD_MS )
|
||||
#define TASK_DELAY_MIN(x) ( (x)*60*1000/portTICK_PERIOD_MS )
|
||||
|
||||
#define configTICK_TC_IRQ ATPASTE2(AVR32_TC_IRQ, configTICK_TC_CHANNEL)
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Architecture specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 4
|
||||
#define portNOP() {__asm__ __volatile__ ("nop");}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* INTC-specific. */
|
||||
#define DISABLE_ALL_EXCEPTIONS() Disable_global_exception()
|
||||
#define ENABLE_ALL_EXCEPTIONS() Enable_global_exception()
|
||||
|
||||
#define DISABLE_ALL_INTERRUPTS() Disable_global_interrupt()
|
||||
#define ENABLE_ALL_INTERRUPTS() Enable_global_interrupt()
|
||||
|
||||
#define DISABLE_INT_LEVEL(int_lev) Disable_interrupt_level(int_lev)
|
||||
#define ENABLE_INT_LEVEL(int_lev) Enable_interrupt_level(int_lev)
|
||||
|
||||
|
||||
/*
|
||||
* Debug trace.
|
||||
* Activated if and only if configDBG is nonzero.
|
||||
* Prints a formatted string to stdout.
|
||||
* The current source file name and line number are output with a colon before
|
||||
* the formatted string.
|
||||
* A carriage return and a linefeed are appended to the output.
|
||||
* stdout is redirected to the USART configured by configDBG_USART.
|
||||
* The parameters are the same as for the standard printf function.
|
||||
* There is no return value.
|
||||
* SHALL NOT BE CALLED FROM WITHIN AN INTERRUPT as fputs and printf use malloc,
|
||||
* which is interrupt-unsafe with the current __malloc_lock and __malloc_unlock.
|
||||
*/
|
||||
#if configDBG
|
||||
#define portDBG_TRACE(...) \
|
||||
{ \
|
||||
fputs(__FILE__ ":" ASTRINGZ(__LINE__) ": ", stdout); \
|
||||
printf(__VA_ARGS__); \
|
||||
fputs("\r\n", stdout); \
|
||||
}
|
||||
#else
|
||||
#define portDBG_TRACE(...)
|
||||
#endif
|
||||
|
||||
|
||||
/* Critical section management. */
|
||||
#define portDISABLE_INTERRUPTS() DISABLE_ALL_INTERRUPTS()
|
||||
#define portENABLE_INTERRUPTS() ENABLE_ALL_INTERRUPTS()
|
||||
|
||||
|
||||
extern void vPortEnterCritical( void );
|
||||
extern void vPortExitCritical( void );
|
||||
|
||||
#define portENTER_CRITICAL() vPortEnterCritical();
|
||||
#define portEXIT_CRITICAL() vPortExitCritical();
|
||||
|
||||
|
||||
/* Added as there is no such function in FreeRTOS. */
|
||||
extern void *pvPortRealloc( void *pv, size_t xSize );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*=============================================================================================*/
|
||||
|
||||
/*
|
||||
* Restore Context for cases other than INTi.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile void *volatile pxCurrentTCB; \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
/* Set SP to point to new stack */ \
|
||||
"mov r8, LWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"ld.w sp, r0[0] \n\t"\
|
||||
\
|
||||
/* Restore ulCriticalNesting variable */ \
|
||||
"ld.w r0, sp++ \n\t"\
|
||||
"mov r8, LWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"st.w r8[0], r0 \n\t"\
|
||||
\
|
||||
/* Restore R0..R7 */ \
|
||||
"ldm sp++, r0-r7 \n\t"\
|
||||
/* R0-R7 should not be used below this line */ \
|
||||
/* Skip PC and SR (will do it at the end) */ \
|
||||
"sub sp, -2*4 \n\t"\
|
||||
/* Restore R8..R12 and LR */ \
|
||||
"ldm sp++, r8-r12, lr \n\t"\
|
||||
/* Restore SR */ \
|
||||
"ld.w r0, sp[-8*4] \n\t" /* R0 is modified, is restored later. */\
|
||||
"mtsr "ASTRINGZ(AVR32_SR)", r0 \n\t"\
|
||||
/* Restore r0 */ \
|
||||
"ld.w r0, sp[-9*4] \n\t"\
|
||||
/* Restore PC */ \
|
||||
"ld.w pc, sp[-7*4]" /* Get PC from stack - PC is the 7th register saved */ \
|
||||
); \
|
||||
\
|
||||
/* Force import of global symbols from assembly */ \
|
||||
ulCriticalNesting; \
|
||||
pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* portSAVE_CONTEXT_INT() and portRESTORE_CONTEXT_INT(): for INT0..3 exceptions.
|
||||
* portSAVE_CONTEXT_SCALL() and portRESTORE_CONTEXT_SCALL(): for the scall exception.
|
||||
*
|
||||
* Had to make different versions because registers saved on the system stack
|
||||
* are not the same between INT0..3 exceptions and the scall exception.
|
||||
*/
|
||||
|
||||
// Task context stack layout:
|
||||
// R8 (*)
|
||||
// R9 (*)
|
||||
// R10 (*)
|
||||
// R11 (*)
|
||||
// R12 (*)
|
||||
// R14/LR (*)
|
||||
// R15/PC (*)
|
||||
// SR (*)
|
||||
// R0
|
||||
// R1
|
||||
// R2
|
||||
// R3
|
||||
// R4
|
||||
// R5
|
||||
// R6
|
||||
// R7
|
||||
// ulCriticalNesting
|
||||
// (*) automatically done for INT0..INT3, but not for SCALL
|
||||
|
||||
/*
|
||||
* The ISR used for the scheduler tick depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/*
|
||||
* portSAVE_CONTEXT_OS_INT() for OS Tick exception.
|
||||
*/
|
||||
#define portSAVE_CONTEXT_OS_INT() \
|
||||
{ \
|
||||
/* Save R0..R7 */ \
|
||||
__asm__ __volatile__ ("stm --sp, r0-r7"); \
|
||||
\
|
||||
/* With the cooperative scheduler, as there is no context switch by interrupt, */ \
|
||||
/* there is also no context save. */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT_OS_INT() for Tick exception.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT_OS_INT() \
|
||||
{ \
|
||||
__asm__ __volatile__ ( \
|
||||
/* Restore R0..R7 */ \
|
||||
"ldm sp++, r0-r7 \n\t"\
|
||||
\
|
||||
/* With the cooperative scheduler, as there is no context switch by interrupt, */ \
|
||||
/* there is also no context restore. */ \
|
||||
"rete" \
|
||||
); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* portSAVE_CONTEXT_OS_INT() for OS Tick exception.
|
||||
*/
|
||||
#define portSAVE_CONTEXT_OS_INT() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile void *volatile pxCurrentTCB; \
|
||||
\
|
||||
/* When we come here */ \
|
||||
/* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
/* Save R0..R7 */ \
|
||||
"stm --sp, r0-r7 \n\t"\
|
||||
\
|
||||
/* Save ulCriticalNesting variable - R0 is overwritten */ \
|
||||
"mov r8, LWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"st.w --sp, r0 \n\t"\
|
||||
\
|
||||
/* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
|
||||
/* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
|
||||
/* level and allow other lower interrupt level to occur). */ \
|
||||
/* In this case we don't want to do a task switch because we don't know what the stack */ \
|
||||
/* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
|
||||
/* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
|
||||
/* will just be restoring the interrupt handler, no way!!! */ \
|
||||
/* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \
|
||||
"ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\
|
||||
"bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\
|
||||
"cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\
|
||||
"brhi LABEL_INT_SKIP_SAVE_CONTEXT_"ASTRINGZ(__LINE__)" \n\t"\
|
||||
\
|
||||
/* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
|
||||
/* NOTE: we don't enter a critical section here because all interrupt handlers */ \
|
||||
/* MUST perform a SAVE_CONTEXT/RESTORE_CONTEXT in the same way as */ \
|
||||
/* portSAVE_CONTEXT_OS_INT/port_RESTORE_CONTEXT_OS_INT if they call OS functions. */ \
|
||||
/* => all interrupt handlers must use portENTER_SWITCHING_ISR/portEXIT_SWITCHING_ISR. */ \
|
||||
"mov r8, LWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"st.w r0[0], sp \n"\
|
||||
\
|
||||
"LABEL_INT_SKIP_SAVE_CONTEXT_"ASTRINGZ(__LINE__)":" \
|
||||
); \
|
||||
}
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT_OS_INT() for Tick exception.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT_OS_INT() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile void *volatile pxCurrentTCB; \
|
||||
\
|
||||
/* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
|
||||
/* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
|
||||
/* level and allow other lower interrupt level to occur). */ \
|
||||
/* In this case we don't want to do a task switch because we don't know what the stack */ \
|
||||
/* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
|
||||
/* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
|
||||
/* will just be restoring the interrupt handler, no way!!! */ \
|
||||
__asm__ __volatile__ ( \
|
||||
"ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\
|
||||
"bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\
|
||||
"cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\
|
||||
"brhi LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__) \
|
||||
); \
|
||||
\
|
||||
/* Else */ \
|
||||
/* because it is here safe, always call vTaskSwitchContext() since an OS tick occurred. */ \
|
||||
/* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */\
|
||||
portENTER_CRITICAL(); \
|
||||
vTaskSwitchContext(); \
|
||||
portEXIT_CRITICAL(); \
|
||||
\
|
||||
/* Restore all registers */ \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
/* Set SP to point to new stack */ \
|
||||
"mov r8, LWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"ld.w sp, r0[0] \n"\
|
||||
\
|
||||
"LABEL_INT_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)": \n\t"\
|
||||
\
|
||||
/* Restore ulCriticalNesting variable */ \
|
||||
"ld.w r0, sp++ \n\t"\
|
||||
"mov r8, LWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"st.w r8[0], r0 \n\t"\
|
||||
\
|
||||
/* Restore R0..R7 */ \
|
||||
"ldm sp++, r0-r7 \n\t"\
|
||||
\
|
||||
/* Now, the stack should be R8..R12, LR, PC and SR */ \
|
||||
"rete" \
|
||||
); \
|
||||
\
|
||||
/* Force import of global symbols from assembly */ \
|
||||
ulCriticalNesting; \
|
||||
pxCurrentTCB; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* portSAVE_CONTEXT_SCALL() for SupervisorCALL exception.
|
||||
*
|
||||
* NOTE: taskYIELD()(== SCALL) MUST NOT be called in a mode > supervisor mode.
|
||||
*
|
||||
*/
|
||||
#define portSAVE_CONTEXT_SCALL() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile void *volatile pxCurrentTCB; \
|
||||
\
|
||||
/* Warning: the stack layout after SCALL doesn't match the one after an interrupt. */ \
|
||||
/* If SR[M2:M0] == 001 */ \
|
||||
/* PC and SR are on the stack. */ \
|
||||
/* Else (other modes) */ \
|
||||
/* Nothing on the stack. */ \
|
||||
\
|
||||
/* WARNING NOTE: the else case cannot happen as it is strictly forbidden to call */ \
|
||||
/* vTaskDelay() and vTaskDelayUntil() OS functions (that result in a taskYield()) */ \
|
||||
/* in an interrupt|exception handler. */ \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
/* in order to save R0-R7 */ \
|
||||
"sub sp, 6*4 \n\t"\
|
||||
/* Save R0..R7 */ \
|
||||
"stm --sp, r0-r7 \n\t"\
|
||||
\
|
||||
/* in order to save R8-R12 and LR */ \
|
||||
/* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \
|
||||
"sub r7, sp,-16*4 \n\t"\
|
||||
/* Copy PC and SR in other places in the stack. */ \
|
||||
"ld.w r0, r7[-2*4] \n\t" /* Read SR */\
|
||||
"st.w r7[-8*4], r0 \n\t" /* Copy SR */\
|
||||
"ld.w r0, r7[-1*4] \n\t" /* Read PC */\
|
||||
"st.w r7[-7*4], r0 \n\t" /* Copy PC */\
|
||||
\
|
||||
/* Save R8..R12 and LR on the stack. */ \
|
||||
"stm --r7, r8-r12, lr \n\t"\
|
||||
\
|
||||
/* Arriving here we have the following stack organizations: */ \
|
||||
/* R8..R12, LR, PC, SR, R0..R7. */ \
|
||||
\
|
||||
/* Now we can finalize the save. */ \
|
||||
\
|
||||
/* Save ulCriticalNesting variable - R0 is overwritten */ \
|
||||
"mov r8, LWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"st.w --sp, r0" \
|
||||
); \
|
||||
\
|
||||
/* Disable the its which may cause a context switch (i.e. cause a change of */ \
|
||||
/* pxCurrentTCB). */ \
|
||||
/* Basically, all accesses to the pxCurrentTCB structure should be put in a */ \
|
||||
/* critical section because it is a global structure. */ \
|
||||
portENTER_CRITICAL(); \
|
||||
\
|
||||
/* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
|
||||
__asm__ __volatile__ ( \
|
||||
"mov r8, LWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"st.w r0[0], sp" \
|
||||
); \
|
||||
}
|
||||
|
||||
/*
|
||||
* portRESTORE_CONTEXT() for SupervisorCALL exception.
|
||||
*/
|
||||
#define portRESTORE_CONTEXT_SCALL() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile void *volatile pxCurrentTCB; \
|
||||
\
|
||||
/* Restore all registers */ \
|
||||
\
|
||||
/* Set SP to point to new stack */ \
|
||||
__asm__ __volatile__ ( \
|
||||
"mov r8, LWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"ld.w sp, r0[0]" \
|
||||
); \
|
||||
\
|
||||
/* Leave pxCurrentTCB variable access critical section */ \
|
||||
portEXIT_CRITICAL(); \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
/* Restore ulCriticalNesting variable */ \
|
||||
"ld.w r0, sp++ \n\t"\
|
||||
"mov r8, LWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"st.w r8[0], r0 \n\t"\
|
||||
\
|
||||
/* skip PC and SR */ \
|
||||
/* do not use SP if interrupts occurs, SP must be left at bottom of stack */ \
|
||||
"sub r7, sp, -10*4 \n\t"\
|
||||
/* Restore r8-r12 and LR */ \
|
||||
"ldm r7++, r8-r12, lr \n\t"\
|
||||
\
|
||||
/* RETS will take care of the extra PC and SR restore. */ \
|
||||
/* So, we have to prepare the stack for this. */ \
|
||||
"ld.w r0, r7[-8*4] \n\t" /* Read SR */\
|
||||
"st.w r7[-2*4], r0 \n\t" /* Copy SR */\
|
||||
"ld.w r0, r7[-7*4] \n\t" /* Read PC */\
|
||||
"st.w r7[-1*4], r0 \n\t" /* Copy PC */\
|
||||
\
|
||||
/* Restore R0..R7 */ \
|
||||
"ldm sp++, r0-r7 \n\t"\
|
||||
\
|
||||
"sub sp, -6*4 \n\t"\
|
||||
\
|
||||
"rets" \
|
||||
); \
|
||||
\
|
||||
/* Force import of global symbols from assembly */ \
|
||||
ulCriticalNesting; \
|
||||
pxCurrentTCB; \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The ISR used depends on whether the cooperative or
|
||||
* the preemptive scheduler is being used.
|
||||
*/
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/*
|
||||
* ISR entry and exit macros. These are only required if a task switch
|
||||
* is required from the ISR.
|
||||
*/
|
||||
#define portENTER_SWITCHING_ISR() \
|
||||
{ \
|
||||
/* Save R0..R7 */ \
|
||||
__asm__ __volatile__ ("stm --sp, r0-r7"); \
|
||||
\
|
||||
/* With the cooperative scheduler, as there is no context switch by interrupt, */ \
|
||||
/* there is also no context save. */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1
|
||||
*/
|
||||
#define portEXIT_SWITCHING_ISR() \
|
||||
{ \
|
||||
__asm__ __volatile__ ( \
|
||||
/* Restore R0..R7 */ \
|
||||
"ldm sp++, r0-r7 \n\t"\
|
||||
\
|
||||
/* With the cooperative scheduler, as there is no context switch by interrupt, */ \
|
||||
/* there is also no context restore. */ \
|
||||
"rete" \
|
||||
); \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* ISR entry and exit macros. These are only required if a task switch
|
||||
* is required from the ISR.
|
||||
*/
|
||||
#define portENTER_SWITCHING_ISR() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile void *volatile pxCurrentTCB; \
|
||||
\
|
||||
/* When we come here */ \
|
||||
/* Registers R8..R12, LR, PC and SR had already been pushed to system stack */ \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
/* Save R0..R7 */ \
|
||||
"stm --sp, r0-r7 \n\t"\
|
||||
\
|
||||
/* Save ulCriticalNesting variable - R0 is overwritten */ \
|
||||
"mov r8, LWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"st.w --sp, r0 \n\t"\
|
||||
\
|
||||
/* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
|
||||
/* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
|
||||
/* level and allow other lower interrupt level to occur). */ \
|
||||
/* In this case we don't want to do a task switch because we don't know what the stack */ \
|
||||
/* currently looks like (we don't know what the interrupted interrupt handler was doing). */ \
|
||||
/* Saving SP in pxCurrentTCB and then later restoring it (thinking restoring the task) */ \
|
||||
/* will just be restoring the interrupt handler, no way!!! */ \
|
||||
/* So, since we won't do a vTaskSwitchContext(), it's of no use to save SP. */ \
|
||||
"ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\
|
||||
"bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\
|
||||
"cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\
|
||||
"brhi LABEL_ISR_SKIP_SAVE_CONTEXT_"ASTRINGZ(__LINE__)" \n\t"\
|
||||
\
|
||||
/* Store SP in the first member of the structure pointed to by pxCurrentTCB */ \
|
||||
"mov r8, LWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"st.w r0[0], sp \n"\
|
||||
\
|
||||
"LABEL_ISR_SKIP_SAVE_CONTEXT_"ASTRINGZ(__LINE__)":" \
|
||||
); \
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Input parameter: in R12, boolean. Perform a vTaskSwitchContext() if 1
|
||||
*/
|
||||
#define portEXIT_SWITCHING_ISR() \
|
||||
{ \
|
||||
extern volatile uint32_t ulCriticalNesting; \
|
||||
extern volatile void *volatile pxCurrentTCB; \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
/* Check if INT0 or higher were being handled (case where the OS tick interrupted another */ \
|
||||
/* interrupt handler (which was of a higher priority level but decided to lower its priority */ \
|
||||
/* level and allow other lower interrupt level to occur). */ \
|
||||
/* In this case it's of no use to switch context and restore a new SP because we purposedly */ \
|
||||
/* did not previously save SP in its TCB. */ \
|
||||
"ld.w r0, sp[9*4] \n\t" /* Read SR in stack */\
|
||||
"bfextu r0, r0, 22, 3 \n\t" /* Extract the mode bits to R0. */\
|
||||
"cp.w r0, 1 \n\t" /* Compare the mode bits with supervisor mode(b'001) */\
|
||||
"brhi LABEL_ISR_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)" \n\t"\
|
||||
\
|
||||
/* If a switch is required then we just need to call */ \
|
||||
/* vTaskSwitchContext() as the context has already been */ \
|
||||
/* saved. */ \
|
||||
"cp.w r12, 1 \n\t" /* Check if Switch context is required. */\
|
||||
"brne LABEL_ISR_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)":C" \
|
||||
); \
|
||||
\
|
||||
/* A critical section has to be used here because vTaskSwitchContext handles FreeRTOS linked lists. */\
|
||||
portENTER_CRITICAL(); \
|
||||
vTaskSwitchContext(); \
|
||||
portEXIT_CRITICAL(); \
|
||||
\
|
||||
__asm__ __volatile__ ( \
|
||||
"LABEL_ISR_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)": \n\t"\
|
||||
/* Restore the context of which ever task is now the highest */ \
|
||||
/* priority that is ready to run. */ \
|
||||
\
|
||||
/* Restore all registers */ \
|
||||
\
|
||||
/* Set SP to point to new stack */ \
|
||||
"mov r8, LWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(pxCurrentTCB)") \n\t"\
|
||||
"ld.w r0, r8[0] \n\t"\
|
||||
"ld.w sp, r0[0] \n"\
|
||||
\
|
||||
"LABEL_ISR_SKIP_RESTORE_CONTEXT_"ASTRINGZ(__LINE__)": \n\t"\
|
||||
\
|
||||
/* Restore ulCriticalNesting variable */ \
|
||||
"ld.w r0, sp++ \n\t"\
|
||||
"mov r8, LWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"orh r8, HWRD("ASTRINGZ(ulCriticalNesting)") \n\t"\
|
||||
"st.w r8[0], r0 \n\t"\
|
||||
\
|
||||
/* Restore R0..R7 */ \
|
||||
"ldm sp++, r0-r7 \n\t"\
|
||||
\
|
||||
/* Now, the stack should be R8..R12, LR, PC and SR */ \
|
||||
"rete" \
|
||||
); \
|
||||
\
|
||||
/* Force import of global symbols from assembly */ \
|
||||
ulCriticalNesting; \
|
||||
pxCurrentTCB; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define portYIELD() {__asm__ __volatile__ ("scall");}
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
93
portable/IAR/AVR32_UC3/read.c
Normal file
93
portable/IAR/AVR32_UC3/read.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*This file is prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file *********************************************************************
|
||||
*
|
||||
* \brief System-specific implementation of the \ref __read function used by
|
||||
the standard library.
|
||||
*
|
||||
* - Compiler: IAR EWAVR32
|
||||
* - Supported devices: All AVR32 devices with a USART module can be used.
|
||||
* - AppNote:
|
||||
*
|
||||
* \author Atmel Corporation: http://www.atmel.com \n
|
||||
* Support and FAQ: http://support.atmel.no/
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of ATMEL may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
|
||||
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <yfuns.h>
|
||||
#include <avr32/io.h>
|
||||
#include "usart.h"
|
||||
|
||||
|
||||
_STD_BEGIN
|
||||
|
||||
|
||||
#pragma module_name = "?__read"
|
||||
|
||||
|
||||
extern volatile avr32_usart_t *volatile stdio_usart_base;
|
||||
|
||||
|
||||
/*! \brief Reads a number of bytes, at most \a size, into the memory area
|
||||
* pointed to by \a buffer.
|
||||
*
|
||||
* \param handle File handle to read from.
|
||||
* \param buffer Pointer to buffer to write read bytes to.
|
||||
* \param size Number of bytes to read.
|
||||
*
|
||||
* \return The number of bytes read, \c 0 at the end of the file, or
|
||||
* \c _LLIO_ERROR on failure.
|
||||
*/
|
||||
size_t __read(int handle, uint8_t *buffer, size_t size)
|
||||
{
|
||||
int nChars = 0;
|
||||
|
||||
// This implementation only reads from stdin.
|
||||
// For all other file handles, it returns failure.
|
||||
if (handle != _LLIO_STDIN)
|
||||
{
|
||||
return _LLIO_ERROR;
|
||||
}
|
||||
|
||||
for (; size > 0; --size)
|
||||
{
|
||||
int c = usart_getchar(stdio_usart_base);
|
||||
if (c < 0)
|
||||
break;
|
||||
|
||||
*buffer++ = c;
|
||||
++nChars;
|
||||
}
|
||||
|
||||
return nChars;
|
||||
}
|
||||
|
||||
|
||||
_STD_END
|
||||
103
portable/IAR/AVR32_UC3/write.c
Normal file
103
portable/IAR/AVR32_UC3/write.c
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
/*This file is prepared for Doxygen automatic documentation generation.*/
|
||||
/*! \file *********************************************************************
|
||||
*
|
||||
* \brief System-specific implementation of the \ref __write function used by
|
||||
the standard library.
|
||||
*
|
||||
* - Compiler: IAR EWAVR32
|
||||
* - Supported devices: All AVR32 devices with a USART module can be used.
|
||||
* - AppNote:
|
||||
*
|
||||
* \author Atmel Corporation: http://www.atmel.com \n
|
||||
* Support and FAQ: http://support.atmel.no/
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of ATMEL may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
|
||||
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#include <yfuns.h>
|
||||
#include <avr32/io.h>
|
||||
#include "usart.h"
|
||||
|
||||
|
||||
_STD_BEGIN
|
||||
|
||||
|
||||
#pragma module_name = "?__write"
|
||||
|
||||
|
||||
//! Pointer to the base of the USART module instance to use for stdio.
|
||||
__no_init volatile avr32_usart_t *volatile stdio_usart_base;
|
||||
|
||||
|
||||
/*! \brief Writes a number of bytes, at most \a size, from the memory area
|
||||
* pointed to by \a buffer.
|
||||
*
|
||||
* If \a buffer is zero then \ref __write performs flushing of internal buffers,
|
||||
* if any. In this case, \a handle can be \c -1 to indicate that all handles
|
||||
* should be flushed.
|
||||
*
|
||||
* \param handle File handle to write to.
|
||||
* \param buffer Pointer to buffer to read bytes to write from.
|
||||
* \param size Number of bytes to write.
|
||||
*
|
||||
* \return The number of bytes written, or \c _LLIO_ERROR on failure.
|
||||
*/
|
||||
size_t __write(int handle, const uint8_t *buffer, size_t size)
|
||||
{
|
||||
size_t nChars = 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)
|
||||
{
|
||||
return _LLIO_ERROR;
|
||||
}
|
||||
|
||||
++nChars;
|
||||
}
|
||||
|
||||
return nChars;
|
||||
}
|
||||
|
||||
|
||||
_STD_END
|
||||
1914
portable/IAR/AtmelSAM7S64/AT91SAM7S64.h
Normal file
1914
portable/IAR/AtmelSAM7S64/AT91SAM7S64.h
Normal file
File diff suppressed because it is too large
Load diff
1812
portable/IAR/AtmelSAM7S64/AT91SAM7S64_inc.h
Normal file
1812
portable/IAR/AtmelSAM7S64/AT91SAM7S64_inc.h
Normal file
File diff suppressed because it is too large
Load diff
2715
portable/IAR/AtmelSAM7S64/AT91SAM7X128.h
Normal file
2715
portable/IAR/AtmelSAM7S64/AT91SAM7X128.h
Normal file
File diff suppressed because it is too large
Load diff
2446
portable/IAR/AtmelSAM7S64/AT91SAM7X128_inc.h
Normal file
2446
portable/IAR/AtmelSAM7S64/AT91SAM7X128_inc.h
Normal file
File diff suppressed because it is too large
Load diff
2715
portable/IAR/AtmelSAM7S64/AT91SAM7X256.h
Normal file
2715
portable/IAR/AtmelSAM7S64/AT91SAM7X256.h
Normal file
File diff suppressed because it is too large
Load diff
2446
portable/IAR/AtmelSAM7S64/AT91SAM7X256_inc.h
Normal file
2446
portable/IAR/AtmelSAM7S64/AT91SAM7X256_inc.h
Normal file
File diff suppressed because it is too large
Load diff
105
portable/IAR/AtmelSAM7S64/ISR_Support.h
Normal file
105
portable/IAR/AtmelSAM7S64/ISR_Support.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN ulCriticalNesting
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Context save and restore macro definitions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
portSAVE_CONTEXT MACRO
|
||||
|
||||
; Push R0 as we are going to use the register.
|
||||
STMDB SP!, {R0}
|
||||
|
||||
; Set R0 to point to the task stack pointer.
|
||||
STMDB SP, {SP}^
|
||||
NOP
|
||||
SUB SP, SP, #4
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push the return address onto the stack.
|
||||
STMDB R0!, {LR}
|
||||
|
||||
; Now we have saved LR we can use it instead of R0.
|
||||
MOV LR, R0
|
||||
|
||||
; Pop R0 so we can save it onto the system mode stack.
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push all the system mode registers onto the task stack.
|
||||
STMDB LR, {R0-LR}^
|
||||
NOP
|
||||
SUB LR, LR, #60
|
||||
|
||||
; Push the SPSR onto the task stack.
|
||||
MRS R0, SPSR
|
||||
STMDB LR!, {R0}
|
||||
|
||||
LDR R0, =ulCriticalNesting
|
||||
LDR R0, [R0]
|
||||
STMDB LR!, {R0}
|
||||
|
||||
; Store the new top of stack for the task.
|
||||
LDR R1, =pxCurrentTCB
|
||||
LDR R0, [R1]
|
||||
STR LR, [R0]
|
||||
|
||||
ENDM
|
||||
|
||||
|
||||
portRESTORE_CONTEXT MACRO
|
||||
|
||||
; Set the LR to the task stack.
|
||||
LDR R1, =pxCurrentTCB
|
||||
LDR R0, [R1]
|
||||
LDR LR, [R0]
|
||||
|
||||
; The critical nesting depth is the first item on the stack.
|
||||
; Load it into the ulCriticalNesting variable.
|
||||
LDR R0, =ulCriticalNesting
|
||||
LDMFD LR!, {R1}
|
||||
STR R1, [R0]
|
||||
|
||||
; Get the SPSR from the stack.
|
||||
LDMFD LR!, {R0}
|
||||
MSR SPSR_cxsf, R0
|
||||
|
||||
; Restore all system mode registers for the task.
|
||||
LDMFD LR, {R0-R14}^
|
||||
NOP
|
||||
|
||||
; Restore the return address.
|
||||
LDR LR, [LR, #+60]
|
||||
|
||||
; And return - correcting the offset in the LR to obtain the
|
||||
; correct address.
|
||||
SUBS PC, LR, #4
|
||||
|
||||
ENDM
|
||||
|
||||
3265
portable/IAR/AtmelSAM7S64/lib_AT91SAM7S64.h
Normal file
3265
portable/IAR/AtmelSAM7S64/lib_AT91SAM7S64.h
Normal file
File diff suppressed because it is too large
Load diff
4558
portable/IAR/AtmelSAM7S64/lib_AT91SAM7X128.h
Normal file
4558
portable/IAR/AtmelSAM7S64/lib_AT91SAM7X128.h
Normal file
File diff suppressed because it is too large
Load diff
4558
portable/IAR/AtmelSAM7S64/lib_AT91SAM7X256.h
Normal file
4558
portable/IAR/AtmelSAM7S64/lib_AT91SAM7X256.h
Normal file
File diff suppressed because it is too large
Load diff
259
portable/IAR/AtmelSAM7S64/port.c
Normal file
259
portable/IAR/AtmelSAM7S64/port.c
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Atmel ARM7 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the initial stack. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
|
||||
/* Constants required to setup the PIT. */
|
||||
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
|
||||
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
|
||||
#define portINT_LEVEL_SENSITIVE 0
|
||||
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
|
||||
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the PIT to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* 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
|
||||
during the kernel initialisation process. */
|
||||
uint32_t ulCriticalNesting = ( uint32_t ) 9999;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* 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
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
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--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The status register is set for system mode, with interrupts enabled. */
|
||||
*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--;
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
static __arm __irq void vPortNonPreemptiveTick( void );
|
||||
static __arm __irq void vPortNonPreemptiveTick( void )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Currently the IAR port requires the preemptive tick function to be
|
||||
defined in an asm file. */
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
AT91PS_PITC pxPIT = AT91C_BASE_PITC;
|
||||
|
||||
/* Setup the AIC for PIT interrupts. The interrupt routine chosen depends
|
||||
on whether the preemptive or cooperative scheduler is being used. */
|
||||
#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. */
|
||||
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 )
|
||||
{
|
||||
/* Disable interrupts first! */
|
||||
__disable_interrupt();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
__enable_interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
88
portable/IAR/AtmelSAM7S64/portasm.s79
Normal file
88
portable/IAR/AtmelSAM7S64/portasm.s79
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
RSEG ICODE:CODE
|
||||
CODE32
|
||||
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN xTaskIncrementTick
|
||||
|
||||
PUBLIC vPortYieldProcessor
|
||||
PUBLIC vPortPreemptiveTick
|
||||
PUBLIC vPortStartFirstTask
|
||||
|
||||
#include "AT91SAM7S64_inc.h"
|
||||
#include "ISR_Support.h"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Starting the first task is just a matter of restoring the context that
|
||||
; was created by pxPortInitialiseStack().
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Manual context switch function. This is the SWI hander.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortYieldProcessor:
|
||||
ADD LR, LR, #4 ; Add 4 to the LR to make the LR appear exactly
|
||||
; as if the context was saved during and IRQ
|
||||
; handler.
|
||||
|
||||
portSAVE_CONTEXT ; Save the context of the current task...
|
||||
LDR R0, =vTaskSwitchContext ; before selecting the next task to execute.
|
||||
mov lr, pc
|
||||
BX R0
|
||||
portRESTORE_CONTEXT ; Restore the context of the selected task.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Preemptive context switch function. This will only ever get installed if
|
||||
; portUSE_PREEMPTION is set to 1 in portmacro.h.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortPreemptiveTick:
|
||||
portSAVE_CONTEXT ; Save the context of the current task.
|
||||
|
||||
LDR R0, =xTaskIncrementTick ; Increment the tick count - this may wake a task.
|
||||
mov lr, pc
|
||||
BX R0
|
||||
|
||||
CMP R0, #0
|
||||
BEQ SkipContextSwitch
|
||||
LDR R0, =vTaskSwitchContext ; Select the next task to execute.
|
||||
mov lr, pc
|
||||
BX R0
|
||||
SkipContextSwitch
|
||||
LDR R14, =AT91C_BASE_PITC ; Clear the PIT interrupt
|
||||
LDR R0, [R14, #PITC_PIVR ]
|
||||
|
||||
LDR R14, =AT91C_BASE_AIC ; Mark the End of Interrupt on the AIC
|
||||
STR R14, [R14, #AIC_EOICR]
|
||||
|
||||
portRESTORE_CONTEXT ; Restore the context of the selected task.
|
||||
|
||||
|
||||
END
|
||||
|
||||
111
portable/IAR/AtmelSAM7S64/portmacro.h
Normal file
111
portable/IAR/AtmelSAM7S64/portmacro.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portYIELD() asm ( "SWI 0" )
|
||||
#define portNOP() asm ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
__arm __interwork void vPortDisableInterruptsFromThumb( void );
|
||||
__arm __interwork void vPortEnableInterruptsFromThumb( void );
|
||||
__arm __interwork void vPortEnterCritical( void );
|
||||
__arm __interwork void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __disable_interrupt()
|
||||
#define portENABLE_INTERRUPTS() __enable_interrupt()
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern void vTaskSwitchContext( void ); \
|
||||
\
|
||||
if( xSwitchRequired ) \
|
||||
{ \
|
||||
vTaskSwitchContext(); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
||||
78
portable/IAR/AtmelSAM9XE/ISR_Support.h
Normal file
78
portable/IAR/AtmelSAM9XE/ISR_Support.h
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
EXTERN pxCurrentTCB
|
||||
EXTERN ulCriticalNesting
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Context save and restore macro definitions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
portSAVE_CONTEXT MACRO
|
||||
|
||||
; Push R0 as we are going to use the register.
|
||||
STMDB SP!, {R0}
|
||||
|
||||
; Set R0 to point to the task stack pointer.
|
||||
STMDB SP, {SP}^
|
||||
NOP
|
||||
SUB SP, SP, #4
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push the return address onto the stack.
|
||||
STMDB R0!, {LR}
|
||||
|
||||
; Now we have saved LR we can use it instead of R0.
|
||||
MOV LR, R0
|
||||
|
||||
; Pop R0 so we can save it onto the system mode stack.
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push all the system mode registers onto the task stack.
|
||||
STMDB LR, {R0-LR}^
|
||||
NOP
|
||||
SUB LR, LR, #60
|
||||
|
||||
; Push the SPSR onto the task stack.
|
||||
MRS R0, SPSR
|
||||
STMDB LR!, {R0}
|
||||
|
||||
LDR R0, =ulCriticalNesting
|
||||
LDR R0, [R0]
|
||||
STMDB LR!, {R0}
|
||||
|
||||
; Store the new top of stack for the task.
|
||||
LDR R1, =pxCurrentTCB
|
||||
LDR R0, [R1]
|
||||
STR LR, [R0]
|
||||
|
||||
ENDM
|
||||
|
||||
|
||||
portRESTORE_CONTEXT MACRO
|
||||
|
||||
; Set the LR to the task stack.
|
||||
LDR R1, =pxCurrentTCB
|
||||
LDR R0, [R1]
|
||||
LDR LR, [R0]
|
||||
|
||||
; The critical nesting depth is the first item on the stack.
|
||||
; Load it into the ulCriticalNesting variable.
|
||||
LDR R0, =ulCriticalNesting
|
||||
LDMFD LR!, {R1}
|
||||
STR R1, [R0]
|
||||
|
||||
; Get the SPSR from the stack.
|
||||
LDMFD LR!, {R0}
|
||||
MSR SPSR_cxsf, R0
|
||||
|
||||
; Restore all system mode registers for the task.
|
||||
LDMFD LR, {R0-R14}^
|
||||
NOP
|
||||
|
||||
; Restore the return address.
|
||||
LDR LR, [LR, #+60]
|
||||
|
||||
; And return - correcting the offset in the LR to obtain the
|
||||
; correct address.
|
||||
SUBS PC, LR, #4
|
||||
|
||||
ENDM
|
||||
|
||||
256
portable/IAR/AtmelSAM9XE/port.c
Normal file
256
portable/IAR/AtmelSAM9XE/port.c
Normal file
|
|
@ -0,0 +1,256 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Atmel ARM7 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Hardware includes. */
|
||||
#include <board.h>
|
||||
#include <pio/pio.h>
|
||||
#include <pio/pio_it.h>
|
||||
#include <pit/pit.h>
|
||||
#include <aic/aic.h>
|
||||
#include <tc/tc.h>
|
||||
#include <utility/led.h>
|
||||
#include <utility/trace.h>
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Constants required to setup the initial stack. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
|
||||
/* Constants required to setup the PIT. */
|
||||
#define port1MHz_IN_Hz ( 1000000ul )
|
||||
#define port1SECOND_IN_uS ( 1000000.0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
|
||||
#define portINT_LEVEL_SENSITIVE 0
|
||||
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
|
||||
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the PIT to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* The PIT interrupt handler - the RTOS tick. */
|
||||
static void vPortTickISR( void );
|
||||
|
||||
/* 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
|
||||
during the kernel initialisation process. */
|
||||
uint32_t ulCriticalNesting = ( uint32_t ) 9999;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* To ensure asserts in tasks.c don't fail, although in this case the assert
|
||||
is not really required. */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* 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
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
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--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The status register is set for system mode, with interrupts enabled. */
|
||||
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
|
||||
|
||||
#ifdef THUMB_INTERWORK
|
||||
{
|
||||
/* We want the task to start in thumb mode. */
|
||||
*pxTopOfStack |= portTHUMB_MODE_BIT;
|
||||
}
|
||||
#endif
|
||||
|
||||
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 )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static __arm void vPortTickISR( void )
|
||||
{
|
||||
volatile 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. */
|
||||
if( xTaskIncrementTick() != pdFALSE )
|
||||
{
|
||||
vTaskSwitchContext();
|
||||
}
|
||||
|
||||
/* Clear the PIT interrupt. */
|
||||
ulDummy = AT91C_BASE_PITC->PITC_PIVR;
|
||||
|
||||
/* To remove compiler warning. */
|
||||
( void ) ulDummy;
|
||||
|
||||
/* The AIC is cleared in the asm wrapper, outside of this function. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
const uint32_t ulPeriodIn_uS = ( 1.0 / ( double ) configTICK_RATE_HZ ) * port1SECOND_IN_uS;
|
||||
|
||||
/* Setup the PIT for the required frequency. */
|
||||
PIT_Init( ulPeriodIn_uS, BOARD_MCK / port1MHz_IN_Hz );
|
||||
|
||||
/* Setup the PIT interrupt. */
|
||||
AIC_DisableIT( AT91C_ID_SYS );
|
||||
AIC_ConfigureIT( AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, vPortTickISR );
|
||||
AIC_EnableIT( AT91C_ID_SYS );
|
||||
PIT_EnableIT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts first! */
|
||||
__disable_irq();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
__enable_irq();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
34
portable/IAR/AtmelSAM9XE/portasm.s79
Normal file
34
portable/IAR/AtmelSAM9XE/portasm.s79
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
RSEG ICODE:CODE
|
||||
CODE32
|
||||
|
||||
EXTERN vTaskSwitchContext
|
||||
|
||||
PUBLIC vPortYieldProcessor
|
||||
PUBLIC vPortStartFirstTask
|
||||
|
||||
#include "ISR_Support.h"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Starting the first task is just a matter of restoring the context that
|
||||
; was created by pxPortInitialiseStack().
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Manual context switch function. This is the SWI hander.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortYieldProcessor:
|
||||
ADD LR, LR, #4 ; Add 4 to the LR to make the LR appear exactly
|
||||
; as if the context was saved during and IRQ
|
||||
; handler.
|
||||
|
||||
portSAVE_CONTEXT ; Save the context of the current task...
|
||||
LDR R0, =vTaskSwitchContext ; before selecting the next task to execute.
|
||||
mov lr, pc
|
||||
BX R0
|
||||
portRESTORE_CONTEXT ; Restore the context of the selected task.
|
||||
|
||||
|
||||
END
|
||||
|
||||
114
portable/IAR/AtmelSAM9XE/portmacro.h
Normal file
114
portable/IAR/AtmelSAM9XE/portmacro.h
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include <intrinsics.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portYIELD() asm ( "SWI 0" )
|
||||
#define portNOP() asm ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
__arm __interwork void vPortDisableInterruptsFromThumb( void );
|
||||
__arm __interwork void vPortEnableInterruptsFromThumb( void );
|
||||
__arm __interwork void vPortEnterCritical( void );
|
||||
__arm __interwork void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __disable_irq()
|
||||
#define portENABLE_INTERRUPTS() __enable_irq()
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern void vTaskSwitchContext( void ); \
|
||||
\
|
||||
if( xSwitchRequired ) \
|
||||
{ \
|
||||
vTaskSwitchContext(); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
||||
105
portable/IAR/LPC2000/ISR_Support.h
Normal file
105
portable/IAR/LPC2000/ISR_Support.h
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
EXTERN pxCurrentTCB
|
||||
EXTERN ulCriticalNesting
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Context save and restore macro definitions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
portSAVE_CONTEXT MACRO
|
||||
|
||||
; Push R0 as we are going to use the register.
|
||||
STMDB SP!, {R0}
|
||||
|
||||
; Set R0 to point to the task stack pointer.
|
||||
STMDB SP, {SP}^
|
||||
NOP
|
||||
SUB SP, SP, #4
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push the return address onto the stack.
|
||||
STMDB R0!, {LR}
|
||||
|
||||
; Now we have saved LR we can use it instead of R0.
|
||||
MOV LR, R0
|
||||
|
||||
; Pop R0 so we can save it onto the system mode stack.
|
||||
LDMIA SP!, {R0}
|
||||
|
||||
; Push all the system mode registers onto the task stack.
|
||||
STMDB LR, {R0-LR}^
|
||||
NOP
|
||||
SUB LR, LR, #60
|
||||
|
||||
; Push the SPSR onto the task stack.
|
||||
MRS R0, SPSR
|
||||
STMDB LR!, {R0}
|
||||
|
||||
LDR R0, =ulCriticalNesting
|
||||
LDR R0, [R0]
|
||||
STMDB LR!, {R0}
|
||||
|
||||
; Store the new top of stack for the task.
|
||||
LDR R1, =pxCurrentTCB
|
||||
LDR R0, [R1]
|
||||
STR LR, [R0]
|
||||
|
||||
ENDM
|
||||
|
||||
|
||||
portRESTORE_CONTEXT MACRO
|
||||
|
||||
; Set the LR to the task stack.
|
||||
LDR R1, =pxCurrentTCB
|
||||
LDR R0, [R1]
|
||||
LDR LR, [R0]
|
||||
|
||||
; The critical nesting depth is the first item on the stack.
|
||||
; Load it into the ulCriticalNesting variable.
|
||||
LDR R0, =ulCriticalNesting
|
||||
LDMFD LR!, {R1}
|
||||
STR R1, [R0]
|
||||
|
||||
; Get the SPSR from the stack.
|
||||
LDMFD LR!, {R0}
|
||||
MSR SPSR_cxsf, R0
|
||||
|
||||
; Restore all system mode registers for the task.
|
||||
LDMFD LR, {R0-R14}^
|
||||
NOP
|
||||
|
||||
; Restore the return address.
|
||||
LDR LR, [LR, #+60]
|
||||
|
||||
; And return - correcting the offset in the LR to obtain the
|
||||
; correct address.
|
||||
SUBS PC, LR, #4
|
||||
|
||||
ENDM
|
||||
|
||||
317
portable/IAR/LPC2000/port.c
Normal file
317
portable/IAR/LPC2000/port.c
Normal file
|
|
@ -0,0 +1,317 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the Philips ARM7 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Changes from V3.2.2
|
||||
|
||||
+ 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
|
||||
value was actually used.
|
||||
*/
|
||||
|
||||
/* Standard includes. */
|
||||
#include <stdlib.h>
|
||||
#include <intrinsics.h>
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/* Constants required to setup the tick ISR. */
|
||||
#define portENABLE_TIMER ( ( uint8_t ) 0x01 )
|
||||
#define portPRESCALE_VALUE 0x00
|
||||
#define portINTERRUPT_ON_MATCH ( ( uint32_t ) 0x01 )
|
||||
#define portRESET_COUNT_ON_MATCH ( ( uint32_t ) 0x02 )
|
||||
|
||||
/* Constants required to setup the initial stack. */
|
||||
#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, interrupts enabled. */
|
||||
#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 )
|
||||
#define portINSTRUCTION_SIZE ( ( StackType_t ) 4 )
|
||||
|
||||
/* Constants required to setup the PIT. */
|
||||
#define portPIT_CLOCK_DIVISOR ( ( uint32_t ) 16 )
|
||||
#define portPIT_COUNTER_VALUE ( ( ( configCPU_CLOCK_HZ / portPIT_CLOCK_DIVISOR ) / 1000UL ) * portTICK_PERIOD_MS )
|
||||
|
||||
/* Constants required to handle interrupts. */
|
||||
#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 )
|
||||
#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 )
|
||||
|
||||
/* Constants required to handle critical sections. */
|
||||
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
|
||||
|
||||
|
||||
#define portINT_LEVEL_SENSITIVE 0
|
||||
#define portPIT_ENABLE ( ( uint16_t ) 0x1 << 24 )
|
||||
#define portPIT_INT_ENABLE ( ( uint16_t ) 0x1 << 25 )
|
||||
|
||||
/* Constants required to setup the VIC for the tick ISR. */
|
||||
#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 )
|
||||
#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 )
|
||||
#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 )
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Setup the PIT to generate the tick interrupts. */
|
||||
static void prvSetupTimerInterrupt( void );
|
||||
|
||||
/* 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
|
||||
during the kernel initialisation process. */
|
||||
uint32_t ulCriticalNesting = ( uint32_t ) 9999;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See header file for description.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
StackType_t *pxOriginalTOS;
|
||||
|
||||
pxOriginalTOS = pxTopOfStack;
|
||||
|
||||
/* Setup the initial stack of the task. The stack is set exactly as
|
||||
expected by the portRESTORE_CONTEXT() macro. */
|
||||
|
||||
/* 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
|
||||
as it would within an IRQ ISR. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode + portINSTRUCTION_SIZE;
|
||||
pxTopOfStack--;
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaaaaaa; /* R14 */
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pxOriginalTOS; /* Stack used when task starts goes in R13. */
|
||||
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--;
|
||||
|
||||
/* When the task starts is will expect to find the function parameter in
|
||||
R0. */
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
|
||||
pxTopOfStack--;
|
||||
|
||||
/* The status register is set for system mode, with interrupts enabled. */
|
||||
*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--;
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
extern void vPortStartFirstTask( void );
|
||||
|
||||
/* Start the timer that generates the tick ISR. Interrupts are disabled
|
||||
here already. */
|
||||
prvSetupTimerInterrupt();
|
||||
|
||||
/* Start the first task. */
|
||||
vPortStartFirstTask();
|
||||
|
||||
/* Should not get here! */
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEndScheduler( void )
|
||||
{
|
||||
/* It is unlikely that the ARM port will require this function as there
|
||||
is nothing to return to. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if configUSE_PREEMPTION == 0
|
||||
|
||||
/* The cooperative scheduler requires a normal IRQ service routine to
|
||||
simply increment the system tick. */
|
||||
static __arm __irq void vPortNonPreemptiveTick( void );
|
||||
static __arm __irq void vPortNonPreemptiveTick( void )
|
||||
{
|
||||
/* 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();
|
||||
|
||||
/* Ready for the next interrupt. */
|
||||
T0IR = portTIMER_MATCH_ISR_BIT;
|
||||
VICVectAddr = portCLEAR_VIC_INTERRUPT;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static void prvSetupTimerInterrupt( void )
|
||||
{
|
||||
uint32_t ulCompareMatch;
|
||||
|
||||
/* A 1ms tick does not require the use of the timer prescale. This is
|
||||
defaulted to zero but can be used if necessary. */
|
||||
T0PR = portPRESCALE_VALUE;
|
||||
|
||||
/* Calculate the match value required for our wanted tick rate. */
|
||||
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Protect against divide by zero. Using an if() statement still results
|
||||
in a warning - hence the #if. */
|
||||
#if portPRESCALE_VALUE != 0
|
||||
{
|
||||
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
|
||||
}
|
||||
#endif
|
||||
|
||||
T0MR0 = ulCompareMatch;
|
||||
|
||||
/* Generate tick with timer 0 compare match. */
|
||||
T0MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH;
|
||||
|
||||
/* Setup the VIC for the timer. */
|
||||
VICIntSelect &= ~( 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 );
|
||||
|
||||
VICVectAddr0 = ( uint32_t ) vPortPreemptiveTickEntry;
|
||||
}
|
||||
#else
|
||||
{
|
||||
extern void ( vNonPreemptiveTick )( void );
|
||||
|
||||
VICVectAddr0 = ( int32_t ) vPortNonPreemptiveTick;
|
||||
}
|
||||
#endif
|
||||
|
||||
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. */
|
||||
T0TCR = portENABLE_TIMER;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortEnterCritical( void )
|
||||
{
|
||||
/* Disable interrupts first! */
|
||||
__disable_interrupt();
|
||||
|
||||
/* Now interrupts are disabled ulCriticalNesting can be accessed
|
||||
directly. Increment ulCriticalNesting to keep a count of how many times
|
||||
portENTER_CRITICAL() has been called. */
|
||||
ulCriticalNesting++;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vPortExitCritical( void )
|
||||
{
|
||||
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
|
||||
{
|
||||
/* Decrement the nesting count as we are leaving a critical section. */
|
||||
ulCriticalNesting--;
|
||||
|
||||
/* If the nesting level has reached zero then interrupts should be
|
||||
re-enabled. */
|
||||
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
|
||||
{
|
||||
__enable_interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
76
portable/IAR/LPC2000/portasm.s79
Normal file
76
portable/IAR/LPC2000/portasm.s79
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
;/*
|
||||
; * FreeRTOS Kernel V10.3.0
|
||||
; * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
; *
|
||||
; * Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
; * this software and associated documentation files (the "Software"), to deal in
|
||||
; * the Software without restriction, including without limitation the rights to
|
||||
; * 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,
|
||||
; * subject to the following conditions:
|
||||
; *
|
||||
; * The above copyright notice and this permission notice shall be included in all
|
||||
; * copies or substantial portions of the Software.
|
||||
; *
|
||||
; * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
; * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
; * 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
|
||||
; * 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.
|
||||
; *
|
||||
; * http://www.FreeRTOS.org
|
||||
; * http://aws.amazon.com/freertos
|
||||
; *
|
||||
; * 1 tab == 4 spaces!
|
||||
; */
|
||||
|
||||
RSEG ICODE:CODE
|
||||
CODE32
|
||||
|
||||
EXTERN vTaskSwitchContext
|
||||
EXTERN vPortPreemptiveTick
|
||||
|
||||
PUBLIC vPortPreemptiveTickEntry
|
||||
PUBLIC vPortYieldProcessor
|
||||
PUBLIC vPortStartFirstTask
|
||||
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "ISR_Support.h"
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Starting the first task is just a matter of restoring the context that
|
||||
; was created by pxPortInitialiseStack().
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortStartFirstTask:
|
||||
portRESTORE_CONTEXT
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Manual context switch function. This is the SWI hander.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortYieldProcessor:
|
||||
ADD LR, LR, #4 ; Add 4 to the LR to make the LR appear exactly
|
||||
; as if the context was saved during and IRQ
|
||||
; handler.
|
||||
|
||||
portSAVE_CONTEXT ; Save the context of the current task...
|
||||
LDR R0, =vTaskSwitchContext ; before selecting the next task to execute.
|
||||
mov lr, pc
|
||||
BX R0
|
||||
portRESTORE_CONTEXT ; Restore the context of the selected task.
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
; Preemptive context switch function. This will only ever get installed if
|
||||
; portUSE_PREEMPTION is set to 1 in portmacro.h.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
vPortPreemptiveTickEntry:
|
||||
#if configUSE_PREEMPTION == 1
|
||||
portSAVE_CONTEXT ; Save the context of the current task...
|
||||
LDR R0, =vPortPreemptiveTick; before selecting the next task to execute.
|
||||
mov lr, pc
|
||||
BX R0
|
||||
portRESTORE_CONTEXT ; Restore the context of the selected task.
|
||||
#endif
|
||||
|
||||
END
|
||||
|
||||
113
portable/IAR/LPC2000/portmacro.h
Normal file
113
portable/IAR/LPC2000/portmacro.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
#include <intrinsics.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT short
|
||||
#define portSTACK_TYPE uint32_t
|
||||
#define portBASE_TYPE long
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef long BaseType_t;
|
||||
typedef unsigned long UBaseType_t;
|
||||
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portBYTE_ALIGNMENT 8
|
||||
#define portYIELD() asm ( "SWI 0" )
|
||||
#define portNOP() asm ( "NOP" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section handling. */
|
||||
__arm __interwork void vPortDisableInterruptsFromThumb( void );
|
||||
__arm __interwork void vPortEnableInterruptsFromThumb( void );
|
||||
__arm __interwork void vPortEnterCritical( void );
|
||||
__arm __interwork void vPortExitCritical( void );
|
||||
|
||||
#define portDISABLE_INTERRUPTS() __disable_interrupt()
|
||||
#define portENABLE_INTERRUPTS() __enable_interrupt()
|
||||
#define portENTER_CRITICAL() vPortEnterCritical()
|
||||
#define portEXIT_CRITICAL() vPortExitCritical()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
|
||||
{ \
|
||||
extern void vTaskSwitchContext( void ); \
|
||||
\
|
||||
if( xSwitchRequired ) \
|
||||
{ \
|
||||
vTaskSwitchContext(); \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
|
||||
173
portable/IAR/MSP430/port.c
Normal file
173
portable/IAR/MSP430/port.c
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MSP430 port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Constants required for hardware setup. The tick ISR runs off the ACLK,
|
||||
not the MCLK. */
|
||||
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
|
||||
/* We require the address of the pxCurrentTCB variable, but don't want to know
|
||||
any details of its type. */
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
|
||||
/* 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 section is exited the count is decremented - with interrupts only
|
||||
being re-enabled if the count is zero.
|
||||
|
||||
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
|
||||
sequence. */
|
||||
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Sets up the periodic ISR used for the RTOS tick. This uses timer 0, but
|
||||
* could have alternatively used the watchdog timer or timer 1.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
/*
|
||||
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.
|
||||
|
||||
*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
|
||||
executing an ISR. We want the stack to look just as if this has happened
|
||||
so place a pointer to the start of the task on the stack first - followed
|
||||
by the flags we want the task to use when it starts up. */
|
||||
*pxTopOfStack = ( StackType_t ) pxCode;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = portFLAGS_INT_ENABLED;
|
||||
pxTopOfStack--;
|
||||
|
||||
/* Next the general purpose registers. */
|
||||
*pxTopOfStack = ( StackType_t ) 0x4444;
|
||||
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--;
|
||||
|
||||
/* 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
|
||||
initially set to zero. */
|
||||
*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 )
|
||||
{
|
||||
/* It is unlikely that the MSP430 port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Hardware initialisation to generate the RTOS tick. This uses timer 0
|
||||
* but could alternatively use the watchdog timer or timer 1.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
/* Ensure the timer is stopped. */
|
||||
TACTL = 0;
|
||||
|
||||
/* Run the timer of the ACLK. */
|
||||
TACTL = TASSEL_1;
|
||||
|
||||
/* Clear everything to start with. */
|
||||
TACTL |= TACLR;
|
||||
|
||||
/* Set the compare match value according to the tick rate we want. */
|
||||
TACCR0 = portACLK_FREQUENCY_HZ / configTICK_RATE_HZ;
|
||||
|
||||
/* Enable the interrupts. */
|
||||
TACCTL0 = CCIE;
|
||||
|
||||
/* Start up clean. */
|
||||
TACTL |= TACLR;
|
||||
|
||||
/* Up mode. */
|
||||
TACTL |= MC_1;
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
84
portable/IAR/MSP430/portasm.h
Normal file
84
portable/IAR/MSP430/portasm.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTASM_H
|
||||
#define PORTASM_H
|
||||
|
||||
portSAVE_CONTEXT macro
|
||||
|
||||
IMPORT pxCurrentTCB
|
||||
IMPORT usCriticalNesting
|
||||
|
||||
/* Save the remaining registers. */
|
||||
push r4
|
||||
push r5
|
||||
push r6
|
||||
push r7
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
mov.w &usCriticalNesting, r14
|
||||
push r14
|
||||
mov.w &pxCurrentTCB, r12
|
||||
mov.w r1, 0(r12)
|
||||
endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
portRESTORE_CONTEXT macro
|
||||
mov.w &pxCurrentTCB, r12
|
||||
mov.w @r12, r1
|
||||
pop r15
|
||||
mov.w r15, &usCriticalNesting
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop r7
|
||||
pop r6
|
||||
pop r5
|
||||
pop r4
|
||||
|
||||
/* The last thing on the stack will be the status register.
|
||||
Ensure the power down bits are clear ready for the next
|
||||
time this power down register is popped from the stack. */
|
||||
bic.w #0xf0,0(SP)
|
||||
|
||||
reti
|
||||
endm
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#endif
|
||||
|
||||
106
portable/IAR/MSP430/portext.s43
Normal file
106
portable/IAR/MSP430/portext.s43
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
#include "FreeRTOSConfig.h"
|
||||
#include "portasm.h"
|
||||
|
||||
IMPORT xTaskIncrementTick
|
||||
IMPORT vTaskSwitchContext
|
||||
IMPORT vPortSetupTimerInterrupt
|
||||
|
||||
EXPORT vTickISR
|
||||
EXPORT vPortYield
|
||||
EXPORT xPortStartScheduler
|
||||
|
||||
RSEG CODE
|
||||
|
||||
/*
|
||||
* The RTOS tick ISR.
|
||||
*
|
||||
* If the cooperative scheduler is in use this simply increments the tick
|
||||
* count.
|
||||
*
|
||||
* If the preemptive scheduler is in use a context switch can also occur.
|
||||
*/
|
||||
vTickISR:
|
||||
portSAVE_CONTEXT
|
||||
|
||||
call #xTaskIncrementTick
|
||||
cmp.w #0x0, R12
|
||||
jeq SkipContextSwitch
|
||||
call #vTaskSwitchContext
|
||||
SkipContextSwitch:
|
||||
|
||||
portRESTORE_CONTEXT
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Manual context switch called by the portYIELD() macro.
|
||||
*/
|
||||
vPortYield:
|
||||
|
||||
/* Mimic an interrupt by pushing the SR. */
|
||||
push SR
|
||||
|
||||
/* Now the SR is stacked we can disable interrupts. */
|
||||
dint
|
||||
|
||||
/* Save the context of the current task. */
|
||||
portSAVE_CONTEXT
|
||||
|
||||
/* Switch to the highest priority task that is ready to run. */
|
||||
call #vTaskSwitchContext
|
||||
|
||||
/* Restore the context of the new task. */
|
||||
portRESTORE_CONTEXT
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Start off the scheduler by initialising the RTOS tick timer, then restoring
|
||||
* the context of the first task.
|
||||
*/
|
||||
xPortStartScheduler:
|
||||
|
||||
/* Setup the hardware to generate the tick. Interrupts are disabled
|
||||
when this function is called. */
|
||||
call #vPortSetupTimerInterrupt
|
||||
|
||||
/* Restore the context of the first task that is going to run. */
|
||||
portRESTORE_CONTEXT
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/* Install vTickISR as the timer A0 interrupt. */
|
||||
ASEG
|
||||
ORG 0xFFE0 + TIMERA0_VECTOR
|
||||
|
||||
_vTickISR_: DC16 vTickISR
|
||||
|
||||
|
||||
END
|
||||
|
||||
133
portable/IAR/MSP430/portmacro.h
Normal file
133
portable/IAR/MSP430/portmacro.h
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef PORTMACRO_H
|
||||
#define PORTMACRO_H
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Port specific definitions.
|
||||
*
|
||||
* The settings in this file configure FreeRTOS correctly for the
|
||||
* given hardware and compiler.
|
||||
*
|
||||
* These settings should not be altered.
|
||||
*-----------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* Type definitions. */
|
||||
#define portCHAR char
|
||||
#define portFLOAT float
|
||||
#define portDOUBLE double
|
||||
#define portLONG long
|
||||
#define portSHORT int
|
||||
#define portSTACK_TYPE uint16_t
|
||||
#define portBASE_TYPE short
|
||||
|
||||
typedef portSTACK_TYPE StackType_t;
|
||||
typedef short BaseType_t;
|
||||
typedef unsigned short UBaseType_t;
|
||||
|
||||
|
||||
#if( configUSE_16_BIT_TICKS == 1 )
|
||||
typedef uint16_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffff
|
||||
#else
|
||||
typedef uint32_t TickType_t;
|
||||
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Interrupt control macros. */
|
||||
#define portDISABLE_INTERRUPTS() _DINT(); _NOP()
|
||||
#define portENABLE_INTERRUPTS() _EINT(); _NOP()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Critical section control macros. */
|
||||
#define portNO_CRITICAL_SECTION_NESTING ( ( uint16_t ) 0 )
|
||||
|
||||
#define portENTER_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
portDISABLE_INTERRUPTS(); \
|
||||
\
|
||||
/* Now interrupts are disabled usCriticalNesting can be accessed */ \
|
||||
/* directly. Increment ulCriticalNesting to keep a count of how many */ \
|
||||
/* times portENTER_CRITICAL() has been called. */ \
|
||||
usCriticalNesting++; \
|
||||
}
|
||||
|
||||
#define portEXIT_CRITICAL() \
|
||||
{ \
|
||||
extern volatile uint16_t usCriticalNesting; \
|
||||
\
|
||||
if( usCriticalNesting > portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
/* Decrement the nesting count as we are leaving a critical section. */ \
|
||||
usCriticalNesting--; \
|
||||
\
|
||||
/* If the nesting level has reached zero then interrupts should be */ \
|
||||
/* re-enabled. */ \
|
||||
if( usCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
|
||||
{ \
|
||||
portENABLE_INTERRUPTS(); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task utilities. */
|
||||
|
||||
/*
|
||||
* Manual context switch called by portYIELD or taskYIELD.
|
||||
*/
|
||||
extern void vPortYield( void );
|
||||
#define portYIELD() vPortYield()
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Hardware specifics. */
|
||||
#define portBYTE_ALIGNMENT 2
|
||||
#define portSTACK_GROWTH ( -1 )
|
||||
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
|
||||
#define portNOP()
|
||||
#define portPOINTER_SIZE_TYPE uint16_t
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/* Task function macros as described on the FreeRTOS.org WEB site. */
|
||||
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||
|
||||
#if configINTERRUPT_EXAMPLE_METHOD == 2
|
||||
|
||||
extern void vTaskSwitchContext( void );
|
||||
#define portYIELD_FROM_ISR( x ) if( x ) vTaskSwitchContext()
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* PORTMACRO_H */
|
||||
|
||||
63
portable/IAR/MSP430X/data_model.h
Normal file
63
portable/IAR/MSP430X/data_model.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
#ifndef DATA_MODEL_H
|
||||
#define DATA_MODEL_H
|
||||
|
||||
#if __DATA_MODEL__ == __DATA_MODEL_SMALL__
|
||||
#define pushm_x pushm.w
|
||||
#define popm_x popm.w
|
||||
#define push_x push.w
|
||||
#define pop_x pop.w
|
||||
#define mov_x mov.w
|
||||
#define cmp_x cmp.w
|
||||
#endif
|
||||
|
||||
#if __DATA_MODEL__ == __DATA_MODEL_MEDIUM__
|
||||
#define pushm_x pushm.a
|
||||
#define popm_x popm.a
|
||||
#define push_x pushx.a
|
||||
#define pop_x popx.a
|
||||
#define mov_x mov.w
|
||||
#define cmp_x cmp.w
|
||||
#endif
|
||||
|
||||
#if __DATA_MODEL__ == __DATA_MODEL_LARGE__
|
||||
#define pushm_x pushm.a
|
||||
#define popm_x popm.a
|
||||
#define push_x pushx.a
|
||||
#define pop_x popx.a
|
||||
#define mov_x movx.a
|
||||
#define cmp_x cmpx.a
|
||||
#endif
|
||||
|
||||
#ifndef pushm_x
|
||||
#error The assembler options must define one of the following symbols: __DATA_MODEL_SMALL__, __DATA_MODEL_MEDIUM__, or __DATA_MODEL_LARGE__
|
||||
#endif
|
||||
|
||||
#endif /* DATA_MODEL_H */
|
||||
|
||||
182
portable/IAR/MSP430X/port.c
Normal file
182
portable/IAR/MSP430X/port.c
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* FreeRTOS Kernel V10.3.0
|
||||
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* 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,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* http://www.FreeRTOS.org
|
||||
* http://aws.amazon.com/freertos
|
||||
*
|
||||
* 1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
/* Scheduler includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
/*-----------------------------------------------------------
|
||||
* Implementation of functions defined in portable.h for the MSP430X port.
|
||||
*----------------------------------------------------------*/
|
||||
|
||||
/* Constants required for hardware setup. The tick ISR runs off the ACLK,
|
||||
not the MCLK. */
|
||||
#define portACLK_FREQUENCY_HZ ( ( TickType_t ) 32768 )
|
||||
#define portINITIAL_CRITICAL_NESTING ( ( uint16_t ) 10 )
|
||||
#define portFLAGS_INT_ENABLED ( ( StackType_t ) 0x08 )
|
||||
|
||||
/* We require the address of the pxCurrentTCB variable, but don't want to know
|
||||
any details of its type. */
|
||||
typedef void TCB_t;
|
||||
extern volatile TCB_t * volatile pxCurrentTCB;
|
||||
|
||||
/* 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 section is exited the count is decremented - with interrupts only
|
||||
being re-enabled if the count is zero.
|
||||
|
||||
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
|
||||
sequence. */
|
||||
volatile uint16_t usCriticalNesting = portINITIAL_CRITICAL_NESTING;
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
/*
|
||||
* Sets up the periodic ISR used for the RTOS tick. This uses timer 0, but
|
||||
* could have alternatively used the watchdog timer or timer 1.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void );
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initialise the stack of a task to look exactly as if a call to
|
||||
* portSAVE_CONTEXT had been called.
|
||||
*
|
||||
* See the header file portable.h.
|
||||
*/
|
||||
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
|
||||
{
|
||||
uint16_t *pusTopOfStack;
|
||||
uint32_t *pulTopOfStack;
|
||||
|
||||
/*
|
||||
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.
|
||||
|
||||
*pxTopOfStack = ( StackType_t ) 0x1111;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x2222;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x3333;
|
||||
*/
|
||||
|
||||
/* 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
|
||||
to be explicitly cast to the correct size so this function will work
|
||||
whichever data model is being used. */
|
||||
if( sizeof( StackType_t ) == sizeof( uint16_t ) )
|
||||
{
|
||||
/* Make room for a 20 bit value stored as a 32 bit value. */
|
||||
pusTopOfStack = ( uint16_t * ) pxTopOfStack;
|
||||
pusTopOfStack--;
|
||||
pulTopOfStack = ( uint32_t * ) pusTopOfStack;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
/* Next the general purpose registers. */
|
||||
#ifdef PRELOAD_REGISTER_VALUES
|
||||
*pxTopOfStack = ( StackType_t ) 0xffff;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xeeee;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xdddd;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xbbbb;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0xaaaa;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x9999;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x8888;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x6666;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x5555;
|
||||
pxTopOfStack--;
|
||||
*pxTopOfStack = ( StackType_t ) 0x4444;
|
||||
pxTopOfStack--;
|
||||
#else
|
||||
pxTopOfStack -= 3;
|
||||
*pxTopOfStack = ( StackType_t ) pvParameters;
|
||||
pxTopOfStack -= 9;
|
||||
#endif
|
||||
|
||||
|
||||
/* 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
|
||||
initially set to zero. */
|
||||
*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 )
|
||||
{
|
||||
/* It is unlikely that the MSP430 port will get stopped. If required simply
|
||||
disable the tick interrupt here. */
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Hardware initialisation to generate the RTOS tick.
|
||||
*/
|
||||
void vPortSetupTimerInterrupt( void )
|
||||
{
|
||||
vApplicationSetupTimerInterrupt();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#pragma vector=configTICK_VECTOR
|
||||
__interrupt __raw void vTickISREntry( void )
|
||||
{
|
||||
extern void vPortTickISR( void );
|
||||
|
||||
__bic_SR_register_on_exit( SCG1 + SCG0 + OSCOFF + CPUOFF );
|
||||
vPortTickISR();
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue