Style: redo the stuyles

This commit is contained in:
Alfred Gedeon 2020-08-12 22:46:27 -07:00
parent 98b53bd3cd
commit 888d5aa8b6
55 changed files with 10171 additions and 9890 deletions

View file

@ -26,16 +26,16 @@
*/
/*
* Changes from V1.00:
*
Changes from V1.00:
+ Call to taskYIELD() from within tick ISR has been replaced by the more
+ efficient portSWITCH_CONTEXT().
efficient portSWITCH_CONTEXT().
+ ISR function definitions renamed to include the prv prefix.
+
+ Changes from V2.6.1
+
Changes from V2.6.1
+ Replaced the sUsingPreemption variable with the configUSE_PREEMPTION
+ macro to be consistent with the later ports.
macro to be consistent with the later ports.
*/
/*-----------------------------------------------------------
@ -68,16 +68,14 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz );
static void prvExitFunction( void );
/* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */
is being used. */
#if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */
being used. */
static void __interrupt __far prvPreemptiveTick( void );
#else
/* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */
being used. */
static void __interrupt __far prvNonPreemptiveTick( void );
#endif
@ -90,8 +88,8 @@ 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(). */
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. */
@ -105,11 +103,11 @@ BaseType_t xPortStartScheduler( void )
/* 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. */
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. */
vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
#if( configUSE_PREEMPTION == 1 )
@ -145,7 +143,7 @@ BaseType_t xPortStartScheduler( void )
/*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative scheduler
* is being used. */
is being used. */
#if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void )
{
@ -159,15 +157,15 @@ BaseType_t xPortStartScheduler( void )
/* Reset the PIC ready for the next time. */
portRESET_PIC();
}
#else /* if ( configUSE_PREEMPTION == 1 ) */
#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. */
so we don't have to switch in the context of the next task. */
xTaskIncrementTick();
portRESET_PIC();
}
#endif /* if ( configUSE_PREEMPTION == 1 ) */
#endif
/*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void )
@ -180,8 +178,8 @@ static void __interrupt __far prvYieldProcessor( void )
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. */
scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 );
}
/*-----------------------------------------------------------*/
@ -192,19 +190,18 @@ static void prvExitFunction( void )
uint16_t usTimer0Control;
/* Interrupts should be disabled here anyway - but no
* harm in making sure. */
harm in making sure. */
portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE )
{
/* Put back the switch interrupt routines that was in place
* before the scheduler started. */
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. */
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. */
@ -244,3 +241,4 @@ static void prvSetTickFrequency( uint32_t ulTickRateHz )
/*lint +e950 */

View file

@ -61,8 +61,7 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/
/* Critical section handling. */
#define portENTER_CRITICAL() \
__asm{ pushf } \
#define portENTER_CRITICAL() __asm{ pushf } \
__asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf }
@ -95,3 +94,4 @@ typedef unsigned short UBaseType_t;
#define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */

View file

@ -26,15 +26,15 @@
*/
/*
* Changes from V2.6.1
*
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
+
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.
its proper value when the scheduler exits.
*/
#include <stdlib.h>
@ -61,21 +61,19 @@ 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. */
scheduler is being used. */
#if( configUSE_PREEMPTION == 1 )
/* Tick service routine used by the scheduler when preemptive scheduling is
* being used. */
being used. */
static void __interrupt __far prvPreemptiveTick( void );
#else
/* Tick service routine used by the scheduler when cooperative scheduling is
* being used. */
being used. */
static void __interrupt __far prvNonPreemptiveTick( void );
#endif
@ -83,7 +81,7 @@ static void prvPortResetPIC( void );
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. */
@ -113,7 +111,7 @@ BaseType_t xPortStartScheduler( void )
/* 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. */
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 );
@ -121,15 +119,15 @@ BaseType_t xPortStartScheduler( void )
prvSetTickFrequency( configTICK_RATE_HZ );
/* Put our manual switch (yield) function on a known
* vector. */
vector. */
_dos_setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
/* Put the old tick on a different interrupt number so we can
* call it when we want. */
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. */
scheduler is being used. */
#if( configUSE_PREEMPTION == 1 )
{
/* Put our tick switch function on the timer interrupt. */
@ -143,8 +141,8 @@ BaseType_t xPortStartScheduler( void )
#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. */
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. */
@ -166,7 +164,7 @@ BaseType_t xPortStartScheduler( void )
/*-----------------------------------------------------------*/
/* The ISR used depends on whether the preemptive or cooperative
* scheduler is being used. */
scheduler is being used. */
#if( configUSE_PREEMPTION == 1 )
static void __interrupt __far prvPreemptiveTick( void )
{
@ -180,15 +178,15 @@ BaseType_t xPortStartScheduler( void )
/* Reset the PIC ready for the next time. */
prvPortResetPIC();
}
#else /* if ( configUSE_PREEMPTION == 1 ) */
#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. */
so we don't have to switch in the context of the next task. */
xTaskIncrementTick();
prvPortResetPIC();
}
#endif /* if ( configUSE_PREEMPTION == 1 ) */
#endif
/*-----------------------------------------------------------*/
static void __interrupt __far prvYieldProcessor( void )
@ -201,22 +199,19 @@ static void __interrupt __far prvYieldProcessor( void )
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. */
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
};
__asm{ int portSWITCH_INT_NUMBER + 1 };
}
else
{
/* Reset the PIC as the DOS tick is not being called to
* do it. */
do it. */
__asm
{
mov al, 20H
@ -229,8 +224,8 @@ static void prvPortResetPIC( void )
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. */
scheduler. This means we are not going to be using a
task stack frame so the task can be deleted. */
longjmp( xJumpBuf, 1 );
}
/*-----------------------------------------------------------*/
@ -240,9 +235,8 @@ static void prvExitFunction( void )
void ( __interrupt __far *pxOriginalTickISR )();
/* Interrupts should be disabled here anyway - but no
* harm in making sure. */
harm in making sure. */
portDISABLE_INTERRUPTS();
if( xSchedulerRunning == pdTRUE )
{
/* Set the DOS tick back onto the timer ticker. */
@ -251,13 +245,12 @@ static void prvExitFunction( void )
prvSetTickFrequencyDefault();
/* Put back the switch interrupt routines that was in place
* before the scheduler started. */
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. */
interrupts without the scheduler being called. */
portENABLE_INTERRUPTS();
}
/*-----------------------------------------------------------*/
@ -292,3 +285,4 @@ static void prvSetTickFrequencyDefault( void )
/*lint +e950 */

View file

@ -61,8 +61,7 @@ typedef unsigned short UBaseType_t;
/*-----------------------------------------------------------*/
/* Critical section management. */
#define portENTER_CRITICAL() \
__asm{ pushf } \
#define portENTER_CRITICAL() __asm{ pushf } \
__asm{ cli } \
#define portEXIT_CRITICAL() __asm{ popf }
@ -95,3 +94,4 @@ typedef unsigned short UBaseType_t;
#define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters )
#endif /* PORTMACRO_H */

View file

@ -47,10 +47,10 @@ 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 } \
@ -83,4 +83,5 @@ void portFIRST_CONTEXT( void );
__asm { iret }
#endif /* ifndef PORT_ASM_H */
#endif

View file

@ -26,14 +26,14 @@
*/
/*
* Changes from V1.00:
*
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
+
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.
*/
@ -45,14 +45,12 @@
/*-----------------------------------------------------------*/
/* 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;
/* Place a few bytes of known values on the bottom of the stack.
* This is just useful for debugging. */
This is just useful for debugging. */
*pxTopOfStack = 0x1111;
pxTopOfStack--;
@ -69,8 +67,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
/*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. */
instruction to load the program counter, so first there would be the
function call with parameters preamble. */
*pxTopOfStack = FP_SEG( pvParameters );
pxTopOfStack--;
@ -90,8 +88,8 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
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. */
switch function. These are loaded with values simply to make debugging
easier. */
*pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
@ -104,9 +102,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--;
/* We need the true data segment. */
__asm {
MOV DS_Reg, DS
};
__asm{ MOV DS_Reg, DS };
*pxTopOfStack = DS_Reg; /* DS */
pxTopOfStack--;
@ -121,3 +117,4 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
return pxTopOfStack;
}
/*-----------------------------------------------------------*/

View file

@ -38,7 +38,7 @@
#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_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 )
@ -55,15 +55,15 @@
#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 )
#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
#else
@ -97,7 +97,7 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting
variable. */
* variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*-----------------------------------------------------------*/
@ -130,10 +130,12 @@ 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. */
* interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
@ -153,22 +155,23 @@ static void prvTaskExitError( void )
volatile uint32_t ulDummy = 0UL;
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
* 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();
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. */
* 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. */
}
}
/*-----------------------------------------------------------*/
@ -176,15 +179,15 @@ volatile uint32_t ulDummy = 0UL;
void vPortSVCHandler( void )
{
/* This function is no longer used, but retained for backward
compatibility. */
* 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. */
* 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. */
@ -214,11 +217,11 @@ 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;
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. */
* here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
@ -228,11 +231,11 @@ BaseType_t xPortStartScheduler( void )
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. */
* 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();
@ -244,7 +247,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
* Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
@ -255,7 +258,7 @@ void vPortYield( void )
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. */
* within the specified behaviour for the architecture. */
__asm volatile ( "dsb" ::: "memory" );
__asm volatile ( "isb" );
}
@ -274,6 +277,7 @@ void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
@ -407,43 +411,44 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
}
/* 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. */
* 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. */
* tick periods. -1 is used because this code will execute part way
* through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
* method as that will mask interrupts that should exit sleep mode. */
__asm volatile ( "cpsid i" ::: "memory" );
__asm volatile ( "dsb" );
__asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
* 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. */
* this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
* periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
* above. */
__asm volatile ( "cpsie i" ::: "memory" );
}
else
@ -452,69 +457,71 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
* zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
* 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 );
/* 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. */
* 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" );
/* 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. */
* 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" );
/* 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 register to ensure the
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
* the time the SysTick is stopped for is accounted for as best it can
* be, but using the tickless mode will inevitably result in some tiny
* drift of the time maintained by the kernel with respect to calendar
* time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and
been set back to the current reload value (the reload back being
correct for the entire expected idle time) or if the SysTick is yet
to count to zero (in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */
* been set back to the current reload value (the reload back being
* correct for the entire expected idle time) or if the SysTick is yet
* to count to zero (in which case an interrupt other than the SysTick
* must have brought the system out of sleep mode). */
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
/* The tick interrupt is already pending, and the SysTick count
reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
* reloaded with ulReloadValue. Reset the
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
* period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something
that took too long. */
* underflowed because the post sleep hook did something
* that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
@ -523,30 +530,30 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */
* 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). */
* Work out how long the sleep lasted rounded to complete tick
* periods (not the ulReload value which accounted for part
* ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
* was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
* 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. */
* 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 );

View file

@ -64,7 +64,7 @@ typedef unsigned long UBaseType_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. */
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
@ -122,4 +122,3 @@ extern void vClearInterruptMaskFromISR( uint32_t ulMask ) __attribute__((naked)
#endif
#endif /* PORTMACRO_H */

View file

@ -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

View file

@ -244,6 +244,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_TRUSTZONE == 1 )
/**
* @brief Allocate a secure context for the task.
*
@ -269,6 +270,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
/**
* @brief Checks whether or not the processor is privileged.
*

View file

@ -96,7 +96,8 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged )
#else /* configENABLE_MPU */
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
#endif /* configENABLE_MPU */
@ -104,6 +105,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
uint8_t * pucStackMemory = NULL;
uint32_t ulIPSR;
SecureContextHandle_t xSecureContextHandle = NULL;
#if ( configENABLE_MPU == 1 )
uint32_t * pulCurrentStackPointer = NULL;
#endif /* configENABLE_MPU */
@ -144,6 +146,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
* context switch. */
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
pulCurrentStackPointer--;
if( ulIsTaskPrivileged )
{
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
@ -162,7 +165,6 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
/* 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 */
}

View file

@ -70,7 +70,8 @@ void SecureContext_Init( void );
* otherwise.
*/
#if ( configENABLE_MPU == 1 )
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged );
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged );
#else /* configENABLE_MPU */
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
#endif /* configENABLE_MPU */

View file

@ -63,6 +63,7 @@
/* 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 ];
@ -191,6 +192,7 @@ uint8_t *puc;
/* 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;
@ -204,6 +206,7 @@ uint8_t *puc;
/* 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 )
@ -289,6 +292,7 @@ void *pvReturn = NULL;
* one of adequate size is found. */
pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock;
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{
pxPreviousBlock = pxBlock;
@ -376,7 +380,7 @@ void *pvReturn = NULL;
mtCOVERAGE_TEST_MARKER();
}
}
#endif
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
return pvReturn;

View file

@ -127,7 +127,7 @@
{ \
secureportDISABLE_SECURE_INTERRUPTS(); \
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
for( ;; ); \
for( ; ; ) {; } \
}
#endif /* __SECURE_PORT_MACROS_H__ */

View file

@ -244,6 +244,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_TRUSTZONE == 1 )
/**
* @brief Allocate a secure context for the task.
*
@ -269,6 +270,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
/**
* @brief Checks whether or not the processor is privileged.
*

View file

@ -34,8 +34,8 @@
#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
#endif
@ -45,8 +45,9 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
/* 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. */
* as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif
@ -54,7 +55,7 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#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_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 )
@ -85,17 +86,17 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
#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. */
#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. */
* 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
#else
@ -129,7 +130,7 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting
variable. */
* variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
@ -171,10 +172,12 @@ 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. */
* interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
@ -194,22 +197,23 @@ static void prvTaskExitError( void )
volatile uint32_t ulDummy = 0UL;
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
* 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();
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. */
* 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. */
}
}
/*-----------------------------------------------------------*/
@ -258,7 +262,7 @@ 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 */
* See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
#if ( configASSERT_DEFINED == 1 )
@ -268,15 +272,15 @@ BaseType_t xPortStartScheduler( void )
volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible.
Save the interrupt priority value that is about to be clobbered. */
* functions can be called. ISR safe functions are those that end in
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible.
*
* Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all
possible bits. */
* possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
@ -286,8 +290,9 @@ BaseType_t xPortStartScheduler( void )
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
* of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
@ -297,8 +302,8 @@ BaseType_t xPortStartScheduler( void )
#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. */
* priority bits matches the number of priority bits actually queried
* from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
}
#endif
@ -306,29 +311,29 @@ BaseType_t xPortStartScheduler( void )
#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. */
* 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. */
* register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
value. */
* 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;
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. */
* here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
@ -338,11 +343,11 @@ BaseType_t xPortStartScheduler( void )
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. */
* 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();
@ -354,7 +359,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
* Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
@ -365,10 +370,10 @@ void vPortEnterCritical( void )
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. */
* 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 );
@ -380,6 +385,7 @@ void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
@ -427,16 +433,16 @@ void xPortPendSVHandler( void )
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. */
* 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. */
* the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
@ -458,43 +464,44 @@ void xPortSysTickHandler( void )
}
/* 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. */
* 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. */
* tick periods. -1 is used because this code will execute part way
* through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
* method as that will mask interrupts that should exit sleep mode. */
__asm volatile ( "cpsid i" ::: "memory" );
__asm volatile ( "dsb" );
__asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
* 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. */
* this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
* periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
* above. */
__asm volatile ( "cpsie i" ::: "memory" );
}
else
@ -503,69 +510,71 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
* zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
* 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 );
/* 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. */
* 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" );
/* 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. */
* 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" );
/* 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 register to ensure the
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
* the time the SysTick is stopped for is accounted for as best it can
* be, but using the tickless mode will inevitably result in some tiny
* drift of the time maintained by the kernel with respect to calendar
* time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and
been set back to the current reload value (the reload back being
correct for the entire expected idle time) or if the SysTick is yet
to count to zero (in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */
* been set back to the current reload value (the reload back being
* correct for the entire expected idle time) or if the SysTick is yet
* to count to zero (in which case an interrupt other than the SysTick
* must have brought the system out of sleep mode). */
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
/* The tick interrupt is already pending, and the SysTick count
reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
* reloaded with ulReloadValue. Reset the
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
* period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something
that took too long. */
* underflowed because the post sleep hook did something
* that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
@ -574,30 +583,30 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */
* 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). */
* Work out how long the sleep lasted rounded to complete tick
* periods (not the ulReload value which accounted for part
* ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
* was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
* 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. */
* 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 );
@ -653,66 +662,45 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */
* an interrupt that has been assigned a priority above
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
* function. ISR safe FreeRTOS API functions must *only* be called
* from interrupts that have been assigned a priority at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Numerically low interrupt priority numbers represent logically high
* interrupt priorities, therefore the priority of the interrupt must
* be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible.
*
* The following links provide detailed information:
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
* http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
}
/* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority).
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredictable behaviour. */
* 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 */

View file

@ -64,7 +64,7 @@ typedef unsigned long UBaseType_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. */
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
@ -83,7 +83,7 @@ typedef unsigned long UBaseType_t;
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. */ \
* within the specified behaviour for the architecture. */ \
__asm volatile ( "dsb" ::: "memory" ); \
__asm volatile ( "isb" ); \
}
@ -107,8 +107,8 @@ extern void vPortExitCritical( void );
/*-----------------------------------------------------------*/
/* 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. */
* 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 )
/*-----------------------------------------------------------*/
@ -133,6 +133,7 @@ not necessary for to use this port. They are defined so the common demo files
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
return ucReturn;
}
@ -222,7 +223,7 @@ uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
* warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
@ -243,4 +244,3 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
#endif
#endif /* PORTMACRO_H */

View file

@ -74,7 +74,7 @@
#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_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 )
@ -86,6 +86,7 @@
/* 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 )
@ -206,6 +207,7 @@
#define portINITIAL_XPSR ( 0x01000000 )
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/**
* @brief Initial EXC_RETURN value.
*
@ -222,6 +224,7 @@
*/
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else
/**
* @brief Initial EXC_RETURN value.
*
@ -286,6 +289,7 @@
static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 )
/**
* @brief Setup the Memory Protection Unit (MPU).
*/
@ -293,6 +297,7 @@ static void prvTaskExitError( void );
#endif /* configENABLE_MPU */
#if ( configENABLE_FPU == 1 )
/**
* @brief Setup the Floating Point Unit (FPU).
*/
@ -345,33 +350,35 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVI
* @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;
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;
PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/**
* @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;
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/**
* @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only).
*/
static uint32_t ulStoppedTimerCompensation = 0;
PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
@ -397,6 +404,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* 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;
@ -447,12 +455,14 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* 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 );
/* Re-enable interrupts to allow the interrupt that brought the MCU
@ -557,7 +567,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNC
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_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;
}
/*-----------------------------------------------------------*/
@ -591,6 +601,7 @@ volatile uint32_t ulDummy = 0UL;
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__;
@ -601,7 +612,7 @@ volatile uint32_t ulDummy = 0UL;
extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__;
#else
#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__[];
@ -754,6 +765,7 @@ void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION
{
#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__;
@ -784,7 +796,7 @@ uint8_t 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 ];
@ -801,7 +813,7 @@ uint8_t ucSVCNumber;
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
@ -810,22 +822,18 @@ uint8_t ucSVCNumber;
configASSERT( xSecureContext != NULL );
SecureContext_LoadContext( xSecureContext );
}
break;
case portSVC_FREE_SECURE_CONTEXT:
{
/* R0 contains the secure context handle to be freed. */
ulR0 = pulCallerStackAddress[ 0 ];
/* Free the secure context. */
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
}
break;
#endif /* configENABLE_TRUSTZONE */
case portSVC_START_SCHEDULER:
{
#if ( configENABLE_TRUSTZONE == 1 )
{
/* De-prioritize the non-secure exceptions so that the
@ -847,36 +855,39 @@ uint8_t ucSVCNumber;
/* 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__ )
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 */
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
@ -897,6 +908,7 @@ uint8_t ucSVCNumber;
#if ( configENABLE_MPU == 1 )
{
pxTopOfStack--;
if( xRunPrivileged == pdTRUE )
{
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -958,6 +970,7 @@ uint8_t ucSVCNumber;
#if ( configENABLE_MPU == 1 )
{
pxTopOfStack--;
if( xRunPrivileged == pdTRUE )
{
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -988,8 +1001,8 @@ uint8_t ucSVCNumber;
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;
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
#if ( configENABLE_MPU == 1 )
{
@ -1031,10 +1044,23 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
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 )
{
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 );
@ -1046,9 +1072,23 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
* 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;
ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
/* 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 ].ulRBAR = ( ulRegionStartAddress ) |
@ -1060,6 +1100,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
( portMPU_RLAR_ATTR_INDEX0 ) |
( portMPU_RLAR_REGION_ENABLE );
}
}
/* User supplied configurable regions. */
for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )

View file

@ -244,6 +244,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_TRUSTZONE == 1 )
/**
* @brief Allocate a secure context for the task.
*
@ -269,6 +270,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
/**
* @brief Checks whether or not the processor is privileged.
*

View file

@ -96,7 +96,8 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged )
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged )
#else /* configENABLE_MPU */
secureportNON_SECURE_CALLABLE SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize )
#endif /* configENABLE_MPU */
@ -104,6 +105,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
uint8_t * pucStackMemory = NULL;
uint32_t ulIPSR;
SecureContextHandle_t xSecureContextHandle = NULL;
#if ( configENABLE_MPU == 1 )
uint32_t * pulCurrentStackPointer = NULL;
#endif /* configENABLE_MPU */
@ -144,6 +146,7 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
* context switch. */
pulCurrentStackPointer = ( uint32_t * ) xSecureContextHandle->pucStackStart;
pulCurrentStackPointer--;
if( ulIsTaskPrivileged )
{
*( pulCurrentStackPointer ) = securecontextCONTROL_VALUE_PRIVILEGED;
@ -162,7 +165,6 @@ secureportNON_SECURE_CALLABLE void SecureContext_Init( void )
/* 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 */
}

View file

@ -70,7 +70,8 @@ void SecureContext_Init( void );
* otherwise.
*/
#if ( configENABLE_MPU == 1 )
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize, uint32_t ulIsTaskPrivileged );
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize,
uint32_t ulIsTaskPrivileged );
#else /* configENABLE_MPU */
SecureContextHandle_t SecureContext_AllocateContext( uint32_t ulSecureStackSize );
#endif /* configENABLE_MPU */

View file

@ -63,6 +63,7 @@
/* 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 ];
@ -191,6 +192,7 @@ uint8_t *puc;
/* 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;
@ -204,6 +206,7 @@ uint8_t *puc;
/* 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 )
@ -289,6 +292,7 @@ void *pvReturn = NULL;
* one of adequate size is found. */
pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock;
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{
pxPreviousBlock = pxBlock;
@ -376,7 +380,7 @@ void *pvReturn = NULL;
mtCOVERAGE_TEST_MARKER();
}
}
#endif
#endif /* if ( secureconfigUSE_MALLOC_FAILED_HOOK == 1 ) */
secureportASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) secureportBYTE_ALIGNMENT_MASK ) == 0 );
return pvReturn;

View file

@ -127,7 +127,7 @@
{ \
secureportDISABLE_SECURE_INTERRUPTS(); \
secureportDISABLE_NON_SECURE_INTERRUPTS(); \
for( ;; ); \
for( ; ; ) {; } \
}
#endif /* __SECURE_PORT_MACROS_H__ */

View file

@ -74,7 +74,7 @@
#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_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 )
@ -86,6 +86,7 @@
/* 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 )
@ -206,6 +207,7 @@
#define portINITIAL_XPSR ( 0x01000000 )
#if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
/**
* @brief Initial EXC_RETURN value.
*
@ -222,6 +224,7 @@
*/
#define portINITIAL_EXC_RETURN ( 0xfffffffd )
#else
/**
* @brief Initial EXC_RETURN value.
*
@ -286,6 +289,7 @@
static void prvTaskExitError( void );
#if ( configENABLE_MPU == 1 )
/**
* @brief Setup the Memory Protection Unit (MPU).
*/
@ -293,6 +297,7 @@ static void prvTaskExitError( void );
#endif /* configENABLE_MPU */
#if ( configENABLE_FPU == 1 )
/**
* @brief Setup the Floating Point Unit (FPU).
*/
@ -345,33 +350,35 @@ portDONT_DISCARD void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) PRIVI
* @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;
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;
PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
/**
* @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;
PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
/**
* @brief Compensate for the CPU cycles that pass while the SysTick is
* stopped (low power functionality only).
*/
static uint32_t ulStoppedTimerCompensation = 0;
PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
#endif /* configUSE_TICKLESS_IDLE */
/*-----------------------------------------------------------*/
@ -397,6 +404,7 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* 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;
@ -447,12 +455,14 @@ static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
* 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 );
/* Re-enable interrupts to allow the interrupt that brought the MCU
@ -557,7 +567,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNC
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_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;
}
/*-----------------------------------------------------------*/
@ -591,6 +601,7 @@ volatile uint32_t ulDummy = 0UL;
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__;
@ -601,7 +612,7 @@ volatile uint32_t ulDummy = 0UL;
extern uint32_t * __unprivileged_flash_end__;
extern uint32_t * __privileged_sram_start__;
extern uint32_t * __privileged_sram_end__;
#else
#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__[];
@ -754,6 +765,7 @@ void vPortSVCHandler_C( uint32_t *pulCallerStackAddress ) /* PRIVILEGED_FUNCTION
{
#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__;
@ -784,7 +796,7 @@ uint8_t 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 ];
@ -801,7 +813,7 @@ uint8_t ucSVCNumber;
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
}
#else
#else /* if ( configENABLE_MPU == 1 ) */
{
/* Allocate and load a context for the secure task. */
xSecureContext = SecureContext_AllocateContext( ulR0 );
@ -810,22 +822,18 @@ uint8_t ucSVCNumber;
configASSERT( xSecureContext != NULL );
SecureContext_LoadContext( xSecureContext );
}
break;
case portSVC_FREE_SECURE_CONTEXT:
{
/* R0 contains the secure context handle to be freed. */
ulR0 = pulCallerStackAddress[ 0 ];
/* Free the secure context. */
SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
}
break;
#endif /* configENABLE_TRUSTZONE */
case portSVC_START_SCHEDULER:
{
#if ( configENABLE_TRUSTZONE == 1 )
{
/* De-prioritize the non-secure exceptions so that the
@ -847,36 +855,39 @@ uint8_t ucSVCNumber;
/* 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__ )
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 */
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
@ -897,6 +908,7 @@ uint8_t ucSVCNumber;
#if ( configENABLE_MPU == 1 )
{
pxTopOfStack--;
if( xRunPrivileged == pdTRUE )
{
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -958,6 +970,7 @@ uint8_t ucSVCNumber;
#if ( configENABLE_MPU == 1 )
{
pxTopOfStack--;
if( xRunPrivileged == pdTRUE )
{
*pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
@ -988,8 +1001,8 @@ uint8_t ucSVCNumber;
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;
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
#if ( configENABLE_MPU == 1 )
{
@ -1031,10 +1044,23 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
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 )
{
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 );
@ -1046,9 +1072,23 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
* 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;
ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
/* 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 ].ulRBAR = ( ulRegionStartAddress ) |
@ -1060,6 +1100,7 @@ void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
( portMPU_RLAR_ATTR_INDEX0 ) |
( portMPU_RLAR_REGION_ENABLE );
}
}
/* User supplied configurable regions. */
for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )

View file

@ -244,6 +244,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_TRUSTZONE == 1 )
/**
* @brief Allocate a secure context for the task.
*
@ -269,6 +270,7 @@ typedef struct MPU_SETTINGS
/*-----------------------------------------------------------*/
#if ( configENABLE_MPU == 1 )
/**
* @brief Checks whether or not the processor is privileged.
*

View file

@ -26,7 +26,7 @@
*/
/*-----------------------------------------------------------
* 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
@ -45,6 +45,7 @@
/* 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 )
@ -54,8 +55,8 @@
#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_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 )
@ -191,7 +192,10 @@ 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. */
@ -241,8 +245,10 @@ 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__;
@ -261,11 +267,14 @@ uint32_t ulPC;
switch( ucSVCNumber )
{
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
case portSVC_START_SCHEDULER:
portNVIC_SHPR2_REG |= portNVIC_SVC_PRI;
prvRestoreContextOfFirstTask();
break;
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
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
@ -280,8 +289,9 @@ uint32_t ulPC;
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__ )
if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
{
__asm volatile
(
@ -291,9 +301,11 @@ uint32_t ulPC;
::: "r1", "memory"
);
}
break;
#else
case portSVC_RAISE_PRIVILEGE : __asm volatile
#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. */
@ -371,7 +383,7 @@ BaseType_t xPortStartScheduler( void )
* 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;
@ -388,6 +400,7 @@ BaseType_t xPortStartScheduler( void )
/* 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--;
@ -426,8 +439,8 @@ BaseType_t xPortStartScheduler( void )
/* 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;
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();
@ -484,10 +497,12 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
vPortResetPrivilege( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
@ -700,7 +715,10 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
}
/*-----------------------------------------------------------*/
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__[];
@ -818,20 +836,20 @@ uint32_t ul;
* 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 */
@ -844,7 +862,7 @@ uint32_t ul;
* 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

View file

@ -64,7 +64,7 @@ typedef unsigned long UBaseType_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. */
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
@ -126,7 +126,7 @@ typedef struct MPU_SETTINGS
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. */ \
* within the specified behaviour for the architecture. */ \
__asm volatile ( "dsb" ::: "memory" ); \
__asm volatile ( "isb" ); \
}
@ -150,8 +150,8 @@ extern void vPortExitCritical( void );
/*-----------------------------------------------------------*/
/* 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. */
* 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 )
/*-----------------------------------------------------------*/
@ -169,6 +169,7 @@ not necessary for to use this port. They are defined so the common demo files
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
return ucReturn;
}
@ -279,7 +280,7 @@ uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
* warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
@ -296,7 +297,7 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
#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"
#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
/*-----------------------------------------------------------*/
@ -305,4 +306,3 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
#endif
#endif /* PORTMACRO_H */

View file

@ -42,8 +42,9 @@
/* 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. */
* as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif
@ -51,7 +52,7 @@
#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_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 )
@ -60,7 +61,7 @@
#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. */
* r0p1 port. */
#define portCPUID ( *( ( volatile uint32_t * ) 0xE000ed00 ) )
#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL )
#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL )
@ -93,17 +94,17 @@ r0p1 port. */
#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. */
* 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. */
* 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
#else
@ -142,7 +143,7 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting
variable. */
* variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
@ -184,13 +185,15 @@ 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. */
* interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
* of interrupts, and to ensure alignment. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -204,7 +207,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* A save method is being used that requires each task to maintain its
own exec return value. */
* own exec return value. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN;
@ -219,22 +222,23 @@ static void prvTaskExitError( void )
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 ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
* 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();
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. */
* 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. */
}
}
/*-----------------------------------------------------------*/
@ -261,9 +265,9 @@ void vPortSVCHandler( void )
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. */
* 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"
@ -288,12 +292,12 @@ 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 */
* 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. */
* 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 );
@ -304,15 +308,15 @@ BaseType_t xPortStartScheduler( void )
volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible.
Save the interrupt priority value that is about to be clobbered. */
* functions can be called. ISR safe functions are those that end in
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible.
*
* Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all
possible bits. */
* possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
@ -322,8 +326,9 @@ BaseType_t xPortStartScheduler( void )
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
* of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
@ -333,8 +338,8 @@ BaseType_t xPortStartScheduler( void )
#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. */
* priority bits matches the number of priority bits actually queried
* from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
}
#endif
@ -342,29 +347,29 @@ BaseType_t xPortStartScheduler( void )
#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. */
* 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. */
* register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
value. */
* 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;
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. */
* here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
@ -380,11 +385,11 @@ BaseType_t xPortStartScheduler( void )
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. */
* 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();
@ -396,7 +401,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
* Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
@ -407,10 +412,10 @@ void vPortEnterCritical( void )
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. */
* 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 );
@ -422,6 +427,7 @@ void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
@ -489,16 +495,16 @@ void xPortPendSVHandler( void )
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. */
* 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. */
* the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
@ -520,43 +526,44 @@ void xPortSysTickHandler( void )
}
/* 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. */
* 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. */
* tick periods. -1 is used because this code will execute part way
* through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
* method as that will mask interrupts that should exit sleep mode. */
__asm volatile ( "cpsid i" ::: "memory" );
__asm volatile ( "dsb" );
__asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
* 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. */
* this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
* periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
* above. */
__asm volatile ( "cpsie i" ::: "memory" );
}
else
@ -565,69 +572,71 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
* zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
* 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 );
/* 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. */
* 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" );
/* 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. */
* 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" );
/* 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 register to ensure the
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
* the time the SysTick is stopped for is accounted for as best it can
* be, but using the tickless mode will inevitably result in some tiny
* drift of the time maintained by the kernel with respect to calendar
* time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and
been set back to the current reload value (the reload back being
correct for the entire expected idle time) or if the SysTick is yet
to count to zero (in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */
* been set back to the current reload value (the reload back being
* correct for the entire expected idle time) or if the SysTick is yet
* to count to zero (in which case an interrupt other than the SysTick
* must have brought the system out of sleep mode). */
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
/* The tick interrupt is already pending, and the SysTick count
reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
* reloaded with ulReloadValue. Reset the
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
* period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something
that took too long. */
* underflowed because the post sleep hook did something
* that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
@ -636,30 +645,30 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */
* 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). */
* Work out how long the sleep lasted rounded to complete tick
* periods (not the ulReload value which accounted for part
* ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
* was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
* 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. */
* 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 );
@ -731,47 +740,45 @@ static void vPortEnableVFP( void )
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */
* an interrupt that has been assigned a priority above
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
* function. ISR safe FreeRTOS API functions must *only* be called
* from interrupts that have been assigned a priority at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Numerically low interrupt priority numbers represent logically high
* interrupt priorities, therefore the priority of the interrupt must
* be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible.
*
* The following links provide detailed information:
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
* http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
}
/* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority).
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredictable behaviour. */
* 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 */

View file

@ -64,7 +64,7 @@ typedef unsigned long UBaseType_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. */
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
@ -83,7 +83,7 @@ typedef unsigned long UBaseType_t;
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. */ \
* within the specified behaviour for the architecture. */ \
__asm volatile ( "dsb" ::: "memory" ); \
__asm volatile ( "isb" ); \
}
@ -107,8 +107,8 @@ extern void vPortExitCritical( void );
/*-----------------------------------------------------------*/
/* 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. */
* 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 )
/*-----------------------------------------------------------*/
@ -133,6 +133,7 @@ not necessary for to use this port. They are defined so the common demo files
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
return ucReturn;
}
@ -220,7 +221,7 @@ uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
* warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
@ -241,4 +242,3 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
#endif
#endif /* PORTMACRO_H */

View file

@ -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. */
@ -49,8 +49,9 @@ task.h is included from an application file. */
/* 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. */
* as the core. */
#define portNVIC_SYSTICK_CLK ( 0 )
#endif
@ -58,8 +59,8 @@ task.h is included from an application file. */
#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_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 )
@ -68,7 +69,7 @@ task.h is included from an application file. */
#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 portEXPECTED_MPU_TYPE_VALUE ( portTOTAL_NUM_REGIONS << 8UL )
#define portMPU_ENABLE ( 0x01UL )
#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL )
#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL )
@ -108,7 +109,7 @@ task.h is included from an application file. */
#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. */
* have bit-0 clear, as it is loaded into the PC on exit from an ISR. */
#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL )
/*
@ -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;
/*
@ -205,10 +206,13 @@ 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. */
* interrupt. */
pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
pxTopOfStack--;
@ -219,7 +223,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* A save method is being used that requires each task to maintain its
own exec return value. */
* own exec return value. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN;
@ -261,8 +265,10 @@ 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__;
@ -275,21 +281,24 @@ uint32_t ulPC;
#endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */
/* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first
argument (r0) is pulParam[ 0 ]. */
* argument (r0) is pulParam[ 0 ]. */
ulPC = pulParam[ portOFFSET_TO_PC ];
ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
switch( ucSVCNumber )
{
case portSVC_START_SCHEDULER : portNVIC_SYSPRI1_REG |= portNVIC_SVC_PRI;
case portSVC_START_SCHEDULER:
portNVIC_SHPR2_REG |= portNVIC_SVC_PRI;
prvRestoreContextOfFirstTask();
break;
case portSVC_YIELD : portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
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. */
* but do ensure the code is completely
* within the specified behaviour for the
* architecture. */
__asm volatile ( "dsb" ::: "memory" );
__asm volatile ( "isb" );
@ -299,8 +308,9 @@ uint32_t ulPC;
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__ )
if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
{
__asm volatile
(
@ -310,9 +320,11 @@ uint32_t ulPC;
::: "r1", "memory"
);
}
break;
#else
case portSVC_RAISE_PRIVILEGE : __asm volatile
#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. */
@ -348,8 +360,15 @@ static void prvRestoreContextOfFirstTask( void )
" 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. */
" 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. */
@ -376,7 +395,7 @@ 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 */
* http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) );
#if ( configASSERT_DEFINED == 1 )
@ -386,15 +405,15 @@ BaseType_t xPortStartScheduler( void )
volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible.
Save the interrupt priority value that is about to be clobbered. */
* functions can be called. ISR safe functions are those that end in
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible.
*
* Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all
possible bits. */
* possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
@ -404,8 +423,9 @@ BaseType_t xPortStartScheduler( void )
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
* of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
@ -415,8 +435,8 @@ BaseType_t xPortStartScheduler( void )
#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. */
* priority bits matches the number of priority bits actually queried
* from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
}
#endif
@ -424,34 +444,34 @@ BaseType_t xPortStartScheduler( void )
#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. */
* 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. */
* register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
value. */
* 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;
* 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();
/* Start the timer that generates the tick ISR. Interrupts are disabled
here already. */
* here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
@ -464,9 +484,9 @@ BaseType_t xPortStartScheduler( void )
*( 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. */
* 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"
@ -491,7 +511,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
* Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
@ -513,10 +533,12 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege();
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
vPortResetPrivilege( xRunningPrivileged );
}
/*-----------------------------------------------------------*/
@ -562,8 +584,15 @@ void xPortPendSVHandler( void )
" 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. */
" 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. */
@ -640,6 +669,7 @@ static void vPortEnableVFP( void )
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__;
@ -656,7 +686,14 @@ static void prvSetupMPU( void )
extern uint32_t __FLASH_segment_end__[];
extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[];
#endif
#endif /* if defined( __ARMCC_VERSION ) */
/* The only permitted number of regions are 8 or 16. */
configASSERT( ( portTOTAL_NUM_REGIONS == 8 ) || ( portTOTAL_NUM_REGIONS == 16 ) );
/* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
/* Check the expected MPU is present. */
if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
{
@ -666,34 +703,34 @@ static void prvSetupMPU( void )
( portUNPRIVILEGED_FLASH_REGION );
portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( ( 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 );
/* Setup the privileged flash for privileged only access. This is where
the kernel code is placed. */
* 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 ) |
( ( 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 );
/* Setup the privileged data RAM region. This is where the kernel data
is placed. */
* 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 ) |
( ( 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. */
* system peripherals and registers are protected. */
portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) |
( portMPU_REGION_VALID ) |
( portGENERAL_PERIPHERALS_REGION );
@ -716,7 +753,7 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes )
uint32_t ulRegionSize, ulReturnValue = 4;
/* 32 is the smallest region size, 31 is the largest valid value for
ulReturnValue. */
* ulReturnValue. */
for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) )
{
if( ulActualSizeInBytes <= ulRegionSize )
@ -730,7 +767,7 @@ uint32_t ulRegionSize, ulReturnValue = 4;
}
/* Shift the code by one before returning so it can be written directly
into the the correct bit position of the attribute register. */
* into the the correct bit position of the attribute register. */
return( ulReturnValue << 1UL );
}
/*-----------------------------------------------------------*/
@ -765,9 +802,13 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */
}
/*-----------------------------------------------------------*/
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__;
@ -780,7 +821,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR
extern uint32_t __SRAM_segment_end__[];
extern uint32_t __privileged_data_start__[];
extern uint32_t __privileged_data_end__[];
#endif
#endif /* if defined( __ARMCC_VERSION ) */
int32_t lIndex;
uint32_t ul;
@ -795,12 +836,12 @@ uint32_t ul;
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( ( 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 );
/* Re-instate the privileged only RAM region as xRegion[ 0 ] will have
just removed the privileged only parameters. */
* just removed the privileged only parameters. */
xMPUSettings->xRegion[ 1 ].ulRegionBaseAddress =
( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */
( portMPU_REGION_VALID ) |
@ -808,7 +849,7 @@ uint32_t ul;
xMPUSettings->xRegion[ 1 ].ulRegionAttribute =
( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( ( 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 );
@ -822,9 +863,9 @@ uint32_t ul;
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. */
* 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. */
@ -836,7 +877,7 @@ uint32_t ul;
xMPUSettings->xRegion[ 0 ].ulRegionAttribute =
( portMPU_REGION_READ_WRITE ) | /* Read and write. */
( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) |
( portMPU_REGION_CACHEABLE_BUFFERABLE ) |
( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) |
( portMPU_REGION_ENABLE );
}
@ -847,8 +888,8 @@ uint32_t 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. */
* 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 ) |
@ -889,48 +930,46 @@ uint32_t ul;
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */
* an interrupt that has been assigned a priority above
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
* function. ISR safe FreeRTOS API functions must *only* be called
* from interrupts that have been assigned a priority at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Numerically low interrupt priority numbers represent logically high
* interrupt priorities, therefore the priority of the interrupt must
* be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible.
*
* The following links provide detailed information:
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
* http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
}
/* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority).
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
* 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 */
/*-----------------------------------------------------------*/

View file

@ -64,7 +64,7 @@ typedef unsigned long UBaseType_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. */
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
@ -80,6 +80,92 @@ typedef unsigned long UBaseType_t;
#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 )
/* 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
/*
* 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. | |
+-----+---+---+------------------------+--------------------------------------------------------+-------------------------+
+-----------------------------------------+----------------------------------------+
| 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 )
@ -87,9 +173,9 @@ typedef unsigned long UBaseType_t;
#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 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" )
@ -126,7 +212,7 @@ typedef struct MPU_SETTINGS
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. */ \
* within the specified behaviour for the architecture. */ \
__asm volatile ( "dsb" ::: "memory" ); \
__asm volatile ( "isb" ); \
}
@ -150,8 +236,8 @@ extern void vPortExitCritical( void );
/*-----------------------------------------------------------*/
/* 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. */
* 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 )
/*-----------------------------------------------------------*/
@ -169,6 +255,7 @@ not necessary for to use this port. They are defined so the common demo files
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
return ucReturn;
}
@ -279,7 +366,7 @@ uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
* warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
@ -296,7 +383,7 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
#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"
#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
/*-----------------------------------------------------------*/
@ -305,4 +392,3 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
#endif
#endif /* PORTMACRO_H */

View file

@ -26,7 +26,7 @@
*/
/*-----------------------------------------------------------
* 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. */
@ -42,8 +42,9 @@
/* 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. */
* as the core. */
#define portNVIC_SYSTICK_CLK_BIT ( 0 )
#endif
@ -51,7 +52,7 @@
#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_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 )
@ -87,17 +88,17 @@
#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. */
* 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. */
* 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
#else
@ -136,7 +137,7 @@ static void prvTaskExitError( void );
/*-----------------------------------------------------------*/
/* Each task maintains its own interrupt status in the critical nesting
variable. */
* variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
/*
@ -178,13 +179,15 @@ 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. */
* interrupt. */
/* Offset added to account for the way the MCU uses the stack on entry/exit
of interrupts, and to ensure alignment. */
* of interrupts, and to ensure alignment. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_XPSR; /* xPSR */
@ -198,7 +201,7 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* A save method is being used that requires each task to maintain its
own exec return value. */
* own exec return value. */
pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXC_RETURN;
@ -213,22 +216,23 @@ static void prvTaskExitError( void )
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 ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
* 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();
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. */
* 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. */
}
}
/*-----------------------------------------------------------*/
@ -255,9 +259,9 @@ void vPortSVCHandler( void )
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. */
* 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"
@ -282,7 +286,7 @@ 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 */
* See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
#if ( configASSERT_DEFINED == 1 )
@ -292,15 +296,15 @@ BaseType_t xPortStartScheduler( void )
volatile uint8_t ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
ensure interrupt entry is as fast and simple as possible.
Save the interrupt priority value that is about to be clobbered. */
* functions can be called. ISR safe functions are those that end in
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
* ensure interrupt entry is as fast and simple as possible.
*
* Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to all
possible bits. */
* possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
@ -310,8 +314,9 @@ BaseType_t xPortStartScheduler( void )
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
* of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
@ -321,8 +326,8 @@ BaseType_t xPortStartScheduler( void )
#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. */
* priority bits matches the number of priority bits actually queried
* from the hardware. */
configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS );
}
#endif
@ -330,29 +335,29 @@ BaseType_t xPortStartScheduler( void )
#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. */
* 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. */
* register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original
value. */
* 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;
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. */
* here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
@ -368,11 +373,11 @@ BaseType_t xPortStartScheduler( void )
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. */
* 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();
@ -384,7 +389,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
* Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
@ -395,10 +400,10 @@ void vPortEnterCritical( void )
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. */
* 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 );
@ -410,6 +415,7 @@ void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
@ -479,16 +485,16 @@ void xPortPendSVHandler( void )
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. */
* 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. */
* the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
@ -510,43 +516,44 @@ void xPortSysTickHandler( void )
}
/* 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. */
* 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. */
* tick periods. -1 is used because this code will execute part way
* through one of the tick periods. */
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
if( ulReloadValue > ulStoppedTimerCompensation )
{
ulReloadValue -= ulStoppedTimerCompensation;
}
/* Enter a critical section but don't use the taskENTER_CRITICAL()
method as that will mask interrupts that should exit sleep mode. */
* method as that will mask interrupts that should exit sleep mode. */
__asm volatile ( "cpsid i" ::: "memory" );
__asm volatile ( "dsb" );
__asm volatile ( "isb" );
/* If a context switch is pending or a task is waiting for the scheduler
to be unsuspended then abandon the low power entry. */
* 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. */
* this tick period. */
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
* periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above the cpsid instruction()
above. */
* above. */
__asm volatile ( "cpsie i" ::: "memory" );
}
else
@ -555,69 +562,71 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
/* Clear the SysTick count flag and set the count value back to
zero. */
* zero. */
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains
its own wait for interrupt or wait for event instruction, and so wfi
should not be executed again. However, the original expected idle
time variable must remain unmodified, so a copy is taken. */
* 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 );
/* 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. */
* 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" );
/* 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. */
* 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" );
/* 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 register to ensure the
* portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
* the time the SysTick is stopped for is accounted for as best it can
* be, but using the tickless mode will inevitably result in some tiny
* drift of the time maintained by the kernel with respect to calendar
* time*/
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
/* Determine if the SysTick clock has already counted to zero and
been set back to the current reload value (the reload back being
correct for the entire expected idle time) or if the SysTick is yet
to count to zero (in which case an interrupt other than the SysTick
must have brought the system out of sleep mode). */
* been set back to the current reload value (the reload back being
* correct for the entire expected idle time) or if the SysTick is yet
* to count to zero (in which case an interrupt other than the SysTick
* must have brought the system out of sleep mode). */
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
uint32_t ulCalculatedLoadValue;
/* The tick interrupt is already pending, and the SysTick count
reloaded with ulReloadValue. Reset the
portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
period. */
* reloaded with ulReloadValue. Reset the
* portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
* period. */
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
/* Don't allow a tiny value, or values that have somehow
underflowed because the post sleep hook did something
that took too long. */
* underflowed because the post sleep hook did something
* that took too long. */
if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
{
ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
@ -626,30 +635,30 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
/* As the pending tick will be processed as soon as this
function exits, the tick value maintained by the tick is stepped
forward by one less than the time spent waiting. */
* 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). */
* Work out how long the sleep lasted rounded to complete tick
* periods (not the ulReload value which accounted for part
* ticks). */
ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* How many complete tick periods passed while the processor
was waiting? */
* was waiting? */
ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
/* The reload value is set to whatever fraction of a single tick
period remains. */
* 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. */
* 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 );
@ -721,47 +730,45 @@ static void vPortEnableVFP( void )
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
/* The following assertion will fail if a service routine (ISR) for
an interrupt that has been assigned a priority above
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
function. ISR safe FreeRTOS API functions must *only* be called
from interrupts that have been assigned a priority at or below
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Numerically low interrupt priority numbers represent logically high
interrupt priorities, therefore the priority of the interrupt must
be set to a value equal to or numerically *higher* than
configMAX_SYSCALL_INTERRUPT_PRIORITY.
Interrupts that use the FreeRTOS API must not be left at their
default priority of zero as that is the highest possible priority,
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
and therefore also guaranteed to be invalid.
FreeRTOS maintains separate thread and ISR API functions to ensure
interrupt entry is as fast and simple as possible.
The following links provide detailed information:
http://www.freertos.org/RTOS-Cortex-M3-M4.html
http://www.freertos.org/FAQHelp.html */
* an interrupt that has been assigned a priority above
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
* function. ISR safe FreeRTOS API functions must *only* be called
* from interrupts that have been assigned a priority at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Numerically low interrupt priority numbers represent logically high
* interrupt priorities, therefore the priority of the interrupt must
* be set to a value equal to or numerically *higher* than
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
*
* Interrupts that use the FreeRTOS API must not be left at their
* default priority of zero as that is the highest possible priority,
* which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
* and therefore also guaranteed to be invalid.
*
* FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible.
*
* The following links provide detailed information:
* http://www.freertos.org/RTOS-Cortex-M3-M4.html
* http://www.freertos.org/FAQHelp.html */
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
}
/* Priority grouping: The interrupt controller (NVIC) allows the bits
that define each interrupt's priority to be split between bits that
define the interrupt's pre-emption priority bits and bits that define
the interrupt's sub-priority. For simplicity all bits must be defined
to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority).
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredictable behaviour. */
* 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 */

View file

@ -64,7 +64,7 @@ typedef unsigned long UBaseType_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. */
* not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
@ -83,7 +83,7 @@ typedef unsigned long UBaseType_t;
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. */ \
* within the specified behaviour for the architecture. */ \
__asm volatile ( "dsb" ::: "memory" ); \
__asm volatile ( "isb" ); \
}
@ -107,8 +107,8 @@ extern void vPortExitCritical( void );
/*-----------------------------------------------------------*/
/* 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. */
* 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 )
/*-----------------------------------------------------------*/
@ -133,6 +133,7 @@ not necessary for to use this port. They are defined so the common demo files
uint8_t ucReturn;
__asm volatile ( "clz %0, %1" : "=r" ( ucReturn ) : "r" ( ulBitmap ) : "memory" );
return ucReturn;
}
@ -224,7 +225,7 @@ uint32_t ulOriginalBASEPRI, ulNewBASEPRI;
);
/* This return will not be reached but is necessary to prevent compiler
warnings. */
* warnings. */
return ulOriginalBASEPRI;
}
/*-----------------------------------------------------------*/
@ -245,4 +246,3 @@ portFORCE_INLINE static void vPortSetBASEPRI( uint32_t ulNewMaskValue )
#endif
#endif /* PORTMACRO_H */

View file

@ -33,23 +33,23 @@
#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
@ -73,24 +73,24 @@
#endif
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
portmacro.h. */
* portmacro.h. */
#ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT()
#endif
/* A critical section is exited when the critical section nesting count reaches
this value. */
* 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. */
* (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. */
* 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. */
@ -100,19 +100,19 @@ context. */
#define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
point is zero. */
* point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */
#define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user
mode. */
* 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. */
* 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" ); \
@ -139,14 +139,27 @@ the CPU itself before modifying certain hardware registers. */
#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
#else
#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,21 +176,21 @@ 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. */
@ -191,14 +204,16 @@ __attribute__(( used )) const uint32_t ulMaxAPIPriorityMask = ( configMAX_API_CA
/*
* 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. */
* 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;
@ -250,13 +265,13 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are
enabled. */
* 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. */
* the floating point hardware must call vPortTaskUsesFPU() before executing
* any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack;
@ -266,14 +281,17 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px
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. */
* its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
for( ; ; )
{
}
}
/*-----------------------------------------------------------*/
@ -288,12 +306,12 @@ uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
volatile uint8_t ucMaxPriorityValue;
/* Determine how many priority bits are implemented in the GIC.
Save the interrupt priority value that is about to be clobbered. */
*
* 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. */
* all possible bits. */
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */
@ -305,8 +323,9 @@ uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
ucMaxPriorityValue >>= ( uint8_t ) 0x01;
/* If ulCycles reaches 0 then ucMaxPriorityValue must have been
read as 0, indicating a misconfiguration. */
* read as 0, indicating a misconfiguration. */
ulCycles--;
if( ulCycles == 0 )
{
break;
@ -314,17 +333,17 @@ uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
}
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
value. */
* value. */
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
/* Restore the clobbered interrupt priority register to its original
value. */
* 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. */
* 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 );
@ -332,16 +351,16 @@ uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
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. */
* 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. */
* 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. */
@ -353,10 +372,10 @@ uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
}
/* 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. */
* 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;
}
@ -365,7 +384,7 @@ uint32_t ulAPSR, ulCycles = 8; /* 8 bits per byte. */
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
Artificially force an assert. */
* Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
@ -376,15 +395,15 @@ void vPortEnterCritical( void )
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. */
* 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. */
* 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 );
@ -397,15 +416,15 @@ void vPortExitCritical( void )
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{
/* Decrement the nesting count as the critical section is being
exited. */
* exited. */
ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt
priorities must be re-enabled. */
* priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{
/* Critical nesting has reached zero so all interrupt priorities
should be unmasked. */
* should be unmasked. */
portCLEAR_INTERRUPT_MASK();
}
}
@ -415,10 +434,10 @@ void vPortExitCritical( void )
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. */
* 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"
@ -442,7 +461,7 @@ void vPortTaskUsesFPU( void )
uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the
FPU flag (which is saved as part of the task context). */
* FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */
@ -462,10 +481,17 @@ void vPortClearInterruptMask( uint32_t ulNewMaskValue )
uint32_t ulPortSetInterruptMask( void )
{
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. */
* updated. */
portCPU_IRQ_DISABLE();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{
/* Interrupts were already masked. */
@ -478,6 +504,18 @@ uint32_t ulReturn;
__asm volatile ( "dsb \n"
"isb \n"::: "memory" );
}
/* 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;
@ -489,37 +527,34 @@ uint32_t ulReturn;
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. */
* 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. */
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). */
* 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 */
/*-----------------------------------------------------------*/

View file

@ -95,7 +95,7 @@ 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. */
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical();
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
@ -106,17 +106,17 @@ interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
/*-----------------------------------------------------------*/
/* 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. */
* 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. */
* 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. */
* before any floating point instructions are executed. */
void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
@ -154,7 +154,7 @@ void vPortTaskUsesFPU( void );
/* 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
@ -170,9 +170,9 @@ number of bits implemented by the interrupt controller. */
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0
#else
#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
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
/* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
@ -192,4 +192,3 @@ number of bits implemented by the interrupt controller. */
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
#endif /* PORTMACRO_H */

View file

@ -57,10 +57,10 @@
/*-----------------------------------------------------------*/
/* 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 )
volatile uint32_t ulCriticalNesting = 9999UL;
@ -81,26 +81,24 @@ extern __asm void vPortStartFirstTask( void );
/*
* 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;
/* 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. */
expected by the portRESTORE_CONTEXT() macro.
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. */
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. */
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--;
@ -136,7 +134,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--;
/* The last thing onto the stack is the status register, which is set for
* system mode, with interrupts enabled. */
system mode, with interrupts enabled. */
*pxTopOfStack = ( StackType_t ) portINITIAL_SPSR;
if( ( ( uint32_t ) pxCode & 0x01UL ) != 0x00UL )
@ -148,10 +146,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * 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. */
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;
@ -164,7 +162,7 @@ BaseType_t xPortStartScheduler( void )
prvSetupTimerInterrupt();
/* Start the first task. This is done from portISR.c as ARM mode must be
* used. */
used. */
vPortStartFirstTask();
/* Should not get here! */
@ -175,8 +173,8 @@ BaseType_t xPortStartScheduler( void )
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. */
is nothing to return to. If this is required - stop the tick ISR then
return back to main. */
}
/*-----------------------------------------------------------*/
@ -190,14 +188,14 @@ void vPortEndScheduler( void )
void vNonPreemptiveTick( void ) __irq
{
/* Increment the tick count - this may make a delaying task ready
* to run - but a context switch is not performed. */
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 */
}
#else /* if configUSE_PREEMPTION == 0 */
#else
/*
**************************************************************************
@ -209,7 +207,7 @@ void vPortEndScheduler( void )
void vPreemptiveTick( void );
#endif /* if configUSE_PREEMPTION == 0 */
#endif
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void )
@ -217,14 +215,14 @@ static void prvSetupTimerInterrupt( void )
uint32_t ulCompareMatch;
/* A 1ms tick does not require the use of the timer prescale. This is
* defaulted to zero but can be used if necessary. */
defaulted to zero but can be used if necessary. */
T0PR = portPRESCALE_VALUE;
/* Calculate the match value required for our wanted tick rate. */
ulCompareMatch = configCPU_CLOCK_HZ / configTICK_RATE_HZ;
/* Protect against divide by zero. Using an if() statement still results
* in a warning - hence the #if. */
in a warning - hence the #if. */
#if portPRESCALE_VALUE != 0
{
ulCompareMatch /= ( portPRESCALE_VALUE + 1 );
@ -241,7 +239,7 @@ static void prvSetupTimerInterrupt( void )
VICIntEnable |= portTIMER_VIC_CHANNEL_BIT;
/* The ISR installed depends on whether the preemptive or cooperative
* scheduler is being used. */
scheduler is being used. */
#if configUSE_PREEMPTION == 1
{
VICVectAddr0 = ( uint32_t ) vPreemptiveTick;
@ -255,7 +253,7 @@ static void prvSetupTimerInterrupt( void )
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. */
so it is okay to do this here. */
T0TCR = portENABLE_TIMER;
}
/*-----------------------------------------------------------*/
@ -266,8 +264,8 @@ void vPortEnterCritical( void )
__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. */
directly. Increment ulCriticalNesting to keep a count of how many times
portENTER_CRITICAL() has been called. */
ulCriticalNesting++;
}
/*-----------------------------------------------------------*/
@ -280,7 +278,7 @@ void vPortExitCritical( void )
ulCriticalNesting--;
/* If the nesting level has reached zero then interrupts should be
* re-enabled. */
re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{
/* Enable interrupts as per portEXIT_CRITICAL(). */
@ -289,3 +287,5 @@ void vPortExitCritical( void )
}
}
/*-----------------------------------------------------------*/

View file

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

View file

@ -33,23 +33,23 @@
#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
@ -77,7 +77,7 @@
#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
@ -93,23 +93,23 @@
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
#else
#error Invalid configUNIQUE_INTERRUPT_PRIORITIES setting. configUNIQUE_INTERRUPT_PRIORITIES must be set to the number of unique priorities implemented by the target hardware
#endif /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
#endif
/* A critical section is exited when the critical section nesting count reaches
* this value. */
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. */
(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. */
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. */
@ -127,7 +127,7 @@
#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. */
point is zero. */
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Constants required to setup the initial task context. */
@ -139,7 +139,7 @@
#define portAPSR_MODE_BITS_MASK ( 0x1F )
/* The value of the mode bits in the APSR when the CPU is executing in user
* mode. */
mode. */
#define portAPSR_USER_MODE ( 0x10 )
/* Macro to unmask all interrupt priorities. */
@ -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,16 +198,14 @@ 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. */
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;
@ -259,13 +257,13 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are
* enabled. */
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. */
the floating point hardware must call vPortTaskUsesFPU() before executing
any floating point instructions. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
return pxTopOfStack;
@ -275,17 +273,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * 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. */
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ; ; )
{
}
for( ;; );
}
/*-----------------------------------------------------------*/
@ -294,7 +289,7 @@ BaseType_t xPortStartScheduler( void )
uint32_t ulAPSR;
/* Only continue if the CPU is not in User mode. The CPU must be in a
* Privileged mode for the scheduler to start. */
Privileged mode for the scheduler to start. */
__asm( "MRS ulAPSR, APSR" );
ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE );
@ -302,8 +297,8 @@ BaseType_t xPortStartScheduler( void )
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. */
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 )
@ -317,8 +312,8 @@ BaseType_t xPortStartScheduler( void )
}
/* 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. */
a non-privileged mode or the binary point register was not set to its lowest
possible value. */
return 0;
}
/*-----------------------------------------------------------*/
@ -326,7 +321,7 @@ BaseType_t xPortStartScheduler( void )
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
@ -337,15 +332,15 @@ void vPortEnterCritical( void )
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. */
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. */
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 );
@ -358,15 +353,15 @@ void vPortExitCritical( void )
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{
/* Decrement the nesting count as the critical section is being
* exited. */
exited. */
ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */
priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{
/* Critical nesting has reached zero so all interrupt priorities
* should be unmasked. */
should be unmasked. */
portCLEAR_INTERRUPT_MASK();
}
}
@ -376,8 +371,8 @@ void vPortExitCritical( void )
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. */
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"
@ -401,7 +396,7 @@ void vPortTaskUsesFPU( void )
uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context). */
FPU flag (which is saved as part of the task context). */
ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */
@ -423,7 +418,6 @@ uint32_t ulPortSetInterruptMask( void )
uint32_t ulReturn;
__disable_irq();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
{
/* Interrupts were already masked. */
@ -436,7 +430,6 @@ uint32_t ulPortSetInterruptMask( void )
__asm( "DSB \n"
"ISB \n" );
}
__enable_irq();
return ulReturn;
@ -448,36 +441,40 @@ uint32_t ulPortSetInterruptMask( void )
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 */
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 ) );
/* 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). */
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 */

View file

@ -64,7 +64,7 @@
#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. */
not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif
/*-----------------------------------------------------------*/
@ -103,7 +103,7 @@
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. */
interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical();
#define portEXIT_CRITICAL() vPortExitCritical();
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
@ -114,17 +114,17 @@
/*-----------------------------------------------------------*/
/* 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. */
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. */
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. */
before any floating point instructions are executed. */
void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
@ -160,3 +160,4 @@
#endif
#endif /* PORTMACRO_H */

View file

@ -22,6 +22,7 @@
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/
/*-----------------------------------------------------------

View file

@ -22,6 +22,7 @@
* http://www.FreeRTOS.org
* http://aws.amazon.com/freertos
*
* 1 tab == 4 spaces!
*/