Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect more startup config errors on Cortex M #832

Merged
merged 32 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
5f7d21b
Verify installation of PendSV and SVCall handlers
jefftenney Oct 11, 2023
76814d0
Make sure SVCall uses highest exception priority
jefftenney Oct 11, 2023
6237ca3
Fix style and update comments
jefftenney Oct 12, 2023
b957a08
Make equivalent changes to ARMv8-M
jefftenney Oct 13, 2023
efeba96
uncrustify
jefftenney Oct 13, 2023
8fcb11f
match style of parenthesis usage
jefftenney Oct 13, 2023
f8565bc
change vectorTable to pxVectorTable
jefftenney Oct 13, 2023
77b5aa7
Fix typo in address of SHPR2 register
jefftenney Oct 13, 2023
cbe473a
Make equivalent changes to ARMv6-M
jefftenney Oct 13, 2023
f8b89fa
Revert check of SVC handler installation on CM0
jefftenney Oct 16, 2023
5c08b83
Update preexisting comment about not resetting MSP
jefftenney Oct 16, 2023
fde7256
Add configCHECK_HANDLER_INSTALLATION
jefftenney Oct 16, 2023
5d3726f
clean up whitespace
jefftenney Oct 16, 2023
1c76d0a
Merge branch 'upstream/main' into detect-startup-config-errors
jefftenney Oct 16, 2023
830957d
Add comment on configCHECK_HANDLER_INSTALLATION
jefftenney Oct 17, 2023
a7588dc
Add closing #endif (oops)
jefftenney Oct 19, 2023
519d77a
Merge branch 'main' into detect-startup-config-errors
jefftenney Oct 19, 2023
4c8ba4a
Replicate to all Cortex M ports for GCC and IAR
jefftenney Oct 23, 2023
132cabb
Merge branch 'main' into detect-startup-config-errors
jefftenney Oct 23, 2023
9f58ab6
Move macro check to FreeRTOS.h and simplify
jefftenney Oct 25, 2023
84b6981
Replicate to Cortex-M7 r0p1
jefftenney Oct 25, 2023
869f78e
uncrustify
jefftenney Oct 25, 2023
2e6494b
Set SVC priority to zero in ARMv7-M MPU ports
jefftenney Oct 26, 2023
cf85238
Merge branch 'main' into detect-startup-config-errors
kar-rahul-aws Nov 3, 2023
c0f32ba
Merge branch 'main' into detect-startup-config-errors
kar-rahul-aws Nov 7, 2023
7dffde2
Merge branch 'main' into detect-startup-config-errors
aggarg Nov 14, 2023
58b6171
Merge branch 'main' into detect-startup-config-errors
kar-rahul-aws Nov 29, 2023
746010f
Merge branch 'main' into detect-startup-config-errors
chinglee-iot Dec 6, 2023
79cb92a
Merge branch 'main' into detect-startup-config-errors
aggarg Dec 9, 2023
cdf8cc5
Update comments
aggarg Dec 9, 2023
eb825c9
Fix build errors
aggarg Dec 9, 2023
53cfc6d
Fix formatting
aggarg Dec 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions include/FreeRTOS.h
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,17 @@
#define configPRECONDITION_DEFINED 1
#endif

#ifndef configCHECK_HANDLER_INSTALLATION
#define configCHECK_HANDLER_INSTALLATION 1
#else

/* The application has explicitly defined configCHECK_HANDLER_INSTALLATION
* to 1. The checks requires configASSERT() to be defined. */
#if ( ( configCHECK_HANDLER_INSTALLATION == 1 ) && ( configASSERT_DEFINED == 0 ) )
#error You must define configASSERT() when configCHECK_HANDLER_INSTALLATION is 1.
#endif
#endif

#ifndef portMEMORY_BARRIER
#define portMEMORY_BARRIER()
#endif
Expand Down
71 changes: 56 additions & 15 deletions portable/ARMv8M/non_secure/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@
#endif
/*-----------------------------------------------------------*/

/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/

/**
* @brief Constants required to manipulate the NVIC.
*/
Expand All @@ -101,10 +107,18 @@
/**
* @brief Constants required to manipulate the SCB.
*/
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/

/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/

/**
* @brief Constants required to check the validity of an interrupt priority.
*/
Expand Down Expand Up @@ -1598,22 +1612,52 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO

BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
urutva marked this conversation as resolved.
Show resolved Hide resolved
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;

/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */

#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue;

/* 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
* 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 = portNVIC_SHPR2_REG;

/* Determine the number of priority bits available. First write to all
* possible bits. */
* First, determine the number of priority bits available. Write to all
* possible bits in the priority setting for SVCall. */
portNVIC_SHPR2_REG = 0xFF000000;

/* Read the value back to see how many bits stuck. */
Expand All @@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */

/* Calculate the maximum acceptable priority group value for the number
* of bits read back. */

while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulImplementedPrioBits++;
Expand Down Expand Up @@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;

/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
}
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */

/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
/* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;

#if ( configENABLE_MPU == 1 )
{
Expand Down
58 changes: 50 additions & 8 deletions portable/GCC/ARM_CM0/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
#include "FreeRTOS.h"
#include "task.h"

/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
aggarg marked this conversation as resolved.
Show resolved Hide resolved

/* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
Expand All @@ -51,6 +54,10 @@
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )

/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portVECTOR_INDEX_PENDSV ( 14 )

/* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 )

Expand Down Expand Up @@ -200,20 +207,20 @@ void vPortSVCHandler( void )

void vPortStartFirstTask( void )
{
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
* table offset register that can be used to locate the initial stack value.
* Not all M0 parts have the application vector table at address 0. */
/* Don't reset the MSP stack as is done on CM3/4 devices. The vector table
* in some CM0 devices cannot be modified and thus may not hold the
* application's initial MSP value. */
__asm volatile (
" .syntax unified \n"
" ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */
" ldr r3, [r2] \n"
" ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" adds r0, #32 \n" /* Discard everything up to r0. */
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
" adds r0, #32 \n" /* Discard everything up to r0. */
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
" movs r0, #2 \n" /* Switch to the psp stack. */
" msr CONTROL, r0 \n"
" msr CONTROL, r0 \n"
" isb \n"
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
" mov lr, r5 \n" /* lr is now in r5. */
" pop {r3} \n" /* Return address is now in r3. */
" pop {r2} \n" /* Pop and discard XPSR. */
Expand All @@ -231,7 +238,42 @@ void vPortStartFirstTask( void )
*/
BaseType_t xPortStartScheduler( void )
{
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the function xPortPendSVHandler for PendSV
* interrupt.
* 2. Indirect Routing - Install separate handler for PendSV interrupt and
* route program control from that handler to xPortPendSVHandler function.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
/* Point pxVectorTable to the interrupt vector table. Systems without
* a VTOR register provide the value zero in the VTOR register and
* the vector table itself is located at the address 0x00000000. */
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;

/* Validate that the application has correctly installed the FreeRTOS
* handler for PendSV interrupt. We do not check the installation of the
* SysTick handler because the application may choose to drive the RTOS
* tick using a timer other than the SysTick timer by overriding the
* weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handler. For help installing the FreeRTOS handler, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */

/* Make PendSV and SysTick the lowest priority interrupts. */
urutva marked this conversation as resolved.
Show resolved Hide resolved
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;

Expand Down
71 changes: 56 additions & 15 deletions portable/GCC/ARM_CM23/non_secure/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@
#endif
/*-----------------------------------------------------------*/

/**
* @brief Prototype of all Interrupt Service Routines (ISRs).
*/
typedef void ( * portISR_t )( void );
/*-----------------------------------------------------------*/

/**
* @brief Constants required to manipulate the NVIC.
*/
Expand All @@ -101,10 +107,18 @@
/**
* @brief Constants required to manipulate the SCB.
*/
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
/*-----------------------------------------------------------*/

/**
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
*/
#define portVECTOR_INDEX_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/*-----------------------------------------------------------*/

/**
* @brief Constants required to check the validity of an interrupt priority.
*/
Expand Down Expand Up @@ -1598,22 +1612,52 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO

BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
{
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
* for SVCall and PendSV interrupts respectively.
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
* interrupts and route program control from those handlers to
* SVC_Handler and PendSV_Handler functions.
*
* Applications that use Indirect Routing must set
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
* is 1, should be preferred when possible. */
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
{
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;

/* Validate that the application has correctly installed the FreeRTOS
* handlers for SVCall and PendSV interrupts. We do not check the
* installation of the SysTick handler because the application may
* choose to drive the RTOS tick using a timer other than the SysTick
* timer by overriding the weak function vPortSetupTimerInterrupt().
*
* Assertion failures here indicate incorrect installation of the
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
* https://www.FreeRTOS.org/FAQHelp.html.
*
* Systems with a configurable address for the interrupt vector table
* can also encounter assertion failures or even system faults here if
* VTOR is not set correctly to point to the application's vector table. */
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */

#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
{
volatile uint32_t ulOriginalPriority;
volatile uint32_t ulImplementedPrioBits = 0;
volatile uint8_t ucMaxPriorityValue;

/* 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
* 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 = portNVIC_SHPR2_REG;

/* Determine the number of priority bits available. First write to all
* possible bits. */
* First, determine the number of priority bits available. Write to all
* possible bits in the priority setting for SVCall. */
portNVIC_SHPR2_REG = 0xFF000000;

/* Read the value back to see how many bits stuck. */
Expand All @@ -1636,7 +1680,6 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */

/* Calculate the maximum acceptable priority group value for the number
* of bits read back. */

while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
{
ulImplementedPrioBits++;
Expand Down Expand Up @@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
* register. */
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;

/* Restore the clobbered interrupt priority register to its original
* value. */
portNVIC_SHPR2_REG = ulOriginalPriority;
}
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */

/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
/* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
* the highest priority. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
portNVIC_SHPR2_REG = 0;

#if ( configENABLE_MPU == 1 )
{
Expand Down
Loading
Loading