Enable building the GCC Cortex-R5 port without an FPU (#586)

* Ensure configUSE_TASK_FPU_SUPPORT option is set correctly

If one does enable the FPU of the Cortex-R5 processor, then the GCC
compiler will define the macro __ARM_FP. This can be used to ensure,
that the configUSE_TASK_FPU_SUPPORT is set accordingly.

* Enable the implementation of vPortTaskUsesFPU only if configUSE_TASK_FPU_SUPPORT is set to 1

* Remove error case in pxPortInitialiseStack

The case of configUSE_TASK_FPU_SUPPORT is 0 is now handled

* Enable access to FPU registers only if FPU is enabled

* Make minor formating changes

* Format ARM Cortex-R5 port

* Address review comments from @ChristosZosi

* Minor code review suggestions

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>

---------

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>
Co-authored-by: Christos Zosimidis <christos.zosimidis@gmail.com>
Co-authored-by: Gaurav-Aggarwal-AWS <33462878+aggarg@users.noreply.github.com>
Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
This commit is contained in:
Paul Bartell 2023-03-06 08:19:28 -08:00 committed by GitHub
parent 563c57e7da
commit 7b26ea6263
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 380 additions and 257 deletions

View file

@ -74,25 +74,52 @@
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 ) #error configMAX_API_CALL_INTERRUPT_PRIORITY must be greater than ( configUNIQUE_INTERRUPT_PRIORITIES / 2 )
#endif #endif
/* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in /*
* portmacro.h. */ * __ARM_FP is defined by the c preprocessor when FPU support is enabled,
* usually with the -mfpu= argument and -mfloat-abi=.
*
* Note: Some implementations of the c standard library may use FPU registers
* for generic memory operations (memcpy, etc).
* When setting configUSE_TASK_FPU_SUPPORT == 1, care must be taken to
* ensure that the FPU registers are not used without an FPU context.
*/
#if ( configUSE_TASK_FPU_SUPPORT == 0 )
#ifdef __ARM_FP
#error __ARM_FP is defined, so configUSE_TASK_FPU_SUPPORT must be set to either to 1 or 2.
#endif /* __ARM_FP */
#elif ( configUSE_TASK_FPU_SUPPORT == 1 ) || ( configUSE_TASK_FPU_SUPPORT == 2 )
#ifndef __ARM_FP
#error __ARM_FP is not defined, so configUSE_TASK_FPU_SUPPORT must be set to 0.
#endif /* __ARM_FP */
#endif /* configUSE_TASK_FPU_SUPPORT */
/*
* Some vendor specific files default configCLEAR_TICK_INTERRUPT() in
* portmacro.h.
*/
#ifndef configCLEAR_TICK_INTERRUPT #ifndef configCLEAR_TICK_INTERRUPT
#define configCLEAR_TICK_INTERRUPT() #define configCLEAR_TICK_INTERRUPT()
#endif #endif
/* A critical section is exited when the critical section nesting count reaches /*
* this value. */ * A critical section is exited when the critical section nesting count reaches
* this value.
*/
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 ) #define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* In all GICs 255 can be written to the priority mask register to unmask all /*
* (but the lowest) interrupt priority. */ * In all GICs 255 can be written to the priority mask register to unmask all
* (but the lowest) interrupt priority.
*/
#define portUNMASK_VALUE ( 0xFFUL ) #define portUNMASK_VALUE ( 0xFFUL )
/* Tasks are not created with a floating point context, but can be given a /*
* Tasks are not created with a floating point context, but can be given a
* floating point context after they have been created. A variable is stored as * floating point context after they have been created. A variable is stored as
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task * part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
* does not have an FPU context, or any other value if the task does have an FPU * does not have an FPU context, or any other value if the task does have an FPU
* context. */ * context.
*/
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 ) #define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Constants required to setup the initial task context. */ /* Constants required to setup the initial task context. */
@ -101,8 +128,10 @@
#define portINTERRUPT_ENABLE_BIT ( 0x80UL ) #define portINTERRUPT_ENABLE_BIT ( 0x80UL )
#define portTHUMB_MODE_ADDRESS ( 0x01UL ) #define portTHUMB_MODE_ADDRESS ( 0x01UL )
/* Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary /*
* point is zero. */ * Used by portASSERT_IF_INTERRUPT_PRIORITY_INVALID() when ensuring the binary
* point is zero.
*/
#define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 ) #define portBINARY_POINT_BITS ( ( uint8_t ) 0x03 )
/* Masks all bits in the APSR other than the mode bits. */ /* Masks all bits in the APSR other than the mode bits. */
@ -140,15 +169,19 @@
#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff )
#define portBIT_0_SET ( ( uint8_t ) 0x01 ) #define portBIT_0_SET ( ( uint8_t ) 0x01 )
/* Let the user override the pre-loading of the initial LR with the address of /*
* Let the user override the pre-loading of the initial LR with the address of
* prvTaskExitError() in case is messes up unwinding of the stack in the * prvTaskExitError() in case is messes up unwinding of the stack in the
* debugger. */ * debugger.
*/
#ifdef configTASK_RETURN_ADDRESS #ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else #else
#define portTASK_RETURN_ADDRESS prvTaskExitError #define portTASK_RETURN_ADDRESS prvTaskExitError
#endif #endif
#if ( configUSE_TASK_FPU_SUPPORT != 0 )
/* /*
* The space on the stack required to hold the FPU registers. * The space on the stack required to hold the FPU registers.
* *
@ -160,7 +193,8 @@
* the size of the bank remains the same. The FPU has also a 32-bit * the size of the bank remains the same. The FPU has also a 32-bit
* status register. * status register.
*/ */
#define portFPU_REGISTER_WORDS ( ( 16 * 2 ) + 1 ) #define portFPU_REGISTER_WORDS ( ( 16 * 2 ) + 1 )
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -175,6 +209,8 @@ extern void vPortRestoreTaskContext( void );
*/ */
static void prvTaskExitError( void ); static void prvTaskExitError( void );
#if ( configUSE_TASK_FPU_SUPPORT != 0 )
/* /*
* If the application provides an implementation of vApplicationIRQHandler(), * If the application provides an implementation of vApplicationIRQHandler(),
* then it will get called directly without saving the FPU registers on * then it will get called directly without saving the FPU registers on
@ -194,26 +230,36 @@ static void prvTaskExitError( void );
* FPU registers to be saved on interrupt entry their IRQ handler must be * FPU registers to be saved on interrupt entry their IRQ handler must be
* called vApplicationIRQHandler(). * called vApplicationIRQHandler().
*/ */
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__((weak) ); void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) __attribute__( ( weak ) );
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This /*
* A variable is used to keep track of the critical section nesting. This
* variable has to be stored as part of the task context and must be initialised to * variable has to be stored as part of the task context and must be initialised to
* a non zero value to ensure interrupts don't inadvertently become unmasked before * a non zero value to ensure interrupts don't inadvertently become unmasked before
* the scheduler starts. As it is stored as part of the task context it will * the scheduler starts. As it is stored as part of the task context it will
* automatically be set to 0 when the first task is started. */ * automatically be set to 0 when the first task is started.
*/
volatile uint32_t ulCriticalNesting = 9999UL; volatile uint32_t ulCriticalNesting = 9999UL;
/* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then #if ( configUSE_TASK_FPU_SUPPORT != 0 )
* a floating point context must be saved and restored for the task. */
uint32_t ulPortTaskHasFPUContext = pdFALSE; /*
* Saved as part of the task context. If ulPortTaskHasFPUContext is non-zero then
* a floating point context must be saved and restored for the task.
*/
uint32_t ulPortTaskHasFPUContext = pdFALSE;
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
/* Set to 1 to pend a context switch from an ISR. */ /* Set to 1 to pend a context switch from an ISR. */
uint32_t ulPortYieldRequired = pdFALSE; uint32_t ulPortYieldRequired = pdFALSE;
/* Counts the interrupt nesting depth. A context switch is only performed if /*
* if the nesting depth is 0. */ * Counts the interrupt nesting depth. A context switch is only performed if
* if the nesting depth is 0.
*/
uint32_t ulPortInterruptNesting = 0UL; uint32_t ulPortInterruptNesting = 0UL;
/* Used in asm code. */ /* Used in asm code. */
@ -231,12 +277,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode, TaskFunction_t pxCode,
void * pvParameters ) void * pvParameters )
{ {
/* Setup the initial stack of the task. The stack is set exactly as /*
* Setup the initial stack of the task. The stack is set exactly as
* expected by the portRESTORE_CONTEXT() macro. * expected by the portRESTORE_CONTEXT() macro.
* *
* The fist real value on the stack is the status register, which is set for * The fist real value on the stack is the status register, which is set for
* system mode, with interrupts enabled. A few NULLs are added first to ensure * system mode, with interrupts enabled. A few NULLs are added first to ensure
* GDB does not try decoding a non-existent return address. */ * GDB does not try decoding a non-existent return address.
*/
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) NULL; *pxTopOfStack = ( StackType_t ) NULL;
@ -285,24 +333,31 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */ *pxTopOfStack = ( StackType_t ) 0x01010101; /* R1 */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack--;
/* The task will start with a critical nesting count of 0 as interrupts are /*
* enabled. */ * The task will start with a critical nesting count of 0 as interrupts are
* enabled.
*/
pxTopOfStack--;
*pxTopOfStack = portNO_CRITICAL_NESTING; *pxTopOfStack = portNO_CRITICAL_NESTING;
#if( configUSE_TASK_FPU_SUPPORT == 1 ) #if ( configUSE_TASK_FPU_SUPPORT == 1 )
{ {
/* The task will start without a floating point context. A task that /*
uses the floating point hardware must call vPortTaskUsesFPU() before * The task will start without a floating point context.
executing any floating point instructions. */ * A task that uses the floating point hardware must call
* vPortTaskUsesFPU() before executing any floating point
* instructions.
*/
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT; *pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
} }
#elif( configUSE_TASK_FPU_SUPPORT == 2 ) #elif ( configUSE_TASK_FPU_SUPPORT == 2 )
{ {
/* The task will start with a floating point context. Leave enough /*
space for the registers - and ensure they are initialized to 0. */ * The task will start with a floating point context. Leave enough
* space for the registers and ensure they are initialized to 0.
*/
pxTopOfStack -= portFPU_REGISTER_WORDS; pxTopOfStack -= portFPU_REGISTER_WORDS;
memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) ); memset( pxTopOfStack, 0x00, portFPU_REGISTER_WORDS * sizeof( StackType_t ) );
@ -310,9 +365,9 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
*pxTopOfStack = pdTRUE; *pxTopOfStack = pdTRUE;
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
} }
#else #elif ( configUSE_TASK_FPU_SUPPORT != 0 )
{ {
#error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 1, 2, or left undefined. #error Invalid configUSE_TASK_FPU_SUPPORT setting - configUSE_TASK_FPU_SUPPORT must be set to 0, 1, or 2.
} }
#endif /* configUSE_TASK_FPU_SUPPORT */ #endif /* configUSE_TASK_FPU_SUPPORT */
@ -322,12 +377,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
static void prvTaskExitError( void ) static void prvTaskExitError( void )
{ {
/* A function that implements a task must not exit or attempt to return to /*
* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it * its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ). * should instead call vTaskDelete( NULL ).
* *
* Artificially force an assert() to be triggered if configASSERT() is * Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */ * defined, then stop here so application writers can catch the error.
*/
configASSERT( ulPortInterruptNesting == ~0UL ); configASSERT( ulPortInterruptNesting == ~0UL );
portDISABLE_INTERRUPTS(); portDISABLE_INTERRUPTS();
@ -337,11 +394,15 @@ static void prvTaskExitError( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) #if ( configUSE_TASK_FPU_SUPPORT != 0 )
{
void vApplicationFPUSafeIRQHandler( uint32_t ulICCIAR ) /* __attribute__( ( weak ) ) */
{
( void ) ulICCIAR; ( void ) ulICCIAR;
configASSERT( ( volatile void * ) NULL ); configASSERT( ( volatile void * ) NULL );
} }
#endif /* configUSE_TASK_FPU_SUPPORT != 0 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void ) BaseType_t xPortStartScheduler( void )
@ -354,13 +415,16 @@ BaseType_t xPortStartScheduler( void )
volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET ); volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + portINTERRUPT_PRIORITY_REGISTER_OFFSET );
volatile uint8_t ucMaxPriorityValue; volatile uint8_t ucMaxPriorityValue;
/* Determine how many priority bits are implemented in the GIC. /*
* * Determine how many priority bits are implemented in the GIC.
* Save the interrupt priority value that is about to be clobbered. */ * Save the interrupt priority value that is about to be clobbered.
*/
ulOriginalPriority = *pucFirstUserPriorityRegister; ulOriginalPriority = *pucFirstUserPriorityRegister;
/* Determine the number of priority bits available. First write to /*
* all possible bits. */ * Determine the number of priority bits available. First write to
* all possible bits.
*/
*pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read the value back to see how many bits stuck. */ /* Read the value back to see how many bits stuck. */
@ -371,8 +435,10 @@ BaseType_t xPortStartScheduler( void )
{ {
ucMaxPriorityValue >>= ( uint8_t ) 0x01; ucMaxPriorityValue >>= ( uint8_t ) 0x01;
/* If ulCycles reaches 0 then ucMaxPriorityValue must have been /*
* read as 0, indicating a misconfiguration. */ * If ulCycles reaches 0 then ucMaxPriorityValue must have been
* read as 0, indicating a misconfiguration.
*/
ulCycles--; ulCycles--;
if( ulCycles == 0 ) if( ulCycles == 0 )
@ -381,35 +447,45 @@ BaseType_t xPortStartScheduler( void )
} }
} }
/* Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read /*
* value. */ * Sanity check configUNIQUE_INTERRUPT_PRIORITIES matches the read
* value.
*/
configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY ); configASSERT( ucMaxPriorityValue == portLOWEST_INTERRUPT_PRIORITY );
/* Restore the clobbered interrupt priority register to its original /*
* value. */ * Restore the clobbered interrupt priority register to its original
* value.
*/
*pucFirstUserPriorityRegister = ulOriginalPriority; *pucFirstUserPriorityRegister = ulOriginalPriority;
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
/* Only continue if the CPU is not in User mode. The CPU must be in a /*
* Privileged mode for the scheduler to start. */ * Only continue if the CPU is not in User mode. The CPU must be in a
* Privileged mode for the scheduler to start.
*/
__asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" ); __asm volatile ( "MRS %0, APSR" : "=r" ( ulAPSR )::"memory" );
ulAPSR &= portAPSR_MODE_BITS_MASK; ulAPSR &= portAPSR_MODE_BITS_MASK;
configASSERT( ulAPSR != portAPSR_USER_MODE ); configASSERT( ulAPSR != portAPSR_USER_MODE );
if( ulAPSR != portAPSR_USER_MODE ) if( ulAPSR != portAPSR_USER_MODE )
{ {
/* Only continue if the binary point value is set to its lowest possible /*
* Only continue if the binary point value is set to its lowest possible
* setting. See the comments in vPortValidateInterruptPriority() below for * setting. See the comments in vPortValidateInterruptPriority() below for
* more information. */ * more information.
*/
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ) if( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE )
{ {
/* Interrupts are turned off in the CPU itself to ensure tick does /*
* Interrupts are turned off in the CPU itself to ensure tick does
* not execute while the scheduler is being started. Interrupts are * not execute while the scheduler is being started. Interrupts are
* automatically turned back on in the CPU when the first task starts * automatically turned back on in the CPU when the first task starts
* executing. */ * executing.
*/
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
/* Start the timer that generates the tick ISR. */ /* Start the timer that generates the tick ISR. */
@ -420,20 +496,25 @@ BaseType_t xPortStartScheduler( void )
} }
} }
/* Will only get here if vTaskStartScheduler() was called with the CPU in /*
* Will only get here if vTaskStartScheduler() was called with the CPU in
* a non-privileged mode or the binary point register was not set to its lowest * a non-privileged mode or the binary point register was not set to its lowest
* possible value. prvTaskExitError() is referenced to prevent a compiler * possible value. prvTaskExitError() is referenced to prevent a compiler
* warning about it being defined but not referenced in the case that the user * warning about it being defined but not referenced in the case that the user
* defines their own exit address. */ * defines their own exit address.
*/
( void ) prvTaskExitError; ( void ) prvTaskExitError;
return 0; return 0;
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* Not implemented in ports where there is nothing to return to. /*
* Artificially force an assert. */ * Not implemented in ports where there is nothing to return to.
* Artificially force an assert.
*/
configASSERT( ulCriticalNesting == 1000UL ); configASSERT( ulCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -443,16 +524,20 @@ void vPortEnterCritical( void )
/* Mask interrupts up to the max syscall interrupt priority. */ /* Mask interrupts up to the max syscall interrupt priority. */
ulPortSetInterruptMask(); ulPortSetInterruptMask();
/* Now interrupts are disabled ulCriticalNesting can be accessed /*
* Now interrupts are disabled ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times * directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */ * portENTER_CRITICAL() has been called.
*/
ulCriticalNesting++; ulCriticalNesting++;
/* This is not the interrupt safe version of the enter critical function so /*
* This is not the interrupt safe version of the enter critical function so
* assert() if it is being called from an interrupt context. Only API * assert() if it is being called from an interrupt context. Only API
* functions that end in "FromISR" can be used in an interrupt. Only assert if * functions that end in "FromISR" can be used in an interrupt. Only assert if
* the critical nesting count is 1 to protect against recursive calls if the * the critical nesting count is 1 to protect against recursive calls if the
* assert function also uses a critical section. */ * assert function also uses a critical section.
*/
if( ulCriticalNesting == 1 ) if( ulCriticalNesting == 1 )
{ {
configASSERT( ulPortInterruptNesting == 0 ); configASSERT( ulPortInterruptNesting == 0 );
@ -464,16 +549,19 @@ void vPortExitCritical( void )
{ {
if( ulCriticalNesting > portNO_CRITICAL_NESTING ) if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{ {
/* Decrement the nesting count as the critical section is being /* Decrement the nesting count as the critical section is being exited. */
* exited. */
ulCriticalNesting--; ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt /*
* priorities must be re-enabled. */ * If the nesting level has reached zero then all interrupt
* priorities must be re-enabled.
*/
if( ulCriticalNesting == portNO_CRITICAL_NESTING ) if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{ {
/* Critical nesting has reached zero so all interrupt priorities /*
* should be unmasked. */ * Critical nesting has reached zero so all interrupt priorities
* should be unmasked.
*/
portCLEAR_INTERRUPT_MASK(); portCLEAR_INTERRUPT_MASK();
} }
} }
@ -482,11 +570,13 @@ void vPortExitCritical( void )
void FreeRTOS_Tick_Handler( void ) void FreeRTOS_Tick_Handler( void )
{ {
/* Set interrupt mask before altering scheduler structures. The tick /*
* Set interrupt mask before altering scheduler structures. The tick
* handler runs at the lowest priority, so interrupts cannot already be masked, * handler runs at the lowest priority, so interrupts cannot already be masked,
* so there is no need to save and restore the current mask value. It is * 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 * necessary to turn off interrupts in the CPU itself while the ICCPMR is being
* updated. */ * updated.
*/
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ); portICCPMR_PRIORITY_MASK_REGISTER = ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT );
__asm volatile ( "dsb \n" __asm volatile ( "dsb \n"
@ -505,21 +595,23 @@ void FreeRTOS_Tick_Handler( void )
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_FPU_SUPPORT != 2 ) #if ( configUSE_TASK_FPU_SUPPORT == 1 )
void vPortTaskUsesFPU( void ) void vPortTaskUsesFPU( void )
{ {
uint32_t ulInitialFPSCR = 0; uint32_t ulInitialFPSCR = 0;
/* A task is registering the fact that it needs an FPU context. Set the /*
* FPU flag (which is saved as part of the task context). */ * A task is registering the fact that it needs an FPU context. Set the
* FPU flag (which is saved as part of the task context).
*/
ulPortTaskHasFPUContext = pdTRUE; ulPortTaskHasFPUContext = pdTRUE;
/* Initialise the floating point status register. */ /* Initialise the floating point status register. */
__asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" ); __asm volatile ( "FMXR FPSCR, %0" ::"r" ( ulInitialFPSCR ) : "memory" );
} }
#endif /* configUSE_TASK_FPU_SUPPORT */ #endif /* configUSE_TASK_FPU_SUPPORT == 1 */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vPortClearInterruptMask( uint32_t ulNewMaskValue ) void vPortClearInterruptMask( uint32_t ulNewMaskValue )
@ -535,8 +627,7 @@ uint32_t ulPortSetInterruptMask( void )
{ {
uint32_t ulReturn; uint32_t ulReturn;
/* Interrupt in the CPU must be turned off while the ICCPMR is being /* Interrupts must be masked while ICCPMR is updated. */
* updated. */
portCPU_IRQ_DISABLE(); portCPU_IRQ_DISABLE();
if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ) if( portICCPMR_PRIORITY_MASK_REGISTER == ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) )
@ -562,7 +653,8 @@ uint32_t ulPortSetInterruptMask( void )
void vPortValidateInterruptPriority( void ) void vPortValidateInterruptPriority( void )
{ {
/* The following assertion will fail if a service routine (ISR) for /*
* The following assertion will fail if a service routine (ISR) for
* an interrupt that has been assigned a priority above * an interrupt that has been assigned a priority above
* configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
* function. ISR safe FreeRTOS API functions must *only* be called * function. ISR safe FreeRTOS API functions must *only* be called
@ -575,11 +667,13 @@ uint32_t ulPortSetInterruptMask( void )
* configMAX_SYSCALL_INTERRUPT_PRIORITY. * configMAX_SYSCALL_INTERRUPT_PRIORITY.
* *
* FreeRTOS maintains separate thread and ISR API functions to ensure * FreeRTOS maintains separate thread and ISR API functions to ensure
* interrupt entry is as fast and simple as possible. */ * interrupt entry is as fast and simple as possible.
*/
configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) ); configASSERT( portICCRPR_RUNNING_PRIORITY_REGISTER >= ( uint32_t ) ( configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT ) );
/* Priority grouping: The interrupt controller (GIC) allows the bits /*
* Priority grouping: The interrupt controller (GIC) allows the bits
* that define each interrupt's priority to be split between bits that * that define each interrupt's priority to be split between bits that
* define the interrupt's pre-emption priority bits and bits that define * define the interrupt's pre-emption priority bits and bits that define
* the interrupt's sub-priority. For simplicity all bits must be defined * the interrupt's sub-priority. For simplicity all bits must be defined
@ -588,7 +682,8 @@ uint32_t ulPortSetInterruptMask( void )
* *
* The priority grouping is configured by the GIC's binary point register * The priority grouping is configured by the GIC's binary point register
* (ICCBPR). Writing 0 to ICCBPR will ensure it is set to its lowest * (ICCBPR). Writing 0 to ICCBPR will ensure it is set to its lowest
* possible value (which may be above 0). */ * possible value (which may be above 0).
*/
configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE ); configASSERT( ( portICCBPR_BINARY_POINT_REGISTER & portBINARY_POINT_BITS ) <= portMAX_BINARY_POINT_VALUE );
} }

View file

@ -45,7 +45,10 @@
.extern vTaskSwitchContext .extern vTaskSwitchContext
.extern vApplicationIRQHandler .extern vApplicationIRQHandler
.extern ulPortInterruptNesting .extern ulPortInterruptNesting
#if defined( __ARM_FP )
.extern ulPortTaskHasFPUContext .extern ulPortTaskHasFPUContext
#endif /* __ARM_FP */
.global FreeRTOS_IRQ_Handler .global FreeRTOS_IRQ_Handler
.global FreeRTOS_SWI_Handler .global FreeRTOS_SWI_Handler
@ -64,6 +67,7 @@
LDR R1, [R2] LDR R1, [R2]
PUSH {R1} PUSH {R1}
#if defined( __ARM_FP )
/* Does the task have a floating point context that needs saving? If /* Does the task have a floating point context that needs saving? If
ulPortTaskHasFPUContext is 0 then no. */ ulPortTaskHasFPUContext is 0 then no. */
LDR R2, ulPortTaskHasFPUContextConst LDR R2, ulPortTaskHasFPUContextConst
@ -73,11 +77,11 @@
/* Save the floating point context, if any. */ /* Save the floating point context, if any. */
FMRXNE R1, FPSCR FMRXNE R1, FPSCR
VPUSHNE {D0-D15} VPUSHNE {D0-D15}
/*VPUSHNE {D16-D31}*/
PUSHNE {R1} PUSHNE {R1}
/* Save ulPortTaskHasFPUContext itself. */ /* Save ulPortTaskHasFPUContext itself. */
PUSH {R3} PUSH {R3}
#endif /* __ARM_FP */
/* Save the stack pointer in the TCB. */ /* Save the stack pointer in the TCB. */
LDR R0, pxCurrentTCBConst LDR R0, pxCurrentTCBConst
@ -95,8 +99,11 @@
LDR R1, [R0] LDR R1, [R0]
LDR SP, [R1] LDR SP, [R1]
/* Is there a floating point context to restore? If the restored #if defined( __ARM_FP )
ulPortTaskHasFPUContext is zero then no. */ /*
* Is there a floating point context to restore? If the restored
* ulPortTaskHasFPUContext is zero then no.
*/
LDR R0, ulPortTaskHasFPUContextConst LDR R0, ulPortTaskHasFPUContextConst
POP {R1} POP {R1}
STR R1, [R0] STR R1, [R0]
@ -104,9 +111,9 @@
/* Restore the floating point context, if any. */ /* Restore the floating point context, if any. */
POPNE {R0} POPNE {R0}
/*VPOPNE {D16-D31}*/
VPOPNE {D0-D15} VPOPNE {D0-D15}
VMSRNE FPSCR, R0 VMSRNE FPSCR, R0
#endif /* __ARM_FP */
/* Restore the critical section nesting depth. */ /* Restore the critical section nesting depth. */
LDR R0, ulCriticalNestingConst LDR R0, ulCriticalNestingConst
@ -132,8 +139,6 @@
.endm .endm
/****************************************************************************** /******************************************************************************
* SVC handler is used to start the scheduler. * SVC handler is used to start the scheduler.
*****************************************************************************/ *****************************************************************************/
@ -279,12 +284,14 @@ switch_before_exit:
* FPU registers to be saved on interrupt entry their IRQ handler must be * FPU registers to be saved on interrupt entry their IRQ handler must be
* called vApplicationIRQHandler(). * called vApplicationIRQHandler().
*****************************************************************************/ *****************************************************************************/
.align 4 .align 4
.weak vApplicationIRQHandler .weak vApplicationIRQHandler
.type vApplicationIRQHandler, %function .type vApplicationIRQHandler, %function
vApplicationIRQHandler: vApplicationIRQHandler:
PUSH {LR} PUSH {LR}
#if defined( __ARM_FP )
FMRX R1, FPSCR FMRX R1, FPSCR
VPUSH {D0-D15} VPUSH {D0-D15}
PUSH {R1} PUSH {R1}
@ -295,6 +302,7 @@ vApplicationIRQHandler:
POP {R0} POP {R0}
VPOP {D0-D15} VPOP {D0-D15}
VMSR FPSCR, R0 VMSR FPSCR, R0
#endif /* __ARM_FP */
POP {PC} POP {PC}
@ -303,11 +311,15 @@ ulICCEOIRConst: .word ulICCEOIR
ulICCPMRConst: .word ulICCPMR ulICCPMRConst: .word ulICCPMR
pxCurrentTCBConst: .word pxCurrentTCB pxCurrentTCBConst: .word pxCurrentTCB
ulCriticalNestingConst: .word ulCriticalNesting ulCriticalNestingConst: .word ulCriticalNesting
ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
#if defined( __ARM_FP )
ulPortTaskHasFPUContextConst: .word ulPortTaskHasFPUContext
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
#endif /* __ARM_FP */
ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask ulMaxAPIPriorityMaskConst: .word ulMaxAPIPriorityMask
vTaskSwitchContextConst: .word vTaskSwitchContext vTaskSwitchContextConst: .word vTaskSwitchContext
vApplicationIRQHandlerConst: .word vApplicationIRQHandler vApplicationIRQHandlerConst: .word vApplicationIRQHandler
ulPortInterruptNestingConst: .word ulPortInterruptNesting ulPortInterruptNestingConst: .word ulPortInterruptNesting
vApplicationFPUSafeIRQHandlerConst: .word vApplicationFPUSafeIRQHandler
.end .end

View file

@ -27,11 +27,13 @@
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
#define PORTMACRO_H #define PORTMACRO_H
#ifdef __cplusplus /* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* *INDENT-ON* */
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Port specific definitions. * Port specific definitions.
@ -44,34 +46,34 @@
*/ */
/* Type definitions. */ /* Type definitions. */
#define portCHAR char #define portCHAR char
#define portFLOAT float #define portFLOAT float
#define portDOUBLE double #define portDOUBLE double
#define portLONG long #define portLONG long
#define portSHORT short #define portSHORT short
#define portSTACK_TYPE uint32_t #define portSTACK_TYPE uint32_t
#define portBASE_TYPE long #define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t; typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t; typedef long BaseType_t;
typedef unsigned long UBaseType_t; typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t; typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL #define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Hardware specifics. */ /* Hardware specifics. */
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8 #define portBYTE_ALIGNMENT 8
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task utilities. */ /* Task utilities. */
/* Called at the end of an ISR that can cause a context switch. */ /* Called at the end of an ISR that can cause a context switch. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \ #define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \ { \
extern uint32_t ulPortYieldRequired; \ extern uint32_t ulPortYieldRequired; \
\ \
@ -81,64 +83,75 @@
} \ } \
} }
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
#define portYIELD() __asm volatile ( "SWI 0" ::: "memory" ); #define portYIELD() __asm volatile ( "SWI 0" ::: "memory" );
/*----------------------------------------------------------- /*-----------------------------------------------------------
* Critical section control * Critical section control
*----------------------------------------------------------*/ *----------------------------------------------------------*/
extern void vPortEnterCritical( void ); extern void vPortEnterCritical( void );
extern void vPortExitCritical( void ); extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void ); extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue ); extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
extern void vPortInstallFreeRTOSVectorTable( void ); extern void vPortInstallFreeRTOSVectorTable( void );
/* These macros do not globally disable/enable interrupts. They do mask off /*
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */ * These macros do not globally disable/enable interrupts. They do mask off
#define portENTER_CRITICAL() vPortEnterCritical(); * interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY.
#define portEXIT_CRITICAL() vPortExitCritical(); */
#define portDISABLE_INTERRUPTS() ulPortSetInterruptMask() #define portENTER_CRITICAL() vPortEnterCritical();
#define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 ) #define portEXIT_CRITICAL() vPortExitCritical();
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask() #define portDISABLE_INTERRUPTS() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x ) #define portENABLE_INTERRUPTS() vPortClearInterruptMask( 0 )
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are /*
* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these * not required for this port but included in case common demo code that uses these
* macros is used. */ * macros is used.
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) */
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/* Prototype of the FreeRTOS tick handler. This must be installed as the /*
* handler for whichever peripheral is used to generate the RTOS tick. */ * Prototype of the FreeRTOS tick handler. This must be installed as the
void FreeRTOS_Tick_Handler( void ); * handler for whichever peripheral is used to generate the RTOS tick.
*/
void FreeRTOS_Tick_Handler( void );
/* If configUSE_TASK_FPU_SUPPORT is set to 1 (or left undefined) then tasks are /*
created without an FPU context and must call vPortTaskUsesFPU() to give * If configUSE_TASK_FPU_SUPPORT is set to 1, then tasks are created without an
themselves an FPU context before using any FPU instructions. If * FPU context and must call vPortTaskUsesFPU() to allocate an FPU context
configUSE_TASK_FPU_SUPPORT is set to 2 then all tasks will have an FPU context * prior to any FPU instructions. If configUSE_TASK_FPU_SUPPORT is set to 2,
by default. */ * then all tasks have an FPU context allocated by default.
#if( configUSE_TASK_FPU_SUPPORT != 2 ) */
#if ( configUSE_TASK_FPU_SUPPORT == 1 )
void vPortTaskUsesFPU( void ); void vPortTaskUsesFPU( void );
#else
/* Each task has an FPU context already, so define this function away to
nothing to prevent it being called accidentally. */
#define vPortTaskUsesFPU()
#endif /* configUSE_TASK_FPU_SUPPORT */
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
#elif ( configUSE_TASK_FPU_SUPPORT == 2 )
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL ) /*
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL ) * Each task has an FPU context already, so define this function away to
* prevent it being called accidentally.
*/
#define vPortTaskUsesFPU()
#define portTASK_USES_FLOATING_POINT()
#endif /* configUSE_TASK_FPU_SUPPORT */
#define portLOWEST_INTERRUPT_PRIORITY ( ( ( uint32_t ) configUNIQUE_INTERRUPT_PRIORITIES ) - 1UL )
#define portLOWEST_USABLE_INTERRUPT_PRIORITY ( portLOWEST_INTERRUPT_PRIORITY - 1UL )
/* Architecture specific optimisations. */ /* Architecture specific optimisations. */
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif #endif
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */ /* Store/clear the ready priorities in a bit map. */
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
@ -148,57 +161,60 @@ by default. */
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) ) #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( uxReadyPriorities ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#ifdef configASSERT #ifdef configASSERT
void vPortValidateInterruptPriority( void ); void vPortValidateInterruptPriority( void );
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
#endif /* configASSERT */ #endif /* configASSERT */
#define portNOP() __asm volatile ( "NOP" ) #define portNOP() __asm volatile ( "NOP" )
#ifdef __cplusplus /*
} /* extern C */ * The number of bits to shift for an interrupt priority is dependent on the
#endif * number of bits implemented by the interrupt controller.
*/
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
/* The number of bits to shift for an interrupt priority is dependent on the
* number of bits implemented by the interrupt controller. */
#if configUNIQUE_INTERRUPT_PRIORITIES == 16
#define portPRIORITY_SHIFT 4 #define portPRIORITY_SHIFT 4
#define portMAX_BINARY_POINT_VALUE 3 #define portMAX_BINARY_POINT_VALUE 3
#elif configUNIQUE_INTERRUPT_PRIORITIES == 32 #elif configUNIQUE_INTERRUPT_PRIORITIES == 32
#define portPRIORITY_SHIFT 3 #define portPRIORITY_SHIFT 3
#define portMAX_BINARY_POINT_VALUE 2 #define portMAX_BINARY_POINT_VALUE 2
#elif configUNIQUE_INTERRUPT_PRIORITIES == 64 #elif configUNIQUE_INTERRUPT_PRIORITIES == 64
#define portPRIORITY_SHIFT 2 #define portPRIORITY_SHIFT 2
#define portMAX_BINARY_POINT_VALUE 1 #define portMAX_BINARY_POINT_VALUE 1
#elif configUNIQUE_INTERRUPT_PRIORITIES == 128 #elif configUNIQUE_INTERRUPT_PRIORITIES == 128
#define portPRIORITY_SHIFT 1 #define portPRIORITY_SHIFT 1
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#elif configUNIQUE_INTERRUPT_PRIORITIES == 256 #elif configUNIQUE_INTERRUPT_PRIORITIES == 256
#define portPRIORITY_SHIFT 0 #define portPRIORITY_SHIFT 0
#define portMAX_BINARY_POINT_VALUE 0 #define portMAX_BINARY_POINT_VALUE 0
#else /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */ #else /* 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 #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 /* if configUNIQUE_INTERRUPT_PRIORITIES == 16 */
/* Interrupt controller access addresses. */ /* Interrupt controller access addresses. */
#define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 ) #define portICCPMR_PRIORITY_MASK_OFFSET ( 0x04 )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ( 0x0C )
#define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 ) #define portICCEOIR_END_OF_INTERRUPT_OFFSET ( 0x10 )
#define portICCBPR_BINARY_POINT_OFFSET ( 0x08 ) #define portICCBPR_BINARY_POINT_OFFSET ( 0x08 )
#define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 ) #define portICCRPR_RUNNING_PRIORITY_OFFSET ( 0x14 )
#define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) #define portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) ) #define portICCPMR_PRIORITY_MASK_REGISTER ( *( ( volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) ) )
#define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET ) #define portICCIAR_INTERRUPT_ACKNOWLEDGE_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCIAR_INTERRUPT_ACKNOWLEDGE_OFFSET )
#define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET ) #define portICCEOIR_END_OF_INTERRUPT_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCEOIR_END_OF_INTERRUPT_OFFSET )
#define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET ) #define portICCPMR_PRIORITY_MASK_REGISTER_ADDRESS ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCPMR_PRIORITY_MASK_OFFSET )
#define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) ) #define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) )
#define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) ) #define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) )
#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" )
/* *INDENT-OFF* */
#ifdef __cplusplus
} /* extern C */
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */ #endif /* PORTMACRO_H */