µCOS-III从入门到精通 第四章(任务挂起和恢复)

参考教程:【正点原子】手把手教你学UCOS-III实时操作系统_哔哩哔哩_bilibili

一、任务的挂起与恢复的API函数

1、概述

(1)任务挂起和恢复的本质就是调用µCOS-III的API函数。

API函数

描述

OSTaskSuspend()

挂起任务

OSTaskResume()

恢复任务

(2)挂起任务类似暂停任务,它可重新恢复,但删除任务则是将任务永远删除,除非是重新创建任务(任务也会重头开始执行),否则任务将永远消失。

(3)这两个函数不允许在中断中调用,且不能挂起空闲任务。

2、任务挂起函数

(1)任务挂起函数的接口定义:

void OSTaskSuspend
(
    OS_TCB*   p_tcb,    //指向任务控制块的指针
    OS_ERR*   p_err    //指向接收错误代码变量的指针
)

(2)此函数用于无条件地挂起任务,被挂起的任务不会参与任务调度,如果被挂起的任务是当前正在运行的任务,那么就会发起任务调度,将CPU的使用权交给另一个任务。

(3)无论优先级如何,被挂起的任务都将不再被执行(即将任务从就绪列表中暂时移除),直到任务被恢复。

(4)当传入的任务控制块的指针为NULL(或者0),则代表挂起任务自身,也即当前正在运行的任务。

3、任务恢复函数

(1)任务恢复函数的接口定义:

void OSTaskResume
(
    OS_TCB*   p_tcb,    //指向任务控制块的指针
    OS_ERR*   p_err    //指向接收错误代码变量的指针
)

(2)此函数用于恢复被函数OSTaskSuspend挂起的任务,并且只有该函数才能恢复被函数OSTaskSuspend挂起的任务。

(3)可调用多次OSTaskSuspend挂起同一个任务,相应地,解挂时需调用同样次数的OSTaskResume才可恢复任务。

(4)恢复即把任务从新插入到就绪列表,继续运行。

二、任务挂起与恢复实验

1、原理图与实验目标

(1)原理图:

(2)实验目标:

①设计4个任务——start_task、task1、task2、task3:

[1]start_task:用于初始化CPU库、配置Systick中断及优先级,并创建其它三个任务,然后删除自身。

[2]task1:实现LED1状态反转。

[3]task2:实现LED2状态反转。

[4]task3:按下按键1,若task1非挂起,则挂起task1,否则恢复task1;按下按键2,若task2非挂起,则挂起task2,否则恢复task2。

②预期实验现象:

[1]程序下载到板子上后,两个LED灯闪烁。

[2]按下一次按键1后,LED1停止闪烁,接着再按下按键1,LED1恢复闪烁。

[3]按下一次按键2后,LED2停止闪烁,接着再按下按键2,LED2恢复闪烁。

2、实验步骤

(1)将上一章中“任务创建和删除实验”的工程文件夹复制一份,在拷贝版中进行实验。

(2)修改task3的函数实现,并增加两个全局变量用作记录task1和task2的挂起状态。

char task1_state = 0;      //记录task1挂起状态(0为非挂起,1为挂起)
char task2_state = 0;      //记录task2挂起状态(0为非挂起,1为挂起)
void task3(void)
{
	OS_ERR err;
	uint8_t key = 0;
	while(1)
	{
		key = Key_GetNum();    //读取按键键值
		if(key == 1){
			if(task1_state == 0)                  //若task1非挂起
			{
				OSTaskSuspend(&task1_tcb, &err); //挂起task1
				task1_state = 1;                 //更改其状态为挂起
			}
			else if(task1_state == 1)              //若task1挂起
			{
				OSTaskResume(&task1_tcb, &err); //恢复task1
				task1_state = 0;                 //更改其状态为非挂起
			}
		}
		if(key == 2){
			if(task2_state == 0)                  //若task2非挂起
			{
				OSTaskSuspend(&task2_tcb, &err); //挂起task2
				task2_state = 1;                 //更改其状态为挂起
			}
			else if(task2_state == 1)              //若task2挂起
			{
				OSTaskResume(&task2_tcb, &err); //恢复task2
				task2_state = 0;                 //更改其状态为非挂起
			}
		}
		OSTimeDly(10, OS_OPT_TIME_DLY, &err);    //自我阻塞10ms
	}
}

(3)程序完善好后点击“编译”,然后将程序下载到开发板上。

3、程序执行流程

(1)main函数全流程:

①初始化LED模块、按键模块。

②调用UCOS_Test函数。

(2)测试函数全流程:

①创建任务start_task。

②开启任务调度器。

(3)多任务调度执行阶段(发生在开启任务调度器以后):

①start_task任务函数首先进入临界区,在临界区中start_task任务不会被其它任务打断(否则创建task1后,由于task1的优先级较高,start_task任务会被打断),接着start_task任务依次创建任务task1、task2、task3,然后删除自身,接着退出临界区,让出CPU资源。

②三个任务中task3的优先级最高,故优先执行task3,假设先不按下任何按键,task3未接收到任何键码,不做出其它行为,直接自我阻塞10ms,此时task2的优先级最高(除开已阻塞的task3),故执行task2,LED2的状态翻转后,task2自我阻塞500ms,此时未阻塞的就绪任务仅剩task1,故执行task1,LED1的状态翻转后,task1自我阻塞500ms。待task3的自我阻塞时间结束,task3重新抢占CPU,task3自我阻塞后,待task2的自我阻塞时间结束,task2重新抢占CPU,待task1的自我阻塞时间结束,task1重新抢占CPU,以此往复,实现双LED灯闪烁。

③在某次执行task3时,若task1和task2均未挂起,按下按键1,task1将会被挂起。(按下按键1的过程中因为按键消抖使用了OSTimeDly函数,task3会进行短暂的自我阻塞,图中未示出,不过由于task3的优先级最高,阻塞时间结束后task3可重新抢占CPU)

④在某次执行task3时,若task1挂起、task2未挂起,按下按键1,task1将会被恢复。(按下按键1的过程中因为按键消抖使用了OSTimeDly函数,task3会进行短暂的自我阻塞,图中未示出,不过由于task3的优先级最高,阻塞时间结束后task3可重新抢占CPU)

⑤在某次执行task3时,若task1和task2均未挂起,按下按键2,task2将会被挂起。(按下按键2的过程中因为按键消抖使用了OSTimeDly函数,task3会进行短暂的自我阻塞,图中未示出,不过由于task3的优先级最高,阻塞时间结束后task3可重新抢占CPU)

⑥在某次执行task3时,若task2挂起、task1未挂起,按下按键2,task2将会被恢复。(按下按键2的过程中因为按键消抖使用了OSTimeDly函数,task3会进行短暂的自我阻塞,图中未示出,不过由于task3的优先级最高,阻塞时间结束后task3可重新抢占CPU)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zevalin爱灰灰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值