Skip to content

Commit d27a3b5

Browse files
authored
Merge branch 'main' into feature/add_portTASK_SWITCH_HOOK
2 parents aebfc90 + 30e6b8a commit d27a3b5

File tree

35 files changed

+1765
-350
lines changed

35 files changed

+1765
-350
lines changed

include/FreeRTOS.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,17 @@
365365
#define configPRECONDITION_DEFINED 1
366366
#endif
367367

368+
#ifndef configCHECK_HANDLER_INSTALLATION
369+
#define configCHECK_HANDLER_INSTALLATION 1
370+
#else
371+
372+
/* The application has explicitly defined configCHECK_HANDLER_INSTALLATION
373+
* to 1. The checks requires configASSERT() to be defined. */
374+
#if ( ( configCHECK_HANDLER_INSTALLATION == 1 ) && ( configASSERT_DEFINED == 0 ) )
375+
#error You must define configASSERT() when configCHECK_HANDLER_INSTALLATION is 1.
376+
#endif
377+
#endif
378+
368379
#ifndef portMEMORY_BARRIER
369380
#define portMEMORY_BARRIER()
370381
#endif

portable/ARMv8M/non_secure/port.c

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@
8080
#endif
8181
/*-----------------------------------------------------------*/
8282

83+
/**
84+
* @brief Prototype of all Interrupt Service Routines (ISRs).
85+
*/
86+
typedef void ( * portISR_t )( void );
87+
/*-----------------------------------------------------------*/
88+
8389
/**
8490
* @brief Constants required to manipulate the NVIC.
8591
*/
@@ -101,10 +107,18 @@
101107
/**
102108
* @brief Constants required to manipulate the SCB.
103109
*/
104-
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
110+
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
111+
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
105112
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
106113
/*-----------------------------------------------------------*/
107114

115+
/**
116+
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
117+
*/
118+
#define portVECTOR_INDEX_SVC ( 11 )
119+
#define portVECTOR_INDEX_PENDSV ( 14 )
120+
/*-----------------------------------------------------------*/
121+
108122
/**
109123
* @brief Constants required to check the validity of an interrupt priority.
110124
*/
@@ -1598,22 +1612,52 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
15981612

15991613
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
16001614
{
1615+
/* An application can install FreeRTOS interrupt handlers in one of the
1616+
* folllowing ways:
1617+
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
1618+
* for SVCall and PendSV interrupts respectively.
1619+
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
1620+
* interrupts and route program control from those handlers to
1621+
* SVC_Handler and PendSV_Handler functions.
1622+
*
1623+
* Applications that use Indirect Routing must set
1624+
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
1625+
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
1626+
* is 1, should be preferred when possible. */
1627+
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
1628+
{
1629+
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
1630+
1631+
/* Validate that the application has correctly installed the FreeRTOS
1632+
* handlers for SVCall and PendSV interrupts. We do not check the
1633+
* installation of the SysTick handler because the application may
1634+
* choose to drive the RTOS tick using a timer other than the SysTick
1635+
* timer by overriding the weak function vPortSetupTimerInterrupt().
1636+
*
1637+
* Assertion failures here indicate incorrect installation of the
1638+
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
1639+
* https://www.FreeRTOS.org/FAQHelp.html.
1640+
*
1641+
* Systems with a configurable address for the interrupt vector table
1642+
* can also encounter assertion failures or even system faults here if
1643+
* VTOR is not set correctly to point to the application's vector table. */
1644+
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
1645+
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
1646+
}
1647+
#endif /* configCHECK_HANDLER_INSTALLATION */
1648+
16011649
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
16021650
{
1603-
volatile uint32_t ulOriginalPriority;
16041651
volatile uint32_t ulImplementedPrioBits = 0;
16051652
volatile uint8_t ucMaxPriorityValue;
16061653

16071654
/* Determine the maximum priority from which ISR safe FreeRTOS API
1608-
* functions can be called. ISR safe functions are those that end in
1609-
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
1655+
* functions can be called. ISR safe functions are those that end in
1656+
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
16101657
* ensure interrupt entry is as fast and simple as possible.
16111658
*
1612-
* Save the interrupt priority value that is about to be clobbered. */
1613-
ulOriginalPriority = portNVIC_SHPR2_REG;
1614-
1615-
/* Determine the number of priority bits available. First write to all
1616-
* possible bits. */
1659+
* First, determine the number of priority bits available. Write to all
1660+
* possible bits in the priority setting for SVCall. */
16171661
portNVIC_SHPR2_REG = 0xFF000000;
16181662

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

16371681
/* Calculate the maximum acceptable priority group value for the number
16381682
* of bits read back. */
1639-
16401683
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
16411684
{
16421685
ulImplementedPrioBits++;
@@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
16741717
* register. */
16751718
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
16761719
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
1677-
1678-
/* Restore the clobbered interrupt priority register to its original
1679-
* value. */
1680-
portNVIC_SHPR2_REG = ulOriginalPriority;
16811720
}
16821721
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
16831722

1684-
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
1723+
/* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
1724+
* the highest priority. */
16851725
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
16861726
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
1727+
portNVIC_SHPR2_REG = 0;
16871728

16881729
#if ( configENABLE_MPU == 1 )
16891730
{

portable/GCC/ARM_CM0/port.c

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#include "FreeRTOS.h"
3535
#include "task.h"
3636

37+
/* Prototype of all Interrupt Service Routines (ISRs). */
38+
typedef void ( * portISR_t )( void );
39+
3740
/* Constants required to manipulate the NVIC. */
3841
#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
3942
#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
@@ -51,6 +54,10 @@
5154
#define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
5255
#define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
5356

57+
/* Constants used to check the installation of the FreeRTOS interrupt handlers. */
58+
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
59+
#define portVECTOR_INDEX_PENDSV ( 14 )
60+
5461
/* Constants required to set up the initial stack. */
5562
#define portINITIAL_XPSR ( 0x01000000 )
5663

@@ -200,20 +207,20 @@ void vPortSVCHandler( void )
200207

201208
void vPortStartFirstTask( void )
202209
{
203-
/* The MSP stack is not reset as, unlike on M3/4 parts, there is no vector
204-
* table offset register that can be used to locate the initial stack value.
205-
* Not all M0 parts have the application vector table at address 0. */
210+
/* Don't reset the MSP stack as is done on CM3/4 devices. The vector table
211+
* in some CM0 devices cannot be modified and thus may not hold the
212+
* application's initial MSP value. */
206213
__asm volatile (
207214
" .syntax unified \n"
208215
" ldr r2, pxCurrentTCBConst2 \n" /* Obtain location of pxCurrentTCB. */
209216
" ldr r3, [r2] \n"
210217
" ldr r0, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */
211-
" adds r0, #32 \n" /* Discard everything up to r0. */
212-
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
218+
" adds r0, #32 \n" /* Discard everything up to r0. */
219+
" msr psp, r0 \n" /* This is now the new top of stack to use in the task. */
213220
" movs r0, #2 \n" /* Switch to the psp stack. */
214-
" msr CONTROL, r0 \n"
221+
" msr CONTROL, r0 \n"
215222
" isb \n"
216-
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
223+
" pop {r0-r5} \n" /* Pop the registers that are saved automatically. */
217224
" mov lr, r5 \n" /* lr is now in r5. */
218225
" pop {r3} \n" /* Return address is now in r3. */
219226
" pop {r2} \n" /* Pop and discard XPSR. */
@@ -231,7 +238,42 @@ void vPortStartFirstTask( void )
231238
*/
232239
BaseType_t xPortStartScheduler( void )
233240
{
234-
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
241+
/* An application can install FreeRTOS interrupt handlers in one of the
242+
* folllowing ways:
243+
* 1. Direct Routing - Install the function xPortPendSVHandler for PendSV
244+
* interrupt.
245+
* 2. Indirect Routing - Install separate handler for PendSV interrupt and
246+
* route program control from that handler to xPortPendSVHandler function.
247+
*
248+
* Applications that use Indirect Routing must set
249+
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
250+
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
251+
* is 1, should be preferred when possible. */
252+
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
253+
{
254+
/* Point pxVectorTable to the interrupt vector table. Systems without
255+
* a VTOR register provide the value zero in the VTOR register and
256+
* the vector table itself is located at the address 0x00000000. */
257+
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
258+
259+
/* Validate that the application has correctly installed the FreeRTOS
260+
* handler for PendSV interrupt. We do not check the installation of the
261+
* SysTick handler because the application may choose to drive the RTOS
262+
* tick using a timer other than the SysTick timer by overriding the
263+
* weak function vPortSetupTimerInterrupt().
264+
*
265+
* Assertion failures here indicate incorrect installation of the
266+
* FreeRTOS handler. For help installing the FreeRTOS handler, see
267+
* https://www.FreeRTOS.org/FAQHelp.html.
268+
*
269+
* Systems with a configurable address for the interrupt vector table
270+
* can also encounter assertion failures or even system faults here if
271+
* VTOR is not set correctly to point to the application's vector table. */
272+
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == xPortPendSVHandler );
273+
}
274+
#endif /* configCHECK_HANDLER_INSTALLATION */
275+
276+
/* Make PendSV and SysTick the lowest priority interrupts. */
235277
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
236278
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
237279

portable/GCC/ARM_CM23/non_secure/port.c

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@
8080
#endif
8181
/*-----------------------------------------------------------*/
8282

83+
/**
84+
* @brief Prototype of all Interrupt Service Routines (ISRs).
85+
*/
86+
typedef void ( * portISR_t )( void );
87+
/*-----------------------------------------------------------*/
88+
8389
/**
8490
* @brief Constants required to manipulate the NVIC.
8591
*/
@@ -101,10 +107,18 @@
101107
/**
102108
* @brief Constants required to manipulate the SCB.
103109
*/
104-
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( volatile uint32_t * ) 0xe000ed24 )
110+
#define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
111+
#define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
105112
#define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
106113
/*-----------------------------------------------------------*/
107114

115+
/**
116+
* @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
117+
*/
118+
#define portVECTOR_INDEX_SVC ( 11 )
119+
#define portVECTOR_INDEX_PENDSV ( 14 )
120+
/*-----------------------------------------------------------*/
121+
108122
/**
109123
* @brief Constants required to check the validity of an interrupt priority.
110124
*/
@@ -1598,22 +1612,52 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO
15981612

15991613
BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
16001614
{
1615+
/* An application can install FreeRTOS interrupt handlers in one of the
1616+
* folllowing ways:
1617+
* 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
1618+
* for SVCall and PendSV interrupts respectively.
1619+
* 2. Indirect Routing - Install separate handlers for SVCall and PendSV
1620+
* interrupts and route program control from those handlers to
1621+
* SVC_Handler and PendSV_Handler functions.
1622+
*
1623+
* Applications that use Indirect Routing must set
1624+
* configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
1625+
* routing, which is validated here when configCHECK_HANDLER_INSTALLATION
1626+
* is 1, should be preferred when possible. */
1627+
#if ( configCHECK_HANDLER_INSTALLATION == 1 )
1628+
{
1629+
const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
1630+
1631+
/* Validate that the application has correctly installed the FreeRTOS
1632+
* handlers for SVCall and PendSV interrupts. We do not check the
1633+
* installation of the SysTick handler because the application may
1634+
* choose to drive the RTOS tick using a timer other than the SysTick
1635+
* timer by overriding the weak function vPortSetupTimerInterrupt().
1636+
*
1637+
* Assertion failures here indicate incorrect installation of the
1638+
* FreeRTOS handlers. For help installing the FreeRTOS handlers, see
1639+
* https://www.FreeRTOS.org/FAQHelp.html.
1640+
*
1641+
* Systems with a configurable address for the interrupt vector table
1642+
* can also encounter assertion failures or even system faults here if
1643+
* VTOR is not set correctly to point to the application's vector table. */
1644+
configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
1645+
configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
1646+
}
1647+
#endif /* configCHECK_HANDLER_INSTALLATION */
1648+
16011649
#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
16021650
{
1603-
volatile uint32_t ulOriginalPriority;
16041651
volatile uint32_t ulImplementedPrioBits = 0;
16051652
volatile uint8_t ucMaxPriorityValue;
16061653

16071654
/* Determine the maximum priority from which ISR safe FreeRTOS API
1608-
* functions can be called. ISR safe functions are those that end in
1609-
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
1655+
* functions can be called. ISR safe functions are those that end in
1656+
* "FromISR". FreeRTOS maintains separate thread and ISR API functions to
16101657
* ensure interrupt entry is as fast and simple as possible.
16111658
*
1612-
* Save the interrupt priority value that is about to be clobbered. */
1613-
ulOriginalPriority = portNVIC_SHPR2_REG;
1614-
1615-
/* Determine the number of priority bits available. First write to all
1616-
* possible bits. */
1659+
* First, determine the number of priority bits available. Write to all
1660+
* possible bits in the priority setting for SVCall. */
16171661
portNVIC_SHPR2_REG = 0xFF000000;
16181662

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

16371681
/* Calculate the maximum acceptable priority group value for the number
16381682
* of bits read back. */
1639-
16401683
while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
16411684
{
16421685
ulImplementedPrioBits++;
@@ -1674,16 +1717,14 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
16741717
* register. */
16751718
ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
16761719
ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
1677-
1678-
/* Restore the clobbered interrupt priority register to its original
1679-
* value. */
1680-
portNVIC_SHPR2_REG = ulOriginalPriority;
16811720
}
16821721
#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
16831722

1684-
/* Make PendSV, CallSV and SysTick the same priority as the kernel. */
1723+
/* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
1724+
* the highest priority. */
16851725
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
16861726
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
1727+
portNVIC_SHPR2_REG = 0;
16871728

16881729
#if ( configENABLE_MPU == 1 )
16891730
{

0 commit comments

Comments
 (0)