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_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 portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#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 portPRIGROUP_SHIFT ( 8UL )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
#define portINITIAL_XPSR ( 0x01000000UL )
/* The systick is a 24-bit counter. */
#define portMAX_24_BIT_NUMBER ( 0xffffffUL )
@ -169,6 +173,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
*/
#if ( configASSERT_DEFINED == 1 )
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;
#endif /* configASSERT_DEFINED */
@ -241,6 +246,7 @@ portBASE_TYPE xPortStartScheduler( void )
{
volatile unsigned long ulOriginalPriority;
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
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. */
ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
priority register. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* 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;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *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
value. */
@ -606,10 +628,13 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
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 );
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */

View file

@ -94,11 +94,15 @@
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#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 portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#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 portPRIGROUP_SHIFT ( 8UL )
/* Constants required to manipulate the VFP. */
#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 )
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;
#endif /* configASSERT_DEFINED */
@ -259,6 +264,7 @@ portBASE_TYPE xPortStartScheduler( void )
{
volatile unsigned long ulOriginalPriority;
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
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. */
ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
priority register. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* 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;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *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
value. */
@ -656,10 +678,13 @@ static void vPortEnableVFP( void )
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 );
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */

View file

@ -101,7 +101,11 @@
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#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 portPRIGROUP_SHIFT ( 8UL )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
@ -174,6 +178,7 @@ extern void vPortStartFirstTask( void );
*/
#if ( configASSERT_DEFINED == 1 )
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;
#endif /* configASSERT_DEFINED */
@ -209,6 +214,7 @@ portBASE_TYPE xPortStartScheduler( void )
{
volatile unsigned long ulOriginalPriority;
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
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. */
ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
priority register. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* 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;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *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
value. */
@ -508,10 +530,13 @@ __weak void vPortSetupTimerInterrupt( void )
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 );
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */

View file

@ -105,7 +105,11 @@
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#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 portPRIGROUP_SHIFT ( 8UL )
/* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
@ -182,6 +186,7 @@ extern void vPortEnableVFP( void );
*/
#if ( configASSERT_DEFINED == 1 )
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;
#endif /* configASSERT_DEFINED */
@ -229,6 +234,7 @@ portBASE_TYPE xPortStartScheduler( void )
{
volatile unsigned long ulOriginalPriority;
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
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. */
ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
priority register. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* 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;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *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
value. */
@ -534,10 +556,13 @@ __weak void vPortSetupTimerInterrupt( void )
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 );
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */

View file

@ -111,7 +111,11 @@ is defined. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#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 portPRIGROUP_SHIFT ( 8UL )
/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )
@ -182,6 +186,7 @@ static void prvStartFirstTask( void );
*/
#if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */
@ -251,6 +256,7 @@ portBASE_TYPE xPortStartScheduler( void )
{
volatile unsigned long ulOriginalPriority;
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
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. */
ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
priority register. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* 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;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *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
value. */
@ -617,10 +639,13 @@ __asm unsigned long vPortGetIPSR( void )
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 );
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */

View file

@ -111,7 +111,11 @@ is defined. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#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 portPRIGROUP_SHIFT ( 8UL )
/* Constants required to manipulate the VFP. */
#define portFPCCR ( ( volatile unsigned long * ) 0xe000ef34 ) /* Floating point context control register. */
@ -191,6 +195,7 @@ static void prvEnableVFP( void );
*/
#if ( configASSERT_DEFINED == 1 )
static unsigned char ucMaxSysCallPriority = 0;
static unsigned long ulMaxPRIGROUPValue = 0;
static const volatile unsigned char * const pcInterruptPriorityRegisters = ( unsigned char * ) portNVIC_IP_REGISTERS_OFFSET_16;
#endif /* configASSERT_DEFINED */
@ -289,6 +294,7 @@ portBASE_TYPE xPortStartScheduler( void )
{
volatile unsigned long ulOriginalPriority;
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
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. */
ulOriginalPriority = *pcFirstUserPriorityRegister;
/* Write the configMAX_SYSCALL_INTERRUPT_PRIORITY value to an interrupt
priority register. */
*pcFirstUserPriorityRegister = configMAX_SYSCALL_INTERRUPT_PRIORITY;
/* Determine the number of priority bits available. First write to all
possible bits. */
*pcFirstUserPriorityRegister = portMAX_8_BIT_VALUE;
/* 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;
/* Read the value back to see how many bits stuck. */
ucMaxPriorityValue = *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
value. */
@ -680,10 +702,13 @@ __asm unsigned long vPortGetIPSR( void )
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 );
If the application only uses CMSIS libraries for interrupt
configuration then the correct setting can be achieved on all Cortex-M
devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
scheduler. Note however that some vendor specific peripheral libraries
assume a non-zero priority group setting, in which cases using a value
of zero will result in unpredicable behaviour. */
configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
}
#endif /* configASSERT_DEFINED */