本文学习与程序编写基于 正点原子的 STM32F1 UCOS开发手册
编写熟悉一下UCOSIII系统的任务挂起与恢复实验
文章提供测试代码讲解、完整工程下载、测试效果图
目录
任务挂起与恢复目的:
任务挂起的目的
任务恢复的目的
任务函数文件:
任务块头文件 #include "Task_config.h" :
文件整体结构如下:
目前各个文件任务:
#include "main.h"
#include "ComTask.h"
#include "MessageTask.h"
#include "CalculateTask.h"
下载测试效果:
测试工程下载:
任务挂起与恢复目的:
任务挂起的目的
- 任务暂停:当任务需要等待某些事件发生(如I/O操作完成、信号量可用等)时,可以通过挂起任务来释放CPU资源,让其他任务有机会运行。这样可以避免任务长时间占用CPU资源,导致系统响应变慢。
- 资源管理:在某些情况下,可能需要暂时停止某些任务的执行,以便重新分配系统资源或调整任务优先级。通过挂起任务,可以实现资源的动态管理和优化。
- 任务同步:在多任务环境中,任务之间可能存在依赖关系。通过挂起任务,可以实现任务之间的同步,确保任务按照预定的顺序执行。
任务恢复的目的
- 任务继续执行:当挂起任务所等待的事件发生时,或者系统资源得到重新分配后,需要恢复任务的执行。通过恢复任务,可以让任务继续完成其预定的功能。
- 提高系统效率:通过合理地挂起和恢复任务,可以避免任务之间的冲突和竞争,提高系统的运行效率和响应速度。
- 任务管理:在UCOS系统中,任务挂起和恢复是任务管理的重要组成部分。通过这两个操作,可以实现任务的动态调度和优先级调整,从而更好地满足系统的运行需求。
任务函数文件:
工程包含一个TASK组,里面含有各个任务的实际函数体:
#include "ComTask.h"包含串口相关任务操作
#include "MessageTask.h" 包含信号灯状态等 对外释放信号安排的 相关操作
#include "CalculateTask.h" 包含数据计算任务
任务块头文件 #include "Task_config.h" :
这是为了方便 任意其他任务 对 任意任务进行 删除 挂起 恢复 等操作而编写的,
因为每个任务都写在自己的任务文件中,对任务块名称引用需要有专门文件来提供通道
不这么编写就没法有这个实现......
文件整体结构如下:
需要在.c 中定义任务块,然后在.h 文件extern
直接写在.h 文件 不 进行extern,就会报错
#include "Task_config.h" //任务定义文件 /* 开始任务 StartTask */ //任务控制块 OS_TCB StartTaskTCB; //任务堆栈 CPU_STK START_TASK_STK[START_STK_SIZE]; /* ComTask */ //任务控制块 OS_TCB COMTASKTaskTCB; //任务堆栈 CPU_STK COMTASK_TASK_STK[COMTASK_STK_SIZE]; /* MessageTask */ //任务控制块 OS_TCB MessageTaskTaskTCB; //任务堆栈 CPU_STK MessageTask_TASK_STK[MessageTask_STK_SIZE]; /* CalculateTask */ //任务控制块 OS_TCB CalculateTaskTaskTCB; //任务堆栈 __align(8) CPU_STK CalculateTask_TASK_STK[CalculateTask_STK_SIZE];
// Task_config.h #ifndef TASK_CONFIG_H #define TASK_CONFIG_H #include "headfile.h" //任务优先级 #define START_TASK_PRIO 3 //任务堆栈大小 #define START_STK_SIZE 512 //任务控制块 extern OS_TCB StartTaskTCB; //任务堆栈 extern CPU_STK START_TASK_STK[START_STK_SIZE]; //任务函数 //void start_task(void *p_arg); //任务优先级 #define COMTASK_TASK_PRIO 6 //任务堆栈大小 #define COMTASK_STK_SIZE 128 //任务控制块 extern OS_TCB COMTASKTaskTCB; //任务堆栈 extern CPU_STK COMTASK_TASK_STK[COMTASK_STK_SIZE]; //任务函数定义在#include "ComTask.h" //任务优先级 #define MessageTask_TASK_PRIO 6 //任务堆栈大小 #define MessageTask_STK_SIZE 128 //任务控制块 extern OS_TCB MessageTaskTaskTCB; //任务堆栈 extern CPU_STK MessageTask_TASK_STK[MessageTask_STK_SIZE]; //任务函数定义在#include "MessageTask.h" //任务优先级 #define CalculateTask_TASK_PRIO 8 //任务堆栈大小 #define CalculateTask_STK_SIZE 128 //任务控制块 extern OS_TCB CalculateTaskTaskTCB; //任务堆栈 extern __align(8) CPU_STK CalculateTask_TASK_STK[CalculateTask_STK_SIZE]; //任务函数定义在#include "CalculateTask.h" #endif // TASK_CONFIG_H
目前各个文件任务:
#include "main.h"
创建开始任务初始化三个基本任务:
代码如下:
#include "main.h" void start_task(void *p_arg);//开始任务函数 int main(void) { OS_ERR err; CPU_SR_ALLOC(); Init_ALL(); OSInit(&err); //初始化UCOSIII OS_CRITICAL_ENTER();//进入临界区 //创建开始任务 OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块 (CPU_CHAR * )"start task", //任务名字 (OS_TASK_PTR )start_task, //任务函数 (void * )0, //传递给任务函数的参数 (OS_PRIO )START_TASK_PRIO, //任务优先级 (CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址 (CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位 (CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小 (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度, (void * )0, //用户补充的存储区 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项 (OS_ERR * )&err); //存放该函数错误时的返回值 OS_CRITICAL_EXIT(); //退出临界区 OSStart(&err); //开启UCOSIII while(1); } //开始任务函数 void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); p_arg = p_arg; CPU_Init(); #if OS_CFG_STAT_TASK_EN > 0u OSStatTaskCPUUsageInit(&err); //统计任务 #endif #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 CPU_IntDisMeasMaxCurReset(); #endif #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 //使能时间片轮转调度功能,时间片长度为1个系统时钟节拍,既1*5=5ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); #endif OS_CRITICAL_ENTER(); //进入临界区 //创建ComTask任务 OSTaskCreate((OS_TCB * )&COMTASKTaskTCB, (CPU_CHAR * )"com task", (OS_TASK_PTR )comTask, (void * )0, (OS_PRIO )COMTASK_TASK_PRIO, (CPU_STK * )&COMTASK_TASK_STK[0], (CPU_STK_SIZE)COMTASK_STK_SIZE/10, (CPU_STK_SIZE)COMTASK_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建MessageTask任务 OSTaskCreate((OS_TCB * )&MessageTaskTaskTCB, (CPU_CHAR * )"Message task", (OS_TASK_PTR )MessageTask, (void * )0, (OS_PRIO )MessageTask_TASK_PRIO, (CPU_STK * )&MessageTask_TASK_STK[0], (CPU_STK_SIZE)MessageTask_STK_SIZE/10, (CPU_STK_SIZE)MessageTask_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); //创建CalculateTask任务 OSTaskCreate((OS_TCB * )&CalculateTaskTaskTCB, (CPU_CHAR * )"Calculate task", (OS_TASK_PTR )CalculateTask, (void * )0, (OS_PRIO )CalculateTask_TASK_PRIO, (CPU_STK * )&CalculateTask_TASK_STK[0], (CPU_STK_SIZE)CalculateTask_STK_SIZE/10, (CPU_STK_SIZE)CalculateTask_STK_SIZE, (OS_MSG_QTY )0, (OS_TICK )0, (void * )0, (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, (OS_ERR * )&err); OS_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务 OS_CRITICAL_EXIT(); //进入临界区 }
宏定义依赖 在Task_config.h 文件: 目前main.h 完全干干净净:
#include "ComTask.h"
一进来就删除CalculateTask任务
随后 ComTask 打印自己运行次数 等待800ms
代码如下:
#include "ComTask.h" // 删除CalculateTask //ComTask 打印自己运行次数 然后等待800ms void comTask(void * p_arg) { OS_ERR err; int i=0; p_arg = p_arg; OSTaskDel((OS_TCB*)&CalculateTaskTaskTCB,&err); UsartPrintf(USART1, "ComTask delete CalculateTask !\r\n"); //删除CalculateTask while (DEF_TRUE) { i++; UsartPrintf(USART1, "comTask Print%d\r\n",i); //printf("comTask Print%d\r\n",i); //UsartPrintf(USART1, "%d\r\n",i); OSTimeDlyHMSM(0,0,0,800,OS_OPT_TIME_HMSM_STRICT,&err); //延时800ms } }
#include "MessageTask.h"
打印任务MessageTask运行次数 "暂且注释,有问题 会卡主系统"
2024.12.17已解决:将任务栈大小改大些就行:
分别按顺序 205ms间隔延迟 单独点亮 红绿蓝 LED 最后全亮
运行3次后挂起 ComTask 并打印
运行6次后恢复 ComTask 并打印代码如下:
#include "MessageTask.h" /* 打印任务MessageTask运行次数 "暂且注释,有问题 会卡主系统" 分别按顺序 205ms间隔延迟 单独点亮 红绿蓝 LED 最后全亮 运行3次后挂起 ComTask 并打印 运行6次后恢复 ComTask 并打印 */ void MessageTask (void * p_arg) { OS_ERR err; int i=0; p_arg = p_arg; while (DEF_TRUE) { i++; //UsartPrintf(USART1, "MessageTask Print%d\r\n",i); //此行取消注释会卡主系统! //单独亮红灯 LED_RED_L;LED_GREEN_H;LED_Blue_H; OSTimeDlyHMSM(0,0,0,205,OS_OPT_TIME_HMSM_STRICT,&err); //延时205ms //单独亮绿灯 LED_GREEN_L;LED_RED_H;LED_Blue_H; OSTimeDlyHMSM(0,0,0,205,OS_OPT_TIME_HMSM_STRICT,&err); //延时205ms //单独亮蓝灯 LED_Blue_L;LED_RED_H;LED_GREEN_H; OSTimeDlyHMSM(0,0,0,205,OS_OPT_TIME_HMSM_STRICT,&err); //延时205ms //全部点亮 LED_RED_L;LED_GREEN_L;LED_Blue_L; OSTimeDlyHMSM(0,0,0,205,OS_OPT_TIME_HMSM_STRICT,&err); //延时205ms if(i==3) { UsartPrintf(USART1, "M Sus Com\r\n"); //挂起 OSTaskSuspend((OS_TCB*)&COMTASKTaskTCB,&err); } if(i==6) { UsartPrintf(USART1, "M Res Com\r\n"); //恢复 OSTaskResume((OS_TCB*)&COMTASKTaskTCB,&err); } } }
#include "CalculateTask.h"
CalculateTask 打印自己运行次数 然后等待100ms "本次实验将其删除"
代码如下:
#include "CalculateTask.h" //CalculateTask 打印自己运行次数 然后等待100ms "本次实验将其删除" void CalculateTask(void *p_arg) { OS_ERR err; int i=0; p_arg = p_arg; while (DEF_TRUE) { i++; UsartPrintf(USART1, "CalculateTask Print %d\r\n",i); //UsartPrintf(USART1, "C:%d\r\n",i); OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_HMSM_STRICT,&err); //延时100ms } }
下载测试效果:
测试效果与解释如下:
测试工程下载:
https://download.csdn.net/download/qq_64257614/90139444