Moved proj up

This commit is contained in:
Timo Niemann
2026-06-04 10:21:56 +02:00
parent aea013305e
commit 99fb345151
949 changed files with 0 additions and 0 deletions
@@ -0,0 +1,128 @@
/*
* FreeRTOS Kernel V11.3.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
.extern ulTopOfSystemStack
.extern ulInterruptNesting
/*-----------------------------------------------------------*/
.macro portFREERTOS_INTERRUPT_ENTRY
/* Save general purpose registers. */
pusha
/* If ulInterruptNesting is zero the rest of the task context will need
saving and a stack switch might be required. */
movl ulInterruptNesting, %eax
test %eax, %eax
jne 2f
/* Interrupts are not nested, so save the rest of the task context. */
.if configSUPPORT_FPU == 1
/* If the task has a buffer allocated to save the FPU context then
save the FPU context now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
fnsave ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
fwait
1:
/* Save the address of the FPU context, if any. */
push pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl %esp, (%eax)
/* Switch stacks. */
movl ulTopOfSystemStack, %esp
movl %esp, %ebp
2:
/* Increment nesting count. */
add $1, ulInterruptNesting
.endm
/*-----------------------------------------------------------*/
.macro portINTERRUPT_EPILOGUE
cli
sub $1, ulInterruptNesting
/* If the nesting has unwound to zero. */
movl ulInterruptNesting, %eax
test %eax, %eax
jne 2f
/* If a yield was requested then select a new TCB now. */
movl ulPortYieldPending, %eax
test %eax, %eax
je 1f
movl $0, ulPortYieldPending
call vTaskSwitchContext
1:
/* Stack location is first item in the TCB. */
movl pxCurrentTCB, %eax
movl (%eax), %esp
.if configSUPPORT_FPU == 1
/* Restore address of task's FPU context buffer. */
pop pucPortTaskFPUContextBuffer
/* If the task has a buffer allocated in which its FPU context is saved,
then restore it now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
frstor ( %eax )
1:
.endif
2:
popa
.endm
/*-----------------------------------------------------------*/
.macro portFREERTOS_INTERRUPT_EXIT
portINTERRUPT_EPILOGUE
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endm
+688
View File
@@ -0,0 +1,688 @@
/*
* FreeRTOS Kernel V11.3.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
/* Standard includes. */
#include <limits.h>
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 )
/* Check the configuration. */
#if ( configMAX_PRIORITIES > 32 )
#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice.
#endif
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#if ( configISR_STACK_SIZE < ( configMINIMAL_STACK_SIZE * 2 ) )
#warning configISR_STACK_SIZE is probably too small!
#endif /* ( configISR_STACK_SIZE < configMINIMAL_STACK_SIZE * 2 ) */
#if ( ( configMAX_API_CALL_INTERRUPT_PRIORITY > portMAX_PRIORITY ) || ( configMAX_API_CALL_INTERRUPT_PRIORITY < 2 ) )
#error configMAX_API_CALL_INTERRUPT_PRIORITY must be between 2 and 15
#endif
#if ( ( configSUPPORT_FPU == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) )
#error configSUPPORT_DYNAMIC_ALLOCATION must be set to 1 to use this port with an FPU
#endif
/* A critical section is exited when the critical section nesting count reaches
* this value. */
#define portNO_CRITICAL_NESTING ( ( uint32_t ) 0 )
/* Tasks are not created with a floating point context, but can be given a
* floating point context after they have been created. A variable is stored as
* part of the tasks context that holds portNO_FLOATING_POINT_CONTEXT if the task
* does not have an FPU context, or any other value if the task does have an FPU
* context. */
#define portNO_FLOATING_POINT_CONTEXT ( ( StackType_t ) 0 )
/* Only the IF bit is set so tasks start with interrupts enabled. */
#define portINITIAL_EFLAGS ( 0x200UL )
/* Error interrupts are at the highest priority vectors. */
#define portAPIC_LVT_ERROR_VECTOR ( 0xfe )
#define portAPIC_SPURIOUS_INT_VECTOR ( 0xff )
/* EFLAGS bits. */
#define portEFLAGS_IF ( 0x200UL )
/* FPU context size if FSAVE is used. */
#define portFPU_CONTEXT_SIZE_BYTES 108
/* The expected size of each entry in the IDT. Used to check structure packing
* is set correctly. */
#define portEXPECTED_IDT_ENTRY_SIZE 8
/* Default flags setting for entries in the IDT. */
#define portIDT_FLAGS ( 0x8E )
/* This is the lowest possible ISR vector available to application code. */
#define portAPIC_MIN_ALLOWABLE_VECTOR ( 0x20 )
/* If configASSERT() is defined then the system stack is filled with this value
* to allow for a crude stack overflow check. */
#define portSTACK_WORD ( 0xecececec )
/*-----------------------------------------------------------*/
/*
* Starts the first task executing.
*/
extern void vPortStartFirstTask( void );
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*
* Complete one descriptor in the IDT.
*/
static void prvSetInterruptGate( uint8_t ucNumber,
ISR_Handler_t pxHandlerFunction,
uint8_t ucFlags );
/*
* The default handler installed in each IDT position.
*/
extern void vPortCentralInterruptWrapper( void );
/*
* Handler for portYIELD().
*/
extern void vPortYieldCall( void );
/*
* Configure the APIC to generate the RTOS tick.
*/
static void prvSetupTimerInterrupt( void );
/*
* Tick interrupt handler.
*/
extern void vPortTimerHandler( void );
/*
* Check an interrupt vector is not too high, too low, in use by FreeRTOS, or
* already in use by the application.
*/
static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber );
/*-----------------------------------------------------------*/
/* A variable is used to keep track of the critical section nesting. This
* variable must be initialised to a non zero value to ensure interrupts don't
* inadvertently become unmasked before the scheduler starts. It is set to zero
* before the first task starts executing. */
volatile uint32_t ulCriticalNesting = 9999UL;
/* A structure used to map the various fields of an IDT entry into separate
* structure members. */
struct IDTEntry
{
uint16_t usISRLow; /* Low 16 bits of handler address. */
uint16_t usSegmentSelector; /* Flat model means this is not changed. */
uint8_t ucZero; /* Must be set to zero. */
uint8_t ucFlags; /* Flags for this entry. */
uint16_t usISRHigh; /* High 16 bits of handler address. */
}
__attribute__( ( packed ) );
typedef struct IDTEntry IDTEntry_t;
/* Use to pass the location of the IDT to the CPU. */
struct IDTPointer
{
uint16_t usTableLimit;
uint32_t ulTableBase; /* The address of the first entry in xInterruptDescriptorTable. */
}
__attribute__( ( __packed__ ) );
typedef struct IDTPointer IDTPointer_t;
/* The IDT itself. */
static __attribute__( ( aligned( 32 ) ) ) IDTEntry_t xInterruptDescriptorTable[ portNUM_VECTORS ];
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
/* A table in which application defined interrupt handlers are stored. These
* are called by the central interrupt handler if a common interrupt entry
* point it used. */
static ISR_Handler_t xInterruptHandlerTable[ portNUM_VECTORS ] = { NULL };
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
#if ( configSUPPORT_FPU == 1 )
/* Saved as part of the task context. If pucPortTaskFPUContextBuffer is NULL
* then the task does not have an FPU context. If pucPortTaskFPUContextBuffer is
* not NULL then it points to a buffer into which the FPU context can be saved. */
uint8_t * pucPortTaskFPUContextBuffer __attribute__( ( used ) ) = pdFALSE;
#endif /* configSUPPORT_FPU */
/* The stack used by interrupt handlers. */
static uint32_t ulSystemStack[ configISR_STACK_SIZE ] __attribute__( ( used ) ) = { 0 };
/* Don't use the very top of the system stack so the return address
* appears as 0 if the debugger tries to unwind the stack. */
volatile uint32_t ulTopOfSystemStack __attribute__( ( used ) ) = ( uint32_t ) &( ulSystemStack[ configISR_STACK_SIZE - 5 ] );
/* If a yield is requested from an interrupt or from a critical section then
* the yield is not performed immediately, and ulPortYieldPending is set to pdTRUE
* instead to indicate the yield should be performed at the end of the interrupt
* when the critical section is exited. */
volatile uint32_t ulPortYieldPending __attribute__( ( used ) ) = pdFALSE;
/* Counts the interrupt nesting depth. Used to know when to switch to the
* interrupt/system stack and when to save/restore a complete context. */
volatile uint32_t ulInterruptNesting __attribute__( ( used ) ) = 0;
/*-----------------------------------------------------------*/
/*
* See header file for description.
*/
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
TaskFunction_t pxCode,
void * pvParameters )
{
uint32_t ulCodeSegment;
/* Setup the initial stack as expected by the portFREERTOS_INTERRUPT_EXIT macro. */
*pxTopOfStack = 0x00;
pxTopOfStack--;
*pxTopOfStack = 0x00;
pxTopOfStack--;
/* Parameters first. */
*pxTopOfStack = ( StackType_t ) pvParameters;
pxTopOfStack--;
/* There is nothing to return to so assert if attempting to use the return
* address. */
*pxTopOfStack = ( StackType_t ) prvTaskExitError;
pxTopOfStack--;
/* iret used to start the task pops up to here. */
*pxTopOfStack = portINITIAL_EFLAGS;
pxTopOfStack--;
/* CS */
__asm volatile ( "movl %%cs, %0" : "=r" ( ulCodeSegment ) );
*pxTopOfStack = ulCodeSegment;
pxTopOfStack--;
/* First instruction in the task. */
*pxTopOfStack = ( StackType_t ) pxCode;
pxTopOfStack--;
/* General purpose registers as expected by a POPA instruction. */
*pxTopOfStack = 0xEA;
pxTopOfStack--;
*pxTopOfStack = 0xEC;
pxTopOfStack--;
*pxTopOfStack = 0xED1; /* EDX */
pxTopOfStack--;
*pxTopOfStack = 0xEB1; /* EBX */
pxTopOfStack--;
/* Hole for ESP. */
pxTopOfStack--;
*pxTopOfStack = 0x00; /* EBP */
pxTopOfStack--;
*pxTopOfStack = 0xE5; /* ESI */
pxTopOfStack--;
*pxTopOfStack = 0xeeeeeeee; /* EDI */
#if ( configSUPPORT_FPU == 1 )
{
pxTopOfStack--;
/* Buffer for FPU context, which is initialised to NULL as tasks are not
* created with an FPU context. */
*pxTopOfStack = portNO_FLOATING_POINT_CONTEXT;
}
#endif /* configSUPPORT_FPU */
return pxTopOfStack;
}
/*-----------------------------------------------------------*/
static void prvSetInterruptGate( uint8_t ucNumber,
ISR_Handler_t pxHandlerFunction,
uint8_t ucFlags )
{
uint16_t usCodeSegment;
uint32_t ulBase = ( uint32_t ) pxHandlerFunction;
xInterruptDescriptorTable[ ucNumber ].usISRLow = ( uint16_t ) ( ulBase & USHRT_MAX );
xInterruptDescriptorTable[ ucNumber ].usISRHigh = ( uint16_t ) ( ( ulBase >> 16UL ) & USHRT_MAX );
/* When the flat model is used the CS will never change. */
__asm volatile ( "mov %%cs, %0" : "=r" ( usCodeSegment ) );
xInterruptDescriptorTable[ ucNumber ].usSegmentSelector = usCodeSegment;
xInterruptDescriptorTable[ ucNumber ].ucZero = 0;
xInterruptDescriptorTable[ ucNumber ].ucFlags = ucFlags;
}
/*-----------------------------------------------------------*/
void vPortSetupIDT( void )
{
uint32_t ulNum;
IDTPointer_t xIDT;
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
{
for( ulNum = 0; ulNum < portNUM_VECTORS; ulNum++ )
{
/* If a handler has not already been installed on this vector. */
if( ( xInterruptDescriptorTable[ ulNum ].usISRLow == 0x00 ) && ( xInterruptDescriptorTable[ ulNum ].usISRHigh == 0x00 ) )
{
prvSetInterruptGate( ( uint8_t ) ulNum, vPortCentralInterruptWrapper, portIDT_FLAGS );
}
}
}
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/* Set IDT address. */
xIDT.ulTableBase = ( uint32_t ) xInterruptDescriptorTable;
xIDT.usTableLimit = sizeof( xInterruptDescriptorTable ) - 1;
/* Set IDT in CPU. */
__asm volatile ( "lidt %0" ::"m" ( xIDT ) );
}
/*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
* its caller as there is nothing to return to. If a task wants to exit it
* should instead call vTaskDelete( NULL ).
*
* Artificially force an assert() to be triggered if configASSERT() is
* defined, then stop here so application writers can catch the error. */
configASSERT( ulCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ; ; )
{
}
}
/*-----------------------------------------------------------*/
static void prvSetupTimerInterrupt( void )
{
extern void vPortAPICErrorHandlerWrapper( void );
extern void vPortAPICSpuriousHandler( void );
/* Initialise LAPIC to a well known state. */
portAPIC_LDR = 0xFFFFFFFF;
portAPIC_LDR = ( ( portAPIC_LDR & 0x00FFFFFF ) | 0x00000001 );
portAPIC_LVT_TIMER = portAPIC_DISABLE;
portAPIC_LVT_PERF = portAPIC_NMI;
portAPIC_LVT_LINT0 = portAPIC_DISABLE;
portAPIC_LVT_LINT1 = portAPIC_DISABLE;
portAPIC_TASK_PRIORITY = 0;
/* Install APIC timer ISR vector. */
prvSetInterruptGate( ( uint8_t ) portAPIC_TIMER_INT_VECTOR, vPortTimerHandler, portIDT_FLAGS );
/* Install API error handler. */
prvSetInterruptGate( ( uint8_t ) portAPIC_LVT_ERROR_VECTOR, vPortAPICErrorHandlerWrapper, portIDT_FLAGS );
/* Install Yield handler. */
prvSetInterruptGate( ( uint8_t ) portAPIC_YIELD_INT_VECTOR, vPortYieldCall, portIDT_FLAGS );
/* Install spurious interrupt vector. */
prvSetInterruptGate( ( uint8_t ) portAPIC_SPURIOUS_INT_VECTOR, vPortAPICSpuriousHandler, portIDT_FLAGS );
/* Enable the APIC, mapping the spurious interrupt at the same time. */
portAPIC_SPURIOUS_INT = portAPIC_SPURIOUS_INT_VECTOR | portAPIC_ENABLE_BIT;
/* Set timer error vector. */
portAPIC_LVT_ERROR = portAPIC_LVT_ERROR_VECTOR;
/* Set the interrupt frequency. */
portAPIC_TMRDIV = portAPIC_DIV_16;
portAPIC_TIMER_INITIAL_COUNT = ( ( configCPU_CLOCK_HZ >> 4UL ) / configTICK_RATE_HZ ) - 1UL;
}
/*-----------------------------------------------------------*/
BaseType_t xPortStartScheduler( void )
{
BaseType_t xWord;
/* Some versions of GCC require the -mno-ms-bitfields command line option
* for packing to work. */
configASSERT( sizeof( struct IDTEntry ) == portEXPECTED_IDT_ENTRY_SIZE );
/* Fill part of the system stack with a known value to help detect stack
* overflow. A few zeros are left so GDB doesn't get confused unwinding
* the stack. */
for( xWord = 0; xWord < configISR_STACK_SIZE - 20; xWord++ )
{
ulSystemStack[ xWord ] = portSTACK_WORD;
}
/* Initialise Interrupt Descriptor Table (IDT). */
vPortSetupIDT();
/* Initialise LAPIC and install system handlers. */
prvSetupTimerInterrupt();
/* Make sure the stack used by interrupts is aligned. */
ulTopOfSystemStack &= ~portBYTE_ALIGNMENT_MASK;
ulCriticalNesting = 0;
/* Enable LAPIC Counter.*/
portAPIC_LVT_TIMER = portAPIC_TIMER_PERIODIC | portAPIC_TIMER_INT_VECTOR;
/* Sometimes needed. */
portAPIC_TMRDIV = portAPIC_DIV_16;
/* Should not return from the following function as the scheduler will then
* be executing the tasks. */
vPortStartFirstTask();
return 0;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler( void )
{
/* Not implemented in ports where there is nothing to return to.
* Artificially force an assert. */
configASSERT( ulCriticalNesting == 1000UL );
}
/*-----------------------------------------------------------*/
void vPortEnterCritical( void )
{
if( ulCriticalNesting == 0 )
{
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
__asm volatile ( "cli" );
}
#else
{
portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
}
#endif
}
/* Now that interrupts are disabled, ulCriticalNesting can be accessed
* directly. Increment ulCriticalNesting to keep a count of how many times
* portENTER_CRITICAL() has been called. */
ulCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
if( ulCriticalNesting > portNO_CRITICAL_NESTING )
{
/* Decrement the nesting count as the critical section is being
* exited. */
ulCriticalNesting--;
/* If the nesting level has reached zero then all interrupt
* priorities must be re-enabled. */
if( ulCriticalNesting == portNO_CRITICAL_NESTING )
{
/* Critical nesting has reached zero so all interrupt priorities
* should be unmasked. */
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
__asm volatile ( "sti" );
}
#else
{
portAPIC_TASK_PRIORITY = 0;
}
#endif
/* If a yield was pended from within the critical section then
* perform the yield now. */
if( ulPortYieldPending != pdFALSE )
{
ulPortYieldPending = pdFALSE;
__asm volatile ( portYIELD_INTERRUPT );
}
}
}
}
/*-----------------------------------------------------------*/
uint32_t ulPortSetInterruptMask( void )
{
volatile uint32_t ulOriginalMask;
/* Set mask to max syscall priority. */
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
/* Return whether interrupts were already enabled or not. Pop adjusts
* the stack first. */
__asm volatile ( "pushf \t\n"
"pop %0 \t\n"
"cli "
: "=rm" ( ulOriginalMask )::"memory" );
ulOriginalMask &= portEFLAGS_IF;
}
#else
{
/* Return original mask. */
ulOriginalMask = portAPIC_TASK_PRIORITY;
portAPIC_TASK_PRIORITY = portMAX_API_CALL_PRIORITY;
configASSERT( portAPIC_TASK_PRIORITY == portMAX_API_CALL_PRIORITY );
}
#endif /* if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY ) */
return ulOriginalMask;
}
/*-----------------------------------------------------------*/
void vPortClearInterruptMask( uint32_t ulNewMaskValue )
{
#if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY )
{
if( ulNewMaskValue != pdFALSE )
{
__asm volatile ( "sti" );
}
}
#else
{
portAPIC_TASK_PRIORITY = ulNewMaskValue;
configASSERT( portAPIC_TASK_PRIORITY == ulNewMaskValue );
}
#endif /* if ( configMAX_API_CALL_INTERRUPT_PRIORITY == portMAX_PRIORITY ) */
}
/*-----------------------------------------------------------*/
#if ( configSUPPORT_FPU == 1 )
void vPortTaskUsesFPU( void )
{
/* A task is registering the fact that it needs an FPU context. Allocate a
* buffer into which the context can be saved. */
pucPortTaskFPUContextBuffer = ( uint8_t * ) pvPortMalloc( portFPU_CONTEXT_SIZE_BYTES );
configASSERT( pucPortTaskFPUContextBuffer );
/* Initialise the floating point registers. */
__asm volatile ( "fninit" );
}
#endif /* configSUPPORT_FPU */
/*-----------------------------------------------------------*/
void vPortAPICErrorHandler( void )
{
/* Variable to hold the APIC error status for viewing in the debugger. */
volatile uint32_t ulErrorStatus = 0;
portAPIC_ERROR_STATUS = 0;
ulErrorStatus = portAPIC_ERROR_STATUS;
( void ) ulErrorStatus;
/* Force an assert. */
configASSERT( ulCriticalNesting == ~0UL );
}
/*-----------------------------------------------------------*/
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
void vPortCentralInterruptHandler( uint32_t ulVector )
{
if( ulVector < portNUM_VECTORS )
{
if( xInterruptHandlerTable[ ulVector ] != NULL )
{
( xInterruptHandlerTable[ ulVector ] )();
}
}
/* Check for a system stack overflow. */
configASSERT( ulSystemStack[ 10 ] == portSTACK_WORD );
configASSERT( ulSystemStack[ 12 ] == portSTACK_WORD );
configASSERT( ulSystemStack[ 14 ] == portSTACK_WORD );
}
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/*-----------------------------------------------------------*/
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler,
uint32_t ulVectorNumber )
{
BaseType_t xReturn;
xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
if( xReturn != pdFAIL )
{
/* Save the handler passed in by the application in the vector number
* passed in. The addresses are then called from the central interrupt
* handler. */
xInterruptHandlerTable[ ulVectorNumber ] = pxHandler;
}
return xReturn;
}
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/*-----------------------------------------------------------*/
BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler,
uint32_t ulVectorNumber )
{
BaseType_t xReturn;
xReturn = prvCheckValidityOfVectorNumber( ulVectorNumber );
if( xReturn != pdFAIL )
{
taskENTER_CRITICAL();
{
/* Update the IDT to include the application defined handler. */
prvSetInterruptGate( ( uint8_t ) ulVectorNumber, ( ISR_Handler_t ) pxHandler, portIDT_FLAGS );
}
taskEXIT_CRITICAL();
}
return xReturn;
}
/*-----------------------------------------------------------*/
static BaseType_t prvCheckValidityOfVectorNumber( uint32_t ulVectorNumber )
{
BaseType_t xReturn;
/* Check validity of vector number. */
if( ulVectorNumber >= portNUM_VECTORS )
{
/* Too high. */
xReturn = pdFAIL;
}
else if( ulVectorNumber < portAPIC_MIN_ALLOWABLE_VECTOR )
{
/* Too low. */
xReturn = pdFAIL;
}
else if( ulVectorNumber == portAPIC_TIMER_INT_VECTOR )
{
/* In use by FreeRTOS. */
xReturn = pdFAIL;
}
else if( ulVectorNumber == portAPIC_YIELD_INT_VECTOR )
{
/* In use by FreeRTOS. */
xReturn = pdFAIL;
}
else if( ulVectorNumber == portAPIC_LVT_ERROR_VECTOR )
{
/* In use by FreeRTOS. */
xReturn = pdFAIL;
}
else if( ulVectorNumber == portAPIC_SPURIOUS_INT_VECTOR )
{
/* In use by FreeRTOS. */
xReturn = pdFAIL;
}
#if ( configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1 )
else if( xInterruptHandlerTable[ ulVectorNumber ] != NULL )
{
/* Already in use by the application. */
xReturn = pdFAIL;
}
#endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
else
{
xReturn = pdPASS;
}
return xReturn;
}
/*-----------------------------------------------------------*/
void vGenerateYieldInterrupt( void )
{
__asm volatile ( portYIELD_INTERRUPT );
}
+268
View File
@@ -0,0 +1,268 @@
/*
* FreeRTOS Kernel V11.3.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
.file "portASM.S"
#include "FreeRTOSConfig.h"
#include "ISR_Support.h"
.extern pxCurrentTCB
.extern vTaskSwitchContext
.extern vPortCentralInterruptHandler
.extern xTaskIncrementTick
.extern vPortAPICErrorHandler
.extern pucPortTaskFPUContextBuffer
.extern ulPortYieldPending
.global vPortStartFirstTask
.global vPortCentralInterruptWrapper
.global vPortAPICErrorHandlerWrapper
.global vPortTimerHandler
.global vPortYieldCall
.global vPortAPICSpuriousHandler
.text
/*-----------------------------------------------------------*/
.align 4
.func vPortYieldCall
vPortYieldCall:
/* Save general purpose registers. */
pusha
.if configSUPPORT_FPU == 1
/* If the task has a buffer allocated to save the FPU context then save
the FPU context now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
fnsave ( %eax )
fwait
1:
/* Save the address of the FPU context, if any. */
push pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl %esp, (%eax)
call vTaskSwitchContext
/* Find the location of pxCurrentTCB again - a callee saved register could
be used in place of eax to prevent this second load, but that then relies
on the compiler and other asm code. */
movl pxCurrentTCB, %eax
movl (%eax), %esp
.if configSUPPORT_FPU == 1
/* Restore address of task's FPU context buffer. */
pop pucPortTaskFPUContextBuffer
/* If the task has a buffer allocated in which its FPU context is saved,
then restore it now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
frstor ( %eax )
1:
.endif
popa
iret
.endfunc
/*-----------------------------------------------------------*/
.align 4
.func vPortStartFirstTask
vPortStartFirstTask:
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl (%eax), %esp
/* Restore FPU context flag. */
.if configSUPPORT_FPU == 1
pop pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Restore general purpose registers. */
popa
iret
.endfunc
/*-----------------------------------------------------------*/
.align 4
.func vPortAPICErrorHandlerWrapper
vPortAPICErrorHandlerWrapper:
pusha
call vPortAPICErrorHandler
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
/*-----------------------------------------------------------*/
.align 4
.func vPortTimerHandler
vPortTimerHandler:
/* Save general purpose registers. */
pusha
/* Interrupts are not nested, so save the rest of the task context. */
.if configSUPPORT_FPU == 1
/* If the task has a buffer allocated to save the FPU context then save the
FPU context now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
fnsave ( %eax ) /* Save FLOP context into ucTempFPUBuffer array. */
fwait
1:
/* Save the address of the FPU context, if any. */
push pucPortTaskFPUContextBuffer
.endif /* configSUPPORT_FPU */
/* Find the TCB. */
movl pxCurrentTCB, %eax
/* Stack location is first item in the TCB. */
movl %esp, (%eax)
/* Switch stacks. */
movl ulTopOfSystemStack, %esp
movl %esp, %ebp
/* Increment nesting count. */
add $1, ulInterruptNesting
call xTaskIncrementTick
sti
/* Is a switch to another task required? */
test %eax, %eax
je _skip_context_switch
cli
call vTaskSwitchContext
_skip_context_switch:
cli
/* Decrement the variable used to determine if a switch to a system
stack is necessary. */
sub $1, ulInterruptNesting
/* Stack location is first item in the TCB. */
movl pxCurrentTCB, %eax
movl (%eax), %esp
.if configSUPPORT_FPU == 1
/* Restore address of task's FPU context buffer. */
pop pucPortTaskFPUContextBuffer
/* If the task has a buffer allocated in which its FPU context is saved,
then restore it now. */
movl pucPortTaskFPUContextBuffer, %eax
test %eax, %eax
je 1f
frstor ( %eax )
1:
.endif
popa
/* EOI. */
movl $0x00, (0xFEE000B0)
iret
.endfunc
/*-----------------------------------------------------------*/
.if configUSE_COMMON_INTERRUPT_ENTRY_POINT == 1
.align 4
.func vPortCentralInterruptWrapper
vPortCentralInterruptWrapper:
portFREERTOS_INTERRUPT_ENTRY
movl $0xFEE00170, %eax /* Highest In Service Register (ISR) long word. */
movl $8, %ecx /* Loop counter. */
next_isr_long_word:
test %ecx, %ecx /* Loop counter reached 0? */
je wrapper_epilogue /* Looked at all ISR registers without finding a bit set. */
sub $1, %ecx /* Sub 1 from loop counter. */
movl (%eax), %ebx /* Load next ISR long word. */
sub $0x10, %eax /* Point to next ISR long word in case no bits are set in the current long word. */
test %ebx, %ebx /* Are there any bits set? */
je next_isr_long_word /* Look at next ISR long word if no bits were set. */
sti
bsr %ebx, %ebx /* A bit was set, which one? */
movl $32, %eax /* Destination operand for following multiplication. */
mul %ecx /* Calculate base vector for current register, 32 vectors per register. */
add %ebx, %eax /* Add bit offset into register to get final vector number. */
push %eax /* Vector number is function parameter. */
call vPortCentralInterruptHandler
pop %eax /* Remove parameter. */
wrapper_epilogue:
portFREERTOS_INTERRUPT_EXIT
.endfunc
.endif /* configUSE_COMMON_INTERRUPT_ENTRY_POINT */
/*-----------------------------------------------------------*/
.align 4
.func vPortAPISpuriousHandler
vPortAPICSpuriousHandler:
iret
.endfunc
.end
+302
View File
@@ -0,0 +1,302 @@
/*
* FreeRTOS Kernel V11.3.0
* Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* https://www.FreeRTOS.org
* https://github.com/FreeRTOS
*
*/
#ifndef PORTMACRO_H
#define PORTMACRO_H
/* *INDENT-OFF* */
#ifdef __cplusplus
extern "C" {
#endif
/* *INDENT-ON* */
/*-----------------------------------------------------------
* Port specific definitions.
*
* The settings in this file configure FreeRTOS correctly for the given hardware
* and compiler.
*
* These settings should not be altered.
*-----------------------------------------------------------
*/
/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE uint32_t
#define portBASE_TYPE long
typedef portSTACK_TYPE StackType_t;
typedef long BaseType_t;
typedef unsigned long UBaseType_t;
typedef uint32_t TickType_t;
#define portMAX_DELAY ( ( TickType_t ) 0xffffffffUL )
/*-----------------------------------------------------------*/
/* Hardware specifics. */
#define portSTACK_GROWTH ( -1 )
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 32
/*-----------------------------------------------------------*/
/* Task utilities. */
/* The interrupt priority (for vectors 16 to 255) is determined using vector/16.
* The quotient is rounded to the nearest integer with 1 being the lowest priority
* and 15 is the highest. Therefore the following two interrupts are at the lowest
* priority. *NOTE 1* If the yield vector is changed then it must also be changed
* in the portYIELD_INTERRUPT definition immediately below. */
#define portAPIC_TIMER_INT_VECTOR ( 0x21 )
#define portAPIC_YIELD_INT_VECTOR ( 0x20 )
/* Build yield interrupt instruction. */
#define portYIELD_INTERRUPT "int $0x20"
/* APIC register addresses. */
#define portAPIC_EOI ( *( ( volatile uint32_t * ) 0xFEE000B0UL ) )
/* APIC bit definitions. */
#define portAPIC_ENABLE_BIT ( 1UL << 8UL )
#define portAPIC_TIMER_PERIODIC ( 1UL << 17UL )
#define portAPIC_DISABLE ( 1UL << 16UL )
#define portAPIC_NMI ( 4 << 8 )
#define portAPIC_DIV_16 ( 0x03 )
/* Define local API register addresses. */
#define portAPIC_ID_REGISTER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x20UL ) ) )
#define portAPIC_SPURIOUS_INT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xF0UL ) ) )
#define portAPIC_LVT_TIMER ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x320UL ) ) )
#define portAPIC_TIMER_INITIAL_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x380UL ) ) )
#define portAPIC_TIMER_CURRENT_COUNT ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x390UL ) ) )
#define portAPIC_TASK_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x80UL ) ) )
#define portAPIC_LVT_ERROR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x370UL ) ) )
#define portAPIC_ERROR_STATUS ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x280UL ) ) )
#define portAPIC_LDR ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xD0UL ) ) )
#define portAPIC_TMRDIV ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x3E0UL ) ) )
#define portAPIC_LVT_PERF ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x340UL ) ) )
#define portAPIC_LVT_LINT0 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x350UL ) ) )
#define portAPIC_LVT_LINT1 ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0x360UL ) ) )
/* Don't yield if inside a critical section - instead hold the yield pending
* so it is performed when the critical section is exited. */
#define portYIELD() \
{ \
extern volatile uint32_t ulCriticalNesting; \
extern volatile uint32_t ulPortYieldPending; \
if( ulCriticalNesting != 0 ) \
{ \
ulPortYieldPending = pdTRUE; \
} \
else \
{ \
__asm volatile ( portYIELD_INTERRUPT ); \
} \
}
/* Called at the end of an ISR that can cause a context switch - pend a yield if
* xSwitchRequired is not false. */
#define portEND_SWITCHING_ISR( xSwitchRequired ) \
{ \
extern volatile uint32_t ulPortYieldPending; \
if( xSwitchRequired != pdFALSE ) \
{ \
ulPortYieldPending = 1; \
} \
}
/* Same as portEND_SWITCHING_ISR() - take your pick which name to use. */
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
/*-----------------------------------------------------------
* Critical section control
*----------------------------------------------------------*/
/* Critical sections for use in interrupts. */
#define portSET_INTERRUPT_MASK_FROM_ISR() ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vPortClearInterruptMask( x )
extern void vPortEnterCritical( void );
extern void vPortExitCritical( void );
extern uint32_t ulPortSetInterruptMask( void );
extern void vPortClearInterruptMask( uint32_t ulNewMaskValue );
/* These macros do not globally disable/enable interrupts. They do mask off
* interrupts that have a priority below configMAX_API_CALL_INTERRUPT_PRIORITY. */
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
#define portDISABLE_INTERRUPTS() __asm volatile ( "cli" )
#define portENABLE_INTERRUPTS() __asm volatile ( "sti" )
/*-----------------------------------------------------------*/
/* Task function macros as described on the FreeRTOS.org WEB site. These are
* not required for this port but included in case common demo code that uses these
* macros is used. */
#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters )
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters )
/* Architecture specific optimisations. */
#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
/* Store/clear the ready priorities in a bit map. */
#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \
__asm volatile ( "bsr %1, %0\n\t" \
: "=r" ( uxTopPriority ) : "rm" ( uxReadyPriorities ) : "cc" )
#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
#define portNOP() __asm volatile ( "NOP" )
/*-----------------------------------------------------------
* Misc
*----------------------------------------------------------*/
#define portNUM_VECTORS 256
#define portMAX_PRIORITY 15
typedef void ( * ISR_Handler_t ) ( void );
/* Any task that uses the floating point unit MUST call vPortTaskUsesFPU()
* before any floating point instructions are executed. */
#ifndef configSUPPORT_FPU
#define configSUPPORT_FPU 0
#endif
#if configSUPPORT_FPU == 1
void vPortTaskUsesFPU( void );
#define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU()
#endif
/* See the comments under the configUSE_COMMON_INTERRUPT_ENTRY_POINT definition
* below. */
BaseType_t xPortRegisterCInterruptHandler( ISR_Handler_t pxHandler,
uint32_t ulVectorNumber );
BaseType_t xPortInstallInterruptHandler( ISR_Handler_t pxHandler,
uint32_t ulVectorNumber );
#ifndef configAPIC_BASE
/* configAPIC_BASE_ADDRESS sets the base address of the local APIC. It can
* be overridden in FreeRTOSConfig.h should it not be constant. */
#define configAPIC_BASE 0xFEE00000UL
#endif
#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION
/* The FreeRTOS scheduling algorithm selects the task that will enter the
* Running state. configUSE_PORT_OPTIMISED_TASK_SELECTION is used to set how
* that is done.
*
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 0 then the task to
* enter the Running state is selected using a portable algorithm written in
* C. This is the slowest method, but the algorithm does not restrict the
* maximum number of unique RTOS task priorities that are available.
*
* If configUSE_PORT_OPTIMISED_TASK_SELECTION is set to 1 then the task to
* enter the Running state is selected using a single assembly instruction.
* This is the fastest method, but restricts the maximum number of unique RTOS
* task priorities to 32 (the same task priority can be assigned to any number
* of RTOS tasks). */
#warning configUSE_PORT_OPTIMISED_TASK_SELECTION was not defined in FreeRTOSConfig.h and has been defaulted to 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#endif
#ifndef configUSE_COMMON_INTERRUPT_ENTRY_POINT
/* There are two ways of implementing interrupt handlers:
*
* 1) As standard C functions -
*
* This method can only be used if configUSE_COMMON_INTERRUPT_ENTRY_POINT
* is set to 1. The C function is installed using
* xPortRegisterCInterruptHandler().
*
* This is the simplest of the two methods but incurs a slightly longer
* interrupt entry time.
*
* 2) By using an assembly stub that wraps the handler in the FreeRTOS
* portFREERTOS_INTERRUPT_ENTRY and portFREERTOS_INTERRUPT_EXIT macros.
*
* This method can always be used. It is slightly more complex than
* method 1 but benefits from a faster interrupt entry time. */
#warning configUSE_COMMON_INTERRUPT_ENTRY_POINT was not defined in FreeRTOSConfig.h and has been defaulted to 1.
#define configUSE_COMMON_INTERRUPT_ENTRY_POINT 1
#endif
#ifndef configISR_STACK_SIZE
/* Interrupt entry code will switch the stack in use to a dedicated system
* stack.
*
* configISR_STACK_SIZE defines the number of 32-bit values that can be stored
* on the system stack, and must be large enough to hold a potentially nested
* interrupt stack frame. */
#error configISR_STACK_SIZE was not defined in FreeRTOSConfig.h.
#endif
#ifndef configMAX_API_CALL_INTERRUPT_PRIORITY
/* Interrupt safe FreeRTOS functions (those that end in "FromISR" must not
* be called from an interrupt that has a priority above that set by
* configMAX_API_CALL_INTERRUPT_PRIORITY. */
#warning configMAX_API_CALL_INTERRUPT_PRIORITY was not defined in FreeRTOSConfig.h and has been defaulted to 10
#define configMAX_API_CALL_INTERRUPT_PRIORITY 10
#endif
#ifndef configSUPPORT_FPU
#warning configSUPPORT_FPU was not defined in FreeRTOSConfig.h and has been defaulted to 0
#define configSUPPORT_FPU 0
#endif
/* The value written to the task priority register to raise the interrupt mask
* to the maximum from which FreeRTOS API calls can be made. */
#define portAPIC_PRIORITY_SHIFT ( 4UL )
#define portAPIC_MAX_SUB_PRIORITY ( 0x0fUL )
#define portMAX_API_CALL_PRIORITY ( ( configMAX_API_CALL_INTERRUPT_PRIORITY << portAPIC_PRIORITY_SHIFT ) | portAPIC_MAX_SUB_PRIORITY )
/* Asserts if interrupt safe FreeRTOS functions are called from a priority
* above the max system call interrupt priority. */
#define portAPIC_PROCESSOR_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xA0UL ) ) )
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( portAPIC_PROCESSOR_PRIORITY ) <= ( portMAX_API_CALL_PRIORITY ) )
/* *INDENT-OFF* */
#ifdef __cplusplus
}
#endif
/* *INDENT-ON* */
#endif /* PORTMACRO_H */