mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-20 05:21:59 -04:00
Added portASSERT_IF_INTERRUPT_PRIORITY_INVALID() implementation to Cortex-M3 and Cortex-M4F ports.
This commit is contained in:
parent
b521d70e7e
commit
c4eef61d39
|
@ -229,6 +229,9 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
|
||||||
|
|
||||||
#ifndef configASSERT
|
#ifndef configASSERT
|
||||||
#define configASSERT( x )
|
#define configASSERT( x )
|
||||||
|
#define configASSERT_DEFINED 0
|
||||||
|
#else
|
||||||
|
#define configASSERT_DEFINED 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The timers module relies on xTaskGetSchedulerState(). */
|
/* The timers module relies on xTaskGetSchedulerState(). */
|
||||||
|
@ -592,6 +595,10 @@ typedef portBASE_TYPE (*pdTASK_HOOK_CODE)( void * );
|
||||||
#define configINCLUDE_STATS_FORMATTING_FUNCTIONS 0
|
#define configINCLUDE_STATS_FORMATTING_FUNCTIONS 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* For backward compatability. */
|
/* For backward compatability. */
|
||||||
#define eTaskStateGet eTaskGetState
|
#define eTaskStateGet eTaskGetState
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,12 @@ FreeRTOS.org versions prior to V4.4.0 did not include this definition. */
|
||||||
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt prority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
|
||||||
/* Constants required to set up the initial stack. */
|
/* Constants required to set up the initial stack. */
|
||||||
#define portINITIAL_XPSR ( 0x01000000 )
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
@ -166,6 +172,16 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
|
||||||
static unsigned long ulStoppedTimerCompensation = 0;
|
static unsigned long ulStoppedTimerCompensation = 0;
|
||||||
#endif /* configUSE_TICKLESS_IDLE */
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static unsigned char ucMaxSysCallPriority = 0;
|
||||||
|
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -231,6 +247,33 @@ portBASE_TYPE xPortStartScheduler( void )
|
||||||
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 );
|
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile unsigned long ulOriginalPriority;
|
||||||
|
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
|
||||||
|
priority register. */
|
||||||
|
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Read back the written priority to obtain its value as seen by the
|
||||||
|
hardware, which will only implement a subset of the priority bits. */
|
||||||
|
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pcFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
@ -523,4 +566,81 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
|
||||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
unsigned long ulCurrentInterrupt;
|
||||||
|
unsigned char ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
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 CMSIS libraries are being used then the correct setting can be
|
||||||
|
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,13 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#else
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,12 @@
|
||||||
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt prority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
|
||||||
/* Constants required to manipulate the VFP. */
|
/* Constants required to manipulate the VFP. */
|
||||||
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
|
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||||
|
@ -173,6 +179,16 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
|
||||||
static unsigned long ulStoppedTimerCompensation = 0;
|
static unsigned long ulStoppedTimerCompensation = 0;
|
||||||
#endif /* configUSE_TICKLESS_IDLE */
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static unsigned char ucMaxSysCallPriority = 0;
|
||||||
|
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -249,6 +265,33 @@ portBASE_TYPE xPortStartScheduler( void )
|
||||||
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 );
|
configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY );
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile unsigned long ulOriginalPriority;
|
||||||
|
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
|
||||||
|
priority register. */
|
||||||
|
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Read back the written priority to obtain its value as seen by the
|
||||||
|
hardware, which will only implement a subset of the priority bits. */
|
||||||
|
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pcFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
@ -572,4 +615,63 @@ static void vPortEnableVFP( void )
|
||||||
" bx r14 "
|
" bx r14 "
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
unsigned long ulCurrentInterrupt;
|
||||||
|
unsigned char ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
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 CMSIS libraries are being used then the correct setting can be
|
||||||
|
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -181,6 +181,13 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#else
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,12 @@
|
||||||
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt prority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
|
||||||
/* Constants required to set up the initial stack. */
|
/* Constants required to set up the initial stack. */
|
||||||
#define portINITIAL_XPSR ( 0x01000000 )
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
@ -171,6 +177,16 @@ extern void vPortStartFirstTask( void );
|
||||||
static unsigned long ulStoppedTimerCompensation = 0;
|
static unsigned long ulStoppedTimerCompensation = 0;
|
||||||
#endif /* configUSE_TICKLESS_IDLE */
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static unsigned char ucMaxSysCallPriority = 0;
|
||||||
|
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -199,6 +215,33 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
|
||||||
*/
|
*/
|
||||||
portBASE_TYPE xPortStartScheduler( void )
|
portBASE_TYPE xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile unsigned long ulOriginalPriority;
|
||||||
|
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
|
||||||
|
priority register. */
|
||||||
|
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Read back the written priority to obtain its value as seen by the
|
||||||
|
hardware, which will only implement a subset of the priority bits. */
|
||||||
|
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pcFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
@ -425,4 +468,81 @@ __weak void vPortSetupTimerInterrupt( void )
|
||||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
unsigned long ulCurrentInterrupt;
|
||||||
|
unsigned char ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
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 CMSIS libraries are being used then the correct setting can be
|
||||||
|
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,13 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#else
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,12 @@
|
||||||
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt prority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
|
||||||
/* Constants required to manipulate the VFP. */
|
/* Constants required to manipulate the VFP. */
|
||||||
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
|
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||||
|
@ -179,6 +185,16 @@ extern void vPortEnableVFP( void );
|
||||||
static unsigned long ulStoppedTimerCompensation = 0;
|
static unsigned long ulStoppedTimerCompensation = 0;
|
||||||
#endif /* configUSE_TICKLESS_IDLE */
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static unsigned char ucMaxSysCallPriority = 0;
|
||||||
|
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -219,6 +235,33 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
|
||||||
*/
|
*/
|
||||||
portBASE_TYPE xPortStartScheduler( void )
|
portBASE_TYPE xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile unsigned long ulOriginalPriority;
|
||||||
|
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
|
||||||
|
priority register. */
|
||||||
|
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Read back the written priority to obtain its value as seen by the
|
||||||
|
hardware, which will only implement a subset of the priority bits. */
|
||||||
|
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pcFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
@ -451,4 +494,81 @@ __weak void vPortSetupTimerInterrupt( void )
|
||||||
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
unsigned long ulCurrentInterrupt;
|
||||||
|
unsigned char ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
__asm volatile( "mrs %0, ipsr" : "=r"( ulCurrentInterrupt ) );
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
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 CMSIS libraries are being used then the correct setting can be
|
||||||
|
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -172,6 +172,13 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#else
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,12 @@ is defined. */
|
||||||
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt prority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
|
||||||
/* Constants required to set up the initial stack. */
|
/* Constants required to set up the initial stack. */
|
||||||
#define portINITIAL_XPSR ( 0x01000000 )
|
#define portINITIAL_XPSR ( 0x01000000 )
|
||||||
|
|
||||||
|
@ -179,6 +185,16 @@ static void prvStartFirstTask( void );
|
||||||
static unsigned long ulStoppedTimerCompensation = 0;
|
static unsigned long ulStoppedTimerCompensation = 0;
|
||||||
#endif /* configUSE_TICKLESS_IDLE */
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static unsigned char ucMaxSysCallPriority = 0;
|
||||||
|
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -241,6 +257,33 @@ __asm void prvStartFirstTask( void )
|
||||||
*/
|
*/
|
||||||
portBASE_TYPE xPortStartScheduler( void )
|
portBASE_TYPE xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile unsigned long ulOriginalPriority;
|
||||||
|
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
|
||||||
|
priority register. */
|
||||||
|
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Read back the written priority to obtain its value as seen by the
|
||||||
|
hardware, which will only implement a subset of the priority bits. */
|
||||||
|
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pcFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
@ -524,3 +567,72 @@ __asm void vPortClearInterruptMask( unsigned long ulNewMask )
|
||||||
msr basepri, r0
|
msr basepri, r0
|
||||||
bx r14
|
bx r14
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm unsigned long vPortGetIPSR( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, ipsr
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
unsigned long ulCurrentInterrupt;
|
||||||
|
unsigned char ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
ulCurrentInterrupt = vPortGetIPSR();
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Numerically low interrupt priority numbers represent logically high
|
||||||
|
interrupt priorities, therefore the priority of the interrupt must
|
||||||
|
be set to a value equal to or numerically *higher* than
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Interrupts that use the FreeRTOS API must not be left at their
|
||||||
|
default priority of zero as that is the highest possible priority,
|
||||||
|
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
|
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
|
interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
The following links provide detailed information:
|
||||||
|
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
|
http://www.freertos.org/FAQHelp.html */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
that define each interrupt's priority to be split between bits that
|
||||||
|
define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
|
If CMSIS libraries are being used then the correct setting can be
|
||||||
|
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,13 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#else
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,12 @@ is defined. */
|
||||||
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
|
||||||
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
|
||||||
|
|
||||||
|
/* Constants required to check the validity of an interrupt prority. */
|
||||||
|
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
|
||||||
|
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
|
||||||
|
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
|
||||||
|
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
|
||||||
|
|
||||||
/* Constants required to manipulate the VFP. */
|
/* Constants required to manipulate the VFP. */
|
||||||
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
|
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
|
||||||
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL )
|
||||||
|
@ -188,6 +194,16 @@ static void prvEnableVFP( void );
|
||||||
static unsigned long ulStoppedTimerCompensation = 0;
|
static unsigned long ulStoppedTimerCompensation = 0;
|
||||||
#endif /* configUSE_TICKLESS_IDLE */
|
#endif /* configUSE_TICKLESS_IDLE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
|
||||||
|
* FreeRTOS API functions are not called from interrupts that have been assigned
|
||||||
|
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
*/
|
||||||
|
#if ( configASSERT_DEFINED == 1 )
|
||||||
|
static unsigned char ucMaxSysCallPriority = 0;
|
||||||
|
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -279,6 +295,33 @@ __asm void prvEnableVFP( void )
|
||||||
*/
|
*/
|
||||||
portBASE_TYPE xPortStartScheduler( void )
|
portBASE_TYPE xPortStartScheduler( void )
|
||||||
{
|
{
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
{
|
||||||
|
volatile unsigned long ulOriginalPriority;
|
||||||
|
volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
|
||||||
|
|
||||||
|
/* Determine the maximum priority from which ISR safe FreeRTOS API
|
||||||
|
functions can be called. ISR safe functions are those that end in
|
||||||
|
"FromISR". FreeRTOS maintains separate thread and ISR API functions to
|
||||||
|
ensure interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
Save the interrupt priority value that is about to be clobbered. */
|
||||||
|
ulOriginalPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
|
||||||
|
priority register. */
|
||||||
|
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
|
||||||
|
|
||||||
|
/* Read back the written priority to obtain its value as seen by the
|
||||||
|
hardware, which will only implement a subset of the priority bits. */
|
||||||
|
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
|
||||||
|
|
||||||
|
/* Restore the clobbered interrupt priority register to its original
|
||||||
|
value. */
|
||||||
|
*pcFirstUserPriorityRegister = ulOriginalPriority;
|
||||||
|
}
|
||||||
|
#endif /* conifgASSERT_DEFINED */
|
||||||
|
|
||||||
/* Make PendSV and SysTick the lowest priority interrupts. */
|
/* Make PendSV and SysTick the lowest priority interrupts. */
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI;
|
||||||
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI;
|
||||||
|
@ -587,3 +630,72 @@ __asm void vPortClearInterruptMask( unsigned long ulNewMask )
|
||||||
msr basepri, r0
|
msr basepri, r0
|
||||||
bx r14
|
bx r14
|
||||||
}
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
__asm unsigned long vPortGetIPSR( void )
|
||||||
|
{
|
||||||
|
PRESERVE8
|
||||||
|
|
||||||
|
mrs r0, ipsr
|
||||||
|
bx r14
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if( configASSERT_DEFINED == 1 )
|
||||||
|
|
||||||
|
void vPortValidateInterruptPriority( void )
|
||||||
|
{
|
||||||
|
unsigned long ulCurrentInterrupt;
|
||||||
|
unsigned char ucCurrentPriority;
|
||||||
|
|
||||||
|
/* Obtain the number of the currently executing interrupt. */
|
||||||
|
ulCurrentInterrupt = vPortGetIPSR();
|
||||||
|
|
||||||
|
/* Is the interrupt number a user defined interrupt? */
|
||||||
|
if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
|
||||||
|
{
|
||||||
|
/* Look up the interrupt's priority. */
|
||||||
|
ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
|
||||||
|
|
||||||
|
/* The following assertion will fail if a service routine (ISR) for
|
||||||
|
an interrupt that has been assigned a priority above
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
|
||||||
|
function. ISR safe FreeRTOS API functions must *only* be called
|
||||||
|
from interrupts that have been assigned a priority at or below
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Numerically low interrupt priority numbers represent logically high
|
||||||
|
interrupt priorities, therefore the priority of the interrupt must
|
||||||
|
be set to a value equal to or numerically *higher* than
|
||||||
|
configMAX_SYSCALL_INTERRUPT_PRIORITY.
|
||||||
|
|
||||||
|
Interrupts that use the FreeRTOS API must not be left at their
|
||||||
|
default priority of zero as that is the highest possible priority,
|
||||||
|
which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
|
||||||
|
and therefore also guaranteed to be invalid.
|
||||||
|
|
||||||
|
FreeRTOS maintains separate thread and ISR API functions to ensure
|
||||||
|
interrupt entry is as fast and simple as possible.
|
||||||
|
|
||||||
|
The following links provide detailed information:
|
||||||
|
http://www.freertos.org/RTOS-Cortex-M3-M4.html
|
||||||
|
http://www.freertos.org/FAQHelp.html */
|
||||||
|
configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Priority grouping: The interrupt controller (NVIC) allows the bits
|
||||||
|
that define each interrupt's priority to be split between bits that
|
||||||
|
define the interrupt's pre-emption priority bits and bits that define
|
||||||
|
the interrupt's sub-priority. For simplicity all bits must be defined
|
||||||
|
to be pre-emption priority bits. The following assertion will fail if
|
||||||
|
this is not the case (if some bits represent a sub-priority).
|
||||||
|
|
||||||
|
If CMSIS libraries are being used then the correct setting can be
|
||||||
|
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the
|
||||||
|
scheduler. */
|
||||||
|
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* configASSERT_DEFINED */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -171,6 +171,13 @@ not necessary for to use this port. They are defined so the common demo files
|
||||||
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifdef configASSERT
|
||||||
|
void vPortValidateInterruptPriority( void );
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority()
|
||||||
|
#else
|
||||||
|
#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID()
|
||||||
|
#endif
|
||||||
|
|
||||||
/* portNOP() is not required by this port. */
|
/* portNOP() is not required by this port. */
|
||||||
#define portNOP()
|
#define portNOP()
|
||||||
|
|
||||||
|
|
|
@ -940,6 +940,7 @@ xQUEUE *pxQueue;
|
||||||
configASSERT( pxQueue );
|
configASSERT( pxQueue );
|
||||||
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||||
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
|
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
|
||||||
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||||
|
|
||||||
/* Similar to xQueueGenericSend, except we don't block if there is no room
|
/* Similar to xQueueGenericSend, except we don't block if there is no room
|
||||||
in the queue. Also we don't directly wake a task that was blocked on a
|
in the queue. Also we don't directly wake a task that was blocked on a
|
||||||
|
@ -1188,6 +1189,7 @@ xQUEUE *pxQueue;
|
||||||
pxQueue = ( xQUEUE * ) xQueue;
|
pxQueue = ( xQUEUE * ) xQueue;
|
||||||
configASSERT( pxQueue );
|
configASSERT( pxQueue );
|
||||||
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||||
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||||
|
|
||||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
{
|
{
|
||||||
|
@ -1249,6 +1251,7 @@ xQUEUE *pxQueue;
|
||||||
pxQueue = ( xQUEUE * ) xQueue;
|
pxQueue = ( xQUEUE * ) xQueue;
|
||||||
configASSERT( pxQueue );
|
configASSERT( pxQueue );
|
||||||
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( unsigned portBASE_TYPE ) 0U ) ) );
|
||||||
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||||
|
|
||||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
{
|
{
|
||||||
|
|
|
@ -1176,6 +1176,7 @@ tskTCB * pxNewTCB;
|
||||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||||
|
|
||||||
configASSERT( xTaskToResume );
|
configASSERT( xTaskToResume );
|
||||||
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||||
|
|
||||||
pxTCB = ( tskTCB * ) xTaskToResume;
|
pxTCB = ( tskTCB * ) xTaskToResume;
|
||||||
|
|
||||||
|
@ -1414,6 +1415,8 @@ portTickType xTaskGetTickCountFromISR( void )
|
||||||
portTickType xReturn;
|
portTickType xReturn;
|
||||||
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
unsigned portBASE_TYPE uxSavedInterruptStatus;
|
||||||
|
|
||||||
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||||
|
|
||||||
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
xReturn = xTickCount;
|
xReturn = xTickCount;
|
||||||
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
|
||||||
|
|
Loading…
Reference in a new issue