From b0630a3bef8c821567062db8da77941333b239ed Mon Sep 17 00:00:00 2001 From: Alfred Gedeon Date: Wed, 12 Aug 2020 22:46:27 -0700 Subject: [PATCH] Style: redo the stuyles --- portable/BCC/16BitDOS/Flsh186/port.c | 256 ++- portable/BCC/16BitDOS/Flsh186/prtmacro.h | 68 +- portable/BCC/16BitDOS/PC/port.c | 316 ++-- portable/BCC/16BitDOS/PC/prtmacro.h | 68 +- portable/BCC/16BitDOS/common/portasm.h | 67 +- portable/BCC/16BitDOS/common/portcomn.c | 141 +- portable/GCC/ARM_CM0/port.c | 705 ++++---- portable/GCC/ARM_CM0/portmacro.h | 111 +- portable/GCC/ARM_CM23/non_secure/port.c | 1 + portable/GCC/ARM_CM23/non_secure/portasm.c | 714 ++++---- portable/GCC/ARM_CM23/non_secure/portasm.h | 22 +- portable/GCC/ARM_CM23/non_secure/portmacro.h | 340 ++-- portable/GCC/ARM_CM23/secure/secure_context.c | 224 +-- portable/GCC/ARM_CM23/secure/secure_context.h | 11 +- .../GCC/ARM_CM23/secure/secure_context_port.c | 94 +- portable/GCC/ARM_CM23/secure/secure_heap.c | 548 +++--- portable/GCC/ARM_CM23/secure/secure_heap.h | 4 +- portable/GCC/ARM_CM23/secure/secure_init.c | 88 +- .../GCC/ARM_CM23/secure/secure_port_macros.h | 48 +- .../GCC/ARM_CM23_NTZ/non_secure/portasm.c | 558 +++--- .../GCC/ARM_CM23_NTZ/non_secure/portasm.h | 22 +- .../GCC/ARM_CM23_NTZ/non_secure/portmacro.h | 340 ++-- portable/GCC/ARM_CM3/port.c | 952 +++++----- portable/GCC/ARM_CM3/portmacro.h | 292 +-- portable/GCC/ARM_CM33/non_secure/port.c | 1593 +++++++++-------- portable/GCC/ARM_CM33/non_secure/portasm.c | 632 +++---- portable/GCC/ARM_CM33/non_secure/portasm.h | 22 +- portable/GCC/ARM_CM33/non_secure/portmacro.h | 340 ++-- portable/GCC/ARM_CM33/secure/secure_context.c | 224 +-- portable/GCC/ARM_CM33/secure/secure_context.h | 11 +- .../GCC/ARM_CM33/secure/secure_context_port.c | 92 +- portable/GCC/ARM_CM33/secure/secure_heap.c | 548 +++--- portable/GCC/ARM_CM33/secure/secure_heap.h | 4 +- portable/GCC/ARM_CM33/secure/secure_init.c | 88 +- .../GCC/ARM_CM33/secure/secure_port_macros.h | 48 +- portable/GCC/ARM_CM33_NTZ/non_secure/port.c | 1593 +++++++++-------- .../GCC/ARM_CM33_NTZ/non_secure/portasm.c | 462 ++--- .../GCC/ARM_CM33_NTZ/non_secure/portasm.h | 22 +- .../GCC/ARM_CM33_NTZ/non_secure/portmacro.h | 340 ++-- portable/GCC/ARM_CM3_MPU/port.c | 1168 ++++++------ portable/GCC/ARM_CM3_MPU/portmacro.h | 368 ++-- portable/GCC/ARM_CM4F/port.c | 1047 +++++------ portable/GCC/ARM_CM4F/portmacro.h | 292 +-- portable/GCC/ARM_CM4_MPU/port.c | 1317 +++++++------- portable/GCC/ARM_CM4_MPU/portmacro.h | 454 +++-- portable/GCC/ARM_CM7/r0p1/port.c | 1033 +++++------ portable/GCC/ARM_CM7/r0p1/portmacro.h | 300 ++-- portable/GCC/ARM_CR5/port.c | 659 +++---- portable/GCC/ARM_CR5/portmacro.h | 211 ++- portable/RVDS/ARM7_LPC21xx/port.c | 346 ++-- portable/RVDS/ARM7_LPC21xx/portmacro.h | 121 +- portable/RVDS/ARM_CA9/port.c | 557 +++--- portable/RVDS/ARM_CA9/portmacro.h | 161 +- portable/RVDS/ARM_CM7/r0p1/port.c | 15 +- portable/RVDS/ARM_CM7/r0p1/portmacro.h | 3 +- 55 files changed, 10171 insertions(+), 9890 deletions(-) diff --git a/portable/BCC/16BitDOS/Flsh186/port.c b/portable/BCC/16BitDOS/Flsh186/port.c index e42366a3d..45bf8939c 100644 --- a/portable/BCC/16BitDOS/Flsh186/port.c +++ b/portable/BCC/16BitDOS/Flsh186/port.c @@ -26,22 +26,22 @@ */ /* - * Changes from V1.00: - * - + Call to taskYIELD() from within tick ISR has been replaced by the more - + efficient portSWITCH_CONTEXT(). - + ISR function definitions renamed to include the prv prefix. - + - + Changes from V2.6.1 - + - + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION - + macro to be consistent with the later ports. - */ +Changes from V1.00: + + + Call to taskYIELD() from within tick ISR has been replaced by the more + efficient portSWITCH_CONTEXT(). + + ISR function definitions renamed to include the prv prefix. + +Changes from V2.6.1 + + + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + macro to be consistent with the later ports. +*/ /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the Flashlite 186 -* port. -*----------------------------------------------------------*/ + * Implementation of functions defined in portable.h for the Flashlite 186 + * port. + *----------------------------------------------------------*/ #include #include @@ -53,13 +53,13 @@ /*lint -e950 Non ANSI reserved words okay in this file only. */ -#define portTIMER_EOI_TYPE ( 8 ) -#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE ) -#define portTIMER_INT_NUMBER 0x12 +#define portTIMER_EOI_TYPE ( 8 ) +#define portRESET_PIC() portOUTPUT_WORD( ( uint16_t ) 0xff22, portTIMER_EOI_TYPE ) +#define portTIMER_INT_NUMBER 0x12 -#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e ) -#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 ) -#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 ) +#define portTIMER_1_CONTROL_REGISTER ( ( uint16_t ) 0xff5e ) +#define portTIMER_0_CONTROL_REGISTER ( ( uint16_t ) 0xff56 ) +#define portTIMER_INTERRUPT_ENABLE ( ( uint16_t ) 0x2000 ) /* Setup the hardware to generate the required tick frequency. */ static void prvSetTickFrequency( uint32_t ulTickRateHz ); @@ -68,17 +68,15 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz ); static void prvExitFunction( void ); /* The ISR used depends on whether the preemptive or cooperative scheduler - * is being used. */ -#if ( configUSE_PREEMPTION == 1 ) - -/* Tick service routine used by the scheduler when preemptive scheduling is - * being used. */ - static void __interrupt __far prvPreemptiveTick( void ); +is being used. */ +#if( configUSE_PREEMPTION == 1 ) + /* Tick service routine used by the scheduler when preemptive scheduling is + being used. */ + static void __interrupt __far prvPreemptiveTick( void ); #else - -/* Tick service routine used by the scheduler when cooperative scheduling is - * being used. */ - static void __interrupt __far prvNonPreemptiveTick( void ); + /* Tick service routine used by the scheduler when cooperative scheduling is + being used. */ + static void __interrupt __far prvNonPreemptiveTick( void ); #endif /* Trap routine used by taskYIELD() to manually cause a context switch. */ @@ -90,9 +88,9 @@ static void __interrupt __far prvYieldProcessor( void ); static BaseType_t xSchedulerRunning = pdFALSE; /* Points to the original routine installed on the vector we use for manual - * context switches. This is then used to restore the original routine during - * prvExitFunction(). */ -static void( __interrupt __far * pxOldSwitchISR )(); +context switches. This is then used to restore the original routine during +prvExitFunction(). */ +static void ( __interrupt __far *pxOldSwitchISR )(); /* Used to restore the original DOS context when the scheduler is ended. */ static jmp_buf xJumpBuf; @@ -102,145 +100,145 @@ static jmp_buf xJumpBuf; /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { - /* This is called with interrupts already disabled. */ + /* This is called with interrupts already disabled. */ - /* Remember what was on the interrupts we are going to use - * so we can put them back later if required. */ - pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); + /* Remember what was on the interrupts we are going to use + so we can put them back later if required. */ + pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); - /* Put our manual switch (yield) function on a known - * vector. */ - _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); + /* Put our manual switch (yield) function on a known + vector. */ + _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); - #if ( configUSE_PREEMPTION == 1 ) - { - /* Put our tick switch function on the timer interrupt. */ - _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); - } - #else - { - /* We want the timer interrupt to just increment the tick count. */ - _dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick ); - } - #endif + #if( configUSE_PREEMPTION == 1 ) + { + /* Put our tick switch function on the timer interrupt. */ + _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); + } + #else + { + /* We want the timer interrupt to just increment the tick count. */ + _dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick ); + } + #endif - prvSetTickFrequency( configTICK_RATE_HZ ); + prvSetTickFrequency( configTICK_RATE_HZ ); - /* Clean up function if we want to return to DOS. */ - if( setjmp( xJumpBuf ) != 0 ) - { - prvExitFunction(); - xSchedulerRunning = pdFALSE; - } - else - { - xSchedulerRunning = pdTRUE; + /* Clean up function if we want to return to DOS. */ + if( setjmp( xJumpBuf ) != 0 ) + { + prvExitFunction(); + xSchedulerRunning = pdFALSE; + } + else + { + xSchedulerRunning = pdTRUE; - /* Kick off the scheduler by setting up the context of the first task. */ - portFIRST_CONTEXT(); - } + /* Kick off the scheduler by setting up the context of the first task. */ + portFIRST_CONTEXT(); + } - return xSchedulerRunning; + return xSchedulerRunning; } /*-----------------------------------------------------------*/ /* The ISR used depends on whether the preemptive or cooperative scheduler - * is being used. */ -#if ( configUSE_PREEMPTION == 1 ) - static void __interrupt __far prvPreemptiveTick( void ) - { - /* Get the scheduler to update the task states following the tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - /* Switch in the context of the next task to be run. */ - portSWITCH_CONTEXT(); - } +is being used. */ +#if( configUSE_PREEMPTION == 1 ) + static void __interrupt __far prvPreemptiveTick( void ) + { + /* Get the scheduler to update the task states following the tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Switch in the context of the next task to be run. */ + portSWITCH_CONTEXT(); + } - /* Reset the PIC ready for the next time. */ - portRESET_PIC(); - } -#else /* if ( configUSE_PREEMPTION == 1 ) */ - static void __interrupt __far prvNonPreemptiveTick( void ) - { - /* Same as preemptive tick, but the cooperative scheduler is being used - * so we don't have to switch in the context of the next task. */ - xTaskIncrementTick(); - portRESET_PIC(); - } -#endif /* if ( configUSE_PREEMPTION == 1 ) */ + /* Reset the PIC ready for the next time. */ + portRESET_PIC(); + } +#else + static void __interrupt __far prvNonPreemptiveTick( void ) + { + /* Same as preemptive tick, but the cooperative scheduler is being used + so we don't have to switch in the context of the next task. */ + xTaskIncrementTick(); + portRESET_PIC(); + } +#endif /*-----------------------------------------------------------*/ static void __interrupt __far prvYieldProcessor( void ) { - /* Switch in the context of the next task to be run. */ - portSWITCH_CONTEXT(); + /* Switch in the context of the next task to be run. */ + portSWITCH_CONTEXT(); } /*-----------------------------------------------------------*/ void vPortEndScheduler( void ) { - /* Jump back to the processor state prior to starting the - * scheduler. This means we are not going to be using a - * task stack frame so the task can be deleted. */ - longjmp( xJumpBuf, 1 ); + /* Jump back to the processor state prior to starting the + scheduler. This means we are not going to be using a + task stack frame so the task can be deleted. */ + longjmp( xJumpBuf, 1 ); } /*-----------------------------------------------------------*/ static void prvExitFunction( void ) { - const uint16_t usTimerDisable = 0x0000; - uint16_t usTimer0Control; +const uint16_t usTimerDisable = 0x0000; +uint16_t usTimer0Control; - /* Interrupts should be disabled here anyway - but no - * harm in making sure. */ - portDISABLE_INTERRUPTS(); + /* Interrupts should be disabled here anyway - but no + harm in making sure. */ + portDISABLE_INTERRUPTS(); + if( xSchedulerRunning == pdTRUE ) + { + /* Put back the switch interrupt routines that was in place + before the scheduler started. */ + _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); + } - if( xSchedulerRunning == pdTRUE ) - { - /* Put back the switch interrupt routines that was in place - * before the scheduler started. */ - _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); - } + /* Disable the timer used for the tick to ensure the scheduler is + not called before restoring interrupts. There was previously nothing + on this timer so there is no old ISR to restore. */ + portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable ); - /* Disable the timer used for the tick to ensure the scheduler is - * not called before restoring interrupts. There was previously nothing - * on this timer so there is no old ISR to restore. */ - portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerDisable ); - - /* Restart the DOS tick. */ - usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER ); - usTimer0Control |= portTIMER_INTERRUPT_ENABLE; - portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control ); + /* Restart the DOS tick. */ + usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER ); + usTimer0Control |= portTIMER_INTERRUPT_ENABLE; + portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control ); - portENABLE_INTERRUPTS(); + portENABLE_INTERRUPTS(); } /*-----------------------------------------------------------*/ static void prvSetTickFrequency( uint32_t ulTickRateHz ) { - const uint16_t usMaxCountRegister = 0xff5a; - const uint16_t usTimerPriorityRegister = 0xff32; - const uint16_t usTimerEnable = 0xC000; - const uint16_t usRetrigger = 0x0001; - const uint16_t usTimerHighPriority = 0x0000; - uint16_t usTimer0Control; +const uint16_t usMaxCountRegister = 0xff5a; +const uint16_t usTimerPriorityRegister = 0xff32; +const uint16_t usTimerEnable = 0xC000; +const uint16_t usRetrigger = 0x0001; +const uint16_t usTimerHighPriority = 0x0000; +uint16_t usTimer0Control; /* ( CPU frequency / 4 ) / clock 2 max count [inpw( 0xff62 ) = 7] */ - const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL; +const uint32_t ulClockFrequency = ( uint32_t ) 0x7f31a0UL; - uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz; +uint32_t ulTimerCount = ulClockFrequency / ulTickRateHz; - portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger ); - portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount ); - portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority ); + portOUTPUT_WORD( portTIMER_1_CONTROL_REGISTER, usTimerEnable | portTIMER_INTERRUPT_ENABLE | usRetrigger ); + portOUTPUT_WORD( usMaxCountRegister, ( uint16_t ) ulTimerCount ); + portOUTPUT_WORD( usTimerPriorityRegister, usTimerHighPriority ); - /* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */ - usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER ); - usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE; - portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control ); + /* Stop the DOS tick - don't do this if you want to maintain a TOD clock. */ + usTimer0Control = portINPUT_WORD( portTIMER_0_CONTROL_REGISTER ); + usTimer0Control &= ~portTIMER_INTERRUPT_ENABLE; + portOUTPUT_WORD( portTIMER_0_CONTROL_REGISTER, usTimer0Control ); } /*lint +e950 */ + diff --git a/portable/BCC/16BitDOS/Flsh186/prtmacro.h b/portable/BCC/16BitDOS/Flsh186/prtmacro.h index cfd36e1ba..e96ac83f0 100644 --- a/portable/BCC/16BitDOS/Flsh186/prtmacro.h +++ b/portable/BCC/16BitDOS/Flsh186/prtmacro.h @@ -39,59 +39,59 @@ */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE long -#define portLONG long -#define portSHORT int -#define portSTACK_TYPE uint16_t -#define portBASE_TYPE portSHORT +#define portCHAR char +#define portFLOAT float +#define portDOUBLE long +#define portLONG long +#define portSHORT int +#define portSTACK_TYPE uint16_t +#define portBASE_TYPE portSHORT -typedef portSTACK_TYPE StackType_t; -typedef short BaseType_t; -typedef unsigned short UBaseType_t; +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 +#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 + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL #endif /*-----------------------------------------------------------*/ /* Critical section handling. */ -#define portENTER_CRITICAL() \ - __asm{ pushf } \ - __asm{ cli } \ +#define portENTER_CRITICAL() __asm{ pushf } \ + __asm{ cli } \ -#define portEXIT_CRITICAL() __asm{ popf } +#define portEXIT_CRITICAL() __asm{ popf } -#define portDISABLE_INTERRUPTS() __asm{ cli } +#define portDISABLE_INTERRUPTS() __asm{ cli } -#define portENABLE_INTERRUPTS() __asm{ sti } +#define portENABLE_INTERRUPTS() __asm{ sti } /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portNOP() __asm{ nop } -#define portSTACK_GROWTH ( -1 ) -#define portSWITCH_INT_NUMBER 0x80 -#define portYIELD() __asm{ int portSWITCH_INT_NUMBER } -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) -#define portBYTE_ALIGNMENT 2 -#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ +#define portNOP() __asm{ nop } +#define portSTACK_GROWTH ( -1 ) +#define portSWITCH_INT_NUMBER 0x80 +#define portYIELD() __asm{ int portSWITCH_INT_NUMBER } +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 2 +#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ /*-----------------------------------------------------------*/ /* Compiler specifics. */ -#define portINPUT_BYTE( xAddr ) inp( xAddr ) -#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue ) -#define portINPUT_WORD( xAddr ) inpw( xAddr ) -#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue ) +#define portINPUT_BYTE( xAddr ) inp( xAddr ) +#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue ) +#define portINPUT_WORD( xAddr ) inpw( xAddr ) +#define portOUTPUT_WORD( xAddr, usValue ) outpw( xAddr, usValue ) /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) -#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) +#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) #endif /* PORTMACRO_H */ + diff --git a/portable/BCC/16BitDOS/PC/port.c b/portable/BCC/16BitDOS/PC/port.c index da84dd871..70ae70cda 100644 --- a/portable/BCC/16BitDOS/PC/port.c +++ b/portable/BCC/16BitDOS/PC/port.c @@ -26,16 +26,16 @@ */ /* - * Changes from V2.6.1 - * - + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION - + macro to be consistent with the later ports. - + - + Changes from V4.0.1 - + - + Add function prvSetTickFrequencyDefault() to set the DOS tick back to - + its proper value when the scheduler exits. - */ +Changes from V2.6.1 + + + Replaced the sUsingPreemption variable with the configUSE_PREEMPTION + macro to be consistent with the later ports. + +Changes from V4.0.1 + + + Add function prvSetTickFrequencyDefault() to set the DOS tick back to + its proper value when the scheduler exits. +*/ #include #include @@ -46,13 +46,13 @@ #include "portasm.h" /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the industrial -* PC port. -*----------------------------------------------------------*/ + * Implementation of functions defined in portable.h for the industrial + * PC port. + *----------------------------------------------------------*/ /*lint -e950 Non ANSI reserved words okay in this file only. */ -#define portTIMER_INT_NUMBER 0x08 +#define portTIMER_INT_NUMBER 0x08 /* Setup hardware for required tick interrupt rate. */ static void prvSetTickFrequency( uint32_t ulTickRateHz ); @@ -61,29 +61,27 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz ); static void prvExitFunction( void ); /* Either chain to the DOS tick (which itself clears the PIC) or clear the PIC - * directly. We chain to the DOS tick as close as possible to the standard DOS - * tick rate. */ +directly. We chain to the DOS tick as close as possible to the standard DOS +tick rate. */ static void prvPortResetPIC( void ); /* The ISR used depends on whether the preemptive or cooperative - * scheduler is being used. */ -#if ( configUSE_PREEMPTION == 1 ) - -/* Tick service routine used by the scheduler when preemptive scheduling is - * being used. */ - static void __interrupt __far prvPreemptiveTick( void ); +scheduler is being used. */ +#if( configUSE_PREEMPTION == 1 ) + /* Tick service routine used by the scheduler when preemptive scheduling is + being used. */ + static void __interrupt __far prvPreemptiveTick( void ); #else - -/* Tick service routine used by the scheduler when cooperative scheduling is - * being used. */ - static void __interrupt __far prvNonPreemptiveTick( void ); + /* Tick service routine used by the scheduler when cooperative scheduling is + being used. */ + static void __interrupt __far prvNonPreemptiveTick( void ); #endif /* Trap routine used by taskYIELD() to manually cause a context switch. */ static void __interrupt __far prvYieldProcessor( void ); /* Set the tick frequency back so the floppy drive works correctly when the - * scheduler exits. */ +scheduler exits. */ static void prvSetTickFrequencyDefault( void ); /*lint -e956 File scopes necessary here. */ @@ -92,13 +90,13 @@ static void prvSetTickFrequencyDefault( void ); static int16_t sDOSTickCounter; /* Set true when the vectors are set so the scheduler will service the tick. */ -static BaseType_t xSchedulerRunning = pdFALSE; +static BaseType_t xSchedulerRunning = pdFALSE; /* Points to the original routine installed on the vector we use for manual context switches. This is then used to restore the original routine during prvExitFunction(). */ -static void( __interrupt __far * pxOldSwitchISR )(); +static void ( __interrupt __far *pxOldSwitchISR )(); /* Points to the original routine installed on the vector we use to chain to the DOS tick. This is then used to restore the original routine during prvExitFunction(). */ -static void( __interrupt __far * pxOldSwitchISRPlus1 )(); +static void ( __interrupt __far *pxOldSwitchISRPlus1 )(); /* Used to restore the original DOS context when the scheduler is ended. */ static jmp_buf xJumpBuf; @@ -108,187 +106,183 @@ static jmp_buf xJumpBuf; /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { - pxISR pxOriginalTickISR; +pxISR pxOriginalTickISR; + + /* This is called with interrupts already disabled. */ - /* This is called with interrupts already disabled. */ + /* Remember what was on the interrupts we are going to use + so we can put them back later if required. */ + pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); + pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER ); + pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); - /* Remember what was on the interrupts we are going to use - * so we can put them back later if required. */ - pxOldSwitchISR = _dos_getvect( portSWITCH_INT_NUMBER ); - pxOriginalTickISR = _dos_getvect( portTIMER_INT_NUMBER ); - pxOldSwitchISRPlus1 = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); + prvSetTickFrequency( configTICK_RATE_HZ ); - prvSetTickFrequency( configTICK_RATE_HZ ); + /* Put our manual switch (yield) function on a known + vector. */ + _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); - /* Put our manual switch (yield) function on a known - * vector. */ - _dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor ); + /* Put the old tick on a different interrupt number so we can + call it when we want. */ + _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR ); - /* Put the old tick on a different interrupt number so we can - * call it when we want. */ - _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOriginalTickISR ); - - /* The ISR used depends on whether the preemptive or cooperative - * scheduler is being used. */ - #if ( configUSE_PREEMPTION == 1 ) - { - /* Put our tick switch function on the timer interrupt. */ - _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); - } - #else - { - /* We want the timer interrupt to just increment the tick count. */ - _dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick ); - } + /* The ISR used depends on whether the preemptive or cooperative + scheduler is being used. */ + #if( configUSE_PREEMPTION == 1 ) + { + /* Put our tick switch function on the timer interrupt. */ + _dos_setvect( portTIMER_INT_NUMBER, prvPreemptiveTick ); + } + #else + { + /* We want the timer interrupt to just increment the tick count. */ + _dos_setvect( portTIMER_INT_NUMBER, prvNonPreemptiveTick ); + } #endif - /* Setup a counter that is used to call the DOS interrupt as close - * to it's original frequency as can be achieved given our chosen tick - * frequency. */ - sDOSTickCounter = portTICKS_PER_DOS_TICK; + /* Setup a counter that is used to call the DOS interrupt as close + to it's original frequency as can be achieved given our chosen tick + frequency. */ + sDOSTickCounter = portTICKS_PER_DOS_TICK; - /* Clean up function if we want to return to DOS. */ - if( setjmp( xJumpBuf ) != 0 ) - { - prvExitFunction(); - xSchedulerRunning = pdFALSE; - } - else - { - xSchedulerRunning = pdTRUE; + /* Clean up function if we want to return to DOS. */ + if( setjmp( xJumpBuf ) != 0 ) + { + prvExitFunction(); + xSchedulerRunning = pdFALSE; + } + else + { + xSchedulerRunning = pdTRUE; - /* Kick off the scheduler by setting up the context of the first task. */ - portFIRST_CONTEXT(); - } + /* Kick off the scheduler by setting up the context of the first task. */ + portFIRST_CONTEXT(); + } - return xSchedulerRunning; + return xSchedulerRunning; } /*-----------------------------------------------------------*/ /* The ISR used depends on whether the preemptive or cooperative - * scheduler is being used. */ -#if ( configUSE_PREEMPTION == 1 ) - static void __interrupt __far prvPreemptiveTick( void ) - { - /* Get the scheduler to update the task states following the tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - /* Switch in the context of the next task to be run. */ - portSWITCH_CONTEXT(); - } +scheduler is being used. */ +#if( configUSE_PREEMPTION == 1 ) + static void __interrupt __far prvPreemptiveTick( void ) + { + /* Get the scheduler to update the task states following the tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Switch in the context of the next task to be run. */ + portSWITCH_CONTEXT(); + } - /* Reset the PIC ready for the next time. */ - prvPortResetPIC(); - } -#else /* if ( configUSE_PREEMPTION == 1 ) */ - static void __interrupt __far prvNonPreemptiveTick( void ) - { - /* Same as preemptive tick, but the cooperative scheduler is being used - * so we don't have to switch in the context of the next task. */ - xTaskIncrementTick(); - prvPortResetPIC(); - } -#endif /* if ( configUSE_PREEMPTION == 1 ) */ + /* Reset the PIC ready for the next time. */ + prvPortResetPIC(); + } +#else + static void __interrupt __far prvNonPreemptiveTick( void ) + { + /* Same as preemptive tick, but the cooperative scheduler is being used + so we don't have to switch in the context of the next task. */ + xTaskIncrementTick(); + prvPortResetPIC(); + } +#endif /*-----------------------------------------------------------*/ static void __interrupt __far prvYieldProcessor( void ) { - /* Switch in the context of the next task to be run. */ - portSWITCH_CONTEXT(); + /* Switch in the context of the next task to be run. */ + portSWITCH_CONTEXT(); } /*-----------------------------------------------------------*/ static void prvPortResetPIC( void ) { - /* We are going to call the DOS tick interrupt at as close a - * frequency to the normal DOS tick as possible. */ + /* We are going to call the DOS tick interrupt at as close a + frequency to the normal DOS tick as possible. */ - /* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */ - --sDOSTickCounter; - - if( sDOSTickCounter <= 0 ) - { - sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK; - __asm { - int portSWITCH_INT_NUMBER + 1 - }; - } - else - { - /* Reset the PIC as the DOS tick is not being called to - * do it. */ - __asm - { - mov al, 20H - out 20H, al - }; - } + /* WE SHOULD NOT DO THIS IF YIELD WAS CALLED. */ + --sDOSTickCounter; + if( sDOSTickCounter <= 0 ) + { + sDOSTickCounter = ( int16_t ) portTICKS_PER_DOS_TICK; + __asm{ int portSWITCH_INT_NUMBER + 1 }; + } + else + { + /* Reset the PIC as the DOS tick is not being called to + do it. */ + __asm + { + mov al, 20H + out 20H, al + }; + } } /*-----------------------------------------------------------*/ void vPortEndScheduler( void ) { - /* Jump back to the processor state prior to starting the - * scheduler. This means we are not going to be using a - * task stack frame so the task can be deleted. */ - longjmp( xJumpBuf, 1 ); + /* Jump back to the processor state prior to starting the + scheduler. This means we are not going to be using a + task stack frame so the task can be deleted. */ + longjmp( xJumpBuf, 1 ); } /*-----------------------------------------------------------*/ static void prvExitFunction( void ) { - void( __interrupt __far * pxOriginalTickISR )(); +void ( __interrupt __far *pxOriginalTickISR )(); - /* Interrupts should be disabled here anyway - but no - * harm in making sure. */ - portDISABLE_INTERRUPTS(); + /* Interrupts should be disabled here anyway - but no + harm in making sure. */ + portDISABLE_INTERRUPTS(); + if( xSchedulerRunning == pdTRUE ) + { + /* Set the DOS tick back onto the timer ticker. */ + pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); + _dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR ); + prvSetTickFrequencyDefault(); - if( xSchedulerRunning == pdTRUE ) - { - /* Set the DOS tick back onto the timer ticker. */ - pxOriginalTickISR = _dos_getvect( portSWITCH_INT_NUMBER + 1 ); - _dos_setvect( portTIMER_INT_NUMBER, pxOriginalTickISR ); - prvSetTickFrequencyDefault(); - - /* Put back the switch interrupt routines that was in place - * before the scheduler started. */ - _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); - _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 ); - } - - /* The tick timer is back how DOS wants it. We can re-enable - * interrupts without the scheduler being called. */ - portENABLE_INTERRUPTS(); + /* Put back the switch interrupt routines that was in place + before the scheduler started. */ + _dos_setvect( portSWITCH_INT_NUMBER, pxOldSwitchISR ); + _dos_setvect( portSWITCH_INT_NUMBER + 1, pxOldSwitchISRPlus1 ); + } + /* The tick timer is back how DOS wants it. We can re-enable + interrupts without the scheduler being called. */ + portENABLE_INTERRUPTS(); } /*-----------------------------------------------------------*/ static void prvSetTickFrequency( uint32_t ulTickRateHz ) { - const uint16_t usPIT_MODE = ( uint16_t ) 0x43; - const uint16_t usPIT0 = ( uint16_t ) 0x40; - const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL; - const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; - uint32_t ulOutput; +const uint16_t usPIT_MODE = ( uint16_t ) 0x43; +const uint16_t usPIT0 = ( uint16_t ) 0x40; +const uint32_t ulPIT_CONST = ( uint32_t ) 1193180UL; +const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; +uint32_t ulOutput; - /* Setup the 8245 to tick at the wanted frequency. */ - portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); - ulOutput = ulPIT_CONST / ulTickRateHz; - portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) ); - ulOutput >>= 8; - portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) ); + /* Setup the 8245 to tick at the wanted frequency. */ + portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); + ulOutput = ulPIT_CONST / ulTickRateHz; + portOUTPUT_BYTE( usPIT0, ( uint16_t )( ulOutput & ( uint32_t ) 0xff ) ); + ulOutput >>= 8; + portOUTPUT_BYTE( usPIT0, ( uint16_t ) ( ulOutput & ( uint32_t ) 0xff ) ); } /*-----------------------------------------------------------*/ static void prvSetTickFrequencyDefault( void ) { - const uint16_t usPIT_MODE = ( uint16_t ) 0x43; - const uint16_t usPIT0 = ( uint16_t ) 0x40; - const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; +const uint16_t usPIT_MODE = ( uint16_t ) 0x43; +const uint16_t usPIT0 = ( uint16_t ) 0x40; +const uint16_t us8254_CTR0_MODE3 = ( uint16_t ) 0x36; - portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); - portOUTPUT_BYTE( usPIT0, 0 ); - portOUTPUT_BYTE( usPIT0, 0 ); + portOUTPUT_BYTE( usPIT_MODE, us8254_CTR0_MODE3 ); + portOUTPUT_BYTE( usPIT0,0 ); + portOUTPUT_BYTE( usPIT0,0 ); } /*lint +e950 */ + diff --git a/portable/BCC/16BitDOS/PC/prtmacro.h b/portable/BCC/16BitDOS/PC/prtmacro.h index f94ec2310..cfc74f35b 100644 --- a/portable/BCC/16BitDOS/PC/prtmacro.h +++ b/portable/BCC/16BitDOS/PC/prtmacro.h @@ -39,59 +39,59 @@ */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT long -#define portDOUBLE long -#define portLONG long -#define portSHORT int -#define portSTACK_TYPE uint16_t -#define portBASE_TYPE portSHORT +#define portCHAR char +#define portFLOAT long +#define portDOUBLE long +#define portLONG long +#define portSHORT int +#define portSTACK_TYPE uint16_t +#define portBASE_TYPE portSHORT -typedef portSTACK_TYPE StackType_t; -typedef short BaseType_t; -typedef unsigned short UBaseType_t; +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 +#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 + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL #endif /*-----------------------------------------------------------*/ /* Critical section management. */ -#define portENTER_CRITICAL() \ - __asm{ pushf } \ - __asm{ cli } \ +#define portENTER_CRITICAL() __asm{ pushf } \ + __asm{ cli } \ -#define portEXIT_CRITICAL() __asm{ popf } +#define portEXIT_CRITICAL() __asm{ popf } -#define portDISABLE_INTERRUPTS() __asm{ cli } +#define portDISABLE_INTERRUPTS() __asm{ cli } -#define portENABLE_INTERRUPTS() __asm{ sti } +#define portENABLE_INTERRUPTS() __asm{ sti } /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portNOP() __asm{ nop } -#define portSTACK_GROWTH ( -1 ) -#define portSWITCH_INT_NUMBER 0x80 -#define portYIELD() __asm{ int portSWITCH_INT_NUMBER } -#define portDOS_TICK_RATE ( 18.20648 ) -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) -#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) ) -#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ -#define portBYTE_ALIGNMENT ( 2 ) +#define portNOP() __asm{ nop } +#define portSTACK_GROWTH ( -1 ) +#define portSWITCH_INT_NUMBER 0x80 +#define portYIELD() __asm{ int portSWITCH_INT_NUMBER } +#define portDOS_TICK_RATE ( 18.20648 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portTICKS_PER_DOS_TICK ( ( uint16_t ) ( ( ( portDOUBLE ) configTICK_RATE_HZ / portDOS_TICK_RATE ) + 0.5 ) ) +#define portINITIAL_SW ( ( portSTACK_TYPE ) 0x0202 ) /* Start the tasks with interrupts enabled. */ +#define portBYTE_ALIGNMENT ( 2 ) /*-----------------------------------------------------------*/ /* Compiler specifics. */ -#define portINPUT_BYTE( xAddr ) inp( xAddr ) -#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue ) +#define portINPUT_BYTE( xAddr ) inp( xAddr ) +#define portOUTPUT_BYTE( xAddr, ucValue ) outp( xAddr, ucValue ) /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters ) -#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters ) +#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters ) #endif /* PORTMACRO_H */ + diff --git a/portable/BCC/16BitDOS/common/portasm.h b/portable/BCC/16BitDOS/common/portasm.h index 45d13027c..2b199c61b 100644 --- a/portable/BCC/16BitDOS/common/portasm.h +++ b/portable/BCC/16BitDOS/common/portasm.h @@ -47,40 +47,41 @@ void portSWITCH_CONTEXT( void ); void portFIRST_CONTEXT( void ); /* There are slightly different versions depending on whether you are building - * to include debugger information. If debugger information is used then there - * are a couple of extra bytes left of the ISR stack (presumably for use by the - * debugger). The true stack pointer is then stored in the bp register. We add - * 2 to the stack pointer to remove the extra bytes before we restore our context. */ +to include debugger information. If debugger information is used then there +are a couple of extra bytes left of the ISR stack (presumably for use by the +debugger). The true stack pointer is then stored in the bp register. We add +2 to the stack pointer to remove the extra bytes before we restore our context. */ -#define portSWITCH_CONTEXT() \ - asm { mov ax, seg pxCurrentTCB } \ - asm { mov ds, ax } \ - asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \ - asm { mov es : 0x2[ bx ], ss } \ - asm { mov es:[ bx ], sp } \ - asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \ - asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \ - asm { mov ds, ax } \ - asm { les bx, dword ptr pxCurrentTCB } \ - asm { mov ss, es:[ bx + 2 ] } \ - asm { mov sp, es:[ bx ] } +#define portSWITCH_CONTEXT() \ + asm { mov ax, seg pxCurrentTCB } \ + asm { mov ds, ax } \ + asm { les bx, pxCurrentTCB } /* Save the stack pointer into the TCB. */ \ + asm { mov es:0x2[ bx ], ss } \ + asm { mov es:[ bx ], sp } \ + asm { call far ptr vTaskSwitchContext } /* Perform the switch. */ \ + asm { mov ax, seg pxCurrentTCB } /* Restore the stack pointer from the TCB. */ \ + asm { mov ds, ax } \ + asm { les bx, dword ptr pxCurrentTCB } \ + asm { mov ss, es:[ bx + 2 ] } \ + asm { mov sp, es:[ bx ] } -#define portFIRST_CONTEXT() \ - __asm { mov ax, seg pxCurrentTCB } \ - __asm { mov ds, ax } \ - __asm { les bx, dword ptr pxCurrentTCB } \ - __asm { mov ss, es:[ bx + 2 ] } \ - __asm { mov sp, es:[ bx ] } \ - __asm { pop bp } \ - __asm { pop di } \ - __asm { pop si } \ - __asm { pop ds } \ - __asm { pop es } \ - __asm { pop dx } \ - __asm { pop cx } \ - __asm { pop bx } \ - __asm { pop ax } \ - __asm { iret } +#define portFIRST_CONTEXT() \ + __asm { mov ax, seg pxCurrentTCB } \ + __asm { mov ds, ax } \ + __asm { les bx, dword ptr pxCurrentTCB } \ + __asm { mov ss, es:[ bx + 2 ] } \ + __asm { mov sp, es:[ bx ] } \ + __asm { pop bp } \ + __asm { pop di } \ + __asm { pop si } \ + __asm { pop ds } \ + __asm { pop es } \ + __asm { pop dx } \ + __asm { pop cx } \ + __asm { pop bx } \ + __asm { pop ax } \ + __asm { iret } -#endif /* ifndef PORT_ASM_H */ +#endif + diff --git a/portable/BCC/16BitDOS/common/portcomn.c b/portable/BCC/16BitDOS/common/portcomn.c index 593cf38b1..c230b141c 100644 --- a/portable/BCC/16BitDOS/common/portcomn.c +++ b/portable/BCC/16BitDOS/common/portcomn.c @@ -26,16 +26,16 @@ */ /* - * Changes from V1.00: - * - + pxPortInitialiseStack() now initialises the stack of new tasks to the - + same format used by the compiler. This allows the compiler generated - + interrupt mechanism to be used for context switches. - + - + Changes from V2.6.1 - + - + Move usPortCheckFreeStackSpace() to tasks.c. - */ +Changes from V1.00: + + + pxPortInitialiseStack() now initialises the stack of new tasks to the + same format used by the compiler. This allows the compiler generated + interrupt mechanism to be used for context switches. + +Changes from V2.6.1 + + + Move usPortCheckFreeStackSpace() to tasks.c. +*/ #include @@ -45,79 +45,76 @@ /*-----------------------------------------------------------*/ /* See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { - StackType_t DS_Reg = 0; +StackType_t DS_Reg = 0; - /* Place a few bytes of known values on the bottom of the stack. - * This is just useful for debugging. */ + /* Place a few bytes of known values on the bottom of the stack. + This is just useful for debugging. */ - *pxTopOfStack = 0x1111; - pxTopOfStack--; - *pxTopOfStack = 0x2222; - pxTopOfStack--; - *pxTopOfStack = 0x3333; - pxTopOfStack--; - *pxTopOfStack = 0x4444; - pxTopOfStack--; - *pxTopOfStack = 0x5555; - pxTopOfStack--; + *pxTopOfStack = 0x1111; + pxTopOfStack--; + *pxTopOfStack = 0x2222; + pxTopOfStack--; + *pxTopOfStack = 0x3333; + pxTopOfStack--; + *pxTopOfStack = 0x4444; + pxTopOfStack--; + *pxTopOfStack = 0x5555; + pxTopOfStack--; - /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ + /*lint -e950 -e611 -e923 Lint doesn't like this much - but nothing I can do about it. */ - /* We are going to start the scheduler using a return from interrupt - * instruction to load the program counter, so first there would be the - * function call with parameters preamble. */ + /* We are going to start the scheduler using a return from interrupt + instruction to load the program counter, so first there would be the + function call with parameters preamble. */ + + *pxTopOfStack = FP_SEG( pvParameters ); + pxTopOfStack--; + *pxTopOfStack = FP_OFF( pvParameters ); + pxTopOfStack--; + *pxTopOfStack = FP_SEG( pxCode ); + pxTopOfStack--; + *pxTopOfStack = FP_OFF( pxCode ); + pxTopOfStack--; - *pxTopOfStack = FP_SEG( pvParameters ); - pxTopOfStack--; - *pxTopOfStack = FP_OFF( pvParameters ); - pxTopOfStack--; - *pxTopOfStack = FP_SEG( pxCode ); - pxTopOfStack--; - *pxTopOfStack = FP_OFF( pxCode ); - pxTopOfStack--; + /* Next the status register and interrupt return address. */ + *pxTopOfStack = portINITIAL_SW; + pxTopOfStack--; + *pxTopOfStack = FP_SEG( pxCode ); + pxTopOfStack--; + *pxTopOfStack = FP_OFF( pxCode ); + pxTopOfStack--; - /* Next the status register and interrupt return address. */ - *pxTopOfStack = portINITIAL_SW; - pxTopOfStack--; - *pxTopOfStack = FP_SEG( pxCode ); - pxTopOfStack--; - *pxTopOfStack = FP_OFF( pxCode ); - pxTopOfStack--; + /* The remaining registers would be pushed on the stack by our context + switch function. These are loaded with values simply to make debugging + easier. */ + *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */ + pxTopOfStack--; - /* The remaining registers would be pushed on the stack by our context - * switch function. These are loaded with values simply to make debugging - * easier. */ - *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */ - pxTopOfStack--; + /* We need the true data segment. */ + __asm{ MOV DS_Reg, DS }; - /* We need the true data segment. */ - __asm { - MOV DS_Reg, DS - }; + *pxTopOfStack = DS_Reg; /* DS */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0x0123; /* SI */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */ - *pxTopOfStack = DS_Reg; /* DS */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x0123; /* SI */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */ + /*lint +e950 +e611 +e923 */ - /*lint +e950 +e611 +e923 */ - - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ + diff --git a/portable/GCC/ARM_CM0/port.c b/portable/GCC/ARM_CM0/port.c index 2b32b2002..e5b500a43 100644 --- a/portable/GCC/ARM_CM0/port.c +++ b/portable/GCC/ARM_CM0/port.c @@ -26,48 +26,48 @@ */ /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM0 port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the ARM CM0 port. +*----------------------------------------------------------*/ /* 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 portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) -#define portMIN_INTERRUPT_PRIORITY ( 255UL ) -#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL ) -#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL ) +#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_SHPR3_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 portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#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 ) +#define portINITIAL_XPSR ( 0x01000000 ) /* The systick is a 24-bit counter. */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) +#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. */ + * occurred while the SysTick counter is stopped during tickless idle + * calculations. */ #ifndef portMISSED_COUNTS_FACTOR - #define portMISSED_COUNTS_FACTOR ( 45UL ) + #define portMISSED_COUNTS_FACTOR ( 45UL ) #endif /* 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. */ + * prvTaskExitError() in case it messes up unwinding of the stack in the + * debugger. */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* @@ -80,14 +80,14 @@ void vPortSetupTimerInterrupt( void ); /* * Exception handlers. */ -void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortPendSVHandler( void ) __attribute__( ( naked ) ); void xPortSysTickHandler( void ); void vPortSVCHandler( void ); /* * Start first task is a separate function so it can be tested in isolation. */ -static void vPortStartFirstTask( void ) __attribute__ (( naked )); +static void vPortStartFirstTask( void ) __attribute__( ( naked ) ); /* * Used to catch tasks that attempt to return from their implementing function. @@ -97,32 +97,32 @@ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* Each task maintains its own interrupt status in the critical nesting -variable. */ + * 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; + * 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; +#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; +#if ( configUSE_TICKLESS_IDLE == 1 ) + static uint32_t ulStoppedTimerCompensation = 0; #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ @@ -130,81 +130,84 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * See header file for description. */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +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 ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack -= 8; /* R11..R4. */ + /* 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 ) portTASK_RETURN_ADDRESS; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack -= 8; /* R11..R4. */ - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ static void prvTaskExitError( void ) { -volatile uint32_t ulDummy = 0UL; + 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 ). + /* 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(); - 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(); - 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. */ - } + 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. */ + } } /*-----------------------------------------------------------*/ void vPortSVCHandler( void ) { - /* This function is no longer used, but retained for backward - compatibility. */ + /* This function is no longer used, but retained for backward + * compatibility. */ } /*-----------------------------------------------------------*/ void vPortStartFirstTask( void ) { - /* 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. */ - __asm volatile( - " .syntax unified \n" - " ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */ - " ldr r3, [r2] \n" - " ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " movs r0, #2 \n" /* Switch to the psp stack. */ - " msr CONTROL, r0 \n" - " isb \n" - " pop {r0-r5} \n" /* Pop the registers that are saved automatically. */ - " mov lr, r5 \n" /* lr is now in r5. */ - " pop {r3} \n" /* Return address is now in r3. */ - " pop {r2} \n" /* Pop and discard XPSR. */ - " cpsie i \n" /* The first task has its context and interrupts can be enabled. */ - " bx r3 \n" /* Finally, jump to the user defined task code. */ - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB " - ); + /* 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. */ + __asm volatile ( + " .syntax unified \n" + " ldr r2, pxCurrentTCBConst2 \n"/* Obtain location of pxCurrentTCB. */ + " ldr r3, [r2] \n" + " ldr r0, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " movs r0, #2 \n"/* Switch to the psp stack. */ + " msr CONTROL, r0 \n" + " isb \n" + " pop {r0-r5} \n"/* Pop the registers that are saved automatically. */ + " mov lr, r5 \n"/* lr is now in r5. */ + " pop {r3} \n"/* Return address is now in r3. */ + " pop {r2} \n"/* Pop and discard XPSR. */ + " cpsie i \n"/* The first task has its context and interrupts can be enabled. */ + " bx r3 \n"/* Finally, jump to the user defined task code. */ + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB " + ); } /*-----------------------------------------------------------*/ @@ -213,158 +216,159 @@ void vPortStartFirstTask( void ) */ BaseType_t xPortStartScheduler( void ) { - /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ - portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; - portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - vPortSetupTimerInterrupt(); + /* 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; + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; - /* Start the first task. */ - vPortStartFirstTask(); + /* Start the first task. */ + vPortStartFirstTask(); - /* 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 optimisation does not remove the - symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); + /* 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 optimisation does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); - /* Should not get here! */ - return 0; + /* 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 ); + /* 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_BIT; + /* Set a PendSV to request a context switch. */ + 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" ); + /* 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 ) { - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - __asm volatile( "dsb" ::: "memory" ); - __asm volatile( "isb" ); + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } } /*-----------------------------------------------------------*/ uint32_t ulSetInterruptMaskFromISR( void ) { - __asm volatile( - " mrs r0, PRIMASK \n" - " cpsid i \n" - " bx lr " - ::: "memory" - ); + __asm volatile ( + " mrs r0, PRIMASK \n" + " cpsid i \n" + " bx lr " + ::: "memory" + ); } /*-----------------------------------------------------------*/ void vClearInterruptMaskFromISR( __attribute__( ( unused ) ) uint32_t ulMask ) { - __asm volatile( - " msr PRIMASK, r0 \n" - " bx lr " - ::: "memory" - ); + __asm volatile ( + " msr PRIMASK, r0 \n" + " bx lr " + ::: "memory" + ); } /*-----------------------------------------------------------*/ void xPortPendSVHandler( void ) { - /* This is a naked function. */ + /* This is a naked function. */ - __asm volatile - ( - " .syntax unified \n" - " mrs r0, psp \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " subs r0, r0, #32 \n" /* Make space for the remaining low registers. */ - " str r0, [r2] \n" /* Save the new top of stack. */ - " stmia r0!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ - " mov r4, r8 \n" /* Store the high registers. */ - " mov r5, r9 \n" - " mov r6, r10 \n" - " mov r7, r11 \n" - " stmia r0!, {r4-r7} \n" - " \n" - " push {r3, r14} \n" - " cpsid i \n" - " bl vTaskSwitchContext \n" - " cpsie i \n" - " pop {r2, r3} \n" /* lr goes in r3. r2 now holds tcb pointer. */ - " \n" - " ldr r1, [r2] \n" - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " adds r0, r0, #16 \n" /* Move to the high registers. */ - " ldmia r0!, {r4-r7} \n" /* Pop the high registers. */ - " mov r8, r4 \n" - " mov r9, r5 \n" - " mov r10, r6 \n" - " mov r11, r7 \n" - " \n" - " msr psp, r0 \n" /* Remember the new top of stack for the task. */ - " \n" - " subs r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ - " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ - " \n" - " bx r3 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB " - ); + __asm volatile + ( + " .syntax unified \n" + " mrs r0, psp \n" + " \n" + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " subs r0, r0, #32 \n"/* Make space for the remaining low registers. */ + " str r0, [r2] \n"/* Save the new top of stack. */ + " stmia r0!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */ + " mov r4, r8 \n"/* Store the high registers. */ + " mov r5, r9 \n" + " mov r6, r10 \n" + " mov r7, r11 \n" + " stmia r0!, {r4-r7} \n" + " \n" + " push {r3, r14} \n" + " cpsid i \n" + " bl vTaskSwitchContext \n" + " cpsie i \n" + " pop {r2, r3} \n"/* lr goes in r3. r2 now holds tcb pointer. */ + " \n" + " ldr r1, [r2] \n" + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " adds r0, r0, #16 \n"/* Move to the high registers. */ + " ldmia r0!, {r4-r7} \n"/* Pop the high registers. */ + " mov r8, r4 \n" + " mov r9, r5 \n" + " mov r10, r6 \n" + " mov r11, r7 \n" + " \n" + " msr psp, r0 \n"/* Remember the new top of stack for the task. */ + " \n" + " subs r0, r0, #32 \n"/* Go back for the low registers that are not automatically restored. */ + " ldmia r0!, {r4-r7} \n"/* Pop low registers. */ + " \n" + " bx r3 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB " + ); } /*-----------------------------------------------------------*/ void xPortSysTickHandler( void ) { -uint32_t ulPreviousMask; + 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_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); } /*-----------------------------------------------------------*/ @@ -372,189 +376,192 @@ uint32_t ulPreviousMask; * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +__attribute__( ( weak ) ) 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 */ + /* 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; + /* 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; + /* 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 ) +#if ( configUSE_TICKLESS_IDLE == 1 ) - __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; + __attribute__( ( 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; - } + /* 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; + /* 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; - } + /* 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 ) ); - /* Enter a critical section but don't use the taskENTER_CRITICAL() - method as that will mask interrupts that should exit sleep mode. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } - /* 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; + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* 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; - /* Reset the reload register to the value required for normal tick - periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts - see comments above the cpsid instruction() - above. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - /* Clear the SysTick count flag and set the count value back to - zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* 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 ) - { - __asm volatile( "dsb" ::: "memory" ); - __asm volatile( "wfi" ); - __asm volatile( "isb" ); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* 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. */ - __asm volatile( "cpsie i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + /* 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 ); - /* 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. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "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 ); + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - /* 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; + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); + /* 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. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); - } + /* 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 ); - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + /* 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; - /* 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; + /* 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 ); - /* How many complete tick periods passed while the processor - was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + /* 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 ); + } - /* The reload value is set to whatever fraction of a single tick - period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - /* 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; + /* 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; - /* Exit with interrpts enabled. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - } + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } #endif /* configUSE_TICKLESS_IDLE */ diff --git a/portable/GCC/ARM_CM0/portmacro.h b/portable/GCC/ARM_CM0/portmacro.h index 2e59a83dc..bd6e735e6 100644 --- a/portable/GCC/ARM_CM0/portmacro.h +++ b/portable/GCC/ARM_CM0/portmacro.h @@ -27,11 +27,11 @@ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*----------------------------------------------------------- * Port specific definitions. @@ -44,82 +44,81 @@ extern "C" { */ /* 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 + #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 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 + #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 +/* 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 -#define portDONT_DISCARD __attribute__(( used )) + #define portSTACK_GROWTH ( -1 ) + #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) + #define portBYTE_ALIGNMENT 8 + #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* Scheduler utilities. */ -extern void vPortYield( void ); -#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) ) -#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) -#define portYIELD() vPortYield() -#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT -#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) + extern void vPortYield( void ); + #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) + #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) + #define portYIELD() vPortYield() + #define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT + #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 ) __attribute__((naked)); -extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__((naked)); + extern void vPortEnterCritical( void ); + extern void vPortExitCritical( void ); + extern uint32_t ulSetInterruptMaskFromISR( void ) __attribute__( ( naked ) ); + extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__( ( naked ) ); -#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vClearInterruptMaskFromISR( 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() + #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMaskFromISR() + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMaskFromISR( 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() /*-----------------------------------------------------------*/ /* 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 + #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 portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) + #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) -#define portNOP() + #define portNOP() -#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ - diff --git a/portable/GCC/ARM_CM23/non_secure/port.c b/portable/GCC/ARM_CM23/non_secure/port.c index 8cd327dde..3f39bc3b1 100644 --- a/portable/GCC/ARM_CM23/non_secure/port.c +++ b/portable/GCC/ARM_CM23/non_secure/port.c @@ -22,6 +22,7 @@ * 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 diff --git a/portable/GCC/ARM_CM23/non_secure/portasm.c b/portable/GCC/ARM_CM23/non_secure/portasm.c index 1c649a182..d9eb31935 100644 --- a/portable/GCC/ARM_CM23/non_secure/portasm.c +++ b/portable/GCC/ARM_CM23/non_secure/portasm.c @@ -39,415 +39,415 @@ * header files. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if( configENABLE_FPU == 1 ) - #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. +#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 void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " \n" - " ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r3, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r5, #1 \n" /* r5 = 1. */ - " bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ - " str r4, [r2] \n" /* Disable MPU. */ - " \n" - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ - " ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */ - " ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r4, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ - " movs r5, #4 \n" /* r5 = 4. */ - " str r5, [r2] \n" /* Program RNR = 4. */ - " ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */ - " movs r5, #5 \n" /* r5 = 5. */ - " str r5, [r2] \n" /* Program RNR = 5. */ - " ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */ - " movs r5, #6 \n" /* r5 = 6. */ - " str r5, [r2] \n" /* Program RNR = 6. */ - " ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */ - " movs r5, #7 \n" /* r5 = 7. */ - " str r5, [r2] \n" /* Program RNR = 7. */ - " ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst2 \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */ - " \n" - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r5, #1 \n" /* r5 = 1. */ - " orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ - " str r4, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ - " ldr r5, xSecureContextConst2 \n" - " str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */ - " msr psplim, r2 \n" /* Set this task's PSPLIM value. */ - " msr control, r3 \n" /* Set this task's CONTROL value. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r4 \n" /* Finally, branch to EXC_RETURN. */ - #else /* configENABLE_MPU */ - " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ - " ldr r4, xSecureContextConst2 \n" - " str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ - " msr psplim, r2 \n" /* Set this task's PSPLIM value. */ - " movs r1, #2 \n" /* r1 = 2. */ - " msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r3 \n" /* Finally, branch to EXC_RETURN. */ - #endif /* configENABLE_MPU */ - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - "xSecureContextConst2: .word xSecureContext \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst2: .word 0xe000ed94 \n" - "xMAIR0Const2: .word 0xe000edc0 \n" - "xRNRConst2: .word 0xe000ed98 \n" - "xRBARConst2: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - ); + __asm volatile + ( + " .syntax unified \n" + " \n" + " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r3, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r5, #1 \n"/* r5 = 1. */ + " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ + " str r4, [r2] \n"/* Disable MPU. */ + " \n" + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ + " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ + " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r4, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ + " movs r5, #4 \n"/* r5 = 4. */ + " str r5, [r2] \n"/* Program RNR = 4. */ + " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */ + " movs r5, #5 \n"/* r5 = 5. */ + " str r5, [r2] \n"/* Program RNR = 5. */ + " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */ + " movs r5, #6 \n"/* r5 = 6. */ + " str r5, [r2] \n"/* Program RNR = 6. */ + " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */ + " movs r5, #7 \n"/* r5 = 7. */ + " str r5, [r2] \n"/* Program RNR = 7. */ + " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst2 \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */ + " \n" + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r5, #1 \n"/* r5 = 1. */ + " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ + " str r4, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ + " ldr r5, xSecureContextConst2 \n" + " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ + " msr psplim, r2 \n"/* Set this task's PSPLIM value. */ + " msr control, r3 \n"/* Set this task's CONTROL value. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r4 \n"/* Finally, branch to EXC_RETURN. */ + #else /* configENABLE_MPU */ + " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ + " ldr r4, xSecureContextConst2 \n" + " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ + " msr psplim, r2 \n"/* Set this task's PSPLIM value. */ + " movs r1, #2 \n"/* r1 = 2. */ + " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r3 \n"/* Finally, branch to EXC_RETURN. */ + #endif /* configENABLE_MPU */ + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + "xSecureContextConst2: .word xSecureContext \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst2: .word 0xe000ed94 \n" + "xMAIR0Const2: .word 0xe000edc0 \n" + "xRNRConst2: .word 0xe000ed98 \n" + "xRBARConst2: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ); } /*-----------------------------------------------------------*/ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " movs r1, #1 \n" /* r1 = 1. */ - " tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ - " beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */ - " movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " bx lr \n" /* Return. */ - " running_privileged: \n" - " movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n" /* Return. */ - " \n" - " .align 4 \n" - ::: "r0", "r1", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " movs r1, #1 \n"/* r1 = 1. */ + " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ + " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */ + " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " bx lr \n"/* Return. */ + " running_privileged: \n" + " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ + " \n" + " .align 4 \n" + ::: "r0", "r1", "memory" + ); } /*-----------------------------------------------------------*/ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, control \n" /* Read the CONTROL register. */ - " movs r1, #1 \n" /* r1 = 1. */ - " bics r0, r1 \n" /* Clear the bit 0. */ - " msr control, r0 \n" /* Write back the new CONTROL value. */ - " bx lr \n" /* Return to the caller. */ - ::: "r0", "r1", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* Read the CONTROL register. */ + " movs r1, #1 \n"/* r1 = 1. */ + " bics r0, r1 \n"/* Clear the bit 0. */ + " msr control, r0 \n"/* Write back the new CONTROL value. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "r1", "memory" + ); } /*-----------------------------------------------------------*/ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " movs r1, #1 \n" /* r1 = 1. */ - " orrs r0, r1 \n" /* r0 = r0 | r1. */ - " msr control, r0 \n" /* CONTROL = r0. */ - " bx lr \n" /* Return to the caller. */ - :::"r0", "r1", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " movs r1, #1 \n"/* r1 = 1. */ + " orrs r0, r1 \n"/* r0 = r0 | r1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "r1", "memory" + ); } /*-----------------------------------------------------------*/ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */ - " ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ - " msr msp, r0 \n" /* Set the MSP back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " dsb \n" - " isb \n" - " svc %0 \n" /* System call to start the first task. */ - " nop \n" - " \n" - " .align 4 \n" - "xVTORConst: .word 0xe000ed08 \n" - :: "i" ( portSVC_START_SCHEDULER ) : "memory" - ); + __asm volatile + ( + " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ + " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ + " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ + " dsb \n" + " isb \n" + " svc %0 \n"/* System call to start the first task. */ + " nop \n" + " \n" + " .align 4 \n" + "xVTORConst: .word 0xe000ed08 \n" + ::"i" ( portSVC_START_SCHEDULER ) : "memory" + ); } /*-----------------------------------------------------------*/ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, PRIMASK \n" - " cpsid i \n" - " bx lr \n" - ::: "memory" - ); + __asm volatile + ( + " mrs r0, PRIMASK \n" + " cpsid i \n" + " bx lr \n" + ::: "memory" + ); } /*-----------------------------------------------------------*/ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " msr PRIMASK, r0 \n" - " bx lr \n" - ::: "memory" - ); + __asm volatile + ( + " msr PRIMASK, r0 \n" + " bx lr \n" + ::: "memory" + ); } /*-----------------------------------------------------------*/ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " .extern SecureContext_SaveContext \n" - " .extern SecureContext_LoadContext \n" - " \n" - " mrs r1, psp \n" /* Read PSP in r1. */ - " ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ - " ldr r0, [r2] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ - " \n" - " cbz r0, save_ns_context \n" /* No secure context to save. */ - " push {r0-r2, r14} \n" - " bl SecureContext_SaveContext \n" - " pop {r0-r3} \n" /* LR is now in r3. */ - " mov lr, r3 \n" /* LR = r3. */ - " lsls r2, r3, #25 \n" /* 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 \n" /* 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, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r2, [r3] \n" /* Read pxCurrentTCB. */ - #if( configENABLE_MPU == 1 ) - " subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mrs r3, control \n" /* r3 = CONTROL. */ - " mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ - " stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ - #else /* configENABLE_MPU */ - " subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */ - #endif /* configENABLE_MPU */ - " b select_next_task \n" - " \n" - " save_ns_context: \n" - " ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r2, [r3] \n" /* Read pxCurrentTCB. */ - #if( configENABLE_MPU == 1 ) - " subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " adds r1, r1, #16 \n" /* r1 = r1 + 16. */ - " stmia r1!, {r4-r7} \n" /* Store the low registers that are not saved automatically. */ - " mov r4, r8 \n" /* r4 = r8. */ - " mov r5, r9 \n" /* r5 = r9. */ - " mov r6, r10 \n" /* r6 = r10. */ - " mov r7, r11 \n" /* r7 = r11. */ - " stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mrs r3, control \n" /* r3 = CONTROL. */ - " mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ - " subs r1, r1, #48 \n" /* r1 = r1 - 48. */ - " stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ - #else /* configENABLE_MPU */ - " subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " stmia r1!, {r0, r2-r7} \n" /* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */ - " mov r4, r8 \n" /* r4 = r8. */ - " mov r5, r9 \n" /* r5 = r9. */ - " mov r6, r10 \n" /* r6 = r10. */ - " mov r7, r11 \n" /* r7 = r11. */ - " stmia r1!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ - #endif /* configENABLE_MPU */ - " \n" - " select_next_task: \n" - " cpsid i \n" - " bl vTaskSwitchContext \n" - " cpsie i \n" - " \n" - " ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r3, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r5, #1 \n" /* r5 = 1. */ - " bics r4, r5 \n" /* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ - " str r4, [r2] \n" /* Disable MPU. */ - " \n" - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ - " ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */ - " ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r4, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ - " movs r5, #4 \n" /* r5 = 4. */ - " str r5, [r2] \n" /* Program RNR = 4. */ - " ldmia r3!, {r6,r7} \n" /* Read first set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write first set of RBAR/RLAR registers. */ - " movs r5, #5 \n" /* r5 = 5. */ - " str r5, [r2] \n" /* Program RNR = 5. */ - " ldmia r3!, {r6,r7} \n" /* Read second set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write second set of RBAR/RLAR registers. */ - " movs r5, #6 \n" /* r5 = 6. */ - " str r5, [r2] \n" /* Program RNR = 6. */ - " ldmia r3!, {r6,r7} \n" /* Read third set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write third set of RBAR/RLAR registers. */ - " movs r5, #7 \n" /* r5 = 7. */ - " str r5, [r2] \n" /* Program RNR = 7. */ - " ldmia r3!, {r6,r7} \n" /* Read fourth set of RBAR/RLAR from TCB. */ - " ldr r4, xRBARConst \n" /* r4 = 0xe000ed9c [Location of RBAR]. */ - " stmia r4!, {r6,r7} \n" /* Write fourth set of RBAR/RLAR registers. */ - " \n" - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r5, #1 \n" /* r5 = 1. */ - " orrs r4, r5 \n" /* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ - " str r4, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */ - " msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ - " msr control, r3 \n" /* Restore the CONTROL register value for the task. */ - " mov lr, r4 \n" /* LR = r4. */ - " ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ - " str r0, [r2] \n" /* Restore the task's xSecureContext. */ - " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ - " push {r1,r4} \n" - " bl SecureContext_LoadContext \n" /* Restore the secure context. */ - " pop {r1,r4} \n" - " mov lr, r4 \n" /* LR = r4. */ - " lsls r2, r4, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */ - " bx lr \n" - #else /* configENABLE_MPU */ - " ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */ - " msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ - " mov lr, r3 \n" /* LR = r3. */ - " ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ - " str r0, [r2] \n" /* Restore the task's xSecureContext. */ - " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ - " push {r1,r3} \n" - " bl SecureContext_LoadContext \n" /* Restore the secure context. */ - " pop {r1,r3} \n" - " mov lr, r3 \n" /* LR = r3. */ - " lsls r2, r3, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */ - " bx lr \n" - #endif /* configENABLE_MPU */ - " \n" - " restore_ns_context: \n" - " adds r1, r1, #16 \n" /* Move to the high registers. */ - " ldmia r1!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ - " mov r8, r4 \n" /* r8 = r4. */ - " mov r9, r5 \n" /* r9 = r5. */ - " mov r10, r6 \n" /* r10 = r6. */ - " mov r11, r7 \n" /* r11 = r7. */ - " msr psp, r1 \n" /* Remember the new top of stack for the task. */ - " subs r1, r1, #32 \n" /* Go back to the low registers. */ - " ldmia r1!, {r4-r7} \n" /* Restore the low registers that are not automatically restored. */ - " bx lr \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - "xSecureContextConst: .word xSecureContext \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst: .word 0xe000ed94 \n" - "xMAIR0Const: .word 0xe000edc0 \n" - "xRNRConst: .word 0xe000ed98 \n" - "xRBARConst: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - ); + __asm volatile + ( + " .syntax unified \n" + " .extern SecureContext_SaveContext \n" + " .extern SecureContext_LoadContext \n" + " \n" + " mrs r1, psp \n"/* Read PSP in r1. */ + " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ + " ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ + " \n" + " cbz r0, save_ns_context \n"/* No secure context to save. */ + " push {r0-r2, r14} \n" + " bl SecureContext_SaveContext \n" + " pop {r0-r3} \n"/* LR is now in r3. */ + " mov lr, r3 \n"/* LR = r3. */ + " lsls r2, r3, #25 \n"/* 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 \n"/* 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, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r2, [r3] \n"/* Read pxCurrentTCB. */ + #if ( configENABLE_MPU == 1 ) + " subs r1, r1, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mrs r3, control \n"/* r3 = CONTROL. */ + " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ + " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ + #else /* configENABLE_MPU */ + " subs r1, r1, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ + #endif /* configENABLE_MPU */ + " b select_next_task \n" + " \n" + " save_ns_context: \n" + " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r2, [r3] \n"/* Read pxCurrentTCB. */ + #if ( configENABLE_MPU == 1 ) + " subs r1, r1, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " adds r1, r1, #16 \n"/* r1 = r1 + 16. */ + " stmia r1!, {r4-r7} \n"/* Store the low registers that are not saved automatically. */ + " mov r4, r8 \n"/* r4 = r8. */ + " mov r5, r9 \n"/* r5 = r9. */ + " mov r6, r10 \n"/* r6 = r10. */ + " mov r7, r11 \n"/* r7 = r11. */ + " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mrs r3, control \n"/* r3 = CONTROL. */ + " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ + " subs r1, r1, #48 \n"/* r1 = r1 - 48. */ + " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ + #else /* configENABLE_MPU */ + " subs r1, r1, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " stmia r1!, {r0, r2-r7} \n"/* Store xSecureContext, PSPLIM, LR and the low registers that are not saved automatically. */ + " mov r4, r8 \n"/* r4 = r8. */ + " mov r5, r9 \n"/* r5 = r9. */ + " mov r6, r10 \n"/* r6 = r10. */ + " mov r7, r11 \n"/* r7 = r11. */ + " stmia r1!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ + #endif /* configENABLE_MPU */ + " \n" + " select_next_task: \n" + " cpsid i \n" + " bl vTaskSwitchContext \n" + " cpsie i \n" + " \n" + " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r3, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r5, #1 \n"/* r5 = 1. */ + " bics r4, r5 \n"/* r4 = r4 & ~r5 i.e. Clear the bit 0 in r4. */ + " str r4, [r2] \n"/* Disable MPU. */ + " \n" + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ + " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ + " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r4, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ + " movs r5, #4 \n"/* r5 = 4. */ + " str r5, [r2] \n"/* Program RNR = 4. */ + " ldmia r3!, {r6,r7} \n"/* Read first set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write first set of RBAR/RLAR registers. */ + " movs r5, #5 \n"/* r5 = 5. */ + " str r5, [r2] \n"/* Program RNR = 5. */ + " ldmia r3!, {r6,r7} \n"/* Read second set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write second set of RBAR/RLAR registers. */ + " movs r5, #6 \n"/* r5 = 6. */ + " str r5, [r2] \n"/* Program RNR = 6. */ + " ldmia r3!, {r6,r7} \n"/* Read third set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write third set of RBAR/RLAR registers. */ + " movs r5, #7 \n"/* r5 = 7. */ + " str r5, [r2] \n"/* Program RNR = 7. */ + " ldmia r3!, {r6,r7} \n"/* Read fourth set of RBAR/RLAR from TCB. */ + " ldr r4, xRBARConst \n"/* r4 = 0xe000ed9c [Location of RBAR]. */ + " stmia r4!, {r6,r7} \n"/* Write fourth set of RBAR/RLAR registers. */ + " \n" + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r5, #1 \n"/* r5 = 1. */ + " orrs r4, r5 \n"/* r4 = r4 | r5 i.e. Set the bit 0 in r4. */ + " str r4, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " ldmia r1!, {r0, r2-r4} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */ + " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ + " msr control, r3 \n"/* Restore the CONTROL register value for the task. */ + " mov lr, r4 \n"/* LR = r4. */ + " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ + " str r0, [r2] \n"/* Restore the task's xSecureContext. */ + " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ + " push {r1,r4} \n" + " bl SecureContext_LoadContext \n"/* Restore the secure context. */ + " pop {r1,r4} \n" + " mov lr, r4 \n"/* LR = r4. */ + " lsls r2, r4, #25 \n"/* 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 \n"/* 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 \n"/* Remember the new top of stack for the task. */ + " bx lr \n" + #else /* configENABLE_MPU */ + " ldmia r1!, {r0, r2-r3} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */ + " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ + " mov lr, r3 \n"/* LR = r3. */ + " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ + " str r0, [r2] \n"/* Restore the task's xSecureContext. */ + " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ + " push {r1,r3} \n" + " bl SecureContext_LoadContext \n"/* Restore the secure context. */ + " pop {r1,r3} \n" + " mov lr, r3 \n"/* LR = r3. */ + " lsls r2, r3, #25 \n"/* 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 \n"/* 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 \n"/* Remember the new top of stack for the task. */ + " bx lr \n" + #endif /* configENABLE_MPU */ + " \n" + " restore_ns_context: \n" + " adds r1, r1, #16 \n"/* Move to the high registers. */ + " ldmia r1!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ + " mov r8, r4 \n"/* r8 = r4. */ + " mov r9, r5 \n"/* r9 = r5. */ + " mov r10, r6 \n"/* r10 = r6. */ + " mov r11, r7 \n"/* r11 = r7. */ + " msr psp, r1 \n"/* Remember the new top of stack for the task. */ + " subs r1, r1, #32 \n"/* Go back to the low registers. */ + " ldmia r1!, {r4-r7} \n"/* Restore the low registers that are not automatically restored. */ + " bx lr \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + "xSecureContextConst: .word xSecureContext \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst: .word 0xe000ed94 \n" + "xMAIR0Const: .word 0xe000edc0 \n" + "xRNRConst: .word 0xe000ed98 \n" + "xRBARConst: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ); } /*-----------------------------------------------------------*/ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " movs r0, #4 \n" - " mov r1, lr \n" - " tst r0, r1 \n" - " beq stacking_used_msp \n" - " mrs r0, psp \n" - " ldr r2, svchandler_address_const \n" - " bx r2 \n" - " stacking_used_msp: \n" - " mrs r0, msp \n" - " ldr r2, svchandler_address_const \n" - " bx r2 \n" - " \n" - " .align 4 \n" - "svchandler_address_const: .word vPortSVCHandler_C \n" - ); + __asm volatile + ( + " movs r0, #4 \n" + " mov r1, lr \n" + " tst r0, r1 \n" + " beq stacking_used_msp \n" + " mrs r0, psp \n" + " ldr r2, svchandler_address_const \n" + " bx r2 \n" + " stacking_used_msp: \n" + " mrs r0, msp \n" + " ldr r2, svchandler_address_const \n" + " bx r2 \n" + " \n" + " .align 4 \n" + "svchandler_address_const: .word vPortSVCHandler_C \n" + ); } /*-----------------------------------------------------------*/ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " svc %0 \n" /* Secure context is allocated in the supervisor call. */ - " bx lr \n" /* Return. */ - :: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" - ); + __asm volatile + ( + " svc %0 \n"/* Secure context is allocated in the supervisor call. */ + " bx lr \n"/* Return. */ + ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" + ); } /*-----------------------------------------------------------*/ -void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ +void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */ - " ldr r0, [r1] \n" /* The first item on the stack is the task's xSecureContext. */ - " cmp r0, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */ - " beq free_secure_context \n" - " bx lr \n" /* There is no secure context (xSecureContext is NULL). */ - " free_secure_context: \n" - " svc %0 \n" /* Secure context is freed in the supervisor call. */ - " bx lr \n" /* Return. */ - :: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" - ); + __asm volatile + ( + " ldr r1, [r0] \n"/* The first item in the TCB is the top of the stack. */ + " ldr r0, [r1] \n"/* The first item on the stack is the task's xSecureContext. */ + " cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ + " beq free_secure_context \n" + " bx lr \n"/* There is no secure context (xSecureContext is NULL). */ + " free_secure_context: \n" + " svc %0 \n"/* Secure context is freed in the supervisor call. */ + " bx lr \n"/* Return. */ + ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" + ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/non_secure/portasm.h b/portable/GCC/ARM_CM23/non_secure/portasm.h index 71d711c69..fdba1b177 100644 --- a/portable/GCC/ARM_CM23/non_secure/portasm.h +++ b/portable/GCC/ARM_CM23/non_secure/portasm.h @@ -38,14 +38,14 @@ * @brief Restore the context of the first task so that the first task starts * executing. */ -void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +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 )); +BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); /** * @brief Raises the privilege level by clearing the bit 0 of the CONTROL @@ -58,7 +58,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Lowers the privilege level by setting the bit 0 of the CONTROL @@ -68,32 +68,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vResetPrivilege( void ) __attribute__ (( naked )); +void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Starts the first task. */ -void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Disables interrupts. */ -uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Enables interrupts. */ -void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief PendSV Exception handler. */ -void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief SVC Handler. */ -void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Allocate a Secure context for the calling task. @@ -101,13 +101,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * @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 )); +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; +void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; #endif /* __PORT_ASM_H__ */ diff --git a/portable/GCC/ARM_CM23/non_secure/portmacro.h b/portable/GCC/ARM_CM23/non_secure/portmacro.h index 2e8bba256..747cdc766 100644 --- a/portable/GCC/ARM_CM23/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM23/non_secure/portmacro.h @@ -26,11 +26,11 @@ */ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*------------------------------------------------------------------------------ * Port specific definitions. @@ -42,109 +42,109 @@ extern "C" { *------------------------------------------------------------------------------ */ -#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_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_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 */ + #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 + #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 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 + #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 +/* 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 __attribute__(( used )) + #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 __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ -extern BaseType_t xPortIsInsideInterrupt( void ); + extern BaseType_t xPortIsInsideInterrupt( void ); -extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; + extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortExitCritical( 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 */; + 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_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 */ + #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 */ + #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. */ + #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. * @@ -156,155 +156,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * 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 */ + #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. */ + #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_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_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 ) + #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; + 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; + 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 + #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 ) + #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() + #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 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 + #ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + #endif /*-----------------------------------------------------------*/ /** * @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 ) + #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 ) + #if ( configENABLE_TRUSTZONE == 1 ) - /** - * @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 */ +/** + * @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() + #if ( configENABLE_MPU == 1 ) - /** - * @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 Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ + #define portIS_PRIVILEGED() xIsPrivileged() - /** - * @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 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" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM23/secure/secure_context.c b/portable/GCC/ARM_CM23/secure/secure_context.c index 39fabbf60..5608c7240 100644 --- a/portable/GCC/ARM_CM23/secure/secure_context.c +++ b/portable/GCC/ARM_CM23/secure/secure_context.c @@ -40,7 +40,7 @@ * Bit[0] - 0 --> Thread mode is privileged. * Bit[1] - 1 --> Thread mode uses PSP. */ -#define securecontextCONTROL_VALUE_PRIVILEGED 0x02 +#define securecontextCONTROL_VALUE_PRIVILEGED 0x02 /** * @brief CONTROL value for un-privileged tasks. @@ -48,7 +48,7 @@ * Bit[0] - 1 --> Thread mode is un-privileged. * Bit[1] - 1 --> Thread mode uses PSP. */ -#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03 +#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03 /*-----------------------------------------------------------*/ /** @@ -59,146 +59,148 @@ */ 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. */ + 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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); + /* 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 ) + { + /* 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 ) +#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 ) + 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 */ + uint8_t * pucStackMemory = NULL; + uint32_t ulIPSR; + SecureContextHandle_t xSecureContextHandle = NULL; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( ulIPSR ); + #if ( configENABLE_MPU == 1 ) + uint32_t * pulCurrentStackPointer = NULL; + #endif /* configENABLE_MPU */ - /* 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 ) ); + /* Read the Interrupt Program Status Register (IPSR) value. */ + secureportREAD_IPSR( ulIPSR ); - if( xSecureContextHandle != NULL ) - { - /* Allocate the stack space. */ - pucStackMemory = pvPortMalloc( ulSecureStackSize ); + /* 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( 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; + if( xSecureContextHandle != NULL ) + { + /* Allocate the stack space. */ + pucStackMemory = pvPortMalloc( ulSecureStackSize ); - /* The stack cannot go beyond this location. This value is - * programmed in the PSPLIM register on context switch.*/ - xSecureContextHandle->pucStackLimit = pucStackMemory; + 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; - #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; - } + /* The stack cannot go beyond this location. This value is + * programmed in the PSPLIM register on context switch.*/ + xSecureContextHandle->pucStackLimit = pucStackMemory; - /* 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; + #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--; - } - #endif /* configENABLE_MPU */ - } - else - { - /* Free the context to avoid memory leak and make sure to return - * NULL to indicate failure. */ - vPortFree( xSecureContextHandle ); - xSecureContextHandle = NULL; - } - } - } + if( ulIsTaskPrivileged ) + { + *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED; + } + else + { + *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED; + } - return xSecureContextHandle; + /* 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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); + /* 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 stack space. */ + vPortFree( xSecureContextHandle->pucStackLimit ); - /* Free the context itself. */ - vPortFree( xSecureContextHandle ); - } + /* Free the context itself. */ + vPortFree( xSecureContextHandle ); + } } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/secure/secure_context.h b/portable/GCC/ARM_CM23/secure/secure_context.h index 747c2c6fd..62ef6bb94 100644 --- a/portable/GCC/ARM_CM23/secure/secure_context.h +++ b/portable/GCC/ARM_CM23/secure/secure_context.h @@ -37,13 +37,13 @@ /** * @brief PSP value when no task's context is loaded. */ -#define securecontextNO_STACK 0x0 +#define securecontextNO_STACK 0x0 /** * @brief Opaque handle. */ struct SecureContext; -typedef struct SecureContext* SecureContextHandle_t; +typedef struct SecureContext * SecureContextHandle_t; /*-----------------------------------------------------------*/ /** @@ -69,10 +69,11 @@ void SecureContext_Init( void ); * @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 ); +#if ( configENABLE_MPU == 1 ) + SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, + uint32_t ulIsTaskPrivileged ); #else /* configENABLE_MPU */ - SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ); + SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ); #endif /* configENABLE_MPU */ /** diff --git a/portable/GCC/ARM_CM23/secure/secure_context_port.c b/portable/GCC/ARM_CM23/secure/secure_context_port.c index 616cfd78e..d7ef92b12 100644 --- a/portable/GCC/ARM_CM23/secure/secure_context_port.c +++ b/portable/GCC/ARM_CM23/secure/secure_context_port.c @@ -31,61 +31,61 @@ /* Secure port macros. */ #include "secure_port_macros.h" -#if( configENABLE_FPU == 1 ) - #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. +#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 secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle ) { - /* xSecureContextHandle value is in r0. */ - __asm volatile - ( - " .syntax unified \n" - " \n" - " mrs r1, ipsr \n" /* r1 = IPSR. */ - " cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ - " ldmia r0!, {r1, r2} \n" /* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */ - #if( configENABLE_MPU == 1 ) - " ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */ - " msr control, r3 \n" /* CONTROL = r3. */ - #endif /* configENABLE_MPU */ - " msr psplim, r2 \n" /* PSPLIM = r2. */ - " msr psp, r1 \n" /* PSP = r1. */ - " \n" - " load_ctx_therad_mode: \n" - " nop \n" - " \n" - :::"r0", "r1", "r2" - ); + /* xSecureContextHandle value is in r0. */ + __asm volatile + ( + " .syntax unified \n" + " \n" + " mrs r1, ipsr \n"/* r1 = IPSR. */ + " cbz r1, load_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */ + " ldmia r0!, {r1, r2} \n"/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */ + #if ( configENABLE_MPU == 1 ) + " ldmia r1!, {r3} \n"/* Read CONTROL register value from task's stack. r3 = CONTROL. */ + " msr control, r3 \n"/* CONTROL = r3. */ + #endif /* configENABLE_MPU */ + " msr psplim, r2 \n"/* PSPLIM = r2. */ + " msr psp, r1 \n"/* PSP = r1. */ + " \n" + " load_ctx_therad_mode: \n" + " nop \n" + " \n" + ::: "r0", "r1", "r2" + ); } /*-----------------------------------------------------------*/ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle ) { - /* xSecureContextHandle value is in r0. */ - __asm volatile - ( - " .syntax unified \n" - " \n" - " mrs r1, ipsr \n" /* r1 = IPSR. */ - " cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ - " mrs r1, psp \n" /* r1 = PSP. */ - #if( configENABLE_MPU == 1 ) - " mrs r2, control \n" /* r2 = CONTROL. */ - " subs r1, r1, #4 \n" /* Make space for the CONTROL value on the stack. */ - " str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ - " stmia r1!, {r2} \n" /* Store CONTROL value on the stack. */ - #else /* configENABLE_MPU */ - " str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ - #endif /* configENABLE_MPU */ - " movs r1, %0 \n" /* r1 = securecontextNO_STACK. */ - " msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */ - " msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */ - " \n" - " save_ctx_therad_mode: \n" - " nop \n" - " \n" - :: "i" ( securecontextNO_STACK ) : "r1", "memory" - ); + /* xSecureContextHandle value is in r0. */ + __asm volatile + ( + " .syntax unified \n" + " \n" + " mrs r1, ipsr \n"/* r1 = IPSR. */ + " cbz r1, save_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */ + " mrs r1, psp \n"/* r1 = PSP. */ + #if ( configENABLE_MPU == 1 ) + " mrs r2, control \n"/* r2 = CONTROL. */ + " subs r1, r1, #4 \n"/* Make space for the CONTROL value on the stack. */ + " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ + " stmia r1!, {r2} \n"/* Store CONTROL value on the stack. */ + #else /* configENABLE_MPU */ + " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ + #endif /* configENABLE_MPU */ + " movs r1, %0 \n"/* r1 = securecontextNO_STACK. */ + " msr psplim, r1 \n"/* PSPLIM = securecontextNO_STACK. */ + " msr psp, r1 \n"/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */ + " \n" + " save_ctx_therad_mode: \n" + " nop \n" + " \n" + ::"i" ( securecontextNO_STACK ) : "r1", "memory" + ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/secure/secure_heap.c b/portable/GCC/ARM_CM23/secure/secure_heap.c index 7995a7f12..76b6ee1c3 100644 --- a/portable/GCC/ARM_CM23/secure/secure_heap.c +++ b/portable/GCC/ARM_CM23/secure/secure_heap.c @@ -37,37 +37,38 @@ /** * @brief Total heap size. */ -#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) ) +#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) ) /* No test marker by default. */ #ifndef mtCOVERAGE_TEST_MARKER - #define mtCOVERAGE_TEST_MARKER() + #define mtCOVERAGE_TEST_MARKER() #endif /* No tracing by default. */ #ifndef traceMALLOC - #define traceMALLOC( pvReturn, xWantedSize ) + #define traceMALLOC( pvReturn, xWantedSize ) #endif /* No tracing by default. */ #ifndef traceFREE - #define traceFREE( pv, xBlockSize ) + #define traceFREE( pv, xBlockSize ) #endif /* Block sizes must not get too small. */ -#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) +#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) /* Assumes 8bit bytes! */ -#define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) +#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 ]; +#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 ]; + static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ]; #endif /* configAPPLICATION_ALLOCATED_HEAP */ /** @@ -77,8 +78,8 @@ */ 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. */ + struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */ + size_t xBlockSize; /**< The size of the free block. */ } BlockLink_t; /*-----------------------------------------------------------*/ @@ -97,7 +98,7 @@ static void prvHeapInit( void ); * * @param[in] pxBlockToInsert The block being freed. */ -static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ); /*-----------------------------------------------------------*/ /** @@ -109,7 +110,7 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( s /** * @brief Create a couple of list links to mark the start and end of the list. */ -static BlockLink_t xStart, *pxEnd = NULL; +static BlockLink_t xStart, * pxEnd = NULL; /** * @brief Keeps track of the number of free bytes remaining, but says nothing @@ -130,321 +131,324 @@ static size_t xBlockAllocatedBit = 0; static void prvHeapInit( void ) { -BlockLink_t *pxFirstFreeBlock; -uint8_t *pucAlignedHeap; -size_t uxAddress; -size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE; + 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; + /* 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; - } + 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; + 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; + /* 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; + /* 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; + /* 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; + /* 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 ); + /* 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 ) +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) { -BlockLink_t *pxIterator; -uint8_t *puc; + 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. */ - } + /* 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 after + * make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; - /* 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( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* 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(); - } + /* 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 ) +void * pvPortMalloc( size_t xWantedSize ) { -BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; -void *pvReturn = NULL; + 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(); - } + /* 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; + /* 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(); - } + /* 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( ( 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; - /* 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 ); + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } - /* This block is being returned for use so must be taken out - * of the list of free blocks. */ - pxPreviousBlock->pxNextFreeBlock = 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 ); - /* 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 ); + /* This block is being returned for use so must be taken out + * of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; - /* Calculate the sizes of two blocks split from the single - * block. */ - pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; - pxBlock->xBlockSize = xWantedSize; + /* 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 ); - /* Insert the new block into the list of free blocks. */ - prvInsertBlockIntoFreeList( pxNewBlockLink ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Calculate the sizes of two blocks split from the single + * block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; - xFreeBytesRemaining -= pxBlock->xBlockSize; + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( pxNewBlockLink ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) - { - xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + xFreeBytesRemaining -= pxBlock->xBlockSize; - /* 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(); - } + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - traceMALLOC( pvReturn, xWantedSize ); + /* 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(); + } - #if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) - { - if( pvReturn == NULL ) - { - extern void vApplicationMallocFailedHook( void ); - vApplicationMallocFailedHook(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif + traceMALLOC( pvReturn, xWantedSize ); - secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 ); - return pvReturn; + #if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */ + + secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 ); + return pvReturn; } /*-----------------------------------------------------------*/ -void vPortFree( void *pv ) +void vPortFree( void * pv ) { -uint8_t *puc = ( uint8_t * ) pv; -BlockLink_t *pxLink; + 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; + 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; + /* 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 ); + /* 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; + 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(); - } - } + 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; + return xFreeBytesRemaining; } /*-----------------------------------------------------------*/ size_t xPortGetMinimumEverFreeHeapSize( void ) { - return xMinimumEverFreeBytesRemaining; + return xMinimumEverFreeBytesRemaining; } /*-----------------------------------------------------------*/ void vPortInitialiseBlocks( void ) { - /* This just exists to keep the linker quiet. */ + /* This just exists to keep the linker quiet. */ } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/secure/secure_heap.h b/portable/GCC/ARM_CM23/secure/secure_heap.h index aa67e39d8..d5ddaa853 100644 --- a/portable/GCC/ARM_CM23/secure/secure_heap.h +++ b/portable/GCC/ARM_CM23/secure/secure_heap.h @@ -39,13 +39,13 @@ * @return Pointer to the memory region if the allocation is successful, NULL * otherwise. */ -void *pvPortMalloc( size_t xWantedSize ); +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 ); +void vPortFree( void * pv ); #endif /* __SECURE_HEAP_H__ */ diff --git a/portable/GCC/ARM_CM23/secure/secure_init.c b/portable/GCC/ARM_CM23/secure/secure_init.c index 629186130..6f0be2547 100644 --- a/portable/GCC/ARM_CM23/secure/secure_init.c +++ b/portable/GCC/ARM_CM23/secure/secure_init.c @@ -37,69 +37,69 @@ /** * @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 ) +#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 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 ) +#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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); - } + /* 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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); + /* 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 ); + /* 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 ); - } + /* 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 ); + } } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/secure/secure_port_macros.h b/portable/GCC/ARM_CM23/secure/secure_port_macros.h index 14ed3f022..d0ace6242 100644 --- a/portable/GCC/ARM_CM23/secure/secure_port_macros.h +++ b/portable/GCC/ARM_CM23/secure/secure_port_macros.h @@ -31,103 +31,103 @@ /** * @brief Byte alignment requirements. */ -#define secureportBYTE_ALIGNMENT 8 -#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 ) +#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 + #define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root #else - #define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used)) + #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" ) + __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" ) + __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 ) ) + __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 ) ) + __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 ) ) + __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 ) ) + __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" ) + __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 ) ) + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) ) /** * @brief PRIMASK value to enable interrupts. */ -#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0 +#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0 /** * @brief PRIMASK value to disable interrupts. */ -#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1 +#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1 /** * @brief Disable secure interrupts. */ -#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL ) +#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 ) +#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 ) +#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( ;; ); \ - } +#define secureportASSERT( x ) \ + if( ( x ) == 0 ) \ + { \ + secureportDISABLE_SECURE_INTERRUPTS(); \ + secureportDISABLE_NON_SECURE_INTERRUPTS(); \ + for( ; ; ) {; } \ + } #endif /* __SECURE_PORT_MACROS_H__ */ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c b/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c index a34ef5185..cf57e6e91 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.c @@ -39,328 +39,328 @@ * header files. */ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -#if( configENABLE_FPU == 1 ) - #error Cortex-M23 does not have a Floating Point Unit (FPU) and therefore configENABLE_FPU must be set to 0. +#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 void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " \n" - " ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r1, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r4, #1 \n" /* r4 = 1. */ - " bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ - " \n" - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ - " ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */ - " ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r4, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ - " movs r4, #4 \n" /* r4 = 4. */ - " str r4, [r2] \n" /* Program RNR = 4. */ - " ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */ - " movs r4, #5 \n" /* r4 = 5. */ - " str r4, [r2] \n" /* Program RNR = 5. */ - " ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */ - " movs r4, #6 \n" /* r4 = 6. */ - " str r4, [r2] \n" /* Program RNR = 6. */ - " ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */ - " movs r4, #7 \n" /* r4 = 7. */ - " str r4, [r2] \n" /* Program RNR = 7. */ - " ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst2 \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */ - " \n" - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r4, #1 \n" /* r4 = 1. */ - " orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ - " msr psplim, r1 \n" /* Set this task's PSPLIM value. */ - " msr control, r2 \n" /* Set this task's CONTROL value. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r3 \n" /* Finally, branch to EXC_RETURN. */ - #else /* configENABLE_MPU */ - " ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ - " msr psplim, r1 \n" /* Set this task's PSPLIM value. */ - " movs r1, #2 \n" /* r1 = 2. */ - " msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r2 \n" /* Finally, branch to EXC_RETURN. */ - #endif /* configENABLE_MPU */ - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst2: .word 0xe000ed94 \n" - "xMAIR0Const2: .word 0xe000edc0 \n" - "xRNRConst2: .word 0xe000ed98 \n" - "xRBARConst2: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - ); + __asm volatile + ( + " .syntax unified \n" + " \n" + " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r1, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r4, #1 \n"/* r4 = 1. */ + " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ + " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ + " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r4, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ + " movs r4, #4 \n"/* r4 = 4. */ + " str r4, [r2] \n"/* Program RNR = 4. */ + " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */ + " movs r4, #5 \n"/* r4 = 5. */ + " str r4, [r2] \n"/* Program RNR = 5. */ + " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */ + " movs r4, #6 \n"/* r4 = 6. */ + " str r4, [r2] \n"/* Program RNR = 6. */ + " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */ + " movs r4, #7 \n"/* r4 = 7. */ + " str r4, [r2] \n"/* Program RNR = 7. */ + " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst2 \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */ + " \n" + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r4, #1 \n"/* r4 = 1. */ + " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ + " msr psplim, r1 \n"/* Set this task's PSPLIM value. */ + " msr control, r2 \n"/* Set this task's CONTROL value. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r3 \n"/* Finally, branch to EXC_RETURN. */ + #else /* configENABLE_MPU */ + " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ + " msr psplim, r1 \n"/* Set this task's PSPLIM value. */ + " movs r1, #2 \n"/* r1 = 2. */ + " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r2 \n"/* Finally, branch to EXC_RETURN. */ + #endif /* configENABLE_MPU */ + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst2: .word 0xe000ed94 \n" + "xMAIR0Const2: .word 0xe000edc0 \n" + "xRNRConst2: .word 0xe000ed98 \n" + "xRBARConst2: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ); } /*-----------------------------------------------------------*/ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " movs r1, #1 \n" /* r1 = 1. */ - " tst r0, r1 \n" /* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ - " beq running_privileged \n" /* If the result of previous AND operation was 0, branch. */ - " movs r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " bx lr \n" /* Return. */ - " running_privileged: \n" - " movs r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n" /* Return. */ - " \n" - " .align 4 \n" - ::: "r0", "r1", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " movs r1, #1 \n"/* r1 = 1. */ + " tst r0, r1 \n"/* Perform r0 & r1 (bitwise AND) and update the conditions flag. */ + " beq running_privileged \n"/* If the result of previous AND operation was 0, branch. */ + " movs r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " bx lr \n"/* Return. */ + " running_privileged: \n" + " movs r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ + " \n" + " .align 4 \n" + ::: "r0", "r1", "memory" + ); } /*-----------------------------------------------------------*/ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, control \n" /* Read the CONTROL register. */ - " movs r1, #1 \n" /* r1 = 1. */ - " bics r0, r1 \n" /* Clear the bit 0. */ - " msr control, r0 \n" /* Write back the new CONTROL value. */ - " bx lr \n" /* Return to the caller. */ - ::: "r0", "r1", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* Read the CONTROL register. */ + " movs r1, #1 \n"/* r1 = 1. */ + " bics r0, r1 \n"/* Clear the bit 0. */ + " msr control, r0 \n"/* Write back the new CONTROL value. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "r1", "memory" + ); } /*-----------------------------------------------------------*/ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " movs r1, #1 \n" /* r1 = 1. */ - " orrs r0, r1 \n" /* r0 = r0 | r1. */ - " msr control, r0 \n" /* CONTROL = r0. */ - " bx lr \n" /* Return to the caller. */ - :::"r0", "r1", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " movs r1, #1 \n"/* r1 = 1. */ + " orrs r0, r1 \n"/* r0 = r0 | r1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "r1", "memory" + ); } /*-----------------------------------------------------------*/ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */ - " ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ - " msr msp, r0 \n" /* Set the MSP back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " dsb \n" - " isb \n" - " svc %0 \n" /* System call to start the first task. */ - " nop \n" - " \n" - " .align 4 \n" - "xVTORConst: .word 0xe000ed08 \n" - :: "i" ( portSVC_START_SCHEDULER ) : "memory" - ); + __asm volatile + ( + " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ + " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ + " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ + " dsb \n" + " isb \n" + " svc %0 \n"/* System call to start the first task. */ + " nop \n" + " \n" + " .align 4 \n" + "xVTORConst: .word 0xe000ed08 \n" + ::"i" ( portSVC_START_SCHEDULER ) : "memory" + ); } /*-----------------------------------------------------------*/ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, PRIMASK \n" - " cpsid i \n" - " bx lr \n" - ::: "memory" - ); + __asm volatile + ( + " mrs r0, PRIMASK \n" + " cpsid i \n" + " bx lr \n" + ::: "memory" + ); } /*-----------------------------------------------------------*/ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " msr PRIMASK, r0 \n" - " bx lr \n" - ::: "memory" - ); + __asm volatile + ( + " msr PRIMASK, r0 \n" + " bx lr \n" + ::: "memory" + ); } /*-----------------------------------------------------------*/ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " \n" - " mrs r0, psp \n" /* Read PSP in r0. */ - " ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r1, [r2] \n" /* Read pxCurrentTCB. */ - #if( configENABLE_MPU == 1 ) - " subs r0, r0, #44 \n" /* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */ - " str r0, [r1] \n" /* Save the new top of stack in TCB. */ - " mrs r1, psplim \n" /* r1 = PSPLIM. */ - " mrs r2, control \n" /* r2 = CONTROL. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " stmia r0!, {r1-r7} \n" /* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */ - " mov r4, r8 \n" /* r4 = r8. */ - " mov r5, r9 \n" /* r5 = r9. */ - " mov r6, r10 \n" /* r6 = r10. */ - " mov r7, r11 \n" /* r7 = r11. */ - " stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ - #else /* configENABLE_MPU */ - " subs r0, r0, #40 \n" /* Make space for PSPLIM, LR and the remaining registers on the stack. */ - " str r0, [r1] \n" /* Save the new top of stack in TCB. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " stmia r0!, {r2-r7} \n" /* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */ - " mov r4, r8 \n" /* r4 = r8. */ - " mov r5, r9 \n" /* r5 = r9. */ - " mov r6, r10 \n" /* r6 = r10. */ - " mov r7, r11 \n" /* r7 = r11. */ - " stmia r0!, {r4-r7} \n" /* Store the high registers that are not saved automatically. */ - #endif /* configENABLE_MPU */ - " \n" - " cpsid i \n" - " bl vTaskSwitchContext \n" - " cpsie i \n" - " \n" - " ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r1, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r4, #1 \n" /* r4 = 1. */ - " bics r3, r4 \n" /* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ - " \n" - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ - " ldr r4, [r1] \n" /* r4 = *r1 i.e. r4 = MAIR0. */ - " ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r4, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ - " movs r4, #4 \n" /* r4 = 4. */ - " str r4, [r2] \n" /* Program RNR = 4. */ - " ldmia r1!, {r5,r6} \n" /* Read first set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write first set of RBAR/RLAR registers. */ - " movs r4, #5 \n" /* r4 = 5. */ - " str r4, [r2] \n" /* Program RNR = 5. */ - " ldmia r1!, {r5,r6} \n" /* Read second set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write second set of RBAR/RLAR registers. */ - " movs r4, #6 \n" /* r4 = 6. */ - " str r4, [r2] \n" /* Program RNR = 6. */ - " ldmia r1!, {r5,r6} \n" /* Read third set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write third set of RBAR/RLAR registers. */ - " movs r4, #7 \n" /* r4 = 7. */ - " str r4, [r2] \n" /* Program RNR = 7. */ - " ldmia r1!, {r5,r6} \n" /* Read fourth set of RBAR/RLAR from TCB. */ - " ldr r3, xRBARConst \n" /* r3 = 0xe000ed9c [Location of RBAR]. */ - " stmia r3!, {r5,r6} \n" /* Write fourth set of RBAR/RLAR registers. */ - " \n" - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " movs r4, #1 \n" /* r4 = 1. */ - " orrs r3, r4 \n" /* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " adds r0, r0, #28 \n" /* Move to the high registers. */ - " ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ - " mov r8, r4 \n" /* r8 = r4. */ - " mov r9, r5 \n" /* r9 = r5. */ - " mov r10, r6 \n" /* r10 = r6. */ - " mov r11, r7 \n" /* r11 = r7. */ - " msr psp, r0 \n" /* Remember the new top of stack for the task. */ - " subs r0, r0, #44 \n" /* Move to the starting of the saved context. */ - " ldmia r0!, {r1-r7} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */ - " msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ - " msr control, r2 \n" /* Restore the CONTROL register value for the task. */ - " bx r3 \n" - #else /* configENABLE_MPU */ - " adds r0, r0, #24 \n" /* Move to the high registers. */ - " ldmia r0!, {r4-r7} \n" /* Restore the high registers that are not automatically restored. */ - " mov r8, r4 \n" /* r8 = r4. */ - " mov r9, r5 \n" /* r9 = r5. */ - " mov r10, r6 \n" /* r10 = r6. */ - " mov r11, r7 \n" /* r11 = r7. */ - " msr psp, r0 \n" /* Remember the new top of stack for the task. */ - " subs r0, r0, #40 \n" /* Move to the starting of the saved context. */ - " ldmia r0!, {r2-r7} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */ - " msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ - " bx r3 \n" - #endif /* configENABLE_MPU */ - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst: .word 0xe000ed94 \n" - "xMAIR0Const: .word 0xe000edc0 \n" - "xRNRConst: .word 0xe000ed98 \n" - "xRBARConst: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - ); + __asm volatile + ( + " .syntax unified \n" + " \n" + " mrs r0, psp \n"/* Read PSP in r0. */ + " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r1, [r2] \n"/* Read pxCurrentTCB. */ + #if ( configENABLE_MPU == 1 ) + " subs r0, r0, #44 \n"/* Make space for PSPLIM, CONTROL, LR and the remaining registers on the stack. */ + " str r0, [r1] \n"/* Save the new top of stack in TCB. */ + " mrs r1, psplim \n"/* r1 = PSPLIM. */ + " mrs r2, control \n"/* r2 = CONTROL. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " stmia r0!, {r1-r7} \n"/* Store on the stack - PSPLIM, CONTROL, LR and low registers that are not automatically saved. */ + " mov r4, r8 \n"/* r4 = r8. */ + " mov r5, r9 \n"/* r5 = r9. */ + " mov r6, r10 \n"/* r6 = r10. */ + " mov r7, r11 \n"/* r7 = r11. */ + " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ + #else /* configENABLE_MPU */ + " subs r0, r0, #40 \n"/* Make space for PSPLIM, LR and the remaining registers on the stack. */ + " str r0, [r1] \n"/* Save the new top of stack in TCB. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " stmia r0!, {r2-r7} \n"/* Store on the stack - PSPLIM, LR and low registers that are not automatically saved. */ + " mov r4, r8 \n"/* r4 = r8. */ + " mov r5, r9 \n"/* r5 = r9. */ + " mov r6, r10 \n"/* r6 = r10. */ + " mov r7, r11 \n"/* r7 = r11. */ + " stmia r0!, {r4-r7} \n"/* Store the high registers that are not saved automatically. */ + #endif /* configENABLE_MPU */ + " \n" + " cpsid i \n" + " bl vTaskSwitchContext \n" + " cpsie i \n" + " \n" + " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r1, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r4, #1 \n"/* r4 = 1. */ + " bics r3, r4 \n"/* r3 = r3 & ~r4 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ + " ldr r4, [r1] \n"/* r4 = *r1 i.e. r4 = MAIR0. */ + " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r4, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ + " movs r4, #4 \n"/* r4 = 4. */ + " str r4, [r2] \n"/* Program RNR = 4. */ + " ldmia r1!, {r5,r6} \n"/* Read first set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write first set of RBAR/RLAR registers. */ + " movs r4, #5 \n"/* r4 = 5. */ + " str r4, [r2] \n"/* Program RNR = 5. */ + " ldmia r1!, {r5,r6} \n"/* Read second set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write second set of RBAR/RLAR registers. */ + " movs r4, #6 \n"/* r4 = 6. */ + " str r4, [r2] \n"/* Program RNR = 6. */ + " ldmia r1!, {r5,r6} \n"/* Read third set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write third set of RBAR/RLAR registers. */ + " movs r4, #7 \n"/* r4 = 7. */ + " str r4, [r2] \n"/* Program RNR = 7. */ + " ldmia r1!, {r5,r6} \n"/* Read fourth set of RBAR/RLAR from TCB. */ + " ldr r3, xRBARConst \n"/* r3 = 0xe000ed9c [Location of RBAR]. */ + " stmia r3!, {r5,r6} \n"/* Write fourth set of RBAR/RLAR registers. */ + " \n" + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " movs r4, #1 \n"/* r4 = 1. */ + " orrs r3, r4 \n"/* r3 = r3 | r4 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " adds r0, r0, #28 \n"/* Move to the high registers. */ + " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ + " mov r8, r4 \n"/* r8 = r4. */ + " mov r9, r5 \n"/* r9 = r5. */ + " mov r10, r6 \n"/* r10 = r6. */ + " mov r11, r7 \n"/* r11 = r7. */ + " msr psp, r0 \n"/* Remember the new top of stack for the task. */ + " subs r0, r0, #44 \n"/* Move to the starting of the saved context. */ + " ldmia r0!, {r1-r7} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r7 restored. */ + " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ + " msr control, r2 \n"/* Restore the CONTROL register value for the task. */ + " bx r3 \n" + #else /* configENABLE_MPU */ + " adds r0, r0, #24 \n"/* Move to the high registers. */ + " ldmia r0!, {r4-r7} \n"/* Restore the high registers that are not automatically restored. */ + " mov r8, r4 \n"/* r8 = r4. */ + " mov r9, r5 \n"/* r9 = r5. */ + " mov r10, r6 \n"/* r10 = r6. */ + " mov r11, r7 \n"/* r11 = r7. */ + " msr psp, r0 \n"/* Remember the new top of stack for the task. */ + " subs r0, r0, #40 \n"/* Move to the starting of the saved context. */ + " ldmia r0!, {r2-r7} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r7 restored. */ + " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ + " bx r3 \n" + #endif /* configENABLE_MPU */ + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst: .word 0xe000ed94 \n" + "xMAIR0Const: .word 0xe000edc0 \n" + "xRNRConst: .word 0xe000ed98 \n" + "xRBARConst: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ); } /*-----------------------------------------------------------*/ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " movs r0, #4 \n" - " mov r1, lr \n" - " tst r0, r1 \n" - " beq stacking_used_msp \n" - " mrs r0, psp \n" - " ldr r2, svchandler_address_const \n" - " bx r2 \n" - " stacking_used_msp: \n" - " mrs r0, msp \n" - " ldr r2, svchandler_address_const \n" - " bx r2 \n" - " \n" - " .align 4 \n" - "svchandler_address_const: .word vPortSVCHandler_C \n" - ); + __asm volatile + ( + " movs r0, #4 \n" + " mov r1, lr \n" + " tst r0, r1 \n" + " beq stacking_used_msp \n" + " mrs r0, psp \n" + " ldr r2, svchandler_address_const \n" + " bx r2 \n" + " stacking_used_msp: \n" + " mrs r0, msp \n" + " ldr r2, svchandler_address_const \n" + " bx r2 \n" + " \n" + " .align 4 \n" + "svchandler_address_const: .word vPortSVCHandler_C \n" + ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h b/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h index 71d711c69..fdba1b177 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portasm.h @@ -38,14 +38,14 @@ * @brief Restore the context of the first task so that the first task starts * executing. */ -void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +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 )); +BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); /** * @brief Raises the privilege level by clearing the bit 0 of the CONTROL @@ -58,7 +58,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Lowers the privilege level by setting the bit 0 of the CONTROL @@ -68,32 +68,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vResetPrivilege( void ) __attribute__ (( naked )); +void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Starts the first task. */ -void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Disables interrupts. */ -uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Enables interrupts. */ -void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief PendSV Exception handler. */ -void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief SVC Handler. */ -void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Allocate a Secure context for the calling task. @@ -101,13 +101,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * @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 )); +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; +void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; #endif /* __PORT_ASM_H__ */ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h index 2e8bba256..747cdc766 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h @@ -26,11 +26,11 @@ */ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*------------------------------------------------------------------------------ * Port specific definitions. @@ -42,109 +42,109 @@ extern "C" { *------------------------------------------------------------------------------ */ -#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_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_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 */ + #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 + #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 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 + #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 +/* 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 __attribute__(( used )) + #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 __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ -extern BaseType_t xPortIsInsideInterrupt( void ); + extern BaseType_t xPortIsInsideInterrupt( void ); -extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; + extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortExitCritical( 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 */; + 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_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 */ + #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 */ + #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. */ + #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. * @@ -156,155 +156,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * 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 */ + #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. */ + #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_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_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 ) + #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; + 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; + 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 + #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 ) + #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() + #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 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 + #ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + #endif /*-----------------------------------------------------------*/ /** * @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 ) + #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 ) + #if ( configENABLE_TRUSTZONE == 1 ) - /** - * @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 */ +/** + * @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() + #if ( configENABLE_MPU == 1 ) - /** - * @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 Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ + #define portIS_PRIVILEGED() xIsPrivileged() - /** - * @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 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" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM3/port.c b/portable/GCC/ARM_CM3/port.c index d37802a70..b21fb2042 100644 --- a/portable/GCC/ARM_CM3/port.c +++ b/portable/GCC/ARM_CM3/port.c @@ -26,80 +26,81 @@ */ /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM3 port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the ARM CM3 port. +*----------------------------------------------------------*/ /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" /* For backward compatibility, ensure configKERNEL_INTERRUPT_PRIORITY is -defined. The value should also ensure backward compatibility. -FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ + * defined. The value should also ensure backward compatibility. + * FreeRTOS.org versions prior to V4.4.0 did not include this definition. */ #ifndef configKERNEL_INTERRUPT_PRIORITY - #define configKERNEL_INTERRUPT_PRIORITY 255 + #define configKERNEL_INTERRUPT_PRIORITY 255 #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 ) + #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 ) + +/* 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_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_SHPR3_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_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 ) +#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 ) +#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 ) +#define portVECTACTIVE_MASK ( 0xFFUL ) /* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000UL ) +#define portINITIAL_XPSR ( 0x01000000UL ) /* The systick is a 24-bit counter. */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) +#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 ) + * 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 ) + * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ +#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) /* 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. */ + * prvTaskExitError() in case it messes up unwinding of the stack in the + * debugger. */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* @@ -112,14 +113,14 @@ void vPortSetupTimerInterrupt( void ); /* * Exception handlers. */ -void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortPendSVHandler( void ) __attribute__( ( naked ) ); void xPortSysTickHandler( void ); -void vPortSVCHandler( void ) __attribute__ (( naked )); +void vPortSVCHandler( void ) __attribute__( ( naked ) ); /* * Start first task is a separate function so it can be tested in isolation. */ -static void prvPortStartFirstTask( void ) __attribute__ (( naked )); +static void prvPortStartFirstTask( void ) __attribute__( ( naked ) ); /* * Used to catch tasks that attempt to return from their implementing function. @@ -129,30 +130,30 @@ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* Each task maintains its own interrupt status in the critical nesting -variable. */ + * 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; +#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; +#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; +#if ( configUSE_TICKLESS_IDLE == 1 ) + static uint32_t ulStoppedTimerCompensation = 0; #endif /* configUSE_TICKLESS_IDLE */ /* @@ -160,10 +161,10 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; * 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; +#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 */ /*-----------------------------------------------------------*/ @@ -171,84 +172,87 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * See header file for description. */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +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 ) portTASK_RETURN_ADDRESS; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + /* 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 ) portTASK_RETURN_ADDRESS; /* 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; + return pxTopOfStack; } /*-----------------------------------------------------------*/ static void prvTaskExitError( void ) { -volatile uint32_t ulDummy = 0UL; + 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 ). + /* 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(); - 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(); - 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. */ - } + 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. */ + } } /*-----------------------------------------------------------*/ void vPortSVCHandler( void ) { - __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n" /* Restore the task stack pointer. */ - " isb \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " orr r14, #0xd \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ + " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n"/* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " orr r14, #0xd \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); } /*-----------------------------------------------------------*/ static void prvPortStartFirstTask( void ) { - __asm volatile( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc 0 \n" /* System call to start first task. */ - " nop \n" - " .ltorg \n" - ); + __asm volatile ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n"/* System call to start first task. */ + " nop \n" + " .ltorg \n" + ); } /*-----------------------------------------------------------*/ @@ -257,356 +261,361 @@ static void prvPortStartFirstTask( void ) */ 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 ); + /* 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; + #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. + /* 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; - 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; - /* 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; - /* 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; - /* 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; - /* 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; - } + 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 __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 + #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; + /* 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 */ + /* 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; + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - vPortSetupTimerInterrupt(); + /* 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; + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; - /* Start the first task. */ - prvPortStartFirstTask(); + /* Start the first task. */ + prvPortStartFirstTask(); - /* 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 optimisation does not remove the - symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); + /* 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 optimisation does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); - /* Should not get here! */ - return 0; + /* 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 ); + /* Not implemented in ports where there is nothing to return to. + * Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ void vPortEnterCritical( void ) { - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; + 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 ); - } + /* 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(); - } + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } } /*-----------------------------------------------------------*/ void xPortPendSVHandler( void ) { - /* This is a naked function. */ + /* This is a naked function. */ - __asm volatile - ( - " mrs r0, psp \n" - " isb \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ - " \n" - " stmdb sp!, {r3, r14} \n" - " mov r0, %0 \n" - " msr basepri, r0 \n" - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " ldmia sp!, {r3, r14} \n" - " \n" /* Restore the context, including the critical nesting count. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ - " msr psp, r0 \n" - " isb \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) - ); + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " stmdb r0!, {r4-r11} \n"/* Save the remaining registers. */ + " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3, r14} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3, r14} \n" + " \n"/* Restore the context, including the critical nesting count. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n"/* Pop the registers. */ + " msr psp, r0 \n" + " isb \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); } /*-----------------------------------------------------------*/ 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(); + /* 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 ) +#if ( configUSE_TICKLESS_IDLE == 1 ) - __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; + __attribute__( ( 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; - } + /* 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; + /* 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; - } + /* 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 ) ); - /* Enter a critical section but don't use the taskENTER_CRITICAL() - method as that will mask interrupts that should exit sleep mode. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } - /* 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; + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* 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; - /* Reset the reload register to the value required for normal tick - periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts - see comments above the cpsid instruction() - above. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - /* Clear the SysTick count flag and set the count value back to - zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* 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 ) - { - __asm volatile( "dsb" ::: "memory" ); - __asm volatile( "wfi" ); - __asm volatile( "isb" ); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* 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. */ - __asm volatile( "cpsie i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + /* 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 ); - /* 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. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "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 ); + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - /* 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; + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); + /* 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. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); - } + /* 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 ); - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + /* 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; - /* 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; + /* 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 ); - /* How many complete tick periods passed while the processor - was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + /* 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 ); + } - /* The reload value is set to whatever fraction of a single tick - period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - /* 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; + /* 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; - /* Exit with interrupts enabled. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - } + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ @@ -615,104 +624,83 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +__attribute__( ( 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 */ + /* 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; + /* 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 ); + /* 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 ) +#if ( configASSERT_DEFINED == 1 ) - void vPortValidateInterruptPriority( void ) - { - uint32_t ulCurrentInterrupt; - uint8_t ucCurrentPriority; + 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" ); + /* 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 ]; + /* 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. + /* 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 ); + } - 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 ); - } + /* 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 */ - - - - - - - - - - - - - - - - - - - - - diff --git a/portable/GCC/ARM_CM3/portmacro.h b/portable/GCC/ARM_CM3/portmacro.h index 673d93757..acfed763c 100644 --- a/portable/GCC/ARM_CM3/portmacro.h +++ b/portable/GCC/ARM_CM3/portmacro.h @@ -27,11 +27,11 @@ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*----------------------------------------------------------- * Port specific definitions. @@ -44,203 +44,203 @@ extern "C" { */ /* 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 + #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 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 + #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 +/* 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 -#define portDONT_DISCARD __attribute__(( used )) + #define portSTACK_GROWTH ( -1 ) + #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) + #define portBYTE_ALIGNMENT 8 + #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* Scheduler utilities. */ -#define portYIELD() \ -{ \ - /* Set a PendSV to request a context switch. */ \ - 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" ); \ -} + #define portYIELD() \ + { \ + /* Set a PendSV to request a context switch. */ \ + 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" ); \ + } -#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 ) + #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 ) /*-----------------------------------------------------------*/ /* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); -#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) -#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() -#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() + extern void vPortEnterCritical( void ); + extern void vPortExitCritical( void ); + #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x ) + #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() + #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 ) + #define portENTER_CRITICAL() vPortEnterCritical() + #define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* 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 ) + * 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 ) /*-----------------------------------------------------------*/ /* 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 + #ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + #endif /*-----------------------------------------------------------*/ /* Architecture specific optimisations. */ -#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#endif + #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #endif -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - /* Generic helper function. */ - __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) - { - uint8_t ucReturn; +/* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; - __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - return ucReturn; - } + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - /* 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 + return ucReturn; + } - /* 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 ) ) +/* 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 - /*-----------------------------------------------------------*/ - - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) - -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/* 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 ) ) /*-----------------------------------------------------------*/ -#ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() -#endif + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + + #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + + #ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif /* portNOP() is not required by this port. */ -#define portNOP() + #define portNOP() -#define portINLINE __inline + #define portINLINE __inline -#ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) -#endif + #ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) + #endif /*-----------------------------------------------------------*/ -portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) -{ -uint32_t ulCurrentInterrupt; -BaseType_t xReturn; + 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" ); + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } - return xReturn; -} + return xReturn; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortRaiseBASEPRI( void ) -{ -uint32_t ulNewBASEPRI; + portFORCE_INLINE static void vPortRaiseBASEPRI( void ) + { + uint32_t ulNewBASEPRI; - __asm volatile - ( - " mov %0, %1 \n" \ - " msr basepri, %0 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); -} + __asm volatile + ( + " mov %0, %1 \n"\ + " msr basepri, %0 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) -{ -uint32_t ulOriginalBASEPRI, ulNewBASEPRI; + portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) + { + uint32_t ulOriginalBASEPRI, ulNewBASEPRI; - __asm volatile - ( - " mrs %0, basepri \n" \ - " mov %1, %2 \n" \ - " msr basepri, %1 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); + __asm volatile + ( + " mrs %0, basepri \n"\ + " mov %1, %2 \n"\ + " msr basepri, %1 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); - /* This return will not be reached but is necessary to prevent compiler - warnings. */ - return ulOriginalBASEPRI; -} + /* This return will not be reached but is necessary to prevent compiler + * warnings. */ + return ulOriginalBASEPRI; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) -{ - __asm volatile - ( - " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory" - ); -} + portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) + { + __asm volatile + ( + " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" + ); + } /*-----------------------------------------------------------*/ -#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ - diff --git a/portable/GCC/ARM_CM33/non_secure/port.c b/portable/GCC/ARM_CM33/non_secure/port.c index ba6bd2602..3f39bc3b1 100644 --- a/portable/GCC/ARM_CM33/non_secure/port.c +++ b/portable/GCC/ARM_CM33/non_secure/port.c @@ -40,10 +40,10 @@ /* Portasm includes. */ #include "portasm.h" -#if( configENABLE_TRUSTZONE == 1 ) - /* Secure components includes. */ - #include "secure_context.h" - #include "secure_init.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 @@ -63,126 +63,127 @@ * 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. +#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_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_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#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 ) +#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_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#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 ) #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 ) + #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 a the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 0 ) + +/* The way the SysTick is clocked is not modified in case it is not the + * same a the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) #endif /*-----------------------------------------------------------*/ /** * @brief Constants required to manipulate the SCB. */ -#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 ) -#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) +#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) +#define portSCB_MEM_FAULT_ENABLE_BIT ( 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 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 ) +#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_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_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_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_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_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_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_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_ATTR0_POS ( 0UL ) +#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) -#define portMPU_MAIR_ATTR1_POS ( 8UL ) -#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) +#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_ATTR2_POS ( 16UL ) +#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) -#define portMPU_MAIR_ATTR3_POS ( 24UL ) -#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) +#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_ATTR4_POS ( 0UL ) +#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) -#define portMPU_MAIR_ATTR5_POS ( 8UL ) -#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) +#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_ATTR6_POS ( 16UL ) +#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) -#define portMPU_MAIR_ATTR7_POS ( 24UL ) -#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) +#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_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 ) +#define portMPU_RLAR_REGION_ENABLE ( 1UL ) /* Enable privileged access to unmapped region. */ -#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) +#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) /* Enable MPU. */ -#define portMPU_ENABLE_BIT ( 1UL << 0UL ) +#define portMPU_ENABLE_BIT ( 1UL << 0UL ) /* Expected value of the portMPU_TYPE register. */ -#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ +#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ /*-----------------------------------------------------------*/ /** @@ -190,53 +191,55 @@ * * It is needed because the systick is a 24-bit counter. */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) /** * @brief 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 ) +#define portMISSED_COUNTS_FACTOR ( 45UL ) /*-----------------------------------------------------------*/ /** * @brief Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) +#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 ) +#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 ) + +/** + * @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 */ /** @@ -246,13 +249,13 @@ * Bit[0] = 0 ==> The task is privileged. * Bit[0] = 1 ==> The task is not privileged. */ -#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) +#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) /** * @brief Initial CONTROL register values. */ -#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) -#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) +#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) +#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) /** * @brief Let the user override the pre-loading of the initial LR with the @@ -260,23 +263,23 @@ * in the debugger. */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #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 +#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 +#define portNO_SECURE_CONTEXT 0 /*-----------------------------------------------------------*/ /** @@ -285,18 +288,20 @@ */ static void prvTaskExitError( void ); -#if( configENABLE_MPU == 1 ) - /** - * @brief Setup the Memory Protection Unit (MPU). - */ - static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; +#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; +#if ( configENABLE_FPU == 1 ) + +/** + * @brief Setup the Floating Point Unit (FPU). + */ + static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; #endif /* configENABLE_FPU */ /** @@ -338,812 +343,848 @@ void SysTick_Handler( void ) PRIVILEGED_FUNCTION; /** * @brief C part of SVC handler. */ -portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION; +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; +PRIVILEGED_DATA 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; +#if ( configENABLE_TRUSTZONE == 1 ) + +/** + * @brief Saved as part of the task context to indicate which context the + * task is using on the secure side. + */ + PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ -#if( configUSE_TICKLESS_IDLE == 1 ) - /** - * @brief The number of SysTick increments that make up one tick period. - */ - static uint32_t ulTimerCountsForOneTick = 0; +#if ( configUSE_TICKLESS_IDLE == 1 ) - /** - * @brief The maximum number of tick periods that can be suppressed is - * limited by the 24 bit resolution of the SysTick timer. - */ - static uint32_t xMaximumPossibleSuppressedTicks = 0; +/** + * @brief The number of SysTick increments that make up one tick period. + */ + PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; - /** - * @brief Compensate for the CPU cycles that pass while the SysTick is - * stopped (low power functionality only). - */ - static uint32_t ulStoppedTimerCompensation = 0; +/** + * @brief The maximum number of tick periods that can be suppressed is + * limited by the 24 bit resolution of the SysTick timer. + */ + PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; + +/** + * @brief Compensate for the CPU cycles that pass while the SysTick is + * stopped (low power functionality only). + */ + PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ -#if( configUSE_TICKLESS_IDLE == 1 ) - __attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; +#if ( configUSE_TICKLESS_IDLE == 1 ) + __attribute__( ( 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; - } + /* 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; + /* 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; - } + /* 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 ) ); - /* Enter a critical section but don't use the taskENTER_CRITICAL() - * method as that will mask interrupts that should exit sleep mode. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } - /* If a context switch is pending or a task is waiting for the scheduler - * to be un-suspended 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; + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* If a context switch is pending or a task is waiting for the scheduler + * to be un-suspended 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; - /* Reset the reload register to the value required for normal tick - * periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts - see comments above the cpsid instruction() - * above. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - /* Clear the SysTick count flag and set the count value back to - * zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* 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 ) - { - __asm volatile( "dsb" ::: "memory" ); - __asm volatile( "wfi" ); - __asm volatile( "isb" ); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts to allow the interrupt that brought the MCU - * out of sleep mode to execute immediately. See comments above - * the cpsid instruction above. */ - __asm volatile( "cpsie i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + /* 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 ); - /* 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. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "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 ); + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - /* 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; + /* Re-enable interrupts to allow the interrupt that brought the MCU + * out of sleep mode to execute immediately. See comments above + * the cpsid instruction above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); + /* 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. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); - } + /* 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 ); - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + /* 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; - /* 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; + /* 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 ); - /* How many complete tick periods passed while the processor - * was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + /* 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 ); + } - /* The reload value is set to whatever fraction of a single tick - * period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - /* 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; + /* 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; - /* Exit with interrupts enabled. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - } + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ +__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ { - /* 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 */ + /* 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 reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* 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; + /* 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 prvTaskExitError( void ) { -volatile uint32_t ulDummy = 0UL; + 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(); + /* 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. */ - } + 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 ) */ +#if ( configENABLE_MPU == 1 ) + static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if 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 ); + /* 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 /* if defined( __ARMCC_VERSION ) */ + /* 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 ) */ - /* 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 ); + /* 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 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 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 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 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 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 ); + /* 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 ); - /* Enable mem fault. */ - portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; + /* 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 MPU with privileged background access i.e. unmapped - * regions have privileged access. */ - portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); - } - } + /* Enable mem fault. */ + portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; + + /* Enable MPU with privileged background access i.e. unmapped + * regions have privileged access. */ + portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); + } + } #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 */ +#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 ) - ); + /* 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 ); - } + /* 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_REG = portNVIC_PENDSVSET_BIT; + /* Set a PendSV to request a context switch. */ + 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" ); + /* 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++; + 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" ); + /* 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--; + configASSERT( ulCriticalNesting ); + ulCriticalNesting--; - if( ulCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } + if( ulCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } } /*-----------------------------------------------------------*/ void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ { -uint32_t ulPreviousMask; + 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_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); } /*-----------------------------------------------------------*/ -void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ +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 */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) -uint32_t ulPC; + /* 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 */ -#if( configENABLE_TRUSTZONE == 1 ) - uint32_t ulR0; - #if( configENABLE_MPU == 1 ) - uint32_t ulControl, ulIsTaskPrivileged; - #endif /* configENABLE_MPU */ -#endif /* configENABLE_TRUSTZONE */ -uint8_t ucSVCNumber; + uint32_t ulPC; - /* 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 ]; + #if ( configENABLE_TRUSTZONE == 1 ) + uint32_t ulR0; + #if ( configENABLE_MPU == 1 ) + uint32_t ulControl, ulIsTaskPrivileged; + #endif /* configENABLE_MPU */ + #endif /* configENABLE_TRUSTZONE */ + uint8_t ucSVCNumber; - 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 ]; + /* 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 ]; - #if( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + switch( ucSVCNumber ) + { + #if ( configENABLE_TRUSTZONE == 1 ) + case portSVC_ALLOCATE_SECURE_CONTEXT: - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + /* R0 contains the stack size passed as parameter to the + * vPortAllocateSecureContext function. */ + ulR0 = pulCallerStackAddress[ 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 */ + #if ( configENABLE_MPU == 1 ) + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - configASSERT( xSecureContext != NULL ); - SecureContext_LoadContext( xSecureContext ); - } - break; + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - case portSVC_FREE_SECURE_CONTEXT: - { - /* R0 contains the secure context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } + #endif /* configENABLE_MPU */ - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); - } - break; - #endif /* configENABLE_TRUSTZONE */ + configASSERT( xSecureContext != NULL ); + SecureContext_LoadContext( xSecureContext ); + break; - 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(); + case portSVC_FREE_SECURE_CONTEXT: + /* R0 contains the secure context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; - /* Initialize the secure context management system. */ - SecureContext_Init(); - } - #endif /* configENABLE_TRUSTZONE */ + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); + break; + #endif /* configENABLE_TRUSTZONE */ - #if( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ + 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(); - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); - } - break; + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ - #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 */ + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ - default: - { - /* Incorrect SVC call. */ - configASSERT( pdFALSE ); - } - } + /* 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 */ +#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 */ + 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; + /* 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 */ + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + 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 */ - #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 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - #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 */ + #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 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; - #if( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #endif /* portPRELOAD_REGISTERS */ + 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 */ - return pxTopOfStack; + 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_REG |= portNVIC_PENDSV_PRI; - portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - #if( configENABLE_MPU == 1 ) - { - /* Setup the Memory Protection Unit (MPU). */ - prvSetupMPU(); - } - #endif /* configENABLE_MPU */ + #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(); + /* 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; + /* Initialize the critical nesting count ready for the first task. */ + ulCriticalNesting = 0; - /* Start the first task. */ - vStartFirstTask(); + /* 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 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; + /* 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 ); + /* 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; +#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; + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + 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_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ - /* 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 ); + /* 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; + /* 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 ) + { + ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; + ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); + /* If the stack is within the privileged SRAM, do not protect it + * using a separate MPU region. This is needed because privileged + * SRAM is already protected using an MPU region and ARMv8-M does + * not allow overlapping MPU regions. */ + if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && + ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) + { + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; + } + else + { + /* Define the region that allows access to the stack. */ + ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - } + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); - /* 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; + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + } + } - /* Start address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ); + /* 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; - /* 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 ); - } + /* Start address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ); - /* XN. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); - } + /* 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 ); + } - /* End Address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_REGION_ENABLE ); + /* XN. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); + } - /* 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; - } + /* End Address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_REGION_ENABLE ); - lIndex++; - } - } + /* 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; + 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" ); + /* 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; - } + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } - return xReturn; + return xReturn; } -/*-----------------------------------------------------------*/ \ No newline at end of file +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/non_secure/portasm.c b/portable/GCC/ARM_CM33/non_secure/portasm.c index 443dc184e..0c8cb0f0c 100644 --- a/portable/GCC/ARM_CM33/non_secure/portasm.c +++ b/portable/GCC/ARM_CM33/non_secure/portasm.c @@ -41,370 +41,370 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " \n" - " ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r3, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r0, [r3] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ - " str r4, [r2] \n" /* Disable MPU. */ - " \n" - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ - " ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */ - " ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r4, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " movs r4, #4 \n" /* r4 = 4. */ - " str r4, [r2] \n" /* Program RNR = 4. */ - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ - " ldr r2, xRBARConst2 \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ - " ldmia r3!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */ - " stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */ - " \n" - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ - " str r4, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " ldm r0!, {r1-r4} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ - " ldr r5, xSecureContextConst2 \n" - " str r1, [r5] \n" /* Set xSecureContext to this task's value for the same. */ - " msr psplim, r2 \n" /* Set this task's PSPLIM value. */ - " msr control, r3 \n" /* Set this task's CONTROL value. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r4 \n" /* Finally, branch to EXC_RETURN. */ - #else /* configENABLE_MPU */ - " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ - " ldr r4, xSecureContextConst2 \n" - " str r1, [r4] \n" /* Set xSecureContext to this task's value for the same. */ - " msr psplim, r2 \n" /* Set this task's PSPLIM value. */ - " movs r1, #2 \n" /* r1 = 2. */ - " msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r3 \n" /* Finally, branch to EXC_RETURN. */ - #endif /* configENABLE_MPU */ - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - "xSecureContextConst2: .word xSecureContext \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst2: .word 0xe000ed94 \n" - "xMAIR0Const2: .word 0xe000edc0 \n" - "xRNRConst2: .word 0xe000ed98 \n" - "xRBARConst2: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - ); + __asm volatile + ( + " .syntax unified \n" + " \n" + " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r3, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r0, [r3] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ + " str r4, [r2] \n"/* Disable MPU. */ + " \n" + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ + " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ + " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r4, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " movs r4, #4 \n"/* r4 = 4. */ + " str r4, [r2] \n"/* Program RNR = 4. */ + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ + " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ + " ldmia r3!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ + " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ + " \n" + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ + " str r4, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " ldm r0!, {r1-r4} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = EXC_RETURN. */ + " ldr r5, xSecureContextConst2 \n" + " str r1, [r5] \n"/* Set xSecureContext to this task's value for the same. */ + " msr psplim, r2 \n"/* Set this task's PSPLIM value. */ + " msr control, r3 \n"/* Set this task's CONTROL value. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r4 \n"/* Finally, branch to EXC_RETURN. */ + #else /* configENABLE_MPU */ + " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = xSecureContext, r2 = PSPLIM and r3 = EXC_RETURN. */ + " ldr r4, xSecureContextConst2 \n" + " str r1, [r4] \n"/* Set xSecureContext to this task's value for the same. */ + " msr psplim, r2 \n"/* Set this task's PSPLIM value. */ + " movs r1, #2 \n"/* r1 = 2. */ + " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r3 \n"/* Finally, branch to EXC_RETURN. */ + #endif /* configENABLE_MPU */ + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + "xSecureContextConst2: .word xSecureContext \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst2: .word 0xe000ed94 \n" + "xMAIR0Const2: .word 0xe000edc0 \n" + "xRNRConst2: .word 0xe000ed98 \n" + "xRBARConst2: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ); } /*-----------------------------------------------------------*/ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ - " ite ne \n" - " movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n" /* Return. */ - " \n" - " .align 4 \n" - ::: "r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ + " ite ne \n" + " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ + " \n" + " .align 4 \n" + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, control \n" /* Read the CONTROL register. */ - " bic r0, #1 \n" /* Clear the bit 0. */ - " msr control, r0 \n" /* Write back the new CONTROL value. */ - " bx lr \n" /* Return to the caller. */ - ::: "r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* Read the CONTROL register. */ + " bic r0, #1 \n"/* Clear the bit 0. */ + " msr control, r0 \n"/* Write back the new CONTROL value. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " orr r0, #1 \n" /* r0 = r0 | 1. */ - " msr control, r0 \n" /* CONTROL = r0. */ - " bx lr \n" /* Return to the caller. */ - :::"r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " orr r0, #1 \n"/* r0 = r0 | 1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */ - " ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ - " msr msp, r0 \n" /* Set the MSP back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc %0 \n" /* System call to start the first task. */ - " nop \n" - " \n" - " .align 4 \n" - "xVTORConst: .word 0xe000ed08 \n" - :: "i" ( portSVC_START_SCHEDULER ) : "memory" - ); + __asm volatile + ( + " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ + " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ + " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc %0 \n"/* System call to start the first task. */ + " nop \n" + " \n" + " .align 4 \n" + "xVTORConst: .word 0xe000ed08 \n" + ::"i" ( portSVC_START_SCHEDULER ) : "memory" + ); } /*-----------------------------------------------------------*/ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */ - " mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ - " msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ - " dsb \n" - " isb \n" - " bx lr \n" /* Return. */ - :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); + __asm volatile + ( + " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ + " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ + " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ + " dsb \n" + " isb \n" + " bx lr \n"/* Return. */ + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); } /*-----------------------------------------------------------*/ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " msr basepri, r0 \n" /* basepri = ulMask. */ - " dsb \n" - " isb \n" - " bx lr \n" /* Return. */ - ::: "memory" - ); + __asm volatile + ( + " msr basepri, r0 \n"/* basepri = ulMask. */ + " dsb \n" + " isb \n" + " bx lr \n"/* Return. */ + ::: "memory" + ); } /*-----------------------------------------------------------*/ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " .extern SecureContext_SaveContext \n" - " .extern SecureContext_LoadContext \n" - " \n" - " mrs r1, psp \n" /* Read PSP in r1. */ - " ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ - " ldr r0, [r2] \n" /* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ - " \n" - " cbz r0, save_ns_context \n" /* No secure context to save. */ - " push {r0-r2, r14} \n" - " bl SecureContext_SaveContext \n" - " pop {r0-r3} \n" /* LR is now in r3. */ - " mov lr, r3 \n" /* LR = r3. */ - " lsls r2, r3, #25 \n" /* 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 \n" /* 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, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r2, [r3] \n" /* Read pxCurrentTCB. */ - #if( configENABLE_MPU == 1 ) - " subs r1, r1, #16 \n" /* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mrs r3, control \n" /* r3 = CONTROL. */ - " mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ - " stmia r1!, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ - #else /* configENABLE_MPU */ - " subs r1, r1, #12 \n" /* Make space for xSecureContext, PSPLIM and LR on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */ - #endif /* configENABLE_MPU */ - " b select_next_task \n" - " \n" - " save_ns_context: \n" - " ldr r3, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r2, [r3] \n" /* Read pxCurrentTCB. */ - #if( configENABLE_FPU == 1 ) - " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ - " it eq \n" - " vstmdbeq r1!, {s16-s31} \n" /* Store the FPU registers which are not saved automatically. */ - #endif /* configENABLE_FPU */ - #if( configENABLE_MPU == 1 ) - " subs r1, r1, #48 \n" /* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " adds r1, r1, #16 \n" /* r1 = r1 + 16. */ - " stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mrs r3, control \n" /* r3 = CONTROL. */ - " mov r4, lr \n" /* r4 = LR/EXC_RETURN. */ - " subs r1, r1, #16 \n" /* r1 = r1 - 16. */ - " stm r1, {r0, r2-r4} \n" /* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ - #else /* configENABLE_MPU */ - " subs r1, r1, #44 \n" /* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ - " str r1, [r2] \n" /* Save the new top of stack in TCB. */ - " adds r1, r1, #12 \n" /* r1 = r1 + 12. */ - " stm r1, {r4-r11} \n" /* Store the registers that are not saved automatically. */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " subs r1, r1, #12 \n" /* r1 = r1 - 12. */ - " stmia r1!, {r0, r2-r3} \n" /* Store xSecureContext, PSPLIM and LR on the stack. */ - #endif /* configENABLE_MPU */ - " \n" - " select_next_task: \n" - " mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ - " msr basepri, r0 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ - " dsb \n" - " isb \n" - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" /* r0 = 0. */ - " msr basepri, r0 \n" /* Enable interrupts. */ - " \n" - " ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r3, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ - " str r4, [r2] \n" /* Disable MPU. */ - " \n" - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ - " ldr r4, [r3] \n" /* r4 = *r3 i.e. r4 = MAIR0. */ - " ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r4, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " movs r4, #4 \n" /* r4 = 4. */ - " str r4, [r2] \n" /* Program RNR = 4. */ - " adds r3, #4 \n" /* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ - " ldr r2, xRBARConst \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ - " ldmia r3!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */ - " stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */ - " \n" - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ - " str r4, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " ldmia r1!, {r0, r2-r4} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */ - " msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ - " msr control, r3 \n" /* Restore the CONTROL register value for the task. */ - " mov lr, r4 \n" /* LR = r4. */ - " ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ - " str r0, [r2] \n" /* Restore the task's xSecureContext. */ - " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ - " push {r1,r4} \n" - " bl SecureContext_LoadContext \n" /* Restore the secure context. */ - " pop {r1,r4} \n" - " mov lr, r4 \n" /* LR = r4. */ - " lsls r2, r4, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */ - " bx lr \n" - #else /* configENABLE_MPU */ - " ldmia r1!, {r0, r2-r3} \n" /* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */ - " msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ - " mov lr, r3 \n" /* LR = r3. */ - " ldr r2, xSecureContextConst \n" /* Read the location of xSecureContext i.e. &( xSecureContext ). */ - " str r0, [r2] \n" /* Restore the task's xSecureContext. */ - " cbz r0, restore_ns_context \n" /* If there is no secure context for the task, restore the non-secure context. */ - " push {r1,r3} \n" - " bl SecureContext_LoadContext \n" /* Restore the secure context. */ - " pop {r1,r3} \n" - " mov lr, r3 \n" /* LR = r3. */ - " lsls r2, r3, #25 \n" /* 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 \n" /* 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 \n" /* Remember the new top of stack for the task. */ - " bx lr \n" - #endif /* configENABLE_MPU */ - " \n" - " restore_ns_context: \n" - " ldmia r1!, {r4-r11} \n" /* Restore the registers that are not automatically restored. */ - #if( configENABLE_FPU == 1 ) - " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ - " it eq \n" - " vldmiaeq r1!, {s16-s31} \n" /* Restore the FPU registers which are not restored automatically. */ - #endif /* configENABLE_FPU */ - " msr psp, r1 \n" /* Remember the new top of stack for the task. */ - " bx lr \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - "xSecureContextConst: .word xSecureContext \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst: .word 0xe000ed94 \n" - "xMAIR0Const: .word 0xe000edc0 \n" - "xRNRConst: .word 0xe000ed98 \n" - "xRBARConst: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - :: "i"( configMAX_SYSCALL_INTERRUPT_PRIORITY ) - ); + __asm volatile + ( + " .syntax unified \n" + " .extern SecureContext_SaveContext \n" + " .extern SecureContext_LoadContext \n" + " \n" + " mrs r1, psp \n"/* Read PSP in r1. */ + " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ + " ldr r0, [r2] \n"/* Read xSecureContext - Value of xSecureContext must be in r0 as it is used as a parameter later. */ + " \n" + " cbz r0, save_ns_context \n"/* No secure context to save. */ + " push {r0-r2, r14} \n" + " bl SecureContext_SaveContext \n" + " pop {r0-r3} \n"/* LR is now in r3. */ + " mov lr, r3 \n"/* LR = r3. */ + " lsls r2, r3, #25 \n"/* 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 \n"/* 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, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r2, [r3] \n"/* Read pxCurrentTCB. */ + #if ( configENABLE_MPU == 1 ) + " subs r1, r1, #16 \n"/* Make space for xSecureContext, PSPLIM, CONTROL and LR on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mrs r3, control \n"/* r3 = CONTROL. */ + " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ + " stmia r1!, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ + #else /* configENABLE_MPU */ + " subs r1, r1, #12 \n"/* Make space for xSecureContext, PSPLIM and LR on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ + #endif /* configENABLE_MPU */ + " b select_next_task \n" + " \n" + " save_ns_context: \n" + " ldr r3, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r2, [r3] \n"/* Read pxCurrentTCB. */ + #if ( configENABLE_FPU == 1 ) + " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ + " it eq \n" + " vstmdbeq r1!, {s16-s31} \n"/* Store the FPU registers which are not saved automatically. */ + #endif /* configENABLE_FPU */ + #if ( configENABLE_MPU == 1 ) + " subs r1, r1, #48 \n"/* Make space for xSecureContext, PSPLIM, CONTROL, LR and the remaining registers on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " adds r1, r1, #16 \n"/* r1 = r1 + 16. */ + " stm r1, {r4-r11} \n"/* Store the registers that are not saved automatically. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mrs r3, control \n"/* r3 = CONTROL. */ + " mov r4, lr \n"/* r4 = LR/EXC_RETURN. */ + " subs r1, r1, #16 \n"/* r1 = r1 - 16. */ + " stm r1, {r0, r2-r4} \n"/* Store xSecureContext, PSPLIM, CONTROL and LR on the stack. */ + #else /* configENABLE_MPU */ + " subs r1, r1, #44 \n"/* Make space for xSecureContext, PSPLIM, LR and the remaining registers on the stack. */ + " str r1, [r2] \n"/* Save the new top of stack in TCB. */ + " adds r1, r1, #12 \n"/* r1 = r1 + 12. */ + " stm r1, {r4-r11} \n"/* Store the registers that are not saved automatically. */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " subs r1, r1, #12 \n"/* r1 = r1 - 12. */ + " stmia r1!, {r0, r2-r3} \n"/* Store xSecureContext, PSPLIM and LR on the stack. */ + #endif /* configENABLE_MPU */ + " \n" + " select_next_task: \n" + " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ + " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ + " dsb \n" + " isb \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n"/* r0 = 0. */ + " msr basepri, r0 \n"/* Enable interrupts. */ + " \n" + " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r3, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. r1 now points to the top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ + " str r4, [r2] \n"/* Disable MPU. */ + " \n" + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to MAIR0 in TCB. */ + " ldr r4, [r3] \n"/* r4 = *r3 i.e. r4 = MAIR0. */ + " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r4, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " movs r4, #4 \n"/* r4 = 4. */ + " str r4, [r2] \n"/* Program RNR = 4. */ + " adds r3, #4 \n"/* r3 = r3 + 4. r3 now points to first RBAR in TCB. */ + " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ + " ldmia r3!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ + " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ + " \n" + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ + " str r4, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " ldmia r1!, {r0, r2-r4} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM, r3 = CONTROL and r4 = LR. */ + " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ + " msr control, r3 \n"/* Restore the CONTROL register value for the task. */ + " mov lr, r4 \n"/* LR = r4. */ + " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ + " str r0, [r2] \n"/* Restore the task's xSecureContext. */ + " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ + " push {r1,r4} \n" + " bl SecureContext_LoadContext \n"/* Restore the secure context. */ + " pop {r1,r4} \n" + " mov lr, r4 \n"/* LR = r4. */ + " lsls r2, r4, #25 \n"/* 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 \n"/* 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 \n"/* Remember the new top of stack for the task. */ + " bx lr \n" + #else /* configENABLE_MPU */ + " ldmia r1!, {r0, r2-r3} \n"/* Read from stack - r0 = xSecureContext, r2 = PSPLIM and r3 = LR. */ + " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ + " mov lr, r3 \n"/* LR = r3. */ + " ldr r2, xSecureContextConst \n"/* Read the location of xSecureContext i.e. &( xSecureContext ). */ + " str r0, [r2] \n"/* Restore the task's xSecureContext. */ + " cbz r0, restore_ns_context \n"/* If there is no secure context for the task, restore the non-secure context. */ + " push {r1,r3} \n" + " bl SecureContext_LoadContext \n"/* Restore the secure context. */ + " pop {r1,r3} \n" + " mov lr, r3 \n"/* LR = r3. */ + " lsls r2, r3, #25 \n"/* 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 \n"/* 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 \n"/* Remember the new top of stack for the task. */ + " bx lr \n" + #endif /* configENABLE_MPU */ + " \n" + " restore_ns_context: \n" + " ldmia r1!, {r4-r11} \n"/* Restore the registers that are not automatically restored. */ + #if ( configENABLE_FPU == 1 ) + " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ + " it eq \n" + " vldmiaeq r1!, {s16-s31} \n"/* Restore the FPU registers which are not restored automatically. */ + #endif /* configENABLE_FPU */ + " msr psp, r1 \n"/* Remember the new top of stack for the task. */ + " bx lr \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + "xSecureContextConst: .word xSecureContext \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst: .word 0xe000ed94 \n" + "xMAIR0Const: .word 0xe000edc0 \n" + "xRNRConst: .word 0xe000ed98 \n" + "xRBARConst: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); } /*-----------------------------------------------------------*/ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " tst lr, #4 \n" - " ite eq \n" - " mrseq r0, msp \n" - " mrsne r0, psp \n" - " ldr r1, svchandler_address_const \n" - " bx r1 \n" - " \n" - " .align 4 \n" - "svchandler_address_const: .word vPortSVCHandler_C \n" - ); + __asm volatile + ( + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, svchandler_address_const \n" + " bx r1 \n" + " \n" + " .align 4 \n" + "svchandler_address_const: .word vPortSVCHandler_C \n" + ); } /*-----------------------------------------------------------*/ void vPortAllocateSecureContext( uint32_t ulSecureStackSize ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " svc %0 \n" /* Secure context is allocated in the supervisor call. */ - " bx lr \n" /* Return. */ - :: "i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" - ); + __asm volatile + ( + " svc %0 \n"/* Secure context is allocated in the supervisor call. */ + " bx lr \n"/* Return. */ + ::"i" ( portSVC_ALLOCATE_SECURE_CONTEXT ) : "memory" + ); } /*-----------------------------------------------------------*/ -void vPortFreeSecureContext( uint32_t *pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ +void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " ldr r1, [r0] \n" /* The first item in the TCB is the top of the stack. */ - " ldr r0, [r1] \n" /* The first item on the stack is the task's xSecureContext. */ - " cmp r0, #0 \n" /* Raise svc if task's xSecureContext is not NULL. */ - " it ne \n" - " svcne %0 \n" /* Secure context is freed in the supervisor call. */ - " bx lr \n" /* Return. */ - :: "i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" - ); + __asm volatile + ( + " ldr r1, [r0] \n"/* The first item in the TCB is the top of the stack. */ + " ldr r0, [r1] \n"/* The first item on the stack is the task's xSecureContext. */ + " cmp r0, #0 \n"/* Raise svc if task's xSecureContext is not NULL. */ + " it ne \n" + " svcne %0 \n"/* Secure context is freed in the supervisor call. */ + " bx lr \n"/* Return. */ + ::"i" ( portSVC_FREE_SECURE_CONTEXT ) : "memory" + ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/non_secure/portasm.h b/portable/GCC/ARM_CM33/non_secure/portasm.h index 71d711c69..fdba1b177 100644 --- a/portable/GCC/ARM_CM33/non_secure/portasm.h +++ b/portable/GCC/ARM_CM33/non_secure/portasm.h @@ -38,14 +38,14 @@ * @brief Restore the context of the first task so that the first task starts * executing. */ -void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +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 )); +BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); /** * @brief Raises the privilege level by clearing the bit 0 of the CONTROL @@ -58,7 +58,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Lowers the privilege level by setting the bit 0 of the CONTROL @@ -68,32 +68,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vResetPrivilege( void ) __attribute__ (( naked )); +void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Starts the first task. */ -void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Disables interrupts. */ -uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Enables interrupts. */ -void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief PendSV Exception handler. */ -void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief SVC Handler. */ -void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Allocate a Secure context for the calling task. @@ -101,13 +101,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * @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 )); +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; +void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; #endif /* __PORT_ASM_H__ */ diff --git a/portable/GCC/ARM_CM33/non_secure/portmacro.h b/portable/GCC/ARM_CM33/non_secure/portmacro.h index 64fea84e2..bb4d2495d 100644 --- a/portable/GCC/ARM_CM33/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM33/non_secure/portmacro.h @@ -26,11 +26,11 @@ */ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*------------------------------------------------------------------------------ * Port specific definitions. @@ -42,109 +42,109 @@ extern "C" { *------------------------------------------------------------------------------ */ -#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_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_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 */ + #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 + #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 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 + #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 +/* 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 __attribute__(( used )) + #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 __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ -extern BaseType_t xPortIsInsideInterrupt( void ); + extern BaseType_t xPortIsInsideInterrupt( void ); -extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; + extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortExitCritical( 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 */; + 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_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 */ + #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 */ + #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. */ + #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. * @@ -156,155 +156,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * 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 */ + #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. */ + #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_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_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 ) + #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; + 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; + 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 + #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 ) + #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() + #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 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 + #ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + #endif /*-----------------------------------------------------------*/ /** * @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 ) + #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 ) + #if ( configENABLE_TRUSTZONE == 1 ) - /** - * @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 */ +/** + * @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() + #if ( configENABLE_MPU == 1 ) - /** - * @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 Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ + #define portIS_PRIVILEGED() xIsPrivileged() - /** - * @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 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" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM33/secure/secure_context.c b/portable/GCC/ARM_CM33/secure/secure_context.c index 39fabbf60..5608c7240 100644 --- a/portable/GCC/ARM_CM33/secure/secure_context.c +++ b/portable/GCC/ARM_CM33/secure/secure_context.c @@ -40,7 +40,7 @@ * Bit[0] - 0 --> Thread mode is privileged. * Bit[1] - 1 --> Thread mode uses PSP. */ -#define securecontextCONTROL_VALUE_PRIVILEGED 0x02 +#define securecontextCONTROL_VALUE_PRIVILEGED 0x02 /** * @brief CONTROL value for un-privileged tasks. @@ -48,7 +48,7 @@ * Bit[0] - 1 --> Thread mode is un-privileged. * Bit[1] - 1 --> Thread mode uses PSP. */ -#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03 +#define securecontextCONTROL_VALUE_UNPRIVILEGED 0x03 /*-----------------------------------------------------------*/ /** @@ -59,146 +59,148 @@ */ 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. */ + 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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); + /* 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 ) + { + /* 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 ) +#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 ) + 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 */ + uint8_t * pucStackMemory = NULL; + uint32_t ulIPSR; + SecureContextHandle_t xSecureContextHandle = NULL; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( ulIPSR ); + #if ( configENABLE_MPU == 1 ) + uint32_t * pulCurrentStackPointer = NULL; + #endif /* configENABLE_MPU */ - /* 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 ) ); + /* Read the Interrupt Program Status Register (IPSR) value. */ + secureportREAD_IPSR( ulIPSR ); - if( xSecureContextHandle != NULL ) - { - /* Allocate the stack space. */ - pucStackMemory = pvPortMalloc( ulSecureStackSize ); + /* 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( 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; + if( xSecureContextHandle != NULL ) + { + /* Allocate the stack space. */ + pucStackMemory = pvPortMalloc( ulSecureStackSize ); - /* The stack cannot go beyond this location. This value is - * programmed in the PSPLIM register on context switch.*/ - xSecureContextHandle->pucStackLimit = pucStackMemory; + 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; - #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; - } + /* The stack cannot go beyond this location. This value is + * programmed in the PSPLIM register on context switch.*/ + xSecureContextHandle->pucStackLimit = pucStackMemory; - /* 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; + #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--; - } - #endif /* configENABLE_MPU */ - } - else - { - /* Free the context to avoid memory leak and make sure to return - * NULL to indicate failure. */ - vPortFree( xSecureContextHandle ); - xSecureContextHandle = NULL; - } - } - } + if( ulIsTaskPrivileged ) + { + *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED; + } + else + { + *( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_UNPRIVILEGED; + } - return xSecureContextHandle; + /* 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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); + /* 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 stack space. */ + vPortFree( xSecureContextHandle->pucStackLimit ); - /* Free the context itself. */ - vPortFree( xSecureContextHandle ); - } + /* Free the context itself. */ + vPortFree( xSecureContextHandle ); + } } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/secure/secure_context.h b/portable/GCC/ARM_CM33/secure/secure_context.h index 747c2c6fd..62ef6bb94 100644 --- a/portable/GCC/ARM_CM33/secure/secure_context.h +++ b/portable/GCC/ARM_CM33/secure/secure_context.h @@ -37,13 +37,13 @@ /** * @brief PSP value when no task's context is loaded. */ -#define securecontextNO_STACK 0x0 +#define securecontextNO_STACK 0x0 /** * @brief Opaque handle. */ struct SecureContext; -typedef struct SecureContext* SecureContextHandle_t; +typedef struct SecureContext * SecureContextHandle_t; /*-----------------------------------------------------------*/ /** @@ -69,10 +69,11 @@ void SecureContext_Init( void ); * @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 ); +#if ( configENABLE_MPU == 1 ) + SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, + uint32_t ulIsTaskPrivileged ); #else /* configENABLE_MPU */ - SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ); + SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize ); #endif /* configENABLE_MPU */ /** diff --git a/portable/GCC/ARM_CM33/secure/secure_context_port.c b/portable/GCC/ARM_CM33/secure/secure_context_port.c index 6b4bc50c7..0187463ad 100644 --- a/portable/GCC/ARM_CM33/secure/secure_context_port.c +++ b/portable/GCC/ARM_CM33/secure/secure_context_port.c @@ -33,56 +33,56 @@ secureportNON_SECURE_CALLABLE void SecureContext_LoadContext( SecureContextHandle_t xSecureContextHandle ) { - /* xSecureContextHandle value is in r0. */ - __asm volatile - ( - " .syntax unified \n" - " \n" - " mrs r1, ipsr \n" /* r1 = IPSR. */ - " cbz r1, load_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ - " ldmia r0!, {r1, r2} \n" /* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */ - #if( configENABLE_MPU == 1 ) - " ldmia r1!, {r3} \n" /* Read CONTROL register value from task's stack. r3 = CONTROL. */ - " msr control, r3 \n" /* CONTROL = r3. */ - #endif /* configENABLE_MPU */ - " msr psplim, r2 \n" /* PSPLIM = r2. */ - " msr psp, r1 \n" /* PSP = r1. */ - " \n" - " load_ctx_therad_mode: \n" - " nop \n" - " \n" - :::"r0", "r1", "r2" - ); + /* xSecureContextHandle value is in r0. */ + __asm volatile + ( + " .syntax unified \n" + " \n" + " mrs r1, ipsr \n"/* r1 = IPSR. */ + " cbz r1, load_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */ + " ldmia r0!, {r1, r2} \n"/* r1 = xSecureContextHandle->pucCurrentStackPointer, r2 = xSecureContextHandle->pucStackLimit. */ + #if ( configENABLE_MPU == 1 ) + " ldmia r1!, {r3} \n"/* Read CONTROL register value from task's stack. r3 = CONTROL. */ + " msr control, r3 \n"/* CONTROL = r3. */ + #endif /* configENABLE_MPU */ + " msr psplim, r2 \n"/* PSPLIM = r2. */ + " msr psp, r1 \n"/* PSP = r1. */ + " \n" + " load_ctx_therad_mode: \n" + " nop \n" + " \n" + ::: "r0", "r1", "r2" + ); } /*-----------------------------------------------------------*/ secureportNON_SECURE_CALLABLE void SecureContext_SaveContext( SecureContextHandle_t xSecureContextHandle ) { - /* xSecureContextHandle value is in r0. */ - __asm volatile - ( - " .syntax unified \n" - " \n" - " mrs r1, ipsr \n" /* r1 = IPSR. */ - " cbz r1, save_ctx_therad_mode \n" /* Do nothing if the processor is running in the Thread Mode. */ - " mrs r1, psp \n" /* r1 = PSP. */ - #if( configENABLE_FPU == 1 ) - " vstmdb r1!, {s0} \n" /* Trigger the defferred stacking of FPU registers. */ - " vldmia r1!, {s0} \n" /* Nullify the effect of the pervious statement. */ - #endif /* configENABLE_FPU */ - #if( configENABLE_MPU == 1 ) - " mrs r2, control \n" /* r2 = CONTROL. */ - " stmdb r1!, {r2} \n" /* Store CONTROL value on the stack. */ - #endif /* configENABLE_MPU */ - " str r1, [r0] \n" /* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ - " movs r1, %0 \n" /* r1 = securecontextNO_STACK. */ - " msr psplim, r1 \n" /* PSPLIM = securecontextNO_STACK. */ - " msr psp, r1 \n" /* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */ - " \n" - " save_ctx_therad_mode: \n" - " nop \n" - " \n" - :: "i" ( securecontextNO_STACK ) : "r1", "memory" - ); + /* xSecureContextHandle value is in r0. */ + __asm volatile + ( + " .syntax unified \n" + " \n" + " mrs r1, ipsr \n"/* r1 = IPSR. */ + " cbz r1, save_ctx_therad_mode \n"/* Do nothing if the processor is running in the Thread Mode. */ + " mrs r1, psp \n"/* r1 = PSP. */ + #if ( configENABLE_FPU == 1 ) + " vstmdb r1!, {s0} \n"/* Trigger the defferred stacking of FPU registers. */ + " vldmia r1!, {s0} \n"/* Nullify the effect of the pervious statement. */ + #endif /* configENABLE_FPU */ + #if ( configENABLE_MPU == 1 ) + " mrs r2, control \n"/* r2 = CONTROL. */ + " stmdb r1!, {r2} \n"/* Store CONTROL value on the stack. */ + #endif /* configENABLE_MPU */ + " str r1, [r0] \n"/* Save the top of stack in context. xSecureContextHandle->pucCurrentStackPointer = r1. */ + " movs r1, %0 \n"/* r1 = securecontextNO_STACK. */ + " msr psplim, r1 \n"/* PSPLIM = securecontextNO_STACK. */ + " msr psp, r1 \n"/* PSP = securecontextNO_STACK i.e. No stack for thread mode until next task's context is loaded. */ + " \n" + " save_ctx_therad_mode: \n" + " nop \n" + " \n" + ::"i" ( securecontextNO_STACK ) : "r1", "memory" + ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/secure/secure_heap.c b/portable/GCC/ARM_CM33/secure/secure_heap.c index 7995a7f12..76b6ee1c3 100644 --- a/portable/GCC/ARM_CM33/secure/secure_heap.c +++ b/portable/GCC/ARM_CM33/secure/secure_heap.c @@ -37,37 +37,38 @@ /** * @brief Total heap size. */ -#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) ) +#define secureconfigTOTAL_HEAP_SIZE ( ( ( size_t ) ( 10 * 1024 ) ) ) /* No test marker by default. */ #ifndef mtCOVERAGE_TEST_MARKER - #define mtCOVERAGE_TEST_MARKER() + #define mtCOVERAGE_TEST_MARKER() #endif /* No tracing by default. */ #ifndef traceMALLOC - #define traceMALLOC( pvReturn, xWantedSize ) + #define traceMALLOC( pvReturn, xWantedSize ) #endif /* No tracing by default. */ #ifndef traceFREE - #define traceFREE( pv, xBlockSize ) + #define traceFREE( pv, xBlockSize ) #endif /* Block sizes must not get too small. */ -#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) +#define secureheapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) /* Assumes 8bit bytes! */ -#define secureheapBITS_PER_BYTE ( ( size_t ) 8 ) +#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 ]; +#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 ]; + static uint8_t ucHeap[ secureconfigTOTAL_HEAP_SIZE ]; #endif /* configAPPLICATION_ALLOCATED_HEAP */ /** @@ -77,8 +78,8 @@ */ 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. */ + struct A_BLOCK_LINK * pxNextFreeBlock; /**< The next free block in the list. */ + size_t xBlockSize; /**< The size of the free block. */ } BlockLink_t; /*-----------------------------------------------------------*/ @@ -97,7 +98,7 @@ static void prvHeapInit( void ); * * @param[in] pxBlockToInsert The block being freed. */ -static void prvInsertBlockIntoFreeList( BlockLink_t *pxBlockToInsert ); +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ); /*-----------------------------------------------------------*/ /** @@ -109,7 +110,7 @@ static const size_t xHeapStructSize = ( sizeof( BlockLink_t ) + ( ( size_t ) ( s /** * @brief Create a couple of list links to mark the start and end of the list. */ -static BlockLink_t xStart, *pxEnd = NULL; +static BlockLink_t xStart, * pxEnd = NULL; /** * @brief Keeps track of the number of free bytes remaining, but says nothing @@ -130,321 +131,324 @@ static size_t xBlockAllocatedBit = 0; static void prvHeapInit( void ) { -BlockLink_t *pxFirstFreeBlock; -uint8_t *pucAlignedHeap; -size_t uxAddress; -size_t xTotalHeapSize = secureconfigTOTAL_HEAP_SIZE; + 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; + /* 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; - } + 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; + 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; + /* 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; + /* 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; + /* 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; + /* 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 ); + /* 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 ) +static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) { -BlockLink_t *pxIterator; -uint8_t *puc; + 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. */ - } + /* 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 after + * make a contiguous block of memory? */ + puc = ( uint8_t * ) pxIterator; - /* 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( ( puc + pxIterator->xBlockSize ) == ( uint8_t * ) pxBlockToInsert ) + { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - /* 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(); - } + /* 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 ) +void * pvPortMalloc( size_t xWantedSize ) { -BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; -void *pvReturn = NULL; + 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(); - } + /* 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; + /* 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(); - } + /* 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( ( 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; - /* 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 ); + while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ) + { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } - /* This block is being returned for use so must be taken out - * of the list of free blocks. */ - pxPreviousBlock->pxNextFreeBlock = 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 ); - /* 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 ); + /* This block is being returned for use so must be taken out + * of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; - /* Calculate the sizes of two blocks split from the single - * block. */ - pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; - pxBlock->xBlockSize = xWantedSize; + /* 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 ); - /* Insert the new block into the list of free blocks. */ - prvInsertBlockIntoFreeList( pxNewBlockLink ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + /* Calculate the sizes of two blocks split from the single + * block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; - xFreeBytesRemaining -= pxBlock->xBlockSize; + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList( pxNewBlockLink ); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) - { - xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } + xFreeBytesRemaining -= pxBlock->xBlockSize; - /* 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(); - } + if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) + { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } + else + { + mtCOVERAGE_TEST_MARKER(); + } - traceMALLOC( pvReturn, xWantedSize ); + /* 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(); + } - #if( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) - { - if( pvReturn == NULL ) - { - extern void vApplicationMallocFailedHook( void ); - vApplicationMallocFailedHook(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif + traceMALLOC( pvReturn, xWantedSize ); - secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 ); - return pvReturn; + #if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) + { + if( pvReturn == NULL ) + { + extern void vApplicationMallocFailedHook( void ); + vApplicationMallocFailedHook(); + } + else + { + mtCOVERAGE_TEST_MARKER(); + } + } + #endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */ + + secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 ); + return pvReturn; } /*-----------------------------------------------------------*/ -void vPortFree( void *pv ) +void vPortFree( void * pv ) { -uint8_t *puc = ( uint8_t * ) pv; -BlockLink_t *pxLink; + 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; + 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; + /* 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 ); + /* 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; + 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(); - } - } + 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; + return xFreeBytesRemaining; } /*-----------------------------------------------------------*/ size_t xPortGetMinimumEverFreeHeapSize( void ) { - return xMinimumEverFreeBytesRemaining; + return xMinimumEverFreeBytesRemaining; } /*-----------------------------------------------------------*/ void vPortInitialiseBlocks( void ) { - /* This just exists to keep the linker quiet. */ + /* This just exists to keep the linker quiet. */ } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/secure/secure_heap.h b/portable/GCC/ARM_CM33/secure/secure_heap.h index aa67e39d8..d5ddaa853 100644 --- a/portable/GCC/ARM_CM33/secure/secure_heap.h +++ b/portable/GCC/ARM_CM33/secure/secure_heap.h @@ -39,13 +39,13 @@ * @return Pointer to the memory region if the allocation is successful, NULL * otherwise. */ -void *pvPortMalloc( size_t xWantedSize ); +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 ); +void vPortFree( void * pv ); #endif /* __SECURE_HEAP_H__ */ diff --git a/portable/GCC/ARM_CM33/secure/secure_init.c b/portable/GCC/ARM_CM33/secure/secure_init.c index 629186130..6f0be2547 100644 --- a/portable/GCC/ARM_CM33/secure/secure_init.c +++ b/portable/GCC/ARM_CM33/secure/secure_init.c @@ -37,69 +37,69 @@ /** * @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 ) +#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 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 ) +#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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); - } + /* 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; + uint32_t ulIPSR; - /* Read the Interrupt Program Status Register (IPSR) value. */ - secureportREAD_IPSR( 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 ); + /* 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 ); + /* 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 ); - } + /* 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 ); + } } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/secure/secure_port_macros.h b/portable/GCC/ARM_CM33/secure/secure_port_macros.h index 14ed3f022..d0ace6242 100644 --- a/portable/GCC/ARM_CM33/secure/secure_port_macros.h +++ b/portable/GCC/ARM_CM33/secure/secure_port_macros.h @@ -31,103 +31,103 @@ /** * @brief Byte alignment requirements. */ -#define secureportBYTE_ALIGNMENT 8 -#define secureportBYTE_ALIGNMENT_MASK ( 0x0007 ) +#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 + #define secureportNON_SECURE_CALLABLE __cmse_nonsecure_entry __root #else - #define secureportNON_SECURE_CALLABLE __attribute__((cmse_nonsecure_entry)) __attribute__((used)) + #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" ) + __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" ) + __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 ) ) + __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 ) ) + __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 ) ) + __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 ) ) + __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" ) + __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 ) ) + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulIPSR ) ) /** * @brief PRIMASK value to enable interrupts. */ -#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0 +#define secureportPRIMASK_ENABLE_INTERRUPTS_VAL 0 /** * @brief PRIMASK value to disable interrupts. */ -#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1 +#define secureportPRIMASK_DISABLE_INTERRUPTS_VAL 1 /** * @brief Disable secure interrupts. */ -#define secureportDISABLE_SECURE_INTERRUPTS() secureportSET_SECURE_PRIMASK( secureportPRIMASK_DISABLE_INTERRUPTS_VAL ) +#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 ) +#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 ) +#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( ;; ); \ - } +#define secureportASSERT( x ) \ + if( ( x ) == 0 ) \ + { \ + secureportDISABLE_SECURE_INTERRUPTS(); \ + secureportDISABLE_NON_SECURE_INTERRUPTS(); \ + for( ; ; ) {; } \ + } #endif /* __SECURE_PORT_MACROS_H__ */ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c index ba6bd2602..3f39bc3b1 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c @@ -40,10 +40,10 @@ /* Portasm includes. */ #include "portasm.h" -#if( configENABLE_TRUSTZONE == 1 ) - /* Secure components includes. */ - #include "secure_context.h" - #include "secure_init.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 @@ -63,126 +63,127 @@ * 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. +#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_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_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#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 ) +#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_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#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 ) #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 ) + #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 a the core. */ - #define portNVIC_SYSTICK_CLK_BIT ( 0 ) + +/* The way the SysTick is clocked is not modified in case it is not the + * same a the core. */ + #define portNVIC_SYSTICK_CLK_BIT ( 0 ) #endif /*-----------------------------------------------------------*/ /** * @brief Constants required to manipulate the SCB. */ -#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( * ( volatile uint32_t * ) 0xe000ed24 ) -#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) +#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 ) +#define portSCB_MEM_FAULT_ENABLE_BIT ( 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 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 ) +#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_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_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_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_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_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_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_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_ATTR0_POS ( 0UL ) +#define portMPU_MAIR_ATTR0_MASK ( 0x000000ff ) -#define portMPU_MAIR_ATTR1_POS ( 8UL ) -#define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 ) +#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_ATTR2_POS ( 16UL ) +#define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 ) -#define portMPU_MAIR_ATTR3_POS ( 24UL ) -#define portMPU_MAIR_ATTR3_MASK ( 0xff000000 ) +#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_ATTR4_POS ( 0UL ) +#define portMPU_MAIR_ATTR4_MASK ( 0x000000ff ) -#define portMPU_MAIR_ATTR5_POS ( 8UL ) -#define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 ) +#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_ATTR6_POS ( 16UL ) +#define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 ) -#define portMPU_MAIR_ATTR7_POS ( 24UL ) -#define portMPU_MAIR_ATTR7_MASK ( 0xff000000 ) +#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_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 ) +#define portMPU_RLAR_REGION_ENABLE ( 1UL ) /* Enable privileged access to unmapped region. */ -#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) +#define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL ) /* Enable MPU. */ -#define portMPU_ENABLE_BIT ( 1UL << 0UL ) +#define portMPU_ENABLE_BIT ( 1UL << 0UL ) /* Expected value of the portMPU_TYPE register. */ -#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ +#define portEXPECTED_MPU_TYPE_VALUE ( 8UL << 8UL ) /* 8 regions, unified. */ /*-----------------------------------------------------------*/ /** @@ -190,53 +191,55 @@ * * It is needed because the systick is a 24-bit counter. */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) /** * @brief 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 ) +#define portMISSED_COUNTS_FACTOR ( 45UL ) /*-----------------------------------------------------------*/ /** * @brief Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) +#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 ) +#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 ) + +/** + * @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 */ /** @@ -246,13 +249,13 @@ * Bit[0] = 0 ==> The task is privileged. * Bit[0] = 1 ==> The task is not privileged. */ -#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) +#define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL ) /** * @brief Initial CONTROL register values. */ -#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) -#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) +#define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 ) +#define portINITIAL_CONTROL_PRIVILEGED ( 0x2 ) /** * @brief Let the user override the pre-loading of the initial LR with the @@ -260,23 +263,23 @@ * in the debugger. */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #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 +#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 +#define portNO_SECURE_CONTEXT 0 /*-----------------------------------------------------------*/ /** @@ -285,18 +288,20 @@ */ static void prvTaskExitError( void ); -#if( configENABLE_MPU == 1 ) - /** - * @brief Setup the Memory Protection Unit (MPU). - */ - static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; +#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; +#if ( configENABLE_FPU == 1 ) + +/** + * @brief Setup the Floating Point Unit (FPU). + */ + static void prvSetupFPU( void ) PRIVILEGED_FUNCTION; #endif /* configENABLE_FPU */ /** @@ -338,812 +343,848 @@ void SysTick_Handler( void ) PRIVILEGED_FUNCTION; /** * @brief C part of SVC handler. */ -portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVILEGED_FUNCTION; +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; +PRIVILEGED_DATA 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; +#if ( configENABLE_TRUSTZONE == 1 ) + +/** + * @brief Saved as part of the task context to indicate which context the + * task is using on the secure side. + */ + PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ -#if( configUSE_TICKLESS_IDLE == 1 ) - /** - * @brief The number of SysTick increments that make up one tick period. - */ - static uint32_t ulTimerCountsForOneTick = 0; +#if ( configUSE_TICKLESS_IDLE == 1 ) - /** - * @brief The maximum number of tick periods that can be suppressed is - * limited by the 24 bit resolution of the SysTick timer. - */ - static uint32_t xMaximumPossibleSuppressedTicks = 0; +/** + * @brief The number of SysTick increments that make up one tick period. + */ + PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0; - /** - * @brief Compensate for the CPU cycles that pass while the SysTick is - * stopped (low power functionality only). - */ - static uint32_t ulStoppedTimerCompensation = 0; +/** + * @brief The maximum number of tick periods that can be suppressed is + * limited by the 24 bit resolution of the SysTick timer. + */ + PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0; + +/** + * @brief Compensate for the CPU cycles that pass while the SysTick is + * stopped (low power functionality only). + */ + PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0; #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ -#if( configUSE_TICKLESS_IDLE == 1 ) - __attribute__(( weak )) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; +#if ( configUSE_TICKLESS_IDLE == 1 ) + __attribute__( ( 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; - } + /* 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; + /* 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; - } + /* 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 ) ); - /* Enter a critical section but don't use the taskENTER_CRITICAL() - * method as that will mask interrupts that should exit sleep mode. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } - /* If a context switch is pending or a task is waiting for the scheduler - * to be un-suspended 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; + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* If a context switch is pending or a task is waiting for the scheduler + * to be un-suspended 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; - /* Reset the reload register to the value required for normal tick - * periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts - see comments above the cpsid instruction() - * above. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - /* Clear the SysTick count flag and set the count value back to - * zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* 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 ) - { - __asm volatile( "dsb" ::: "memory" ); - __asm volatile( "wfi" ); - __asm volatile( "isb" ); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts to allow the interrupt that brought the MCU - * out of sleep mode to execute immediately. See comments above - * the cpsid instruction above. */ - __asm volatile( "cpsie i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + /* 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 ); - /* 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. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "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 ); + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - /* 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; + /* Re-enable interrupts to allow the interrupt that brought the MCU + * out of sleep mode to execute immediately. See comments above + * the cpsid instruction above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); + /* 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. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); - } + /* 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 ); - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + /* 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; - /* 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; + /* 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 ); - /* How many complete tick periods passed while the processor - * was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + /* 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 ); + } - /* The reload value is set to whatever fraction of a single tick - * period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - /* 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; + /* 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; - /* Exit with interrupts enabled. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - } + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } #endif /* configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ +__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */ { - /* 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 */ + /* 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 reset the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* 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; + /* 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 prvTaskExitError( void ) { -volatile uint32_t ulDummy = 0UL; + 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(); + /* 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. */ - } + 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 ) */ +#if ( configENABLE_MPU == 1 ) + static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */ + { + #if 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 ); + /* 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 /* if defined( __ARMCC_VERSION ) */ + /* 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 ) */ - /* 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 ); + /* 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 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 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 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 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 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 ); + /* 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 ); - /* Enable mem fault. */ - portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; + /* 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 MPU with privileged background access i.e. unmapped - * regions have privileged access. */ - portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); - } - } + /* Enable mem fault. */ + portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT; + + /* Enable MPU with privileged background access i.e. unmapped + * regions have privileged access. */ + portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT ); + } + } #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 */ +#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 ) - ); + /* 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 ); - } + /* 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_REG = portNVIC_PENDSVSET_BIT; + /* Set a PendSV to request a context switch. */ + 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" ); + /* 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++; + 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" ); + /* 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--; + configASSERT( ulCriticalNesting ); + ulCriticalNesting--; - if( ulCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } + if( ulCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } } /*-----------------------------------------------------------*/ void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ { -uint32_t ulPreviousMask; + 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_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); + ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); } /*-----------------------------------------------------------*/ -void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */ +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 */ + #if ( configENABLE_MPU == 1 ) + #if defined( __ARMCC_VERSION ) -uint32_t ulPC; + /* 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 */ -#if( configENABLE_TRUSTZONE == 1 ) - uint32_t ulR0; - #if( configENABLE_MPU == 1 ) - uint32_t ulControl, ulIsTaskPrivileged; - #endif /* configENABLE_MPU */ -#endif /* configENABLE_TRUSTZONE */ -uint8_t ucSVCNumber; + uint32_t ulPC; - /* 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 ]; + #if ( configENABLE_TRUSTZONE == 1 ) + uint32_t ulR0; + #if ( configENABLE_MPU == 1 ) + uint32_t ulControl, ulIsTaskPrivileged; + #endif /* configENABLE_MPU */ + #endif /* configENABLE_TRUSTZONE */ + uint8_t ucSVCNumber; - 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 ]; + /* 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 ]; - #if( configENABLE_MPU == 1 ) - { - /* Read the CONTROL register value. */ - __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); + switch( ucSVCNumber ) + { + #if ( configENABLE_TRUSTZONE == 1 ) + case portSVC_ALLOCATE_SECURE_CONTEXT: - /* The task that raised the SVC is privileged if Bit[0] - * in the CONTROL register is 0. */ - ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); + /* R0 contains the stack size passed as parameter to the + * vPortAllocateSecureContext function. */ + ulR0 = pulCallerStackAddress[ 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 */ + #if ( configENABLE_MPU == 1 ) + { + /* Read the CONTROL register value. */ + __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) ); - configASSERT( xSecureContext != NULL ); - SecureContext_LoadContext( xSecureContext ); - } - break; + /* The task that raised the SVC is privileged if Bit[0] + * in the CONTROL register is 0. */ + ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 ); - case portSVC_FREE_SECURE_CONTEXT: - { - /* R0 contains the secure context handle to be freed. */ - ulR0 = pulCallerStackAddress[ 0 ]; + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged ); + } + #else /* if ( configENABLE_MPU == 1 ) */ + { + /* Allocate and load a context for the secure task. */ + xSecureContext = SecureContext_AllocateContext( ulR0 ); + } + #endif /* configENABLE_MPU */ - /* Free the secure context. */ - SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); - } - break; - #endif /* configENABLE_TRUSTZONE */ + configASSERT( xSecureContext != NULL ); + SecureContext_LoadContext( xSecureContext ); + break; - 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(); + case portSVC_FREE_SECURE_CONTEXT: + /* R0 contains the secure context handle to be freed. */ + ulR0 = pulCallerStackAddress[ 0 ]; - /* Initialize the secure context management system. */ - SecureContext_Init(); - } - #endif /* configENABLE_TRUSTZONE */ + /* Free the secure context. */ + SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 ); + break; + #endif /* configENABLE_TRUSTZONE */ - #if( configENABLE_FPU == 1 ) - { - /* Setup the Floating Point Unit (FPU). */ - prvSetupFPU(); - } - #endif /* configENABLE_FPU */ + 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(); - /* Setup the context of the first task so that the first task starts - * executing. */ - vRestoreContextOfFirstTask(); - } - break; + /* Initialize the secure context management system. */ + SecureContext_Init(); + } + #endif /* configENABLE_TRUSTZONE */ - #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 */ + #if ( configENABLE_FPU == 1 ) + { + /* Setup the Floating Point Unit (FPU). */ + prvSetupFPU(); + } + #endif /* configENABLE_FPU */ - default: - { - /* Incorrect SVC call. */ - configASSERT( pdFALSE ); - } - } + /* 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 */ +#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 */ + 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; + /* 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 */ + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + 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 */ - #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 */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ - #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 */ + #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 */ - pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */ + #if ( configENABLE_MPU == 1 ) + { + pxTopOfStack--; - #if( configENABLE_TRUSTZONE == 1 ) - { - pxTopOfStack--; - *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */ - } - #endif /* configENABLE_TRUSTZONE */ - } - #endif /* portPRELOAD_REGISTERS */ + 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 */ - return pxTopOfStack; + 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_REG |= portNVIC_PENDSV_PRI; - portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - #if( configENABLE_MPU == 1 ) - { - /* Setup the Memory Protection Unit (MPU). */ - prvSetupMPU(); - } - #endif /* configENABLE_MPU */ + #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(); + /* 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; + /* Initialize the critical nesting count ready for the first task. */ + ulCriticalNesting = 0; - /* Start the first task. */ - vStartFirstTask(); + /* 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 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; + /* 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 ); + /* 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; +#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; + #if defined( __ARMCC_VERSION ) + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + 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_sram_start__[]; + extern uint32_t __privileged_sram_end__[]; + #endif /* defined( __ARMCC_VERSION ) */ - /* 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 ); + /* 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; + /* 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 ) + { + ulRegionStartAddress = ( uint32_t ) pxBottomOfStack; + ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1; - xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ) | - ( portMPU_REGION_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ); + /* If the stack is within the privileged SRAM, do not protect it + * using a separate MPU region. This is needed because privileged + * SRAM is already protected using an MPU region and ARMv8-M does + * not allow overlapping MPU regions. */ + if( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ && + ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) + { + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0; + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0; + } + else + { + /* Define the region that allows access to the stack. */ + ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK; + ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK; - xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_ATTR_INDEX0 ) | - ( portMPU_RLAR_REGION_ENABLE ); - } + xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ) | + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ); - /* 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; + xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_ATTR_INDEX0 ) | + ( portMPU_RLAR_REGION_ENABLE ); + } + } - /* Start address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | - ( portMPU_REGION_NON_SHAREABLE ); + /* 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; - /* 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 ); - } + /* Start address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) | + ( portMPU_REGION_NON_SHAREABLE ); - /* XN. */ - if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) - { - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); - } + /* 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 ); + } - /* End Address. */ - xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | - ( portMPU_RLAR_REGION_ENABLE ); + /* XN. */ + if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 ) + { + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER ); + } - /* 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; - } + /* End Address. */ + xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) | + ( portMPU_RLAR_REGION_ENABLE ); - lIndex++; - } - } + /* 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; + 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" ); + /* 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; - } + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } - return xReturn; + return xReturn; } -/*-----------------------------------------------------------*/ \ No newline at end of file +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c b/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c index 1e3a4fc43..132fa4509 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c @@ -41,276 +41,276 @@ void vRestoreContextOfFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " \n" - " ldr r2, pxCurrentTCBConst2 \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r1, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r0, [r1] \n" /* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ - " str r4, [r2] \n" /* Disable MPU. */ - " \n" - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ - " ldr r3, [r1] \n" /* r3 = *r1 i.e. r3 = MAIR0. */ - " ldr r2, xMAIR0Const2 \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r3, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst2 \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " movs r3, #4 \n" /* r3 = 4. */ - " str r3, [r2] \n" /* Program RNR = 4. */ - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ - " ldr r2, xRBARConst2 \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 set of RBAR/RLAR registers from TCB. */ - " stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */ - " \n" - " ldr r2, xMPUCTRLConst2 \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ - " str r4, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " ldm r0!, {r1-r3} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ - " msr psplim, r1 \n" /* Set this task's PSPLIM value. */ - " msr control, r2 \n" /* Set this task's CONTROL value. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r3 \n" /* Finally, branch to EXC_RETURN. */ - #else /* configENABLE_MPU */ - " ldm r0!, {r1-r2} \n" /* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ - " msr psplim, r1 \n" /* Set this task's PSPLIM value. */ - " movs r1, #2 \n" /* r1 = 2. */ - " msr CONTROL, r1 \n" /* Switch to use PSP in the thread mode. */ - " adds r0, #32 \n" /* Discard everything up to r0. */ - " msr psp, r0 \n" /* This is now the new top of stack to use in the task. */ - " isb \n" - " bx r2 \n" /* Finally, branch to EXC_RETURN. */ - #endif /* configENABLE_MPU */ - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst2: .word 0xe000ed94 \n" - "xMAIR0Const2: .word 0xe000edc0 \n" - "xRNRConst2: .word 0xe000ed98 \n" - "xRBARConst2: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - ); + __asm volatile + ( + " .syntax unified \n" + " \n" + " ldr r2, pxCurrentTCBConst2 \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r1, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r0, [r1] \n"/* Read top of stack from TCB - The first item in pxCurrentTCB is the task top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ + " str r4, [r2] \n"/* Disable MPU. */ + " \n" + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ + " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ + " ldr r2, xMAIR0Const2 \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r3, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst2 \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " movs r3, #4 \n"/* r3 = 4. */ + " str r3, [r2] \n"/* Program RNR = 4. */ + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ + " ldr r2, xRBARConst2 \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 set of RBAR/RLAR registers from TCB. */ + " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ + " \n" + " ldr r2, xMPUCTRLConst2 \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ + " str r4, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " ldm r0!, {r1-r3} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL and r3 = EXC_RETURN. */ + " msr psplim, r1 \n"/* Set this task's PSPLIM value. */ + " msr control, r2 \n"/* Set this task's CONTROL value. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r3 \n"/* Finally, branch to EXC_RETURN. */ + #else /* configENABLE_MPU */ + " ldm r0!, {r1-r2} \n"/* Read from stack - r1 = PSPLIM and r2 = EXC_RETURN. */ + " msr psplim, r1 \n"/* Set this task's PSPLIM value. */ + " movs r1, #2 \n"/* r1 = 2. */ + " msr CONTROL, r1 \n"/* Switch to use PSP in the thread mode. */ + " adds r0, #32 \n"/* Discard everything up to r0. */ + " msr psp, r0 \n"/* This is now the new top of stack to use in the task. */ + " isb \n" + " bx r2 \n"/* Finally, branch to EXC_RETURN. */ + #endif /* configENABLE_MPU */ + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst2: .word 0xe000ed94 \n" + "xMAIR0Const2: .word 0xe000edc0 \n" + "xRNRConst2: .word 0xe000ed98 \n" + "xRBARConst2: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ); } /*-----------------------------------------------------------*/ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ - " ite ne \n" - " movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n" /* Return. */ - " \n" - " .align 4 \n" - ::: "r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ + " ite ne \n" + " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ + " \n" + " .align 4 \n" + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vRaisePrivilege( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, control \n" /* Read the CONTROL register. */ - " bic r0, #1 \n" /* Clear the bit 0. */ - " msr control, r0 \n" /* Write back the new CONTROL value. */ - " bx lr \n" /* Return to the caller. */ - ::: "r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* Read the CONTROL register. */ + " bic r0, #1 \n"/* Clear the bit 0. */ + " msr control, r0 \n"/* Write back the new CONTROL value. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " orr r0, #1 \n" /* r0 = r0 | 1. */ - " msr control, r0 \n" /* CONTROL = r0. */ - " bx lr \n" /* Return to the caller. */ - :::"r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " orr r0, #1 \n"/* r0 = r0 | 1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vStartFirstTask( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " ldr r0, xVTORConst \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" /* Read the VTOR register which gives the address of vector table. */ - " ldr r0, [r0] \n" /* The first entry in vector table is stack pointer. */ - " msr msp, r0 \n" /* Set the MSP back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc %0 \n" /* System call to start the first task. */ - " nop \n" - " \n" - " .align 4 \n" - "xVTORConst: .word 0xe000ed08 \n" - :: "i" ( portSVC_START_SCHEDULER ) : "memory" - ); + __asm volatile + ( + " ldr r0, xVTORConst \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n"/* Read the VTOR register which gives the address of vector table. */ + " ldr r0, [r0] \n"/* The first entry in vector table is stack pointer. */ + " msr msp, r0 \n"/* Set the MSP back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc %0 \n"/* System call to start the first task. */ + " nop \n" + " \n" + " .align 4 \n" + "xVTORConst: .word 0xe000ed08 \n" + ::"i" ( portSVC_START_SCHEDULER ) : "memory" + ); } /*-----------------------------------------------------------*/ uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " mrs r0, basepri \n" /* r0 = basepri. Return original basepri value. */ - " mov r1, %0 \n" /* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ - " msr basepri, r1 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ - " dsb \n" - " isb \n" - " bx lr \n" /* Return. */ - :: "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); + __asm volatile + ( + " mrs r0, basepri \n"/* r0 = basepri. Return original basepri value. */ + " mov r1, %0 \n"/* r1 = configMAX_SYSCALL_INTERRUPT_PRIORITY. */ + " msr basepri, r1 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ + " dsb \n" + " isb \n" + " bx lr \n"/* Return. */ + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); } /*-----------------------------------------------------------*/ void vClearInterruptMask( __attribute__( ( unused ) ) uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " msr basepri, r0 \n" /* basepri = ulMask. */ - " dsb \n" - " isb \n" - " bx lr \n" /* Return. */ - ::: "memory" - ); + __asm volatile + ( + " msr basepri, r0 \n"/* basepri = ulMask. */ + " dsb \n" + " isb \n" + " bx lr \n"/* Return. */ + ::: "memory" + ); } /*-----------------------------------------------------------*/ void PendSV_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " .syntax unified \n" - " \n" - " mrs r0, psp \n" /* Read PSP in r0. */ - #if( configENABLE_FPU == 1 ) - " tst lr, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ - " it eq \n" - " vstmdbeq r0!, {s16-s31} \n" /* Store the FPU registers which are not saved automatically. */ - #endif /* configENABLE_FPU */ - #if( configENABLE_MPU == 1 ) - " mrs r1, psplim \n" /* r1 = PSPLIM. */ - " mrs r2, control \n" /* r2 = CONTROL. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " stmdb r0!, {r1-r11} \n" /* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ - #else /* configENABLE_MPU */ - " mrs r2, psplim \n" /* r2 = PSPLIM. */ - " mov r3, lr \n" /* r3 = LR/EXC_RETURN. */ - " stmdb r0!, {r2-r11} \n" /* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ - #endif /* configENABLE_MPU */ - " \n" - " ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r1, [r2] \n" /* Read pxCurrentTCB. */ - " str r0, [r1] \n" /* Save the new top of stack in TCB. */ - " \n" - " mov r0, %0 \n" /* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ - " msr basepri, r0 \n" /* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ - " dsb \n" - " isb \n" - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" /* r0 = 0. */ - " msr basepri, r0 \n" /* Enable interrupts. */ - " \n" - " ldr r2, pxCurrentTCBConst \n" /* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ - " ldr r1, [r2] \n" /* Read pxCurrentTCB. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ - " \n" - #if( configENABLE_MPU == 1 ) - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r4, #1 \n" /* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ - " str r4, [r2] \n" /* Disable MPU. */ - " \n" - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ - " ldr r3, [r1] \n" /* r3 = *r1 i.e. r3 = MAIR0. */ - " ldr r2, xMAIR0Const \n" /* r2 = 0xe000edc0 [Location of MAIR0]. */ - " str r3, [r2] \n" /* Program MAIR0. */ - " ldr r2, xRNRConst \n" /* r2 = 0xe000ed98 [Location of RNR]. */ - " movs r3, #4 \n" /* r3 = 4. */ - " str r3, [r2] \n" /* Program RNR = 4. */ - " adds r1, #4 \n" /* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ - " ldr r2, xRBARConst \n" /* r2 = 0xe000ed9c [Location of RBAR]. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of RBAR/RLAR registers from TCB. */ - " stmia r2!, {r4-r11} \n" /* Write 4 set of RBAR/RLAR registers using alias registers. */ - " \n" - " ldr r2, xMPUCTRLConst \n" /* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ - " ldr r4, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r4, #1 \n" /* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ - " str r4, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " ldmia r0!, {r1-r11} \n" /* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ - #else /* configENABLE_MPU */ - " ldmia r0!, {r2-r11} \n" /* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ - #endif /* configENABLE_MPU */ - " \n" - #if( configENABLE_FPU == 1 ) - " tst r3, #0x10 \n" /* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ - " it eq \n" - " vldmiaeq r0!, {s16-s31} \n" /* Restore the FPU registers which are not restored automatically. */ - #endif /* configENABLE_FPU */ - " \n" - #if( configENABLE_MPU == 1 ) - " msr psplim, r1 \n" /* Restore the PSPLIM register value for the task. */ - " msr control, r2 \n" /* Restore the CONTROL register value for the task. */ - #else /* configENABLE_MPU */ - " msr psplim, r2 \n" /* Restore the PSPLIM register value for the task. */ - #endif /* configENABLE_MPU */ - " msr psp, r0 \n" /* Remember the new top of stack for the task. */ - " bx r3 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - #if( configENABLE_MPU == 1 ) - "xMPUCTRLConst: .word 0xe000ed94 \n" - "xMAIR0Const: .word 0xe000edc0 \n" - "xRNRConst: .word 0xe000ed98 \n" - "xRBARConst: .word 0xe000ed9c \n" - #endif /* configENABLE_MPU */ - :: "i"( configMAX_SYSCALL_INTERRUPT_PRIORITY ) - ); + __asm volatile + ( + " .syntax unified \n" + " \n" + " mrs r0, psp \n"/* Read PSP in r0. */ + #if ( configENABLE_FPU == 1 ) + " tst lr, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ + " it eq \n" + " vstmdbeq r0!, {s16-s31} \n"/* Store the FPU registers which are not saved automatically. */ + #endif /* configENABLE_FPU */ + #if ( configENABLE_MPU == 1 ) + " mrs r1, psplim \n"/* r1 = PSPLIM. */ + " mrs r2, control \n"/* r2 = CONTROL. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " stmdb r0!, {r1-r11} \n"/* Store on the stack - PSPLIM, CONTROL, LR and registers that are not automatically saved. */ + #else /* configENABLE_MPU */ + " mrs r2, psplim \n"/* r2 = PSPLIM. */ + " mov r3, lr \n"/* r3 = LR/EXC_RETURN. */ + " stmdb r0!, {r2-r11} \n"/* Store on the stack - PSPLIM, LR and registers that are not automatically saved. */ + #endif /* configENABLE_MPU */ + " \n" + " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r1, [r2] \n"/* Read pxCurrentTCB. */ + " str r0, [r1] \n"/* Save the new top of stack in TCB. */ + " \n" + " mov r0, %0 \n"/* r0 = configMAX_SYSCALL_INTERRUPT_PRIORITY */ + " msr basepri, r0 \n"/* Disable interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY. */ + " dsb \n" + " isb \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n"/* r0 = 0. */ + " msr basepri, r0 \n"/* Enable interrupts. */ + " \n" + " ldr r2, pxCurrentTCBConst \n"/* Read the location of pxCurrentTCB i.e. &( pxCurrentTCB ). */ + " ldr r1, [r2] \n"/* Read pxCurrentTCB. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. r0 now points to the top of stack. */ + " \n" + #if ( configENABLE_MPU == 1 ) + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r4, #1 \n"/* r4 = r4 & ~1 i.e. Clear the bit 0 in r4. */ + " str r4, [r2] \n"/* Disable MPU. */ + " \n" + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to MAIR0 in TCB. */ + " ldr r3, [r1] \n"/* r3 = *r1 i.e. r3 = MAIR0. */ + " ldr r2, xMAIR0Const \n"/* r2 = 0xe000edc0 [Location of MAIR0]. */ + " str r3, [r2] \n"/* Program MAIR0. */ + " ldr r2, xRNRConst \n"/* r2 = 0xe000ed98 [Location of RNR]. */ + " movs r3, #4 \n"/* r3 = 4. */ + " str r3, [r2] \n"/* Program RNR = 4. */ + " adds r1, #4 \n"/* r1 = r1 + 4. r1 now points to first RBAR in TCB. */ + " ldr r2, xRBARConst \n"/* r2 = 0xe000ed9c [Location of RBAR]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of RBAR/RLAR registers from TCB. */ + " stmia r2!, {r4-r11} \n"/* Write 4 set of RBAR/RLAR registers using alias registers. */ + " \n" + " ldr r2, xMPUCTRLConst \n"/* r2 = 0xe000ed94 [Location of MPU_CTRL]. */ + " ldr r4, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r4, #1 \n"/* r4 = r4 | 1 i.e. Set the bit 0 in r4. */ + " str r4, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " ldmia r0!, {r1-r11} \n"/* Read from stack - r1 = PSPLIM, r2 = CONTROL, r3 = LR and r4-r11 restored. */ + #else /* configENABLE_MPU */ + " ldmia r0!, {r2-r11} \n"/* Read from stack - r2 = PSPLIM, r3 = LR and r4-r11 restored. */ + #endif /* configENABLE_MPU */ + " \n" + #if ( configENABLE_FPU == 1 ) + " tst r3, #0x10 \n"/* Test Bit[4] in LR. Bit[4] of EXC_RETURN is 0 if the FPU is in use. */ + " it eq \n" + " vldmiaeq r0!, {s16-s31} \n"/* Restore the FPU registers which are not restored automatically. */ + #endif /* configENABLE_FPU */ + " \n" + #if ( configENABLE_MPU == 1 ) + " msr psplim, r1 \n"/* Restore the PSPLIM register value for the task. */ + " msr control, r2 \n"/* Restore the CONTROL register value for the task. */ + #else /* configENABLE_MPU */ + " msr psplim, r2 \n"/* Restore the PSPLIM register value for the task. */ + #endif /* configENABLE_MPU */ + " msr psp, r0 \n"/* Remember the new top of stack for the task. */ + " bx r3 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + #if ( configENABLE_MPU == 1 ) + "xMPUCTRLConst: .word 0xe000ed94 \n" + "xMAIR0Const: .word 0xe000edc0 \n" + "xRNRConst: .word 0xe000ed98 \n" + "xRBARConst: .word 0xe000ed9c \n" + #endif /* configENABLE_MPU */ + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); } /*-----------------------------------------------------------*/ void SVC_Handler( void ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */ { - __asm volatile - ( - " tst lr, #4 \n" - " ite eq \n" - " mrseq r0, msp \n" - " mrsne r0, psp \n" - " ldr r1, svchandler_address_const \n" - " bx r1 \n" - " \n" - " .align 4 \n" - "svchandler_address_const: .word vPortSVCHandler_C \n" - ); + __asm volatile + ( + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, svchandler_address_const \n" + " bx r1 \n" + " \n" + " .align 4 \n" + "svchandler_address_const: .word vPortSVCHandler_C \n" + ); } /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h b/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h index 71d711c69..fdba1b177 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.h @@ -38,14 +38,14 @@ * @brief Restore the context of the first task so that the first task starts * executing. */ -void vRestoreContextOfFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +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 )); +BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); /** * @brief Raises the privilege level by clearing the bit 0 of the CONTROL @@ -58,7 +58,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vRaisePrivilege( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Lowers the privilege level by setting the bit 0 of the CONTROL @@ -68,32 +68,32 @@ void vRaisePrivilege( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vResetPrivilege( void ) __attribute__ (( naked )); +void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Starts the first task. */ -void vStartFirstTask( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vStartFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Disables interrupts. */ -uint32_t ulSetInterruptMask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +uint32_t ulSetInterruptMask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Enables interrupts. */ -void vClearInterruptMask( uint32_t ulMask ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +void vClearInterruptMask( uint32_t ulMask ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief PendSV Exception handler. */ -void PendSV_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void PendSV_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief SVC Handler. */ -void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void SVC_Handler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /** * @brief Allocate a Secure context for the calling task. @@ -101,13 +101,13 @@ void SVC_Handler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; * @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 )); +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; +void vPortFreeSecureContext( uint32_t * pulTCB ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; #endif /* __PORT_ASM_H__ */ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h index d2c849c77..bb4d2495d 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h @@ -26,11 +26,11 @@ */ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*------------------------------------------------------------------------------ * Port specific definitions. @@ -42,109 +42,109 @@ extern "C" { *------------------------------------------------------------------------------ */ -#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_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_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 */ + #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 + #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 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 + #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 +/* 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 __attribute__(( used )) + #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 __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ -extern BaseType_t xPortIsInsideInterrupt( void ); + extern BaseType_t xPortIsInsideInterrupt( void ); -extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; + extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; -extern void vPortExitCritical( 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 */; + 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_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 */ + #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 */ + #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. */ + #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. * @@ -156,155 +156,157 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * 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 */ + #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. */ + #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_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_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 ) + #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; + 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; + 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 + #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 ) + #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() + #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 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 + #ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + #endif /*-----------------------------------------------------------*/ /** * @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 ) + #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 ) + #if ( configENABLE_TRUSTZONE == 1 ) - /** - * @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 */ +/** + * @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() + #if ( configENABLE_MPU == 1 ) - /** - * @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 Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ + #define portIS_PRIVILEGED() xIsPrivileged() - /** - * @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 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" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM3_MPU/port.c b/portable/GCC/ARM_CM3_MPU/port.c index a22ce529d..d95503f7f 100644 --- a/portable/GCC/ARM_CM3_MPU/port.c +++ b/portable/GCC/ARM_CM3_MPU/port.c @@ -26,8 +26,8 @@ */ /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM3 port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the ARM CM3 MPU port. +*----------------------------------------------------------*/ /* 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 @@ -41,66 +41,67 @@ #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #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 ( 1UL << 2UL ) + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK ( 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 ( 0 ) + +/* The way the SysTick is clocked is not modified in case it is not the same + * as the core. */ + #define portNVIC_SYSTICK_CLK ( 0 ) #endif /* Constants required to access and 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_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 ) +#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_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SHPR2_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 +#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 /* Constants required to access and manipulate the SysTick. */ -#define portNVIC_SYSTICK_INT ( 0x00000002UL ) -#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) -#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 ) +#define portNVIC_SYSTICK_INT ( 0x00000002UL ) +#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) +#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 set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) -#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) -#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) +#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) /* 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 ) +#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 ) /* Offsets in the stack to the parameters when inside the SVC handler. */ -#define portOFFSET_TO_PC ( 6 ) +#define portOFFSET_TO_PC ( 6 ) /* 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 ) +#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) /*-----------------------------------------------------------*/ /* @@ -125,27 +126,27 @@ void vPortSetupTimerInterrupt( void ); /* * Standard FreeRTOS exception handlers. */ -void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; -void xPortSysTickHandler( void ) __attribute__ ((optimize("3"))) PRIVILEGED_FUNCTION; -void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void xPortPendSVHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; +void xPortSysTickHandler( void ) __attribute__( ( optimize( "3" ) ) ) PRIVILEGED_FUNCTION; +void vPortSVCHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /* * Starts the scheduler by restoring the context of the first task to run. */ -static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +static void prvRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /* * C portion of the SVC handler. The SVC handler is split between an asm entry * and a C wrapper for simplicity of coding and maintenance. */ -static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION; +static void prvSVCHandler( uint32_t * pulRegisters ) __attribute__( ( noinline ) ) 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 )); +BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); /** * @brief Lowers the privilege level by setting the bit 0 of the CONTROL @@ -155,7 +156,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vResetPrivilege( void ) __attribute__ (( naked )); +void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Calls the port specific code to raise the privilege. @@ -182,173 +183,184 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; * 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; + 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 ) +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. */ - 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 = 0; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + /* 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 = 0; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + 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; - } + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED; + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED; + } - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ void vPortSVCHandler( void ) { - /* Assumes psp was in use. */ - __asm volatile - ( - #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ - " tst lr, #4 \n" - " ite eq \n" - " mrseq r0, msp \n" - " mrsne r0, psp \n" - #else - " mrs r0, psp \n" - #endif - " b %0 \n" - ::"i"(prvSVCHandler):"r0", "memory" - ); + /* Assumes psp was in use. */ + __asm volatile + ( + #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + #else + " mrs r0, psp \n" + #endif + " b %0 \n" + ::"i" ( prvSVCHandler ) : "r0", "memory" + ); } /*-----------------------------------------------------------*/ -static void prvSVCHandler( uint32_t *pulParam ) +static void prvSVCHandler( uint32_t * pulParam ) { -uint8_t ucSVCNumber; -uint32_t ulPC; -#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 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 /* #if defined( __ARMCC_VERSION ) */ -#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ + uint8_t ucSVCNumber; + uint32_t ulPC; - /* 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 ]; + #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) + #if defined( __ARMCC_VERSION ) - switch( ucSVCNumber ) - { - case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI; - prvRestoreContextOfFirstTask(); - break; + /* 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 /* #if defined( __ARMCC_VERSION ) */ + #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ - 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" ); + /* 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 ]; - break; + switch( ucSVCNumber ) + { + case portSVC_START_SCHEDULER: + portNVIC_SHPR2_REG |= portNVIC_SVC_PRI; + prvRestoreContextOfFirstTask(); + 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, #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, #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 ) */ + #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. */ - default : /* Unknown SVC call. */ - break; - } + 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, #1 \n"/* Set privilege bit. */ + " msr control, r1 \n"/* Write back new control value. */ + ::: "r1", "memory" + ); + } + + break; + #else /* if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ + case portSVC_RAISE_PRIVILEGE: + __asm volatile + ( + " mrs r1, control \n"/* Obtain current control value. */ + " bic 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; + } } /*-----------------------------------------------------------*/ static void prvRestoreContextOfFirstTask( void ) { - __asm volatile - ( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ - " \n" - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ - " \n" - " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ - " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ - " \n" - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - " \n" - " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ - " msr control, r3 \n" - " msr psp, r0 \n" /* Restore the task stack pointer. */ - " mov r0, #0 \n" - " msr basepri, r0 \n" - " ldr r14, =0xfffffffd \n" /* Load exec return code. */ - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); + __asm volatile + ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " \n" + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ + " \n" + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + " \n" + " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " msr psp, r0 \n"/* Restore the task stack pointer. */ + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldr r14, =0xfffffffd \n"/* Load exec return code. */ + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); } /*-----------------------------------------------------------*/ @@ -357,213 +369,216 @@ static void prvRestoreContextOfFirstTask( void ) */ 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 ) ); + /* 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; + #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. + /* 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; - * 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; - /* 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; - /* 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; - /* 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; - /* 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; - } + 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 __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 + #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; + /* 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 */ + /* Restore the clobbered interrupt priority register to its original + * value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ - /* Make PendSV and SysTick the same priority as the kernel, and the SVC - * handler higher priority so it can be used to exit a critical section (where - * lower priorities are masked). */ - portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; - portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + /* Make PendSV and SysTick the same priority as the kernel, and the SVC + * handler higher priority so it can be used to exit a critical section (where + * lower priorities are masked). */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - /* Configure the regions in the MPU that are common to all tasks. */ - prvSetupMPU(); + /* 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(); + /* 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; + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; - /* Start the first task. */ - __asm volatile( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc %0 \n" /* System call to start first task. */ - " nop \n" - " .ltorg \n" - :: "i" (portSVC_START_SCHEDULER) : "memory" ); + /* Start the first task. */ + __asm volatile ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc %0 \n"/* System call to start first task. */ + " nop \n" + " .ltorg \n" + ::"i" ( portSVC_START_SCHEDULER ) : "memory" ); - /* Should not get here! */ - return 0; + /* 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 ); + /* 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(); + BaseType_t xRunningPrivileged = xPortRaisePrivilege(); - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; - vPortResetPrivilege( xRunningPrivileged ); + vPortResetPrivilege( xRunningPrivileged ); } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { -BaseType_t xRunningPrivileged = xPortRaisePrivilege(); + BaseType_t xRunningPrivileged = xPortRaisePrivilege(); - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } - vPortResetPrivilege( xRunningPrivileged ); + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + + vPortResetPrivilege( xRunningPrivileged ); } /*-----------------------------------------------------------*/ void xPortPendSVHandler( void ) { - /* This is a naked function. */ + /* This is a naked function. */ - __asm volatile - ( - " mrs r0, psp \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " mrs r1, control \n" - " stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ - " \n" - " stmdb sp!, {r3, r14} \n" - " mov r0, %0 \n" - " msr basepri, r0 \n" - " dsb \n" - " isb \n" - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " ldmia sp!, {r3, r14} \n" - " \n" /* Restore the context. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ - " \n" - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ - " \n" - " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ - " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ - " \n" - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - " \n" - " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ - " msr control, r3 \n" - " \n" - " msr psp, r0 \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) - ); + __asm volatile + ( + " mrs r0, psp \n" + " \n" + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " mrs r1, control \n" + " stmdb r0!, {r1, r4-r11} \n"/* Save the remaining registers. */ + " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r3, r14} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " dsb \n" + " isb \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r3, r14} \n" + " \n"/* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " \n" + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ + " \n" + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + " \n" + " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " \n" + " msr psp, r0 \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); } /*-----------------------------------------------------------*/ void xPortSysTickHandler( void ) { -uint32_t ulDummy; + uint32_t ulDummy; - ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); - { - /* Increment the RTOS tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - /* Pend a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); } /*-----------------------------------------------------------*/ @@ -571,288 +586,291 @@ uint32_t ulDummy; * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) { - /* Stop and clear the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* 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 | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE ); + /* 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 | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE ); } /*-----------------------------------------------------------*/ static void prvSetupMPU( void ) { -extern uint32_t __privileged_functions_start__[]; -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__[]; + extern uint32_t __privileged_functions_start__[]; + 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 unprivileged flash for unprivileged read only access. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portUNPRIVILEGED_FLASH_REGION ); + /* Check the expected MPU is present. */ + if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) + { + /* First setup the unprivileged 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 ); + 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 privileged flash for privileged only access. This is where - * the kernel code is * placed. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portPRIVILEGED_FLASH_REGION ); + /* Setup the privileged flash for privileged only access. This is where + * the kernel code is * placed. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_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 ) __privileged_functions_start__ ) ) | - ( portMPU_REGION_ENABLE ); + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | + ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_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 ); + /* 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 ); + 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 ); + /* 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 ); + 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 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 ); - } + /* 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; + 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++; - } - } + /* 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 ); + /* 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 ); } /*-----------------------------------------------------------*/ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ - " ite ne \n" - " movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n" /* Return. */ - " \n" - " .align 4 \n" - ::: "r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ + " ite ne \n" + " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ + " \n" + " .align 4 \n" + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " orr r0, #1 \n" /* r0 = r0 | 1. */ - " msr control, r0 \n" /* CONTROL = r0. */ - " bx lr \n" /* Return to the caller. */ - :::"r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " orr r0, #1 \n"/* r0 = r0 | 1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ -void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) +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; + 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 ); + 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 ); + 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 ); + /* 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 ); + 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. */ + /* 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 ); - } + 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; + 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. */ + 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; - } + 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++; - } - } + lIndex++; + } + } } /*-----------------------------------------------------------*/ -#if( configASSERT_DEFINED == 1 ) +#if ( configASSERT_DEFINED == 1 ) - void vPortValidateInterruptPriority( void ) - { - uint32_t ulCurrentInterrupt; - uint8_t ucCurrentPriority; + 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" ); + /* 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 ]; + /* 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. + /* 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 ); + } - * 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 unpredicable behaviour. */ - configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); - } + /* 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 unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } #endif /* configASSERT_DEFINED */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM3_MPU/portmacro.h b/portable/GCC/ARM_CM3_MPU/portmacro.h index 61da7413a..3df29df08 100644 --- a/portable/GCC/ARM_CM3_MPU/portmacro.h +++ b/portable/GCC/ARM_CM3_MPU/portmacro.h @@ -27,11 +27,11 @@ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*----------------------------------------------------------- * Port specific definitions. @@ -44,265 +44,265 @@ extern "C" { */ /* 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 + #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 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 + #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 +/* 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 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 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 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, #1 \n msr control, r0 " ::: "r0", "memory" ) + #define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " ::: "r0", "memory" ) -typedef struct MPU_REGION_REGISTERS -{ - uint32_t ulRegionBaseAddress; - uint32_t ulRegionAttribute; -} xMPU_REGION_REGISTERS; + 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; + 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 -#define portDONT_DISCARD __attribute__(( used )) + #define portSTACK_GROWTH ( -1 ) + #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) + #define portBYTE_ALIGNMENT 8 + #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* SVC numbers for various services. */ -#define portSVC_START_SCHEDULER 0 -#define portSVC_YIELD 1 -#define portSVC_RAISE_PRIVILEGE 2 + #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; \ - \ - /* 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" ); \ -} + #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; \ + \ + /* 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" ); \ + } -#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 ) + #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 ) /*-----------------------------------------------------------*/ /* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); -#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) -#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() -#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() + extern void vPortEnterCritical( void ); + extern void vPortExitCritical( void ); + #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x ) + #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() + #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 ) + #define portENTER_CRITICAL() vPortEnterCritical() + #define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* 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 ) + * 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 ) /*-----------------------------------------------------------*/ /* Architecture specific optimisations. */ -#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#endif + #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #endif -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - /* Generic helper function. */ - __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) - { - uint8_t ucReturn; +/* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; - __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - return ucReturn; - } + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - /* 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 + return ucReturn; + } - /* 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 ) ) +/* 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 - /*-----------------------------------------------------------*/ - - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) - -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/* 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 ) ) /*-----------------------------------------------------------*/ -#ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() -#endif + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + + #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + + #ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif /* portNOP() is not required by this port. */ -#define portNOP() + #define portNOP() -#define portINLINE __inline + #define portINLINE __inline -#ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) -#endif + #ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) + #endif /*-----------------------------------------------------------*/ -extern BaseType_t xIsPrivileged( void ); -extern void vResetPrivilege( void ); + 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() + #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" ); + */ + #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() + #define portRESET_PRIVILEGE() vResetPrivilege() /*-----------------------------------------------------------*/ -portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) -{ -uint32_t ulCurrentInterrupt; -BaseType_t xReturn; + 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" ); + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } - return xReturn; -} + return xReturn; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortRaiseBASEPRI( void ) -{ -uint32_t ulNewBASEPRI; + portFORCE_INLINE static void vPortRaiseBASEPRI( void ) + { + uint32_t ulNewBASEPRI; - __asm volatile - ( - " mov %0, %1 \n" \ - " msr basepri, %0 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); -} + __asm volatile + ( + " mov %0, %1 \n"\ + " msr basepri, %0 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) -{ -uint32_t ulOriginalBASEPRI, ulNewBASEPRI; + portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) + { + uint32_t ulOriginalBASEPRI, ulNewBASEPRI; - __asm volatile - ( - " mrs %0, basepri \n" \ - " mov %1, %2 \n" \ - " msr basepri, %1 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); + __asm volatile + ( + " mrs %0, basepri \n"\ + " mov %1, %2 \n"\ + " msr basepri, %1 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); - /* This return will not be reached but is necessary to prevent compiler - warnings. */ - return ulOriginalBASEPRI; -} + /* This return will not be reached but is necessary to prevent compiler + * warnings. */ + return ulOriginalBASEPRI; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) -{ - __asm volatile - ( - " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory" - ); -} + portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) + { + __asm volatile + ( + " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" + ); + } /*-----------------------------------------------------------*/ -#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) -#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 + #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 /*-----------------------------------------------------------*/ -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ - diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c index 2dd152536..43ca92fc0 100644 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -26,88 +26,89 @@ */ /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM4F port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the ARM CM4F port. +*----------------------------------------------------------*/ /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" #ifndef __VFP_FP__ - #error This port can only be used when the project options are configured to enable hardware floating point support. + #error This port can only be used when the project options are configured to enable hardware floating point support. #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 ) + #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 ) + +/* 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_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_SHPR3_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_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 ) + * 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_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 ) +#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 ) +#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 ) +#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_XPSR ( 0x01000000 ) +#define portINITIAL_EXC_RETURN ( 0xfffffffd ) /* The systick is a 24-bit counter. */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) /* 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 ) + * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ +#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) /* 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 ) + * occurred while the SysTick counter is stopped during tickless idle + * calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) /* 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. */ + * prvTaskExitError() in case it messes up unwinding of the stack in the + * debugger. */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* @@ -120,19 +121,19 @@ void vPortSetupTimerInterrupt( void ); /* * Exception handlers. */ -void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortPendSVHandler( void ) __attribute__( ( naked ) ); void xPortSysTickHandler( void ); -void vPortSVCHandler( void ) __attribute__ (( naked )); +void vPortSVCHandler( void ) __attribute__( ( naked ) ); /* * Start first task is a separate function so it can be tested in isolation. */ -static void prvPortStartFirstTask( void ) __attribute__ (( naked )); +static void prvPortStartFirstTask( void ) __attribute__( ( naked ) ); /* * Function to enable the VFP. */ -static void vPortEnableVFP( void ) __attribute__ (( naked )); +static void vPortEnableVFP( void ) __attribute__( ( naked ) ); /* * Used to catch tasks that attempt to return from their implementing function. @@ -142,30 +143,30 @@ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* Each task maintains its own interrupt status in the critical nesting -variable. */ + * 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; +#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; +#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; +#if ( configUSE_TICKLESS_IDLE == 1 ) + static uint32_t ulStoppedTimerCompensation = 0; #endif /* configUSE_TICKLESS_IDLE */ /* @@ -173,10 +174,10 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; * 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; +#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 */ /*-----------------------------------------------------------*/ @@ -184,101 +185,104 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * See header file for description. */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +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. */ + /* 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--; + /* 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 ) portTASK_RETURN_ADDRESS; /* LR */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - /* Save code space by skipping register initialisation. */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + /* 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; + /* 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. */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ static void prvTaskExitError( void ) { -volatile uint32_t ulDummy = 0; + volatile uint32_t ulDummy = 0; - /* 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 ). + /* 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(); - 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(); - 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. */ - } + 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. */ + } } /*-----------------------------------------------------------*/ void vPortSVCHandler( void ) { - __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n" /* Restore the task stack pointer. */ - " isb \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ + " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n"/* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); } /*-----------------------------------------------------------*/ static void prvPortStartFirstTask( void ) { - /* Start the first task. This also clears 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. */ - __asm volatile( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */ - " msr control, r0 \n" - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc 0 \n" /* System call to start first task. */ - " nop \n" - " .ltorg \n" - ); + /* Start the first task. This also clears 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. */ + __asm volatile ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ + " msr control, r0 \n" + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n"/* System call to start first task. */ + " nop \n" + " .ltorg \n" + ); } /*-----------------------------------------------------------*/ @@ -287,388 +291,393 @@ static void prvPortStartFirstTask( void ) */ 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 ); + /* 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 ); + /* 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; + #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. + /* 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; - 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; - /* 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; - /* 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; - /* 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; - /* 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; - } + 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 __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 + #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; + /* 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 */ + /* 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; + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - vPortSetupTimerInterrupt(); + /* 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; + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; - /* Ensure the VFP is enabled - it should be anyway. */ - vPortEnableVFP(); + /* Ensure the VFP is enabled - it should be anyway. */ + vPortEnableVFP(); - /* Lazy save always. */ - *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; - /* Start the first task. */ - prvPortStartFirstTask(); + /* Start the first task. */ + prvPortStartFirstTask(); - /* 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 optimisation does not remove the - symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); + /* 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 optimisation does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); - /* Should not get here! */ - return 0; + /* 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 ); + /* Not implemented in ports where there is nothing to return to. + * Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ void vPortEnterCritical( void ) { - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; + 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 ); - } + /* 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(); - } + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } } /*-----------------------------------------------------------*/ void xPortPendSVHandler( void ) { - /* This is a naked function. */ + /* This is a naked function. */ - __asm volatile - ( - " mrs r0, psp \n" - " isb \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ - " it eq \n" - " vstmdbeq r0!, {s16-s31} \n" - " \n" - " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ - " \n" - " stmdb sp!, {r0, r3} \n" - " mov r0, %0 \n" - " msr basepri, r0 \n" - " dsb \n" - " isb \n" - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " ldmia sp!, {r0, r3} \n" - " \n" - " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldr r0, [r1] \n" - " \n" - " ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */ - " \n" - " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ - " it eq \n" - " vldmiaeq r0!, {s16-s31} \n" - " \n" - " msr psp, r0 \n" - " isb \n" - " \n" - #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ - #if WORKAROUND_PMU_CM001 == 1 - " push { r14 } \n" - " pop { pc } \n" - #endif - #endif - " \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) - ); + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ + " it eq \n" + " vstmdbeq r0!, {s16-s31} \n" + " \n" + " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ + " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r0, r3} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " dsb \n" + " isb \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r0, r3} \n" + " \n" + " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldr r0, [r1] \n" + " \n" + " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ + " \n" + " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ + " it eq \n" + " vldmiaeq r0!, {s16-s31} \n" + " \n" + " msr psp, r0 \n" + " isb \n" + " \n" + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ + #if WORKAROUND_PMU_CM001 == 1 + " push { r14 } \n" + " pop { pc } \n" + #endif + #endif + " \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); } /*-----------------------------------------------------------*/ 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(); + /* 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 ) +#if ( configUSE_TICKLESS_IDLE == 1 ) - __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; + __attribute__( ( 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; - } + /* 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; + /* 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; - } + /* 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 ) ); - /* Enter a critical section but don't use the taskENTER_CRITICAL() - method as that will mask interrupts that should exit sleep mode. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } - /* 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; + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* 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; - /* Reset the reload register to the value required for normal tick - periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts - see comments above the cpsid instruction() - above. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - /* Clear the SysTick count flag and set the count value back to - zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* 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 ) - { - __asm volatile( "dsb" ::: "memory" ); - __asm volatile( "wfi" ); - __asm volatile( "isb" ); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* 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. */ - __asm volatile( "cpsie i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + /* 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 ); - /* 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. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "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 ); + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - /* 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; + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); + /* 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. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); - } + /* 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 ); - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + /* 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; - /* 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; + /* 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 ); - /* How many complete tick periods passed while the processor - was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + /* 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 ); + } - /* The reload value is set to whatever fraction of a single tick - period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - /* 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; + /* 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; - /* Exit with interrupts enabled. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - } + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } #endif /* #if configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ @@ -677,101 +686,99 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +__attribute__( ( 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 */ + /* 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; + /* 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 ); + /* 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 ); } /*-----------------------------------------------------------*/ /* This is a naked function. */ static void vPortEnableVFP( void ) { - __asm volatile - ( - " ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */ - " ldr r1, [r0] \n" - " \n" - " orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */ - " str r1, [r0] \n" - " bx r14 \n" - " .ltorg \n" - ); + __asm volatile + ( + " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ + " ldr r1, [r0] \n" + " \n" + " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ + " str r1, [r0] \n" + " bx r14 \n" + " .ltorg \n" + ); } /*-----------------------------------------------------------*/ -#if( configASSERT_DEFINED == 1 ) +#if ( configASSERT_DEFINED == 1 ) - void vPortValidateInterruptPriority( void ) - { - uint32_t ulCurrentInterrupt; - uint8_t ucCurrentPriority; + 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" ); + /* 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 ]; + /* 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. + /* 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 ); + } - 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 ); - } + /* 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 */ - - diff --git a/portable/GCC/ARM_CM4F/portmacro.h b/portable/GCC/ARM_CM4F/portmacro.h index b94366dfd..07f08de9a 100644 --- a/portable/GCC/ARM_CM4F/portmacro.h +++ b/portable/GCC/ARM_CM4F/portmacro.h @@ -27,11 +27,11 @@ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*----------------------------------------------------------- * Port specific definitions. @@ -44,201 +44,201 @@ extern "C" { */ /* 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 + #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 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 + #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 +/* 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 -#define portDONT_DISCARD __attribute__(( used )) + #define portSTACK_GROWTH ( -1 ) + #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) + #define portBYTE_ALIGNMENT 8 + #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* Scheduler utilities. */ -#define portYIELD() \ -{ \ - /* Set a PendSV to request a context switch. */ \ - 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" ); \ -} + #define portYIELD() \ + { \ + /* Set a PendSV to request a context switch. */ \ + 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" ); \ + } -#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 ) + #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 ) /*-----------------------------------------------------------*/ /* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); -#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) -#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() -#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() + extern void vPortEnterCritical( void ); + extern void vPortExitCritical( void ); + #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x ) + #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() + #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 ) + #define portENTER_CRITICAL() vPortEnterCritical() + #define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* 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 ) + * 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 ) /*-----------------------------------------------------------*/ /* 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 + #ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + #endif /*-----------------------------------------------------------*/ /* Architecture specific optimisations. */ -#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#endif + #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #endif -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - /* Generic helper function. */ - __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) - { - uint8_t ucReturn; +/* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; - __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - return ucReturn; - } + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - /* 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 + return ucReturn; + } - /* 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 ) ) +/* 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 - /*-----------------------------------------------------------*/ - - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) - -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/* 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 ) ) /*-----------------------------------------------------------*/ -#ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() -#endif + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + + #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + + #ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif /* portNOP() is not required by this port. */ -#define portNOP() + #define portNOP() -#define portINLINE __inline + #define portINLINE __inline -#ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) -#endif + #ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) + #endif -portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) -{ -uint32_t ulCurrentInterrupt; -BaseType_t xReturn; + 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" ); + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } - return xReturn; -} + return xReturn; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortRaiseBASEPRI( void ) -{ -uint32_t ulNewBASEPRI; + portFORCE_INLINE static void vPortRaiseBASEPRI( void ) + { + uint32_t ulNewBASEPRI; - __asm volatile - ( - " mov %0, %1 \n" \ - " msr basepri, %0 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); -} + __asm volatile + ( + " mov %0, %1 \n"\ + " msr basepri, %0 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) -{ -uint32_t ulOriginalBASEPRI, ulNewBASEPRI; + portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) + { + uint32_t ulOriginalBASEPRI, ulNewBASEPRI; - __asm volatile - ( - " mrs %0, basepri \n" \ - " mov %1, %2 \n" \ - " msr basepri, %1 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); + __asm volatile + ( + " mrs %0, basepri \n"\ + " mov %1, %2 \n"\ + " msr basepri, %1 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); - /* This return will not be reached but is necessary to prevent compiler - warnings. */ - return ulOriginalBASEPRI; -} + /* This return will not be reached but is necessary to prevent compiler + * warnings. */ + return ulOriginalBASEPRI; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) -{ - __asm volatile - ( - " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory" - ); -} + portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) + { + __asm volatile + ( + " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" + ); + } /*-----------------------------------------------------------*/ -#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ - diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c index 447d39feb..af9b53e1f 100644 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -26,12 +26,12 @@ */ /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM3 port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the ARM CM4 MPU port. +*----------------------------------------------------------*/ /* 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. */ + * 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. */ @@ -39,77 +39,78 @@ task.h is included from an application file. */ #include "task.h" #ifndef __VFP_FP__ - #error This port can only be used when the project options are configured to enable hardware floating point support. + #error This port can only be used when the project options are configured to enable hardware floating point support. #endif #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE #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 ( 1UL << 2UL ) + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK ( 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 ( 0 ) + +/* The way the SysTick is clocked is not modified in case it is not the same + * as the core. */ + #define portNVIC_SYSTICK_CLK ( 0 ) #endif /* Constants required to access and 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_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 ) +#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_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SHPR2_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 +#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 ( portTOTAL_NUM_REGIONS << 8UL ) +#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 /* Constants required to access and manipulate the SysTick. */ -#define portNVIC_SYSTICK_INT ( 0x00000002UL ) -#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) -#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 ) +#define portNVIC_SYSTICK_INT ( 0x00000002UL ) +#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) +#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 manipulate the VFP. */ -#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ -#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) /* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000UL ) -#define portINITIAL_EXC_RETURN ( 0xfffffffdUL ) -#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) -#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) +#define portINITIAL_XPSR ( 0x01000000UL ) +#define portINITIAL_EXC_RETURN ( 0xfffffffdUL ) +#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) +#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) /* 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 ) +#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 ) /* Offsets in the stack to the parameters when inside the SVC handler. */ -#define portOFFSET_TO_PC ( 6 ) +#define portOFFSET_TO_PC ( 6 ) /* 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 ) + * 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. @@ -133,32 +134,32 @@ void vPortSetupTimerInterrupt( void ); /* * Standard FreeRTOS exception handlers. */ -void xPortPendSVHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void xPortPendSVHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; void xPortSysTickHandler( void ) PRIVILEGED_FUNCTION; -void vPortSVCHandler( void ) __attribute__ (( naked )) PRIVILEGED_FUNCTION; +void vPortSVCHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /* * Starts the scheduler by restoring the context of the first task to run. */ -static void prvRestoreContextOfFirstTask( void ) __attribute__(( naked )) PRIVILEGED_FUNCTION; +static void prvRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /* * C portion of the SVC handler. The SVC handler is split between an asm entry * and a C wrapper for simplicity of coding and maintenance. */ -static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) PRIVILEGED_FUNCTION; +static void prvSVCHandler( uint32_t * pulRegisters ) __attribute__( ( noinline ) ) PRIVILEGED_FUNCTION; /* * Function to enable the VFP. */ - static void vPortEnableVFP( void ) __attribute__ (( naked )); +static void vPortEnableVFP( void ) __attribute__( ( naked ) ); /** * @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 )); +BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); /** * @brief Lowers the privilege level by setting the bit 0 of the CONTROL @@ -168,7 +169,7 @@ BaseType_t xIsPrivileged( void ) __attribute__ (( naked )); * Bit[0] = 0 --> The processor is running privileged * Bit[0] = 1 --> The processor is running unprivileged. */ -void vResetPrivilege( void ) __attribute__ (( naked )); +void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Calls the port specific code to raise the privilege. @@ -185,8 +186,8 @@ extern void vPortResetPrivilege( BaseType_t xRunningPrivileged ); /*-----------------------------------------------------------*/ /* Each task maintains its own interrupt status in the critical nesting -variable. Note this is not saved as part of the task context as context -switches can only occur when uxCriticalNesting is zero. */ + * variable. Note this is not saved as part of the task context as context + * switches can only occur when uxCriticalNesting is zero. */ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* @@ -195,9 +196,9 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; * 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; + 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 */ /*-----------------------------------------------------------*/ @@ -205,168 +206,186 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * See header file for description. */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged ) +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. */ - 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 = 0; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + /* 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 = 0; /* LR */ + 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; + /* 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. */ + 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; - } + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED; + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED; + } - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ void vPortSVCHandler( void ) { - /* Assumes psp was in use. */ - __asm volatile - ( - #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ - " tst lr, #4 \n" - " ite eq \n" - " mrseq r0, msp \n" - " mrsne r0, psp \n" - #else - " mrs r0, psp \n" - #endif - " b %0 \n" - ::"i"(prvSVCHandler):"r0", "memory" - ); + /* Assumes psp was in use. */ + __asm volatile + ( + #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + #else + " mrs r0, psp \n" + #endif + " b %0 \n" + ::"i" ( prvSVCHandler ) : "r0", "memory" + ); } /*-----------------------------------------------------------*/ -static void prvSVCHandler( uint32_t *pulParam ) +static void prvSVCHandler( uint32_t * pulParam ) { -uint8_t ucSVCNumber; -uint32_t ulPC; -#if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 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 /* #if defined( __ARMCC_VERSION ) */ -#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ + uint8_t ucSVCNumber; + uint32_t ulPC; - /* 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 ]; + #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) + #if defined( __ARMCC_VERSION ) - switch( ucSVCNumber ) - { - case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI; - prvRestoreContextOfFirstTask(); - break; + /* 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 /* #if defined( __ARMCC_VERSION ) */ + #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ - 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" ); + /* 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 ]; - break; + switch( ucSVCNumber ) + { + case portSVC_START_SCHEDULER: + portNVIC_SHPR2_REG |= portNVIC_SVC_PRI; + prvRestoreContextOfFirstTask(); + 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, #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, #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 ) */ + case portSVC_YIELD: + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - default : /* Unknown SVC call. */ - break; - } + /* 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, #1 \n"/* Set privilege bit. */ + " msr control, r1 \n"/* Write back new control value. */ + ::: "r1", "memory" + ); + } + + break; + #else /* if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ + case portSVC_RAISE_PRIVILEGE: + __asm volatile + ( + " mrs r1, control \n"/* Obtain current control value. */ + " bic 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; + } } /*-----------------------------------------------------------*/ static void prvRestoreContextOfFirstTask( void ) { - __asm volatile - ( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ - " \n" - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ - " \n" - " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers from TCB. */ - " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ - " \n" - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - " \n" - " ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */ - " msr control, r3 \n" - " msr psp, r0 \n" /* Restore the task stack pointer. */ - " mov r0, #0 \n" - " msr basepri, r0 \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); + __asm volatile + ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " \n" + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " \n" + #if ( portTOTAL_NUM_REGIONS == 16 ) + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ + " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ + " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ + #endif /* portTOTAL_NUM_REGIONS == 16. */ + " \n" + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + " \n" + " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " msr psp, r0 \n"/* Restore the task stack pointer. */ + " mov r0, #0 \n" + " msr basepri, r0 \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); } /*-----------------------------------------------------------*/ @@ -375,233 +394,243 @@ static void prvRestoreContextOfFirstTask( void ) */ 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 ) ); + /* 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; + #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. + /* 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; - 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; - /* 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; - /* 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; - /* 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; - /* 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; - } + 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 __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 + #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; + /* 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 */ + /* Restore the clobbered interrupt priority register to its original + * value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ - /* Make PendSV and SysTick the same priority as the kernel, and the SVC - handler higher priority so it can be used to exit a critical section (where - lower priorities are masked). */ - portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; - portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; + /* Make PendSV and SysTick the same priority as the kernel, and the SVC + * handler higher priority so it can be used to exit a critical section (where + * lower priorities are masked). */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - /* Configure the regions in the MPU that are common to all tasks. */ - prvSetupMPU(); + /* 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(); + /* 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; + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; - /* Ensure the VFP is enabled - it should be anyway. */ - vPortEnableVFP(); + /* Ensure the VFP is enabled - it should be anyway. */ + vPortEnableVFP(); - /* Lazy save always. */ - *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; - /* Start the first task. This also clears 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. */ - __asm volatile( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */ - " msr control, r0 \n" - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc %0 \n" /* System call to start first task. */ - " nop \n" - " .ltorg \n" - :: "i" (portSVC_START_SCHEDULER) : "memory" ); + /* Start the first task. This also clears 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. */ + __asm volatile ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ + " msr control, r0 \n" + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc %0 \n"/* System call to start first task. */ + " nop \n" + " .ltorg \n" + ::"i" ( portSVC_START_SCHEDULER ) : "memory" ); - /* Should not get here! */ - return 0; + /* 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 ); + /* 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(); + BaseType_t xRunningPrivileged = xPortRaisePrivilege(); - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; - vPortResetPrivilege( xRunningPrivileged ); + vPortResetPrivilege( xRunningPrivileged ); } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { -BaseType_t xRunningPrivileged = xPortRaisePrivilege(); + BaseType_t xRunningPrivileged = xPortRaisePrivilege(); - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } - vPortResetPrivilege( xRunningPrivileged ); + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + + vPortResetPrivilege( xRunningPrivileged ); } /*-----------------------------------------------------------*/ void xPortPendSVHandler( void ) { - /* This is a naked function. */ + /* This is a naked function. */ - __asm volatile - ( - " mrs r0, psp \n" - " isb \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ - " it eq \n" - " vstmdbeq r0!, {s16-s31} \n" - " \n" - " mrs r1, control \n" - " stmdb r0!, {r1, r4-r11, r14} \n" /* Save the remaining registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ - " \n" - " stmdb sp!, {r0, r3} \n" - " mov r0, %0 \n" - " msr basepri, r0 \n" - " dsb \n" - " isb \n" - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " ldmia sp!, {r0, r3} \n" - " \n" /* Restore the context. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ - " \n" - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ - " \n" - " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers from TCB. */ - " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ - " \n" - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ - " \n" - " ldmia r0!, {r3-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry. */ - " msr control, r3 \n" - " \n" - " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ - " it eq \n" - " vldmiaeq r0!, {s16-s31} \n" - " \n" - " msr psp, r0 \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) - ); + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ + " it eq \n" + " vstmdbeq r0!, {s16-s31} \n" + " \n" + " mrs r1, control \n" + " stmdb r0!, {r1, r4-r11, r14} \n"/* Save the remaining registers. */ + " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r0, r3} \n" + " mov r0, %0 \n" + " msr basepri, r0 \n" + " dsb \n" + " isb \n" + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r0, r3} \n" + " \n"/* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " \n" + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " \n" + #if ( portTOTAL_NUM_REGIONS == 16 ) + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ + " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ + " stmia r2, {r4-r11} \n" /* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ + #endif /* portTOTAL_NUM_REGIONS == 16. */ + " \n" + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + " \n" + " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" + " \n" + " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ + " it eq \n" + " vldmiaeq r0!, {s16-s31} \n" + " \n" + " msr psp, r0 \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); } /*-----------------------------------------------------------*/ void xPortSysTickHandler( void ) { -uint32_t ulDummy; + uint32_t ulDummy; - ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); - { - /* Increment the RTOS tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - /* Pend a context switch. */ - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + { + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + /* Pend a context switch. */ + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + } + } + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); } /*-----------------------------------------------------------*/ @@ -609,328 +638,338 @@ uint32_t ulDummy; * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) { - /* Stop and clear the SysTick. */ - portNVIC_SYSTICK_CTRL_REG = 0UL; - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* 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 | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE ); + /* 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 | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE ); } /*-----------------------------------------------------------*/ /* This is a naked function. */ static void vPortEnableVFP( void ) { - __asm volatile - ( - " ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */ - " ldr r1, [r0] \n" - " \n" - " orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */ - " str r1, [r0] \n" - " bx r14 \n" - " .ltorg \n" - ); + __asm volatile + ( + " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ + " ldr r1, [r0] \n" + " \n" + " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ + " str r1, [r0] \n" + " bx r14 \n" + " .ltorg \n" + ); } /*-----------------------------------------------------------*/ static void prvSetupMPU( void ) { -#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 * __FLASH_segment_start__; - extern uint32_t * __FLASH_segment_end__; - extern uint32_t * __privileged_data_start__; - extern uint32_t * __privileged_data_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 __FLASH_segment_start__[]; - extern uint32_t __FLASH_segment_end__[]; - extern uint32_t __privileged_data_start__[]; - extern uint32_t __privileged_data_end__[]; -#endif - /* Check the expected MPU is present. */ - if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) - { - /* First setup the unprivileged flash for unprivileged read only access. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portUNPRIVILEGED_FLASH_REGION ); + #if defined( __ARMCC_VERSION ) - 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 ); + /* 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 * __FLASH_segment_start__; + extern uint32_t * __FLASH_segment_end__; + extern uint32_t * __privileged_data_start__; + extern uint32_t * __privileged_data_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 __FLASH_segment_start__[]; + extern uint32_t __FLASH_segment_end__[]; + extern uint32_t __privileged_data_start__[]; + extern uint32_t __privileged_data_end__[]; + #endif /* if defined( __ARMCC_VERSION ) */ - /* Setup the privileged flash for privileged only access. This is where - the kernel code is placed. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portPRIVILEGED_FLASH_REGION ); + /* The only permitted number of regions are 8 or 16. */ + configASSERT( ( portTOTAL_NUM_REGIONS == 8 ) || ( portTOTAL_NUM_REGIONS == 16 ) ); - portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | - ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | - ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) | - ( portMPU_REGION_ENABLE ); + /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */ + configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ); - /* 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 ); + /* Check the expected MPU is present. */ + if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) + { + /* First setup the unprivileged 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_PRIVILEGED_READ_WRITE ) | - ( portMPU_REGION_CACHEABLE_BUFFERABLE ) | - prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | - ( portMPU_REGION_ENABLE ); + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) | + ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_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 ); + /* Setup the privileged flash for privileged only access. This is where + * the kernel code is placed. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portPRIVILEGED_FLASH_REGION ); - portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) | - ( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) | - ( portMPU_REGION_ENABLE ); + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | + ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) | + ( portMPU_REGION_ENABLE ); - /* Enable the memory fault exception. */ - portNVIC_SYS_CTRL_STATE_REG |= portNVIC_MEM_FAULT_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 ); - /* Enable the MPU with the background region configured. */ - portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE ); - } + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + 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; + 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++; - } - } + /* 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 ); + /* 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 ); } /*-----------------------------------------------------------*/ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ - " ite ne \n" - " movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n" /* Return. */ - " \n" - " .align 4 \n" - ::: "r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ + " ite ne \n" + " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ + " \n" + " .align 4 \n" + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { - __asm volatile - ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " orr r0, #1 \n" /* r0 = r0 | 1. */ - " msr control, r0 \n" /* CONTROL = r0. */ - " bx lr \n" /* Return to the caller. */ - :::"r0", "memory" - ); + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " orr r0, #1 \n"/* r0 = r0 | 1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "memory" + ); } /*-----------------------------------------------------------*/ -void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION * const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth ) +void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) { -#if defined( __ARMCC_VERSION ) - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __SRAM_segment_start__; - extern uint32_t * __SRAM_segment_end__; - extern uint32_t * __privileged_data_start__; - extern uint32_t * __privileged_data_end__; -#else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __SRAM_segment_start__[]; - extern uint32_t __SRAM_segment_end__[]; - extern uint32_t __privileged_data_start__[]; - extern uint32_t __privileged_data_end__[]; -#endif + #if defined( __ARMCC_VERSION ) -int32_t lIndex; -uint32_t ul; + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __SRAM_segment_start__; + extern uint32_t * __SRAM_segment_end__; + extern uint32_t * __privileged_data_start__; + extern uint32_t * __privileged_data_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __SRAM_segment_start__[]; + extern uint32_t __SRAM_segment_end__[]; + extern uint32_t __privileged_data_start__[]; + extern uint32_t __privileged_data_end__[]; + #endif /* if defined( __ARMCC_VERSION ) */ - 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 ); + int32_t lIndex; + uint32_t ul; - 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 ); + 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 ); - /* 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[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | + ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); - 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 ); + /* 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 ); - /* 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[ 1 ].ulRegionAttribute = + ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | + ( portMPU_REGION_ENABLE ); - 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 ); - } + /* 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. */ - lIndex = 0; + xMPUSettings->xRegion[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | /* Read and write. */ + ( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | + ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( portMPU_REGION_ENABLE ); + } - 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. */ + lIndex = 0; - 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; - } + for( ul = 1; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) + { + if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL ) + { + /* Translate the generic region definition contained in + * xRegions into the CM4 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. */ - lIndex++; - } - } + 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 ) +#if ( configASSERT_DEFINED == 1 ) - void vPortValidateInterruptPriority( void ) - { - uint32_t ulCurrentInterrupt; - uint8_t ucCurrentPriority; + 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" ); + /* 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 ]; + /* 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. + /* 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 ); + } - 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 unpredicable behaviour. */ - configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); - } + /* 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 unpredicable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } #endif /* configASSERT_DEFINED */ /*-----------------------------------------------------------*/ - - diff --git a/portable/GCC/ARM_CM4_MPU/portmacro.h b/portable/GCC/ARM_CM4_MPU/portmacro.h index 61da7413a..4588dd2c0 100644 --- a/portable/GCC/ARM_CM4_MPU/portmacro.h +++ b/portable/GCC/ARM_CM4_MPU/portmacro.h @@ -27,11 +27,11 @@ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*----------------------------------------------------------- * Port specific definitions. @@ -44,265 +44,351 @@ extern "C" { */ /* 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 + #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 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 + #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 +/* 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 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 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 ) + /* Location of the TEX,S,C,B bits in the MPU Region Attribute and Size + * Register (RASR). */ + #define portMPU_RASR_TEX_S_C_B_LOCATION ( 16UL ) + #define portMPU_RASR_TEX_S_C_B_MASK ( 0x3FUL ) -#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. */ + /* MPU settings that can be overriden in FreeRTOSConfig.h. */ + #ifndef configTOTAL_MPU_REGIONS + /* Define to 8 for backward compatibility. */ + #define configTOTAL_MPU_REGIONS ( 8UL ) + #endif -#define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr r0, #1 \n msr control, r0 " ::: "r0", "memory" ) + /* + * The TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits define the + * memory type, and where necessary the cacheable and shareable properties + * of the memory region. + * + * The TEX, C, and B bits together indicate the memory type of the region, + * and: + * - For Normal memory, the cacheable properties of the region. + * - For Device memory, whether the region is shareable. + * + * For Normal memory regions, the S bit indicates whether the region is + * shareable. For Strongly-ordered and Device memory, the S bit is ignored. + * + * See the following two tables for setting TEX, S, C and B bits for + * unprivileged flash, privileged flash and privileged RAM regions. + * + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | TEX | C | B | Memory type | Description or Normal region cacheability | Shareable? | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 000 | 0 | 0 | Strongly-ordered | Strongly ordered | Shareable | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 000 | 0 | 1 | Device | Shared device | Shareable | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 000 | 1 | 0 | Normal | Outer and inner write-through; no write allocate | S bit | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 000 | 1 | 1 | Normal | Outer and inner write-back; no write allocate | S bit | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 001 | 0 | 0 | Normal | Outer and inner Non-cacheable | S bit | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 001 | 0 | 1 | Reserved | Reserved | Reserved | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 001 | 1 | 0 | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED | IMPLEMENTATION DEFINED | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 001 | 1 | 1 | Normal | Outer and inner write-back; write and read allocate | S bit | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 010 | 0 | 0 | Device | Non-shared device | Not shareable | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 010 | 0 | 1 | Reserved | Reserved | Reserved | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 010 | 1 | X | Reserved | Reserved | Reserved | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 011 | X | X | Reserved | Reserved | Reserved | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ + | 1BB | A | A | Normal | Cached memory, with AA and BB indicating the inner and | Reserved | + | | | | | outer cacheability rules that must be exported on the | | + | | | | | bus. See the table below for the cacheability policy | | + | | | | | encoding. memory, BB=Outer policy, AA=Inner policy. | | + +-----+---+---+------------------------+--------------------------------------------------------+-------------------------+ -typedef struct MPU_REGION_REGISTERS -{ - uint32_t ulRegionBaseAddress; - uint32_t ulRegionAttribute; -} xMPU_REGION_REGISTERS; + +-----------------------------------------+----------------------------------------+ + | AA or BB subfield of {TEX,C,B} encoding | Cacheability policy | + +-----------------------------------------+----------------------------------------+ + | 00 | Non-cacheable | + +-----------------------------------------+----------------------------------------+ + | 01 | Write-back, write and read allocate | + +-----------------------------------------+----------------------------------------+ + | 10 | Write-through, no write allocate | + +-----------------------------------------+----------------------------------------+ + | 11 | Write-back, no write allocate | + +-----------------------------------------+----------------------------------------+ + */ + + /* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for flash + * region. */ + #ifndef configTEX_S_C_B_FLASH + /* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */ + #define configTEX_S_C_B_FLASH ( 0x07UL ) + #endif + + /* TEX, Shareable (S), Cacheable (C) and Bufferable (B) bits for RAM + * region. */ + #ifndef configTEX_S_C_B_SRAM + /* Default to TEX=000, S=1, C=1, B=1 for backward compatibility. */ + #define configTEX_S_C_B_SRAM ( 0x07UL ) + #endif + + #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 portTOTAL_NUM_REGIONS ( configTOTAL_MPU_REGIONS ) + #define portNUM_CONFIGURABLE_REGIONS ( portTOTAL_NUM_REGIONS - portFIRST_CONFIGURABLE_REGION ) + #define portLAST_CONFIGURABLE_REGION ( portTOTAL_NUM_REGIONS - 1 ) + + #define portSWITCH_TO_USER_MODE() __asm volatile ( " mrs r0, control \n orr 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; + 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 -#define portDONT_DISCARD __attribute__(( used )) + #define portSTACK_GROWTH ( -1 ) + #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) + #define portBYTE_ALIGNMENT 8 + #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* SVC numbers for various services. */ -#define portSVC_START_SCHEDULER 0 -#define portSVC_YIELD 1 -#define portSVC_RAISE_PRIVILEGE 2 + #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; \ - \ - /* 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" ); \ -} + #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; \ + \ + /* 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" ); \ + } -#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 ) + #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 ) /*-----------------------------------------------------------*/ /* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); -#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) -#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() -#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() + extern void vPortEnterCritical( void ); + extern void vPortExitCritical( void ); + #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x ) + #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() + #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 ) + #define portENTER_CRITICAL() vPortEnterCritical() + #define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* 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 ) + * 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 ) /*-----------------------------------------------------------*/ /* Architecture specific optimisations. */ -#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#endif + #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #endif -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - /* Generic helper function. */ - __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) - { - uint8_t ucReturn; +/* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; - __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - return ucReturn; - } + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - /* 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 + return ucReturn; + } - /* 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 ) ) +/* 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 - /*-----------------------------------------------------------*/ - - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) - -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/* 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 ) ) /*-----------------------------------------------------------*/ -#ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() -#endif + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + + #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + + #ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif /* portNOP() is not required by this port. */ -#define portNOP() + #define portNOP() -#define portINLINE __inline + #define portINLINE __inline -#ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) -#endif + #ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) + #endif /*-----------------------------------------------------------*/ -extern BaseType_t xIsPrivileged( void ); -extern void vResetPrivilege( void ); + 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() + #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" ); + */ + #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() + #define portRESET_PRIVILEGE() vResetPrivilege() /*-----------------------------------------------------------*/ -portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) -{ -uint32_t ulCurrentInterrupt; -BaseType_t xReturn; + 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" ); + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } - return xReturn; -} + return xReturn; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortRaiseBASEPRI( void ) -{ -uint32_t ulNewBASEPRI; + portFORCE_INLINE static void vPortRaiseBASEPRI( void ) + { + uint32_t ulNewBASEPRI; - __asm volatile - ( - " mov %0, %1 \n" \ - " msr basepri, %0 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); -} + __asm volatile + ( + " mov %0, %1 \n"\ + " msr basepri, %0 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) -{ -uint32_t ulOriginalBASEPRI, ulNewBASEPRI; + portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) + { + uint32_t ulOriginalBASEPRI, ulNewBASEPRI; - __asm volatile - ( - " mrs %0, basepri \n" \ - " mov %1, %2 \n" \ - " msr basepri, %1 \n" \ - " isb \n" \ - " dsb \n" \ - :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); + __asm volatile + ( + " mrs %0, basepri \n"\ + " mov %1, %2 \n"\ + " msr basepri, %1 \n"\ + " isb \n"\ + " dsb \n"\ + : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); - /* This return will not be reached but is necessary to prevent compiler - warnings. */ - return ulOriginalBASEPRI; -} + /* This return will not be reached but is necessary to prevent compiler + * warnings. */ + return ulOriginalBASEPRI; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) -{ - __asm volatile - ( - " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory" - ); -} + portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) + { + __asm volatile + ( + " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" + ); + } /*-----------------------------------------------------------*/ -#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) -#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 + #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 /*-----------------------------------------------------------*/ -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ - diff --git a/portable/GCC/ARM_CM7/r0p1/port.c b/portable/GCC/ARM_CM7/r0p1/port.c index 1d7df2b75..dc7ac7a41 100644 --- a/portable/GCC/ARM_CM7/r0p1/port.c +++ b/portable/GCC/ARM_CM7/r0p1/port.c @@ -26,82 +26,83 @@ */ /*----------------------------------------------------------- - * Implementation of functions defined in portable.h for the ARM CM4F port. - *----------------------------------------------------------*/ +* Implementation of functions defined in portable.h for the ARM CM7 port. +*----------------------------------------------------------*/ /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" #ifndef __VFP_FP__ - #error This port can only be used when the project options are configured to enable hardware floating point support. + #error This port can only be used when the project options are configured to enable hardware floating point support. #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 ) + #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 ) + +/* 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_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_SHPR3_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_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 ) +#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 ) +#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 ) +#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 ) +#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_XPSR ( 0x01000000 ) +#define portINITIAL_EXC_RETURN ( 0xfffffffd ) /* The systick is a 24-bit counter. */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) /* 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 ) + * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ +#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) /* 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 ) + * occurred while the SysTick counter is stopped during tickless idle + * calculations. */ +#define portMISSED_COUNTS_FACTOR ( 45UL ) /* 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. */ + * prvTaskExitError() in case it messes up unwinding of the stack in the + * debugger. */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* @@ -114,19 +115,19 @@ void vPortSetupTimerInterrupt( void ); /* * Exception handlers. */ -void xPortPendSVHandler( void ) __attribute__ (( naked )); +void xPortPendSVHandler( void ) __attribute__( ( naked ) ); void xPortSysTickHandler( void ); -void vPortSVCHandler( void ) __attribute__ (( naked )); +void vPortSVCHandler( void ) __attribute__( ( naked ) ); /* * Start first task is a separate function so it can be tested in isolation. */ -static void prvPortStartFirstTask( void ) __attribute__ (( naked )); +static void prvPortStartFirstTask( void ) __attribute__( ( naked ) ); /* * Function to enable the VFP. */ -static void vPortEnableVFP( void ) __attribute__ (( naked )); +static void vPortEnableVFP( void ) __attribute__( ( naked ) ); /* * Used to catch tasks that attempt to return from their implementing function. @@ -136,30 +137,30 @@ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* Each task maintains its own interrupt status in the critical nesting -variable. */ + * 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; +#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; +#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; +#if ( configUSE_TICKLESS_IDLE == 1 ) + static uint32_t ulStoppedTimerCompensation = 0; #endif /* configUSE_TICKLESS_IDLE */ /* @@ -167,10 +168,10 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; * 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; +#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 */ /*-----------------------------------------------------------*/ @@ -178,101 +179,104 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * See header file for description. */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +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. */ + /* 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--; + /* 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 ) portTASK_RETURN_ADDRESS; /* LR */ + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ + pxTopOfStack--; + *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */ + pxTopOfStack--; + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - /* Save code space by skipping register initialisation. */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + /* 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; + /* 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. */ + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ static void prvTaskExitError( void ) { -volatile uint32_t ulDummy = 0; + volatile uint32_t ulDummy = 0; - /* 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 ). + /* 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(); - 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(); - 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. */ - } + 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. */ + } } /*-----------------------------------------------------------*/ void vPortSVCHandler( void ) { - __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n" /* Restore the task stack pointer. */ - " isb \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); + __asm volatile ( + " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ + " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n"/* Restore the task stack pointer. */ + " isb \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); } /*-----------------------------------------------------------*/ static void prvPortStartFirstTask( void ) { - /* Start the first task. This also clears 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. */ - __asm volatile( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */ - " msr control, r0 \n" - " cpsie i \n" /* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc 0 \n" /* System call to start first task. */ - " nop \n" - " .ltorg \n" - ); + /* Start the first task. This also clears 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. */ + __asm volatile ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ + " msr control, r0 \n" + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n"/* System call to start first task. */ + " nop \n" + " .ltorg \n" + ); } /*-----------------------------------------------------------*/ @@ -281,384 +285,389 @@ static void prvPortStartFirstTask( void ) */ 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 ); + /* 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; + #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. + /* 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; - 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; - /* 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; - /* 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; - /* 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; - /* 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; - } + 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 __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 + #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; + /* 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 */ + /* 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; + /* Make PendSV and SysTick the lowest priority interrupts. */ + portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; + portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - /* Start the timer that generates the tick ISR. Interrupts are disabled - here already. */ - vPortSetupTimerInterrupt(); + /* 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; + /* Initialise the critical nesting count ready for the first task. */ + uxCriticalNesting = 0; - /* Ensure the VFP is enabled - it should be anyway. */ - vPortEnableVFP(); + /* Ensure the VFP is enabled - it should be anyway. */ + vPortEnableVFP(); - /* Lazy save always. */ - *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; + /* Lazy save always. */ + *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; - /* Start the first task. */ - prvPortStartFirstTask(); + /* Start the first task. */ + prvPortStartFirstTask(); - /* 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 optimisation does not remove the - symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); + /* 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 optimisation does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); - /* Should not get here! */ - return 0; + /* 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 ); + /* Not implemented in ports where there is nothing to return to. + * Artificially force an assert. */ + configASSERT( uxCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ void vPortEnterCritical( void ) { - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; + 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 ); - } + /* 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(); - } + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } } /*-----------------------------------------------------------*/ void xPortPendSVHandler( void ) { - /* This is a naked function. */ + /* This is a naked function. */ - __asm volatile - ( - " mrs r0, psp \n" - " isb \n" - " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ - " ldr r2, [r3] \n" - " \n" - " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ - " it eq \n" - " vstmdbeq r0!, {s16-s31} \n" - " \n" - " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ - " \n" - " stmdb sp!, {r0, r3} \n" - " mov r0, %0 \n" - " cpsid i \n" /* Errata workaround. */ - " msr basepri, r0 \n" - " dsb \n" - " isb \n" - " cpsie i \n" /* Errata workaround. */ - " bl vTaskSwitchContext \n" - " mov r0, #0 \n" - " msr basepri, r0 \n" - " ldmia sp!, {r0, r3} \n" - " \n" - " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldr r0, [r1] \n" - " \n" - " ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */ - " \n" - " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ - " it eq \n" - " vldmiaeq r0!, {s16-s31} \n" - " \n" - " msr psp, r0 \n" - " isb \n" - " \n" - #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ - #if WORKAROUND_PMU_CM001 == 1 - " push { r14 } \n" - " pop { pc } \n" - #endif - #endif - " \n" - " bx r14 \n" - " \n" - " .align 4 \n" - "pxCurrentTCBConst: .word pxCurrentTCB \n" - ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) - ); + __asm volatile + ( + " mrs r0, psp \n" + " isb \n" + " \n" + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r2, [r3] \n" + " \n" + " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ + " it eq \n" + " vstmdbeq r0!, {s16-s31} \n" + " \n" + " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ + " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " \n" + " stmdb sp!, {r0, r3} \n" + " mov r0, %0 \n" + " cpsid i \n"/* Errata workaround. */ + " msr basepri, r0 \n" + " dsb \n" + " isb \n" + " cpsie i \n"/* Errata workaround. */ + " bl vTaskSwitchContext \n" + " mov r0, #0 \n" + " msr basepri, r0 \n" + " ldmia sp!, {r0, r3} \n" + " \n" + " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldr r0, [r1] \n" + " \n" + " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ + " \n" + " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ + " it eq \n" + " vldmiaeq r0!, {s16-s31} \n" + " \n" + " msr psp, r0 \n" + " isb \n" + " \n" + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ + #if WORKAROUND_PMU_CM001 == 1 + " push { r14 } \n" + " pop { pc } \n" + #endif + #endif + " \n" + " bx r14 \n" + " \n" + " .align 4 \n" + "pxCurrentTCBConst: .word pxCurrentTCB \n" + ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) + ); } /*-----------------------------------------------------------*/ 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(); + /* 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 ) +#if ( configUSE_TICKLESS_IDLE == 1 ) - __attribute__((weak)) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; - TickType_t xModifiableIdleTime; + __attribute__( ( 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; - } + /* 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; + /* 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; - } + /* 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 ) ); - /* Enter a critical section but don't use the taskENTER_CRITICAL() - method as that will mask interrupts that should exit sleep mode. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } - /* 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; + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* 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; - /* Reset the reload register to the value required for normal tick - periods. */ - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* Re-enable interrupts - see comments above the cpsid instruction() - above. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - else - { - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + /* Reset the reload register to the value required for normal tick + * periods. */ + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - /* Clear the SysTick count flag and set the count value back to - zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* Re-enable interrupts - see comments above the cpsid instruction() + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - /* 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 ) - { - __asm volatile( "dsb" ::: "memory" ); - __asm volatile( "wfi" ); - __asm volatile( "isb" ); - } - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - /* 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. */ - __asm volatile( "cpsie i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + /* 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 ); - /* 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. */ - __asm volatile( "cpsid i" ::: "memory" ); - __asm volatile( "dsb" ); - __asm volatile( "isb" ); + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "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 ); + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - /* 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; + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); + /* 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. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); - /* 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 ); - } + /* 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 ); - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + /* 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; - /* 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; + /* 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 ); - /* How many complete tick periods passed while the processor - was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + /* 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 ); + } - /* The reload value is set to whatever fraction of a single tick - period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - /* 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; + /* 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; - /* Exit with interrupts enabled. */ - __asm volatile( "cpsie i" ::: "memory" ); - } - } + /* 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. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } #endif /* #if configUSE_TICKLESS_IDLE */ /*-----------------------------------------------------------*/ @@ -667,101 +676,99 @@ void xPortSysTickHandler( void ) * Setup the systick timer to generate the tick interrupts at the required * frequency. */ -__attribute__(( weak )) void vPortSetupTimerInterrupt( void ) +__attribute__( ( 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 */ + /* 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; + /* 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 ); + /* 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 ); } /*-----------------------------------------------------------*/ /* This is a naked function. */ static void vPortEnableVFP( void ) { - __asm volatile - ( - " ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */ - " ldr r1, [r0] \n" - " \n" - " orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */ - " str r1, [r0] \n" - " bx r14 \n" - " .ltorg \n" - ); + __asm volatile + ( + " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ + " ldr r1, [r0] \n" + " \n" + " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ + " str r1, [r0] \n" + " bx r14 \n" + " .ltorg \n" + ); } /*-----------------------------------------------------------*/ -#if( configASSERT_DEFINED == 1 ) +#if ( configASSERT_DEFINED == 1 ) - void vPortValidateInterruptPriority( void ) - { - uint32_t ulCurrentInterrupt; - uint8_t ucCurrentPriority; + 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" ); + /* 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 ]; + /* 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. + /* 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 ); + } - 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 ); - } + /* 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 */ - - diff --git a/portable/GCC/ARM_CM7/r0p1/portmacro.h b/portable/GCC/ARM_CM7/r0p1/portmacro.h index 124e8073a..a65d627b6 100644 --- a/portable/GCC/ARM_CM7/r0p1/portmacro.h +++ b/portable/GCC/ARM_CM7/r0p1/portmacro.h @@ -27,11 +27,11 @@ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus -extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*----------------------------------------------------------- * Port specific definitions. @@ -44,205 +44,205 @@ extern "C" { */ /* 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 + #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 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 + #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 +/* 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 -#define portDONT_DISCARD __attribute__(( used )) + #define portSTACK_GROWTH ( -1 ) + #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) + #define portBYTE_ALIGNMENT 8 + #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* Scheduler utilities. */ -#define portYIELD() \ -{ \ - /* Set a PendSV to request a context switch. */ \ - 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" ); \ -} + #define portYIELD() \ + { \ + /* Set a PendSV to request a context switch. */ \ + 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" ); \ + } -#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 ) + #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 ) /*-----------------------------------------------------------*/ /* Critical section management. */ -extern void vPortEnterCritical( void ); -extern void vPortExitCritical( void ); -#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) vPortSetBASEPRI(x) -#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() -#define portENABLE_INTERRUPTS() vPortSetBASEPRI(0) -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() + extern void vPortEnterCritical( void ); + extern void vPortExitCritical( void ); + #define portSET_INTERRUPT_MASK_FROM_ISR() ulPortRaiseBASEPRI() + #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortSetBASEPRI( x ) + #define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI() + #define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 ) + #define portENTER_CRITICAL() vPortEnterCritical() + #define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* 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 ) + * 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 ) /*-----------------------------------------------------------*/ /* 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 + #ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) + #endif /*-----------------------------------------------------------*/ /* Architecture specific optimisations. */ -#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 -#endif + #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #endif -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 - /* Generic helper function. */ - __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) - { - uint8_t ucReturn; +/* Generic helper function. */ + __attribute__( ( always_inline ) ) static inline uint8_t ucPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint8_t ucReturn; - __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - return ucReturn; - } + __asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" ); - /* 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 + return ucReturn; + } - /* 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 ) ) +/* 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 - /*-----------------------------------------------------------*/ - - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) - -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/* 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 ) ) /*-----------------------------------------------------------*/ -#ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() -#endif + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ( uint32_t ) ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + + #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/*-----------------------------------------------------------*/ + + #ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif /* portNOP() is not required by this port. */ -#define portNOP() + #define portNOP() -#define portINLINE __inline + #define portINLINE __inline -#ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__(( always_inline)) -#endif + #ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) + #endif -portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) -{ -uint32_t ulCurrentInterrupt; -BaseType_t xReturn; + 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" ); + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); - if( ulCurrentInterrupt == 0 ) - { - xReturn = pdFALSE; - } - else - { - xReturn = pdTRUE; - } + if( ulCurrentInterrupt == 0 ) + { + xReturn = pdFALSE; + } + else + { + xReturn = pdTRUE; + } - return xReturn; -} + return xReturn; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortRaiseBASEPRI( void ) -{ -uint32_t ulNewBASEPRI; + portFORCE_INLINE static void vPortRaiseBASEPRI( void ) + { + uint32_t ulNewBASEPRI; - __asm volatile - ( - " mov %0, %1 \n" \ - " cpsid i \n" \ - " msr basepri, %0 \n" \ - " isb \n" \ - " dsb \n" \ - " cpsie i \n" \ - :"=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); -} + __asm volatile + ( + " mov %0, %1 \n"\ + " cpsid i \n"\ + " msr basepri, %0 \n"\ + " isb \n"\ + " dsb \n"\ + " cpsie i \n"\ + : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) -{ -uint32_t ulOriginalBASEPRI, ulNewBASEPRI; + portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) + { + uint32_t ulOriginalBASEPRI, ulNewBASEPRI; - __asm volatile - ( - " mrs %0, basepri \n" \ - " mov %1, %2 \n" \ - " cpsid i \n" \ - " msr basepri, %1 \n" \ - " isb \n" \ - " dsb \n" \ - " cpsie i \n" \ - :"=r" (ulOriginalBASEPRI), "=r" (ulNewBASEPRI) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" - ); + __asm volatile + ( + " mrs %0, basepri \n"\ + " mov %1, %2 \n"\ + " cpsid i \n"\ + " msr basepri, %1 \n"\ + " isb \n"\ + " dsb \n"\ + " cpsie i \n"\ + : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" + ); - /* This return will not be reached but is necessary to prevent compiler - warnings. */ - return ulOriginalBASEPRI; -} + /* This return will not be reached but is necessary to prevent compiler + * warnings. */ + return ulOriginalBASEPRI; + } /*-----------------------------------------------------------*/ -portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) -{ - __asm volatile - ( - " msr basepri, %0 " :: "r" ( ulNewMaskValue ) : "memory" - ); -} + portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue ) + { + __asm volatile + ( + " msr basepri, %0 "::"r" ( ulNewMaskValue ) : "memory" + ); + } /*-----------------------------------------------------------*/ -#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) -#ifdef __cplusplus -} -#endif + #ifdef __cplusplus + } + #endif #endif /* PORTMACRO_H */ - diff --git a/portable/GCC/ARM_CR5/port.c b/portable/GCC/ARM_CR5/port.c index 6823f94d7..0658218a0 100644 --- a/portable/GCC/ARM_CR5/port.c +++ b/portable/GCC/ARM_CR5/port.c @@ -33,120 +33,133 @@ #include "task.h" #ifndef configINTERRUPT_CONTROLLER_BASE_ADDRESS - #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html + #error configINTERRUPT_CONTROLLER_BASE_ADDRESS must be defined. Refer to Cortex-A equivalent: 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. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html + #error configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET must be defined. Refer to Cortex-A equivalent: http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */ #endif #ifndef configUNIQUE_INTERRUPT_PRIORITIES - #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html + #error configUNIQUE_INTERRUPT_PRIORITIES must be defined. Refer to Cortex-A equivalent: http: /*www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html */ #endif #ifndef configSETUP_TICK_INTERRUPT - #error configSETUP_TICK_INTERRUPT() must be defined. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html + #error configSETUP_TICK_INTERRUPT() must be defined. Refer to Cortex-A equivalent: 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. Refer to Cortex-A equivalent: http://www.freertos.org/Using-FreeRTOS-on-Cortex-A-Embedded-Processors.html + #error configMAX_API_CALL_INTERRUPT_PRIORITY must be defined. Refer to Cortex-A equivalent: 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 + #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 + #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 + /* 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 ) + #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #endif /* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in -portmacro.h. */ + * portmacro.h. */ #ifndef configCLEAR_TICK_INTERRUPT - #define 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 ) + * 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 ) + * (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 ) + * 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 portINTERRUPT_ENABLE_BIT ( 0x80UL ) -#define portTHUMB_MODE_ADDRESS ( 0x01UL ) +#define portINITIAL_SPSR ( ( StackType_t ) 0x1f ) /* System mode, ARM mode, IRQ enabled FIQ enabled. */ +#define portTHUMB_MODE_BIT ( ( StackType_t ) 0x20 ) +#define portINTERRUPT_ENABLE_BIT ( 0x80UL ) +#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 ) + * 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 ) +#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 ) + * mode. */ +#define portAPSR_USER_MODE ( 0x10 ) /* The critical section macros only mask interrupts up to an application -determined priority level. Sometimes it is necessary to turn interrupt off in -the CPU itself before modifying certain hardware registers. */ -#define portCPU_IRQ_DISABLE() \ - __asm volatile ( "CPSID i" ::: "memory" ); \ - __asm volatile ( "DSB" ); \ - __asm volatile ( "ISB" ); + * determined priority level. Sometimes it is necessary to turn interrupt off in + * the CPU itself before modifying certain hardware registers. */ +#define portCPU_IRQ_DISABLE() \ + __asm volatile ( "CPSID i" ::: "memory" ); \ + __asm volatile ( "DSB" ); \ + __asm volatile ( "ISB" ); -#define portCPU_IRQ_ENABLE() \ - __asm volatile ( "CPSIE i" ::: "memory" ); \ - __asm volatile ( "DSB" ); \ - __asm volatile ( "ISB" ); +#define portCPU_IRQ_ENABLE() \ + __asm volatile ( "CPSIE i" ::: "memory" ); \ + __asm volatile ( "DSB" ); \ + __asm volatile ( "ISB" ); /* Macro to unmask all interrupt priorities. */ -#define portCLEAR_INTERRUPT_MASK() \ -{ \ - portCPU_IRQ_DISABLE(); \ - portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ - __asm volatile ( "DSB \n" \ - "ISB \n" ); \ - portCPU_IRQ_ENABLE(); \ -} +#define portCLEAR_INTERRUPT_MASK() \ + { \ + portCPU_IRQ_DISABLE(); \ + portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ + __asm volatile ( "DSB \n" \ + "ISB \n"); \ + portCPU_IRQ_ENABLE(); \ + } -#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL -#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) -#define portBIT_0_SET ( ( uint8_t ) 0x01 ) +#define portINTERRUPT_PRIORITY_REGISTER_OFFSET 0x400UL +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#define portBIT_0_SET ( ( uint8_t ) 0x01 ) /* Let the user override the pre-loading of the initial LR with the address of -prvTaskExitError() in case is messes up unwinding of the stack in the -debugger. */ + * prvTaskExitError() in case is messes up unwinding of the stack in the + * debugger. */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif + +/* Adding the necessary stuff in order to be able to determine from C code wheter or not the IRQs are enabled at the processor level (not interrupt controller level) */ +#define GET_CPSR() ({u32 rval = 0U; \ + __asm__ __volatile__(\ + "mrs %0, cpsr\n"\ + : "=r" (rval)\ + );\ + rval;\ + }) + +#define CPSR_IRQ_ENABLE_MASK 0x80U + +#define IS_IRQ_DISABLED() ({unsigned int val = 0; val = (GET_CPSR() & CPSR_IRQ_ENABLE_MASK) ? 1 : 0; val;}) /*-----------------------------------------------------------*/ /* @@ -163,363 +176,385 @@ 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. */ + * 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. */ + * 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. */ + * if the nesting depth is 0. */ uint32_t ulPortInterruptNesting = 0UL; /* Used in asm code. */ -__attribute__(( used )) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS; -__attribute__(( used )) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS; -__attribute__(( used )) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS; -__attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); +__attribute__( ( used ) ) const uint32_t ulICCIAR = portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS; +__attribute__( ( used ) ) const uint32_t ulICCEOIR = portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS; +__attribute__( ( used ) ) const uint32_t ulICCPMR = portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS; +__attribute__( ( used ) ) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); /*-----------------------------------------------------------*/ /* * See header file for description. */ -StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) +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. + /* 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; - 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; + } - if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) - { - /* The task will start in THUMB mode. */ - *pxTopOfStack |= portTHUMB_MODE_BIT; - } + pxTopOfStack--; - pxTopOfStack--; + /* Next the return address, which in this case is the start of the task. */ + *pxTopOfStack = ( StackType_t ) pxCode; + 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--; - /* 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 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; - /* 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; + 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 ). + /* 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(); - 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( ;; ); + for( ; ; ) + { + } } /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { -uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */ + uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */ - #if( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); - volatile uint8_t ucMaxPriorityValue; + #if ( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); + volatile uint8_t ucMaxPriorityValue; - /* Determine how many priority bits are implemented in the GIC. + /* Determine how many priority bits are implemented in the GIC. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = *pucFirstUserPriorityRegister; - 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; - /* 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; - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; + /* Shift to the least significant bits. */ + while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET ) + { + ucMaxPriorityValue >>= ( uint8_t ) 0x01; - /* Shift to the least significant bits. */ - while( ( ucMaxPriorityValue & portBIT_0_SET ) != portBIT_0_SET ) - { - ucMaxPriorityValue >>= ( uint8_t ) 0x01; + /* If ulCycles reaches 0 then ucMaxPriorityValue must have been + * read as 0, indicating a misconfiguration. */ + ulCycles--; - /* If ulCycles reaches 0 then ucMaxPriorityValue must have been - read as 0, indicating a misconfiguration. */ - ulCycles--; - if( ulCycles == 0 ) - { - break; - } - } + if( ulCycles == 0 ) + { + break; + } + } - /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read - value. */ - configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY ); + /* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read + * value. */ + configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY ); - /* Restore the clobbered interrupt priority register to its original - value. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; - } - #endif /* conifgASSERT_DEFINED */ + /* Restore the clobbered interrupt priority register to its original + * value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* conifgASSERT_DEFINED */ - /* 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 ) :: "memory" ); - ulAPSR &= portAPSR_MODE_BITS_MASK; - configASSERT( ulAPSR != portAPSR_USER_MODE ); + /* 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 )::"memory" ); + 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( 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 ) - { - /* Interrupts are turned off in the CPU itself to ensure tick does - not execute while the scheduler is being started. Interrupts are - automatically turned back on in the CPU when the first task starts - executing. */ - portCPU_IRQ_DISABLE(); + if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) + { + /* Interrupts are turned off in the CPU itself to ensure tick does + * not execute while the scheduler is being started. Interrupts are + * automatically turned back on in the CPU when the first task starts + * executing. */ + portCPU_IRQ_DISABLE(); - /* Start the timer that generates the tick ISR. */ - configSETUP_TICK_INTERRUPT(); + /* Start the timer that generates the tick ISR. */ + configSETUP_TICK_INTERRUPT(); - /* Start the first task executing. */ - vPortRestoreTaskContext(); - } - } + /* 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; + /* 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 ); + /* Not implemented in ports where there is nothing to return to. + * Artificially force an assert. */ + configASSERT( ulCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ void vPortEnterCritical( void ) { - /* Mask interrupts up to the max syscall interrupt priority. */ - ulPortSetInterruptMask(); + /* Mask interrupts up to the max syscall interrupt priority. */ + 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++; + /* 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 ); - } + /* 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( 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(); - } - } + /* 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. It is - necessary to turn off interrupts in the CPU itself while the ICCPMR is being - updated. */ - portCPU_IRQ_DISABLE(); - portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); - __asm volatile ( "dsb \n" - "isb \n" ::: "memory" ); - portCPU_IRQ_ENABLE(); + /* 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. It is + * necessary to turn off interrupts in the CPU itself while the ICCPMR is being + * updated. */ + portCPU_IRQ_DISABLE(); + portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); + __asm volatile ( "dsb \n" + "isb \n"::: "memory" ); + portCPU_IRQ_ENABLE(); - /* Increment the RTOS tick. */ - if( xTaskIncrementTick() != pdFALSE ) - { - ulPortYieldRequired = pdTRUE; - } + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + ulPortYieldRequired = pdTRUE; + } - /* Ensure all interrupt priorities are active again. */ - portCLEAR_INTERRUPT_MASK(); - configCLEAR_TICK_INTERRUPT(); + /* Ensure all interrupt priorities are active again. */ + portCLEAR_INTERRUPT_MASK(); + configCLEAR_TICK_INTERRUPT(); } /*-----------------------------------------------------------*/ void vPortTaskUsesFPU( void ) { -uint32_t ulInitialFPSCR = 0; + uint32_t ulInitialFPSCR = 0; - /* A task is registering the fact that it needs an FPU context. Set the - FPU flag (which is saved as part of the task context). */ - ulPortTaskHasFPUContext = pdTRUE; + /* 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) : "memory" ); + /* Initialise the floating point status register. */ + __asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" ); } /*-----------------------------------------------------------*/ void vPortClearInterruptMask( uint32_t ulNewMaskValue ) { - if( ulNewMaskValue == pdFALSE ) - { - portCLEAR_INTERRUPT_MASK(); - } + if( ulNewMaskValue == pdFALSE ) + { + portCLEAR_INTERRUPT_MASK(); + } } /*-----------------------------------------------------------*/ uint32_t ulPortSetInterruptMask( void ) { -uint32_t ulReturn; + uint32_t ulReturn; + uint32_t wasIRQDisabled; + + /* We keep track of if the IRQ are enabled in the CPU (as opposed to interrupts masked in the interrupt controller, like the intend of this function). + * This is very important because when the CPU is interrupted, among other things, the hardware clears the IRQ Enable bit in the CPSR of the IRQ CPU Mode in which + * we enter. */ + wasIRQDisabled = IS_IRQ_DISABLED(); + + /* Interrupt in the CPU must be turned off while the ICCPMR is being + * updated. */ + portCPU_IRQ_DISABLE(); - /* Interrupt in the CPU must be turned off while the ICCPMR is being - updated. */ - portCPU_IRQ_DISABLE(); - 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 volatile ( "dsb \n" - "isb \n" ::: "memory" ); - } - portCPU_IRQ_ENABLE(); + 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 volatile ( "dsb \n" + "isb \n"::: "memory" ); + } - return ulReturn; + /* Just like this function returns a value of wether or not the interrupts where masked in the interrupt controller in order to avoid race condition when + * calling its matching vPortClearInterruptMask function, we needed a 'wasIRQDisabled' variable holding the state of the IRQ Enable bit in the CPSR in order + * to leave that bit in it's original state. Like mentioned above, hardware automatically clear the IRQEnable bit upon trapping into IRQ Mode, so the programmer + * cannot make assumption about it's state. Very rare, but very important race condition is avoided with this when this function is called in an ISR. The race + * condition in question was discovered when integrating tracealyzer code. Inside the function 'void vTaskSwitchContext( void )' in tasks.c, there is a macro 'traceTASK_SWITCHED_IN();' + * which gets replaced by something when using the tracing capabilities. That macro protects some critical section with matching calls to 'ulPortSetInterruptMask' + * and 'vPortClearInterruptMask'. At the time of calling those functions, the interrupt mask is not set in the interrupt controller, thus the only protecting barrier + * against the CPU traping into recursive interrupt was the IRQ Enable bit in the CPSR. By not taking it into acount, the very code that protects the CPU against + * critical section violation just enabled it to happen : A SysTick was waiting to happen, and calling 'portCPU_IRQ_ENABLE' would enable it to occur... Thus triggering a + * switch of context while already performing a switch context. */ + if(!wasIRQDisabled) + portCPU_IRQ_ENABLE(); + + return ulReturn; } /*-----------------------------------------------------------*/ -#if( configASSERT_DEFINED == 1 ) +#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. + 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. */ - 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. + configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); - FreeRTOS maintains separate thread and ISR API functions to ensure - interrupt entry is as fast and simple as possible. */ - - 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). Writing 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 ); - } + /* 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). Writing 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 */ /*-----------------------------------------------------------*/ - - - diff --git a/portable/GCC/ARM_CR5/portmacro.h b/portable/GCC/ARM_CR5/portmacro.h index 3f48ff609..1688b6a64 100644 --- a/portable/GCC/ARM_CR5/portmacro.h +++ b/portable/GCC/ARM_CR5/portmacro.h @@ -26,11 +26,11 @@ */ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H -#ifdef __cplusplus - extern "C" { -#endif + #ifdef __cplusplus + extern "C" { + #endif /*----------------------------------------------------------- * Port specific definitions. @@ -43,153 +43,152 @@ */ /* 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 + #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 portSTACK_TYPE StackType_t; + typedef long BaseType_t; + typedef unsigned long UBaseType_t; -typedef uint32_t TickType_t; -#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portSTACK_GROWTH ( -1 ) -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) -#define portBYTE_ALIGNMENT 8 + #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 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" ::: "memory" ); + #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) + #define portYIELD() __asm volatile ( "SWI 0" ::: "memory" ); /*----------------------------------------------------------- - * Critical section control - *----------------------------------------------------------*/ +* 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 ); + extern void vPortEnterCritical( void ); + extern void vPortExitCritical( void ); + extern uint32_t ulPortSetInterruptMask( void ); + extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); + extern void vPortInstallFreeRTOSVectorTable( void ); /* 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) + * 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 ) + * 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 ); + * 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() + * 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 ) + #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 + #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #endif -#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + #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 ) ) +/* 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 - __builtin_clz( uxReadyPriorities ) ) + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) ) -#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ -#ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() -#endif /* configASSERT */ + #ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif /* configASSERT */ -#define portNOP() __asm volatile( "NOP" ) + #define portNOP() __asm volatile ( "NOP" ) -#ifdef __cplusplus - } /* extern C */ -#endif + #ifdef __cplusplus + } /* extern C */ + #endif /* 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 + * 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 /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */ + #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware + #endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */ /* 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 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 ) ) ) + #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 ) ) ) -#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) + #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) #endif /* PORTMACRO_H */ - diff --git a/portable/RVDS/ARM7_LPC21xx/port.c b/portable/RVDS/ARM7_LPC21xx/port.c index 5b9c4c97e..b111f131b 100644 --- a/portable/RVDS/ARM7_LPC21xx/port.c +++ b/portable/RVDS/ARM7_LPC21xx/port.c @@ -34,35 +34,35 @@ #include "task.h" /* 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 portINSTRUCTION_SIZE ( ( StackType_t ) 4 ) -#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 ) +#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 ) +#define portNO_CRITICAL_SECTION_NESTING ( ( StackType_t ) 0 ) /* 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 ) +#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 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 ) +#define portTIMER_VIC_CHANNEL ( ( uint32_t ) 0x0004 ) +#define portTIMER_VIC_CHANNEL_BIT ( ( uint32_t ) 0x0010 ) +#define portTIMER_VIC_ENABLE ( ( uint32_t ) 0x0020 ) /* Constants required to handle interrupts. */ -#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 ) -#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 ) +#define portTIMER_MATCH_ISR_BIT ( ( uint8_t ) 0x01 ) +#define portCLEAR_VIC_INTERRUPT ( ( uint32_t ) 0 ) /*-----------------------------------------------------------*/ /* The code generated by the Keil compiler does not maintain separate - * stack and frame pointers. The portENTER_CRITICAL macro cannot therefore - * use the stack as per other ports. Instead 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. */ +stack and frame pointers. The portENTER_CRITICAL macro cannot therefore +use the stack as per other ports. Instead 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. */ -#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) +#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) volatile uint32_t ulCriticalNesting = 9999UL; /*-----------------------------------------------------------*/ @@ -70,222 +70,222 @@ volatile uint32_t ulCriticalNesting = 9999UL; /* Setup the timer to generate the tick interrupts. */ static void prvSetupTimerInterrupt( void ); -/* - * The scheduler can only be started from ARM mode, so - * vPortStartFirstSTask() is defined in portISR.c. +/* + * The scheduler can only be started from ARM mode, so + * vPortStartFirstSTask() is defined in portISR.c. */ extern __asm void vPortStartFirstTask( void ); /*-----------------------------------------------------------*/ -/* - * See header file for description. +/* + * See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { - StackType_t * pxOriginalTOS; +StackType_t *pxOriginalTOS; - /* Setup the initial stack of the task. The stack is set exactly as - * expected by the portRESTORE_CONTEXT() macro. - * - * Remember where the top of the (simulated) stack is before we place - * anything on it. */ - pxOriginalTOS = pxTopOfStack; + /* Setup the initial stack of the task. The stack is set exactly as + expected by the portRESTORE_CONTEXT() macro. - /* To ensure asserts in tasks.c don't fail, although in this case the assert - * is not really required. */ - pxTopOfStack--; + Remember where the top of the (simulated) stack is before we place + anything on it. */ + pxOriginalTOS = pxTopOfStack; + + /* To ensure asserts in tasks.c don't fail, although in this case the assert + is not really required. */ + pxTopOfStack--; - /* 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--; + /* 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--; - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ - 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--; + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + pxTopOfStack--; - /* The last thing onto the stack is the status register, which is set for - * system mode, with interrupts enabled. */ - *pxTopOfStack = ( StackType_t ) portINITIAL_SPSR; + /* The last thing onto the stack is the status register, which 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; - } + if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL ) + { + /* We want the task to start in thumb mode. */ + *pxTopOfStack |= portTHUMB_MODE_BIT; + } - pxTopOfStack--; + pxTopOfStack--; - /* The code generated by the Keil compiler does not maintain separate - * stack and frame pointers. The portENTER_CRITICAL macro cannot therefore - * use the stack as per other ports. Instead 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 = portNO_CRITICAL_SECTION_NESTING; + /* The code generated by the Keil compiler does not maintain separate + stack and frame pointers. The portENTER_CRITICAL macro cannot therefore + use the stack as per other ports. Instead 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 = portNO_CRITICAL_SECTION_NESTING; - return pxTopOfStack; + return pxTopOfStack; } /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { - /* Start the timer that generates the tick ISR. */ - prvSetupTimerInterrupt(); + /* Start the timer that generates the tick ISR. */ + prvSetupTimerInterrupt(); - /* Start the first task. This is done from portISR.c as ARM mode must be - * used. */ - vPortStartFirstTask(); + /* Start the first task. This is done from portISR.c as ARM mode must be + used. */ + vPortStartFirstTask(); - /* Should not get here! */ - return 0; + /* 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 this is required - stop the tick ISR then - * return back to main. */ + /* It is unlikely that the ARM port will require this function as there + is nothing to return to. If this is required - stop the tick ISR then + return back to main. */ } /*-----------------------------------------------------------*/ #if configUSE_PREEMPTION == 0 -/* - * The cooperative scheduler requires a normal IRQ service routine to - * simply increment the system tick. - */ - void vNonPreemptiveTick( void ) __irq; - void vNonPreemptiveTick( void ) __irq - { - /* Increment the tick count - this may make a delaying task ready - * to run - but a context switch is not performed. */ - xTaskIncrementTick(); + /* + * The cooperative scheduler requires a normal IRQ service routine to + * simply increment the system tick. + */ + void vNonPreemptiveTick( void ) __irq; + void vNonPreemptiveTick( void ) __irq + { + /* Increment the tick count - this may make a delaying task ready + to run - but a context switch is not performed. */ + xTaskIncrementTick(); - T0IR = portTIMER_MATCH_ISR_BIT; /* Clear the timer event */ - VICVectAddr = portCLEAR_VIC_INTERRUPT; /* Acknowledge the Interrupt */ - } + T0IR = portTIMER_MATCH_ISR_BIT; /* Clear the timer event */ + VICVectAddr = portCLEAR_VIC_INTERRUPT; /* Acknowledge the Interrupt */ + } -#else /* if configUSE_PREEMPTION == 0 */ + #else -/* - ************************************************************************** - * The preemptive scheduler ISR is written in assembler and can be found - * in the portASM.s file. This will only get used if portUSE_PREEMPTION - * is set to 1 in portmacro.h - ************************************************************************** - */ + /* + ************************************************************************** + * The preemptive scheduler ISR is written in assembler and can be found + * in the portASM.s file. This will only get used if portUSE_PREEMPTION + * is set to 1 in portmacro.h + ************************************************************************** + */ - void vPreemptiveTick( void ); + void vPreemptiveTick( void ); -#endif /* if configUSE_PREEMPTION == 0 */ +#endif /*-----------------------------------------------------------*/ static void prvSetupTimerInterrupt( void ) { - uint32_t ulCompareMatch; +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; + /* 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; + /* 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 + /* 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; + T0MR0 = ulCompareMatch; - /* Generate tick with timer 0 compare match. */ - T0MCR = portRESET_COUNT_ON_MATCH | portINTERRUPT_ON_MATCH; + /* 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; + /* 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 + { + VICVectAddr0 = ( uint32_t ) vPreemptiveTick; + } + #else + { + VICVectAddr0 = ( uint32_t ) vNonPreemptiveTick; + } + #endif - /* The ISR installed depends on whether the preemptive or cooperative - * scheduler is being used. */ - #if configUSE_PREEMPTION == 1 - { - VICVectAddr0 = ( uint32_t ) vPreemptiveTick; - } - #else - { - VICVectAddr0 = ( uint32_t ) vNonPreemptiveTick; - } - #endif + VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE; - VICVectCntl0 = portTIMER_VIC_CHANNEL | portTIMER_VIC_ENABLE; - - /* Start the timer - interrupts are disabled when this function is called - * so it is okay to do this here. */ - T0TCR = portENABLE_TIMER; + /* 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 as per portDISABLE_INTERRUPTS(); */ - __disable_irq(); + /* Disable interrupts as per portDISABLE_INTERRUPTS(); */ + __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++; + /* 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( 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 interrupts as per portEXIT_CRITICAL(). */ - __enable_irq(); - } - } + /* If the nesting level has reached zero then interrupts should be + re-enabled. */ + if( ulCriticalNesting == portNO_CRITICAL_NESTING ) + { + /* Enable interrupts as per portEXIT_CRITICAL(). */ + __enable_irq(); + } + } } /*-----------------------------------------------------------*/ + + diff --git a/portable/RVDS/ARM7_LPC21xx/portmacro.h b/portable/RVDS/ARM7_LPC21xx/portmacro.h index 3aed9823e..6f24ac70d 100644 --- a/portable/RVDS/ARM7_LPC21xx/portmacro.h +++ b/portable/RVDS/ARM7_LPC21xx/portmacro.h @@ -27,11 +27,11 @@ #ifndef PORTMACRO_H - #define PORTMACRO_H +#define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +#ifdef __cplusplus +extern "C" { +#endif /*----------------------------------------------------------- * Port specific definitions. @@ -44,57 +44,57 @@ */ /* 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 +#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 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 +#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 portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 /*-----------------------------------------------------------*/ /* Task utilities. */ /*----------------------------------------------------------- -* ISR entry and exit macros. These are only required if a task switch -* is required from an ISR. -*----------------------------------------------------------*/ + * ISR entry and exit macros. These are only required if a task switch + * is required from an ISR. + *----------------------------------------------------------*/ /* If a switch is required then we just need to call */ /* vTaskSwitchContext() as the context has already been */ /* saved. */ - #define portEXIT_SWITCHING_ISR( SwitchRequired ) \ - { \ - extern void vTaskSwitchContext( void ); \ - \ - if( SwitchRequired ) \ - { \ - vTaskSwitchContext(); \ - } \ - } \ +#define portEXIT_SWITCHING_ISR(SwitchRequired) \ +{ \ +extern void vTaskSwitchContext(void); \ + \ + if(SwitchRequired) \ + { \ + vTaskSwitchContext(); \ + } \ +} \ - extern void vPortYield( void ); - #define portYIELD() vPortYield() +extern void vPortYield( void ); +#define portYIELD() vPortYield() /* Critical section management. */ @@ -107,39 +107,40 @@ * take care of that for us. ******************************************************************* */ - #define portDISABLE_INTERRUPTS() __disable_irq() - #define portENABLE_INTERRUPTS() __enable_irq() +#define portDISABLE_INTERRUPTS() __disable_irq() +#define portENABLE_INTERRUPTS() __enable_irq() /*----------------------------------------------------------- -* Critical section control -* -* The code generated by the Keil compiler does not maintain separate -* stack and frame pointers. The portENTER_CRITICAL macro cannot therefore -* use the stack as per other ports. Instead a variable is used to keep -* track of the critical section nesting. This necessitates the use of a -* function in place of the macro. -*----------------------------------------------------------*/ + * Critical section control + * + * The code generated by the Keil compiler does not maintain separate + * stack and frame pointers. The portENTER_CRITICAL macro cannot therefore + * use the stack as per other ports. Instead a variable is used to keep + * track of the critical section nesting. This necessitates the use of a + * function in place of the macro. + *----------------------------------------------------------*/ - extern void vPortEnterCritical( void ); - extern void vPortExitCritical( void ); +extern void vPortEnterCritical( void ); +extern void vPortExitCritical( void ); - #define portENTER_CRITICAL() vPortEnterCritical(); - #define portEXIT_CRITICAL() vPortExitCritical(); +#define portENTER_CRITICAL() vPortEnterCritical(); +#define portEXIT_CRITICAL() vPortExitCritical(); /*-----------------------------------------------------------*/ /* Compiler specifics. */ - #define inline - #define register - #define portNOP() __asm{ NOP } +#define inline +#define register +#define portNOP() __asm{ NOP } /*-----------------------------------------------------------*/ /* 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 portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) - #ifdef __cplusplus - } - #endif +#ifdef __cplusplus +} +#endif #endif /* PORTMACRO_H */ + diff --git a/portable/RVDS/ARM_CA9/port.c b/portable/RVDS/ARM_CA9/port.c index e7c418dbb..250f31304 100644 --- a/portable/RVDS/ARM_CA9/port.c +++ b/portable/RVDS/ARM_CA9/port.c @@ -33,124 +33,124 @@ #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 */ + #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 */ + #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 */ + #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 */ + #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 */ + #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 + #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 + #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 + /* 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 ) + #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #endif #ifndef configCLEAR_TICK_INTERRUPT - #define configCLEAR_TICK_INTERRUPT() + #define configCLEAR_TICK_INTERRUPT() #endif /* The number of bits to shift for an interrupt priority is dependent on the - * number of bits implemented by the interrupt controller. */ +number of bits implemented by the interrupt controller. */ #if configUNIQUE_INTERRUPT_PRIORITIES == 16 - #define portPRIORITY_SHIFT 4 - #define portMAX_BINARY_POINT_VALUE 3 + #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 + #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 + #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 + #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 /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */ - #error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware -#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */ + #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 /* A critical section is exited when the critical section nesting count reaches - * this value. */ -#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) +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 ) +(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 ) +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 ) /* 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 ) ) ) +#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 ) ) ) /* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary - * point is zero. */ -#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) +point is zero. */ +#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) /* 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 ) +#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 ) +#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 ) +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(); \ - } +#define portCLEAR_INTERRUPT_MASK() \ +{ \ + __disable_irq(); \ + portICCPMR_PRIORITY_MASK_REGISTER = portUNMASK_VALUE; \ + __asm( "DSB \n" \ + "ISB \n" ); \ + __enable_irq(); \ +} /*-----------------------------------------------------------*/ @@ -168,29 +168,29 @@ 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. */ +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; /* Used to pass constants into the ASM code. The address at which variables are - * placed is the constant value so indirect loads in the asm code are not - * required. */ +placed is the constant value so indirect loads in the asm code are not +required. */ uint32_t ulICCIAR __attribute__( ( at( portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ) ) ); uint32_t ulICCEOIR __attribute__( ( at( portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ) ) ); uint32_t ulICCPMR __attribute__( ( at( portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ) ) ); uint32_t ulAsmAPIPriorityMask __attribute__( ( at( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) ); /* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then - * a floating point context must be saved and restored for the task. */ +a floating point context must be saved and restored for the task. */ 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. */ +if the nesting depth is 0. */ uint32_t ulPortInterruptNesting = 0UL; /*-----------------------------------------------------------*/ @@ -198,286 +198,283 @@ uint32_t ulPortInterruptNesting = 0UL; /* * See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +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; + /* Setup the initial stack of the task. The stack is set exactly as + expected by the portRESTORE_CONTEXT() macro. - if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) - { - /* The task will start in THUMB mode. */ - *pxTopOfStack |= portTHUMB_MODE_BIT; - } + 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; - pxTopOfStack--; + if( ( ( uint32_t ) pxCode & portTHUMB_MODE_ADDRESS ) != 0x00UL ) + { + /* The task will start in THUMB mode. */ + *pxTopOfStack |= portTHUMB_MODE_BIT; + } - /* Next the return address, which in this case is the start of the task. */ - *pxTopOfStack = ( StackType_t ) pxCode; - pxTopOfStack--; + 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--; + /* Next the return address, which in this case is the start of the task. */ + *pxTopOfStack = ( StackType_t ) pxCode; + pxTopOfStack--; - /* The task will start with a critical nesting count of 0 as interrupts are - * enabled. */ - *pxTopOfStack = portNO_CRITICAL_NESTING; - 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 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; + /* The task will start with a critical nesting count of 0 as interrupts are + enabled. */ + *pxTopOfStack = portNO_CRITICAL_NESTING; + pxTopOfStack--; - return pxTopOfStack; + /* The task will start without a floating point context. A task that uses + the floating point hardware must call vPortTaskUsesFPU() before executing + any floating point instructions. */ + *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; + + return pxTopOfStack; } /*-----------------------------------------------------------*/ static void prvTaskExitError( void ) { - /* 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(); + /* 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 ). - for( ; ; ) - { - } + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ + configASSERT( ulPortInterruptNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + for( ;; ); } /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { - uint32_t ulAPSR; +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( "MRS ulAPSR, APSR" ); - ulAPSR &= portAPSR_MODE_BITS_MASK; - configASSERT( ulAPSR != portAPSR_USER_MODE ); + /* Only continue if the CPU is not in User mode. The CPU must be in a + Privileged mode for the scheduler to start. */ + __asm( "MRS ulAPSR, APSR" ); + 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( 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(); + 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(); - } - } + __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; + /* 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 ); + /* 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(); + /* 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++; + /* 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 ); - } + /* 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( 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(); - } - } + /* 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(); + /* 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; - } + /* Increment the RTOS tick. */ + if( xTaskIncrementTick() != pdFALSE ) + { + ulPortYieldRequired = pdTRUE; + } - /* Ensure all interrupt priorities are active again. */ - portCLEAR_INTERRUPT_MASK(); - configCLEAR_TICK_INTERRUPT(); + /* Ensure all interrupt priorities are active again. */ + portCLEAR_INTERRUPT_MASK(); + configCLEAR_TICK_INTERRUPT(); } /*-----------------------------------------------------------*/ void vPortTaskUsesFPU( void ) { - uint32_t ulInitialFPSCR = 0; +uint32_t ulInitialFPSCR = 0; - /* A task is registering the fact that it needs an FPU context. Set the - * FPU flag (which is saved as part of the task context). */ - ulPortTaskHasFPUContext = pdTRUE; + /* 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, ulInitialFPSCR"); + /* Initialise the floating point status register. */ + __asm( "FMXR FPSCR, ulInitialFPSCR" ); } /*-----------------------------------------------------------*/ void vPortClearInterruptMask( uint32_t ulNewMaskValue ) { - if( ulNewMaskValue == pdFALSE ) - { - portCLEAR_INTERRUPT_MASK(); - } + if( ulNewMaskValue == pdFALSE ) + { + portCLEAR_INTERRUPT_MASK(); + } } /*-----------------------------------------------------------*/ uint32_t ulPortSetInterruptMask( void ) { - uint32_t ulReturn; +uint32_t ulReturn; - __disable_irq(); + __disable_irq(); + if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) + { + /* Interrupts were already masked. */ + ulReturn = pdTRUE; + } + else + { + ulReturn = pdFALSE; + portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); + __asm( "DSB \n" + "ISB \n" ); + } + __enable_irq(); - if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) - { - /* 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; + return ulReturn; } /*-----------------------------------------------------------*/ -#if ( configASSERT_DEFINED == 1 ) +#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 >= ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); + 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. - /* 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 <= portMAX_BINARY_POINT_VALUE ); - } + 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 >= ( 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 <= portMAX_BINARY_POINT_VALUE ); + } #endif /* configASSERT_DEFINED */ + + + + diff --git a/portable/RVDS/ARM_CA9/portmacro.h b/portable/RVDS/ARM_CA9/portmacro.h index f71deb1c8..02a721165 100644 --- a/portable/RVDS/ARM_CA9/portmacro.h +++ b/portable/RVDS/ARM_CA9/portmacro.h @@ -26,11 +26,11 @@ */ #ifndef PORTMACRO_H - #define PORTMACRO_H +#define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +#ifdef __cplusplus +extern "C" { +#endif /*----------------------------------------------------------- * Port specific definitions. @@ -43,120 +43,121 @@ */ /* 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 +#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 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 +#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 + /* 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 /*-----------------------------------------------------------*/ /* Hardware specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 +#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 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" ); +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() __asm( "SWI 0" ); /*----------------------------------------------------------- -* Critical section control -*----------------------------------------------------------*/ + * Critical section control + *----------------------------------------------------------*/ - extern void vPortEnterCritical( void ); - extern void vPortExitCritical( void ); - extern uint32_t ulPortSetInterruptMask( void ); - extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); +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 ) +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 ) +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 ); +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() +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 ) +#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 +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif - #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 +#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 ) ) + /* 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 ) ) + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __clz( uxReadyPriorities ) ) - #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ - #ifdef configASSERT - void vPortValidateInterruptPriority( void ); - #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() - #endif +#ifdef configASSERT + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() +#endif - #define portNOP() __nop() +#define portNOP() __nop() - #ifdef __cplusplus - } - #endif +#ifdef __cplusplus +} +#endif #endif /* PORTMACRO_H */ + diff --git a/portable/RVDS/ARM_CM7/r0p1/port.c b/portable/RVDS/ARM_CM7/r0p1/port.c index 5d3943ada..d20696431 100644 --- a/portable/RVDS/ARM_CM7/r0p1/port.c +++ b/portable/RVDS/ARM_CM7/r0p1/port.c @@ -22,6 +22,7 @@ * http://www.FreeRTOS.org * http://aws.amazon.com/freertos * + * 1 tab == 4 spaces! */ /*----------------------------------------------------------- @@ -237,7 +238,7 @@ __asm void vPortSVCHandler( void ) /* Get the location of the current TCB. */ ldr r3, = pxCurrentTCB - ldr r1, [ r3 ] + ldr r1, [ r3 ] ldr r0, [ r1 ] /* Pop the core registers. */ ldmia r0 !, { @@ -257,7 +258,7 @@ __asm void prvStartFirstTask( void ) /* Use the NVIC offset register to locate the stack. */ ldr r0, = 0xE000ED08 - ldr r0, [ r0 ] + ldr r0, [ r0 ] ldr r0, [ r0 ] /* Set the msp back to the start of the stack. */ msr msp, r0 @@ -274,9 +275,9 @@ __asm void prvStartFirstTask( void ) dsb isb /* Call SVC to start the first task. */ - svc 0 - nop + svc 0 nop + nop } /*-----------------------------------------------------------*/ @@ -286,7 +287,7 @@ __asm void prvEnableVFP( void ) /* The FPU enable bits are in the CPACR. */ ldr.w r0, = 0xE000ED88 - ldr r1, [ r0 ] + ldr r1, [ r0 ] /* Enable CP10 and CP11 coprocessors, then save back. */ orr r1, r1, # ( 0xf << 20 ) @@ -443,7 +444,7 @@ __asm void xPortPendSVHandler( void ) isb /* Get the location of the current TCB. */ ldr r3, = pxCurrentTCB - ldr r2, [ r3 ] + ldr r2, [ r3 ] /* Is the task using the FPU context? If so, push high vfp registers. */ tst r14, # 0x10 @@ -494,7 +495,7 @@ __asm void xPortPendSVHandler( void ) } msr psp, r0 - isb + isb #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ #if WORKAROUND_PMU_CM001 == 1 push { diff --git a/portable/RVDS/ARM_CM7/r0p1/portmacro.h b/portable/RVDS/ARM_CM7/r0p1/portmacro.h index 0d19a0601..b4d8d1bbb 100644 --- a/portable/RVDS/ARM_CM7/r0p1/portmacro.h +++ b/portable/RVDS/ARM_CM7/r0p1/portmacro.h @@ -22,11 +22,12 @@ * http://www.FreeRTOS.org * http://aws.amazon.com/freertos * + * 1 tab == 4 spaces! */ #ifndef PORTMACRO_H -#define PORTMACRO_H + #define PORTMACRO_H #ifdef __cplusplus extern "C" {