提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、任务挂起与恢复的API函数
- 1.具体函数描述
- ①vTaskSuspend()任务挂起(暂停)函数
- ②vTaskResume()任务恢复函数
- ③xTaskResumeFromISR()在中断中恢复挂起任务
- 2.恢复任务函数跟中断恢复任务函数有什么区别?
- 二、任务挂起与恢复的具体例程
- 1.实验目的
- 2.具体代码
- ①创建任务代码
- ②LED、key0,1任务代码
- ③key2进入中断恢复挂起的任务
- 三、任务挂起与恢复的内部实现
- 四、freertos的中断管理
- 1.什么是中断?
- 2.中断优先级分组机制
- 3.中断相关寄存器
- 4.中断管理具体例程
- 5.中断管理总结
前言
本节包括这四个内容,主要掌握1和2,3属于选修内容,如果想深入理解可以学习。
一、任务挂起与恢复的API函数
1.具体函数描述
①vTaskSuspend()任务挂起(暂停)函数
vTaskSuspend()是FreeRTOS中的一个函数,用于暂停任务的执行。当调用此函数时,任务进入暂停状态,并且在恢复之前不具备执行的资格。
该函数的语法如下:
void vTaskSuspend(TaskHandle_t xTaskToSuspend);
在这里,xTaskToSuspend是要暂停的任务的句柄。该句柄是在使用xTaskCreate()或xTaskCreateStatic()函数创建任务时获得的。
当调用vTaskSuspend()时,任务立即从准备运行的任务列表中移除。任务保持在暂停状态,直到使用vTaskResume()函数恢复它。
需要注意的是,vTaskSuspend()不应该从中断服务例程(ISR)中调用。而应该使用vTaskSuspendFromISR()函数从ISR中挂起任务。
②vTaskResume()任务恢复函数
vTaskResume()是FreeRTOS中的一个函数,用于恢复暂停任务的执行。当调用此函数时,任务从暂停状态转换为就绪状态,使其具备执行的资格。
该函数的语法如下:
BaseType_t vTaskResume(TaskHandle_t xTaskToResume);
在这里,xTaskToResume是要恢复的任务的句柄。该句柄是在使用xTaskCreate()或xTaskCreateStatic()函数创建任务时获得的。
当调用vTaskResume()时,任务被添加回准备运行的任务列表中。如果恢复的任务具有比当前运行任务更高的优先级,可能会发生上下文切换,允许恢复的任务立即开始执行。
需要注意的是,vTaskResume()不应该从中断服务例程(ISR)中调用。而应该使用vTaskResumeFromISR()函数从ISR中恢复任务。
vTaskResume()在需要恢复先前暂停的任务的场景中很有用,例如在特定事件或资源可用后。一旦任务被恢复,它将从暂停的位置继续执行。
③xTaskResumeFromISR()在中断中恢复挂起任务
xTaskResumeFromISR()是FreeRTOS中的一个函数,用于从中断服务例程(ISR)中恢复暂停的任务的执行。与vTaskResume()函数不同,xTaskResumeFromISR()是专门设计用于在ISR中恢复任务的函数。
该函数的语法如下:
BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume);
在这里,xTaskToResume是要恢复的任务的句柄。该句柄是在使用xTaskCreate()或xTaskCreateStatic()函数创建任务时获得的。
当调用xTaskResumeFromISR()时,任务从暂停状态转换为就绪状态,使其具备执行的资格。与vTaskResume()不同的是,xTaskResumeFromISR()将任务的恢复操作延迟到稍后的上下文切换中。
在ISR中调用xTaskResumeFromISR()时,需要在ISR返回之前调用一个适当的API来请求上下文切换。这可以通过使用xHigherPriorityTaskWoken参数来完成,该参数在调用API时设置为pdTRUE。
xTaskResumeFromISR()在需要从ISR中恢复先前暂停的任务的场景中很有用,例如在中断处理程序完成后恢复任务的执行。
需要注意的是,由于xTaskResumeFromISR()是从ISR中调用的,因此它具有一些特殊的限制和要求,包括对中断嵌套的支持和使用特殊的上下文切换机制。
2.恢复任务函数跟中断恢复任务函数有什么区别?
恢复任务函数(vTaskResume)和中断恢复任务函数(xTaskResumeFromISR)在功能和用法上有一些区别。
1.调用方式:恢复任务函数可以从任务上下文中调用,而中断恢复任务函数只能从中断服务例程(ISR)中调用。
2.上下文切换:恢复任务函数(vTaskResume)可以立即执行上下文切换,使恢复的任务立即开始执行。而中断恢复任务函数(xTaskResumeFromISR)将任务的恢复操作延迟到稍后的上下文切换中,需要通过调用适当的API来请求上下文切换,并设置xHigherPriorityTaskWoken参数为pdTRUE。
3.中断嵌套:中断恢复任务函数(xTaskResumeFromISR)支持中断嵌套,可以在多个中断级别中正确地恢复任务。而恢复任务函数(vTaskResume)不具备中断嵌套的支持,只能在任务上下文中调用。
4.限制和要求:由于中断恢复任务函数(xTaskResumeFromISR)是从ISR中调用的,因此它具有一些特殊的限制和要求。例如,需要正确配置和处理中断控制器,以及使用特殊的上下文切换机制。
总的来说,恢复任务函数(vTaskResume)适用于从任务上下文中恢复暂停的任务,而中断恢复任务函数(xTaskResumeFromISR)适用于从中断服务例程中恢复暂停的任务.
意思就是说:xTaskResumeFromISR()函数需要在中断服务例程(ISR)中调用。当进入中断并需要恢复暂停的任务时,可以在中断服务函数中调用xTaskResumeFromISR()函数。
在调用xTaskResumeFromISR()函数之前,需要确保已经正确配置和处理中断控制器,并设置xHigherPriorityTaskWoken参数为pdTRUE。这样在中断服务函数返回之前,会立即请求一个上下文切换,使得恢复的任务能够在稍后的上下文切换中开始执行。
注意,xTaskResumeFromISR()函数只能用于从中断上下文中恢复任务,不能从普通任务上下文中调用该函数。如果需要从普通任务上下文中恢复任务,应该使用vTaskResume()函数。
具体关于freertos的中断机制,后面会具体说明。
二、任务挂起与恢复的具体例程
1.实验目的
2.具体代码
代码如下:
①创建任务代码
②LED、key0,1任务代码
③key2进入中断恢复挂起的任务
三、任务挂起与恢复的内部实现
四、freertos的中断管理
主要内容包括:
1.什么是中断?
裸机编程里,中断是一个很重要的概念。这里我也不多说了,如图,由某些条件触发中断请求,然后CPU停止当前程序,进入中断处理程序执行,完毕后返回打断的程序处继续执行。
如果出现了一个中断,同时又出现了一个更加重要的中断请求,即中断嵌套,那怎么办呢?
采用中断优先级分组机制。
2.中断优先级分组机制
看这个中断优先级寄存器,高四位和低四位是不同的,只有高四位才用于优先级表示。那么对于抢占优先级和子优先级这两种配置方法而言,有以下的配置方式:
比如我们最常用的NVIC_PriorityGroup_2,那么抢占优先级有两位,00、01、10、11这4种形式,子优先级同样也是两位。
那对于freeetos来说,中断优先级怎么管理呢?
这里建议只要抢占优先级,采用NVIC_PriorityGroup_4,让抢占优先级占据全部的4位。
3.中断相关寄存器
看不懂,根本看不懂,还是上例程来理解吧。
4.中断管理具体例程
说明:这里创建两个定时器,由于系统管理的优先级范围是5-15,所以如果我关中断,优先级为6的定时器会被关闭,而优先级为4的不会受影响。
(1)首先创建两个基本定时器TIM6和TIM7
(2)修改两个定时器的优先级为4和6
(3)实现每一秒进入一次中断,并打印字符串的功能:只需初始化时配置好分频系数与计数周期,使得每1秒触发中断即可。
stm32f429系列设置系统时钟频率为180MHZ,而TIM6和TIM7的时钟频率是90MHz,所以900000000/10000/9000=1s。
(4)将关闭中断函数放在任务1里面执行
整个任务函数的作用是每秒钟执行一次任务,并在 task1_num 自增到 5 的时候关闭中断,延时 5 秒后再开启中断。当两个定时器1秒进一次中断打印字符串,到5秒时关中断,这时只有不在系统管理的中断优先级为4的定时器能继续运行,5-15优先级的中断会直接停止。然后过5秒后,开中断,两个定时器中断又正常运行。
注意:这里if语句里面,为什么只能用delay_ms(5000);而不能用vTaskDelay(5000);呢?
delay_ms(5000) 和 vTaskDelay(5000) 是两种不同的延时函数。
delay_ms(5000):这是一个常见的延时函数,用于在代码中添加一个指定的毫秒级延时。在该函数中,程序将会一直阻塞,直到经过指定的时间(5秒)后才继续执行后续代码。这种延时函数通常用于裸机编程或非实时操作系统中,因为它会阻塞任务的执行,可能导致任务无法响应其他事件。
vTaskDelay(5000):这是 FreeRTOS 提供的一个延时函数,用于在任务中实现延时。在该函数中,任务将会进入阻塞状态,并将 CPU 时间片让给其他任务或中断处理程序,以便系统可以继续执行其他任务。在经过指定的时间(5秒)后,任务会被重新唤醒,并继续执行后续代码。这种延时函数是实时操作系统中常用的方式,可以实现任务之间的时间片轮转和优先级调度。
总结:delay_ms(5000) 是一个阻塞式的延时函数,会阻塞任务的执行;vTaskDelay(5000) 是 FreeRTOS 提供的一个非阻塞式延时函数,任务在延时期间会进入阻塞状态,让出 CPU 时间片给其他任务.选择使用哪种延时函数取决于具体的应用场景和系统需求。
再注意:系统管理的优先级范围是可以设置的。
看的是BASEPRI寄存器:屏蔽优先级低于某一个阈值的中断,当设置为0时,则不关闭任何中断。当BASEPRI设置为0x50时,代表中断优先级在5-15内的均被屏蔽,0-4的中断优先级正常执行。