- Portal: Blog summary post
- Portal: Cortex-M3_ Interrupt, exception
- Portal: Cortex-M3 notes_ Basics
Note content reference (FreeRTOS Development Manual of punctual atom, authoritative guide of Cortex-M3, authoritative guide of Cortex-M3 and Cortex-M4, etc.)
1. Interrupt configuration macro
When STM32 uses FreeRTOS, the priority group must be set to group 4 (all 4 bits are preemptive priority), so there are (0-15) 16 priorities. And the smaller the priority number, the higher the priority.
- configPRIO_BITS: sets the priority of several bits used by mcu, and the priority of 4 bits used by STM32
- configLIBRARY_LOWEST_INTERRUPT_PRIORITY: sets the lowest priority, so it is (15)
- configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY: set the highest priority that FreeRTOS can manage (5),
2. Configure Pendsv and Systick priorities
Set pendsv and Systick priorities as the lowest priority. Why set the lowest priority? Because task switching is running in pendsv. Why switch tasks in pendsv in order to make other interrupts run in time.
Well, I wrote on other blogs, but I haven't written (~ ~ (OO) ~) yet
In the task scheduler start function vTaskStartScheduler(), there is an interface xPortStartScheduler(), which is used to initialize the hardware related to the scheduler (such as tick timer, FPU unit [floating point operation], PendSV interrupt)
//After code reduction void vTaskStartScheduler( void ) { if( xPortStartScheduler() != pdFALSE ) } /* * See header file for description. */ BaseType_t xPortStartScheduler( void ) { /* Make PendSV and SysTick the lowest priority interrupts. */ portNVIC_SYSPRI2_REG |= portNVIC_PENDSV_PRI; portNVIC_SYSPRI2_REG |= portNVIC_SYSTICK_PRI; } /*-----------------------------------------------------------*/
Set PENDSV_PRI and SYSTICK_PRI priority is to portNVIC_SYSPRI2_REG write data
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
Four adjacent priority registers (8 bits) are assembled into a 32-bit register. So the above is directly to 0xE000_ED20 writes and sets PendSV and Systick priorities
#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
Configkernel here_ INTERRUPT_ Priority is shifted to the left by 16 and 24 respectively. Because four adjacent registers are spliced into a 32-bit register, PendSV is set to the left by 16 bits and Systick is set to the left by 24.
/* Interrupt priorities used by the kernel port layer itself. These are generic to all Cortex-M ports, and do not rely on any particular library functions. */ #define configKERNEL_INTERRUPT_PRIORITY ( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
configKERNEL_INTERRUPT_PRIORITY is the number of registers actually written, because it is not possible to write configLIBRARY_LOWEST_INTERRUPT_PRIORITY (15) is directly written to the register, so it needs to be converted. Because STM32 uses the upper four bits as the priority, it needs to shift 15 to the left by 4 bits to be the real priority. (8 - configPRIO_BITS) is 4.
3. Special register for interrupt masking
For the three registers PRIMASK, FAULTMASK and BASEPRI, please refer to the link [Cortex-M3 note foundation] above for a general understanding of the three interrupt mask registers. BASEPRI register can only mask priority interrupts lower than a certain threshold. FreeRTOS switch interrupts are realized through BASEPRI register.
If you want to mask the priority below a certain threshold, you can write the priority directly into the register, and write 0 to stop shielding interrupts
4. FreeRTOS switch interrupt
Open and interrupt vPortRaiseBASEPRI, close vPortSetBASEPRI, close and write 0
static portFORCE_INLINE void vPortRaiseBASEPRI( void ) { uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY; __asm { /* Set BASEPRI to the max syscall priority to effect a critical section. */ msr basepri, ulNewBASEPRI dsb isb } } static portFORCE_INLINE void vPortSetBASEPRI( uint32_t ulBASEPRI ) { __asm { /* Barrier instructions are not used as this function is only used to lower the BASEPRI value. */ msr basepri, ulBASEPRI } }
Configmax here_ SYSCALL_ INTERRUPT_ Priority is defined as follows
/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) ) /* The highest interrupt priority that can be used by any interrupt service routine that makes calls to interrupt safe FreeRTOS API functions. DO NOT CALL INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER PRIORITY THAN THIS! (higher priorities are lower numeric values. */ #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
Related macros are defined above.