学习freertos:初始化阶段的中断状态

author author     2022-12-07     637

关键词:


学习FreeRTOS(2):初始化阶段的中断状态

分析FreeRTOS的Cortex-M4F移植版(portable/GCC/ARM_CM4F)在初始化阶段CPU中断状态的变化。复位后中断默认处于开启状态,当创建第一个任务时中断被关闭,开启调度器时重新开启中断。总体上也适用于其它Cortex-M,部分细节可能略有差别。

mingdu.zheng at gmail dot com

Cortex-M在复位后,中断处于开启状态,即PRIMASK=0,FAULTMASK=0,BASEPRI=0。第一次调用xTaskCreate创建任务后,中断将会被关闭,BASEPRI=0x80。

// 中断被关闭时的调用栈
// xTaskCreate
// prvAllocateTCBAndStack
// pvPortMallocAligned
// xTaskResumeAll
// taskENTER_CRITICAL
// vPortEnterCritical

默认开启的中断在vPortEnterCritical函数中被关闭。来看一下vPortEnterCritical和vPortExitCritical函数。

void vPortEnterCritical( void )

portDISABLE_INTERRUPTS();
uxCriticalNesting++;

/* This is not the interrupt safe version of the enter critical function so
assert() if it is being called from an interrupt context. Only API
functions that end in "FromISR" can be used in an interrupt. Only assert if
the critical nesting count is 1 to protect against recursive calls if the
assert function also uses a critical section. */
if( uxCriticalNesting == 1 )

configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );

vPortEnterCritical函数首先调用portDISABLE_INTERRUPTS关闭中断,然后将uxCriticalNesting加1。

/*-----------------------------------------------------------*/
// xTaskResumeAll函数结束时调用vPortExitCritical
// xTaskCreate
// prvAllocateTCBAndStack
// pvPortMallocAligned
// xTaskResumeAll
// taskEXIT_CRITICAL
// vPortExitCritical
void vPortExitCritical( void )

configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )

portENABLE_INTERRUPTS();

vPortExitCritical函数首先将uxCriticalNesting减1,如果uxCriticalNesting减到0,那么调用portENABLE_INTERRUPTS重新打开中断。对vPortEnterCritical和vPortExitCritical函数的分析,可以得出一个结论:当xTaskResumeAll调用vPortExitCritical后中断将会重新被打开。而实际上并非如此,因为uxCriticalNesting不是被初始化成0,而是被初始化成0xaaaaaaaa,因此中断仍然处于关闭状态,直到调用vTaskStartScheduler开启调度器并执行第一个线程。

/* Each task maintains its own interrupt status in the critical nesting
variable. */
static UBaseType_t uxCriticalNesting = 0xaaaaaaaa;
// 将uxCriticalNesting设置为0的调用栈
// vTaskStartScheduler
// xPortStartScheduler
BaseType_t xPortStartScheduler( void )

......
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
......
/* Start the first task. */
prvPortStartFirstTask();
......
return 0;
static void prvPortStartFirstTask( void )

__asm volatile(
" ldr r0, =0xE000ED08 \\n" /* Use the NVIC offset register to locate the stack. */
" ldr r0, [r0] \\n"
" ldr r0, [r0] \\n"
" msr msp, r0 \\n" /* Set the msp back to the start of the stack. */
" cpsie i \\n" /* Globally enable interrupts. */
" cpsie f \\n"
" dsb \\n"
" isb \\n"
" svc 0 \\n" /* System call to start first task. */
" nop \\n"
);
void vPortSVCHandler( void )

__asm volatile (
" ldr r3, pxCurrentTCBConst2 \\n" /* Restore the context. */
" ldr r1, [r3] \\n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
" ldr r0, [r1] \\n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, r4-r11, r14 \\n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \\n" /* Restore the task stack pointer. */
" isb \\n"
" mov r0, #0 \\n"
" msr basepri, r0 \\n"
" bx r14 \\n"
" \\n"
" .align 2 \\n"
"pxCurrentTCBConst2: .word pxCurrentTCB \\n"
);

vTaskStartScheduler将uxCriticalNesting设置成0,随后prvPortStartFirstTask触发了一个SVC,SVC处理函数是vPortSVCHandler,vPortSVCHandler开启了中断(mov r0, #0; msr basepri, r0,这两条指令将BASEPRI设置为0,中断处于开启状态)并进入了第一个线程,在这之后vPortEnterCritical和vPortExitCritical才会按照预期的方式工作,在这之前vPortEnterCritical和vPortExitCritical是不起作用的。


stm32g0学习手册——cortexm0+nvic与freertos中断管理

...级:0、1、2、3知识点2        在Cortex-M0上,FreeRTOS内核的临界区屏蔽了所有中断(除了NMI、Hard 查看详情

stm32g0学习手册——cortexm0+nvic与freertos中断管理

...级:0、1、2、3知识点2        在Cortex-M0上,FreeRTOS内核的临界区屏蔽了所有中断(除了NMI、Hard 查看详情

stm32g0学习手册——cortexm0+nvic与freertos中断管理

...级:0、1、2、3知识点2        在Cortex-M0上,FreeRTOS内核的临界区屏蔽了所有中断(除了NMI、HardFault、复位)。知识点3        FreeRTOS任务优先级从0开始,作为最低的紧急RTOS任务优先级,而M0+NVIC... 查看详情

嵌入式freertos的移植任务运行状态以及源码的优化改进(代码片段)

目录前言一、FreeRTOS移植的注意事项二、任务运行状态的获取三、任务运行状态的源码优化前言FreeRTOS因其简洁小巧、功能齐全而深受嵌入式领域欢迎,如下图所示,除Linux外,FreeRTOS为全球嵌入式领域市场份额最多的... 查看详情

嵌入式freertos的移植任务运行状态以及源码的优化改进(代码片段)

目录前言一、FreeRTOS移植的注意事项二、任务运行状态的获取三、任务运行状态的源码优化前言FreeRTOS因其简洁小巧、功能齐全而深受嵌入式领域欢迎,如下图所示,除Linux外,FreeRTOS为全球嵌入式领域市场份额最多的... 查看详情

freertos队列

...间,结构体和队列项在存储空间上是连续的。分配成功后初始化成员,然后调用函数xQueueGenericReset()初始化剩下的结构体成员。假设我们申请了3个队列项,每个队列项占用4字节存储空间(即uxLength=3、uxItemSize=4),则经过初始化... 查看详情

在 STM32 上使用 FreeRTOS 处理多个中断

】在STM32上使用FreeRTOS处理多个中断【英文标题】:HandlingmultipleinterruptswithFreeRTOSonSTM32【发布时间】:2021-01-1620:53:53【问题描述】:我的基于MCU的控制系统必须快速检查18个开关触点状态。我将使用STM32F7MCU,它最大有16个int。处理... 查看详情

原子stm32带freertos程序使用timer3定时器时持续进入中断的问题解决(代码片段)

...ff0c;在中断加一句打印语句,程序持续进入中断,初始化设置的定时器周期都无效。【原因】:1)进一步查看程序,原子的timer.c文件中有一个ConfigureTimeForRunTimeStats函数,使用TIM3为FreeRTOS的时间统计提供时... 查看详情

freertos学习笔记——环境搭建(代码片段)

前言在日常中,我平常都是直接裸机开发,去完成一些小玩意。直到最近,功能需求的不断增加,导致裸机开发的缺点就暴露出来了,中断内的处理变得复杂,处理时间变长,超级循环使得应用程序变... 查看详情

如何通过串口输入获取freertos系统内核状态

参考技术A(1)中断级用OSSched(),任务级用OSIntExit()(2)OSIntExit()使终端层数减1,而只当中断嵌套层数和任务调度锁定层数均为0时才能调OSSched()函数。 查看详情

freertos-中断使用注意

...:1:首先要将中断的嵌套全部设置为抢占优先级。2:将freertos系统内核中断(configKERNEL_INTERRUPT_PRIORITY)的优先级设置成最低。3:将freertos的最大系统调用中断优先级(configMAX_SYSCALL_INTERRUPT_PRIORITY)设置为合适的优先级,比如11... 查看详情

我的opengl学习进阶之旅基本状态管理(代码片段)

...的例子有混合启用、混合银子、剔除启用、剔除曲面。在初始化OpenGLES上下文(EGLContext)时,状态用默认值初始 查看详情

原子stm32带freertos程序使用timer3定时器时持续进入中断的问题解决(代码片段)

...ff0c;在中断加一句打印语句,程序持续进入中断,初始化设置的定时器周期都无效。【原因】:1)进一步查看程序,原子的timer.c文件中有一个ConfigureTimeForRu 查看详情

stm32f103x/freertos系统学习笔记之sr04超声波测距串口输出-cxm(代码片段)

...配置3.HC-SR04超声波测距代码    通用配置    超声波初始化   第一种:外部中断检测法硬件HC-SR04STM32F103C6首先我们使用上一次的搭建好的环境STM32F103x/FreeRTOS系统学习笔记之环境搭建-CXM_CHENxiaomingming的博客-CSDN博客\\RTOS\\stm32F10... 查看详情

freertosfreertos学习笔记(14)—freertos的消息队列(原生api)(代码片段)

摘要:在裸机中我们使用全局变量来传递信息,在操作系统中,使用全局变量传递消息可能会不安全,容易被修改。于是就是用队列来传递消息。队列就是一个数据结构,用于任务间的数据的传递。一、消息队列的基本概念队列... 查看详情

freertos临界段和开关中断

...前须关中断,而临界段代码执行完毕后,要立即开中断。FreeRTOS临界段相关知识补充FreeRTOS的源码中有多处临界段的地方,临界段虽然保护了关键代码的执行不被打断,但也会影响系统的实时性。比如此时某个任务正在调用系统AP... 查看详情

zynq-7000freertos中断:解决rtos中中断无反应问题

...中断,PL到PS的按键中断均工作正常,但是将代码移植到freertos工程时,中断不执行,跟中断无关联的task可以运行。产生这个问题的主要原因,在于PS部分只有一个中断控制器,因此我们只能申请一个中断控制器设备,如果申请了... 查看详情

freertos调度锁,任务锁和中断锁

...中断操作。中断锁中断锁就是RTOS提供的开关中断函数,FreeRTOS没有专门的中断锁函数,使用前一节里面介绍的中断 查看详情