Update the Cortex-M vPortValidateInterruptPriority() implementation to ensure compatibility with the STM32 standard peripheral library.

This commit is contained in:
Richard Barry 2013-07-23 09:44:00 +00:00
parent f522d6a2da
commit 679a3c670c
6 changed files with 311 additions and 161 deletions

View file

@ -97,14 +97,18 @@ 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. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 8UL )
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000UL )
/* The systick is a 24-bit counter. */ /* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
@ -169,6 +173,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
@ -241,6 +246,7 @@ portBASE_TYPE xPortStartScheduler( void )
{ {
volatile unsigned long ulOriginalPriority; volatile unsigned long ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in functions can be called. ISR safe functions are those that end in
@ -250,13 +256,29 @@ portBASE_TYPE xPortStartScheduler( void )
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pcFirstUserPriorityRegister; ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt /* Determine the number of priority bits available. First write to all
priority register. */ possible bits. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY; *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read back the written priority to obtain its value as seen by the /* Read the value back to see how many bits stuck. */
hardware, which will only implement a subset of the priority bits. */ ucMaxPriorityValue = *pcFirstUserPriorityRegister;
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01;
}
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
@ -606,10 +628,13 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
If CMSIS libraries are being used then the correct setting can be If the application only uses CMSIS libraries for interrupt
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the configuration then the correct setting can be achieved on all Cortex-M
scheduler. */ devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 ); scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -94,11 +94,15 @@
#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. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 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. */
@ -176,6 +180,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
@ -259,6 +264,7 @@ portBASE_TYPE xPortStartScheduler( void )
{ {
volatile unsigned long ulOriginalPriority; volatile unsigned long ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in functions can be called. ISR safe functions are those that end in
@ -268,13 +274,29 @@ portBASE_TYPE xPortStartScheduler( void )
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pcFirstUserPriorityRegister; ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt /* Determine the number of priority bits available. First write to all
priority register. */ possible bits. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY; *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read back the written priority to obtain its value as seen by the /* Read the value back to see how many bits stuck. */
hardware, which will only implement a subset of the priority bits. */ ucMaxPriorityValue = *pcFirstUserPriorityRegister;
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01;
}
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
@ -656,10 +678,13 @@ static void vPortEnableVFP( void )
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
If CMSIS libraries are being used then the correct setting can be If the application only uses CMSIS libraries for interrupt
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the configuration then the correct setting can be achieved on all Cortex-M
scheduler. */ devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 ); scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -101,7 +101,11 @@
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 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 )
@ -174,6 +178,7 @@ extern void vPortStartFirstTask( void );
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
@ -209,6 +214,7 @@ portBASE_TYPE xPortStartScheduler( void )
{ {
volatile unsigned long ulOriginalPriority; volatile unsigned long ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in functions can be called. ISR safe functions are those that end in
@ -218,13 +224,29 @@ portBASE_TYPE xPortStartScheduler( void )
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pcFirstUserPriorityRegister; ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt /* Determine the number of priority bits available. First write to all
priority register. */ possible bits. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY; *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read back the written priority to obtain its value as seen by the /* Read the value back to see how many bits stuck. */
hardware, which will only implement a subset of the priority bits. */ ucMaxPriorityValue = *pcFirstUserPriorityRegister;
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01;
}
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
@ -508,10 +530,13 @@ __weak void vPortSetupTimerInterrupt( void )
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
If CMSIS libraries are being used then the correct setting can be If the application only uses CMSIS libraries for interrupt
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the configuration then the correct setting can be achieved on all Cortex-M
scheduler. */ devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 ); scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -105,7 +105,11 @@
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 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. */
@ -182,6 +186,7 @@ extern void vPortEnableVFP( void );
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile unsigned char * const pcInterruptPriorityRegisters = ( const volatile unsigned char * const ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
@ -229,6 +234,7 @@ portBASE_TYPE xPortStartScheduler( void )
{ {
volatile unsigned long ulOriginalPriority; volatile unsigned long ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile char * const pcFirstUserPriorityRegister = ( volatile char * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in functions can be called. ISR safe functions are those that end in
@ -238,13 +244,29 @@ portBASE_TYPE xPortStartScheduler( void )
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pcFirstUserPriorityRegister; ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt /* Determine the number of priority bits available. First write to all
priority register. */ possible bits. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY; *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read back the written priority to obtain its value as seen by the /* Read the value back to see how many bits stuck. */
hardware, which will only implement a subset of the priority bits. */ ucMaxPriorityValue = *pcFirstUserPriorityRegister;
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01;
}
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
@ -534,10 +556,13 @@ __weak void vPortSetupTimerInterrupt( void )
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
If CMSIS libraries are being used then the correct setting can be If the application only uses CMSIS libraries for interrupt
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the configuration then the correct setting can be achieved on all Cortex-M
scheduler. */ devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 ); scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -111,7 +111,11 @@ is defined. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 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 )
@ -182,6 +186,7 @@ static void prvStartFirstTask( void );
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
@ -251,6 +256,7 @@ portBASE_TYPE xPortStartScheduler( void )
{ {
volatile unsigned long ulOriginalPriority; volatile unsigned long ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in functions can be called. ISR safe functions are those that end in
@ -260,13 +266,29 @@ portBASE_TYPE xPortStartScheduler( void )
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pcFirstUserPriorityRegister; ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt /* Determine the number of priority bits available. First write to all
priority register. */ possible bits. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY; *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read back the written priority to obtain its value as seen by the /* Read the value back to see how many bits stuck. */
hardware, which will only implement a subset of the priority bits. */ ucMaxPriorityValue = *pcFirstUserPriorityRegister;
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01;
}
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
@ -617,10 +639,13 @@ __asm unsigned long vPortGetIPSR( void )
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
If CMSIS libraries are being used then the correct setting can be If the application only uses CMSIS libraries for interrupt
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the configuration then the correct setting can be achieved on all Cortex-M
scheduler. */ devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 ); scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */

View file

@ -111,7 +111,11 @@ is defined. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
#define portMAX_8_BIT_VALUE ( ( unsigned char ) 0xff )
#define portTOP_BIT_OF_BYTE ( ( unsigned char ) 0x80 )
#define portMAX_PRIGROUP_BITS ( ( unsigned char ) 7 )
#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
#define portPRIGROUP_SHIFT ( 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. */
@ -191,6 +195,7 @@ static void prvEnableVFP( void );
*/ */
#if ( configASSERT_DEFINED == 1 ) #if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0; static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16; static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */
@ -289,6 +294,7 @@ portBASE_TYPE xPortStartScheduler( void )
{ {
volatile unsigned long ulOriginalPriority; volatile unsigned long ulOriginalPriority;
volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile char * const pcFirstUserPriorityRegister = ( char * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER );
volatile unsigned char ucMaxPriorityValue;
/* Determine the maximum priority from which ISR safe FreeRTOS API /* Determine the maximum priority from which ISR safe FreeRTOS API
functions can be called. ISR safe functions are those that end in functions can be called. ISR safe functions are those that end in
@ -298,13 +304,29 @@ portBASE_TYPE xPortStartScheduler( void )
Save the interrupt priority value that is about to be clobbered. */ Save the interrupt priority value that is about to be clobbered. */
ulOriginalPriority = *pcFirstUserPriorityRegister; ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt /* Determine the number of priority bits available. First write to all
priority register. */ possible bits. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY; *pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* Read back the written priority to obtain its value as seen by the /* Read the value back to see how many bits stuck. */
hardware, which will only implement a subset of the priority bits. */ ucMaxPriorityValue = *pcFirstUserPriorityRegister;
ucMaxSysCallPriority = *pcFirstUserPriorityRegister;
/* Use the same mask on the maximum system call priority. */
ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
/* Calculate the maximum acceptable priority group value for the number
of bits read back. */
ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS;
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulMaxPRIGROUPValue--;
ucMaxPriorityValue <<= ( unsigned char ) 0x01;
}
/* Shift the priority group value back to its position within the AIRCR
register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
/* Restore the clobbered interrupt priority register to its original /* Restore the clobbered interrupt priority register to its original
value. */ value. */
@ -680,10 +702,13 @@ __asm unsigned long vPortGetIPSR( void )
to be pre-emption priority bits. The following assertion will fail if to be pre-emption priority bits. The following assertion will fail if
this is not the case (if some bits represent a sub-priority). this is not the case (if some bits represent a sub-priority).
If CMSIS libraries are being used then the correct setting can be If the application only uses CMSIS libraries for interrupt
achieved by calling NVIC_SetPriorityGrouping( 0 ); before starting the configuration then the correct setting can be achieved on all Cortex-M
scheduler. */ devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) == 0 ); scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
} }
#endif /* configASSERT_DEFINED */ #endif /* configASSERT_DEFINED */