Detect more startup config errors on Cortex M (#832)

Verify that the application has correctly installed PendSV
and SVCall handlers. The application can choose to
disable these checks by setting configCHECK_HANDLER_INSTALLATION
to 0 in their FreeRTOSConfig.h.
This commit is contained in:
Jeff Tenney 2023-12-10 21:57:47 -07:00 committed by GitHub
parent 553caa18ce
commit 30e6b8a5ea
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 1765 additions and 350 deletions

View file

@ -34,10 +34,14 @@
#include "FreeRTOS.h"
#include "task.h"
/* Prototype of all Interrupt Service Routines (ISRs). */
typedef void ( * portISR_t )( void );
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
/* ...then bits in the registers. */
#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
@ -52,6 +56,11 @@
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) 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_SVC ( 11 )
#define portVECTOR_INDEX_PENDSV ( 14 )
/* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
@ -259,6 +268,40 @@ static void prvPortStartFirstTask( void )
*/
BaseType_t xPortStartScheduler( void )
{
/* An application can install FreeRTOS interrupt handlers in one of the
* folllowing ways:
* 1. Direct Routing - Install the functions vPortSVCHandler and
* xPortPendSVHandler 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
* vPortSVCHandler and xPortPendSVHandler 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 ] == vPortSVCHandler );
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
}
#endif /* configCHECK_HANDLER_INSTALLATION */
#if ( configASSERT_DEFINED == 1 )
{
volatile uint8_t ucOriginalPriority;
@ -343,9 +386,11 @@ BaseType_t xPortStartScheduler( void )
}
#endif /* configASSERT_DEFINED */
/* Make PendSV and SysTick the lowest priority interrupts. */
/* 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;
/* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */