UCOS操作系统
前言
任务的删除是直接删除这个任务,以后都不在执行,但是我要是想等某一个状态触发了继续执行怎么办,这个时候就轮到任务的挂起与恢复发挥作用了。
一、任务挂起OSTaskSuspend()函数
有时候有些任务因为某些原因需要暂停运行,但是以后还要运行,因此我们就不能删除掉任务,这里我们可以使用 OSTaskSuspend()函数挂起这个任务,以后再恢复运行,函数OSTaskSuspend()的原型如下:
void OSTaskSuspend (OS_TCB *p_tcb,OS_ERR *p_err)
*p_tcb : 指向需要挂起的任务的 OS_TCB,可以通过指向一个 NULL 指针将调用该函数的任务挂起。
*p_err: 指向一个变量,用来保存该函数的错误码。
我们可以多次调用 OSTaskSuspend ()函数来挂起一个任务,因此我们需要调用同样次数的OSTaskResume()函数才可以恢复被挂起的任务,这一点非常重要。意思是挂起一次,然后需要解挂一次,你可以再次挂起,然后再次解挂。
二、任务恢复 OSTaskResume()函数
OSTaskResume()函数用来恢复被 OSTaskSuspend()函数挂起的任务,OSTaskResume()函数是唯一能恢复被挂起任务的函数。如果被挂起的任务还在等待别的内核对象,比如事件标志组、信号量、互斥信号量、消息队列等,即使使用 OSTaskResume()函数恢复了被挂起的任务,该任务也不一定能立即运行,该任务还是要等相应的内核对象,只有等到内核对象后才可以继续运行,OSTaskResume()函数原型如下:
void OSTaskResume (OS_TCB *p_tcb,OS_ERR *p_err)
*p_tcb : 指向需要解挂的任务的 OS_TCB,指向一个 NULL 指针是无效的,因为该任务正在运行,不需要解挂。
*p_err: 指向一个变量,用来保存该函数的错误码。
三、完整代码
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "includes.h"
//ÈÎÎñÓÅÏȼ¶
#define START_TASK_PRIO 3
//ÈÎÎñ¶ÑÕ»´óС
#define START_STK_SIZE 128
//ÈÎÎñ¿ØÖÆ¿é
OS_TCB StartTaskTCB;
//ÈÎÎñ¶ÑÕ»
CPU_STK START_TASK_STK[START_STK_SIZE];
//ÈÎÎñº¯Êý
void start_task(void *p_arg);
//ÈÎÎñÓÅÏȼ¶
#define TASK1_TASK_PRIO 4
//ÈÎÎñ¶ÑÕ»´óС
#define TASK1_STK_SIZE 128
//ÈÎÎñ¿ØÖÆ¿é
OS_TCB Task1_TaskTCB;
//ÈÎÎñ¶ÑÕ»
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
void task1_task(void *p_arg);
//ÈÎÎñÓÅÏȼ¶
#define TASK2_TASK_PRIO 5
//ÈÎÎñ¶ÑÕ»´óС
#define TASK2_STK_SIZE 128
//ÈÎÎñ¿ØÖÆ¿é
OS_TCB Task2_TaskTCB;
//ÈÎÎñ¶ÑÕ»
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
//ÈÎÎñº¯Êý
void task2_task(void *p_arg);
//LCDË¢ÆÁʱʹÓõÄÑÕÉ«
int lcd_discolor[14]={
WHITE, BLACK, BLUE, BRED,
GRED, GBLUE, RED, MAGENTA,
GREEN, CYAN, YELLOW,BROWN,
BRRED, GRAY };
//Ö÷º¯Êý
int main(void)
{
OS_ERR err;
CPU_SR_ALLOC();
delay_init(); //ʱÖÓ³õʼ»¯
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÖжϷÖ×éÅäÖÃ
uart_init(115200); //´®¿Ú³õʼ»¯
LED_Init(); //LED³õʼ»¯
LCD_Init(); //LCD³õʼ»¯
POINT_COLOR = RED;
LCD_ShowString(30,10,200,16,16,"ALIENTEK STM32F1");
LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 6-2");
LCD_ShowString(30,50,200,16,16,"Task Suspend and Resume");
LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK");
LCD_ShowString(30,90,200,16,16,"2015/3/19");
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
}
//¿ªÊ¼ÈÎÎñÈÎÎñº¯Êý
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(); //½øÈëÁÙ½çÇø
//´´½¨TASK1ÈÎÎñ
OSTaskCreate((OS_TCB * )&Task1_TaskTCB,
(CPU_CHAR * )"Task1 task",
(OS_TASK_PTR )task1_task,
(void * )0,
(OS_PRIO )TASK1_TASK_PRIO,
(CPU_STK * )&TASK1_TASK_STK[0],
(CPU_STK_SIZE)TASK1_STK_SIZE/10,
(CPU_STK_SIZE)TASK1_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);
//´´½¨TASK2ÈÎÎñ
OSTaskCreate((OS_TCB * )&Task2_TaskTCB,
(CPU_CHAR * )"task2 task",
(OS_TASK_PTR )task2_task,
(void * )0,
(OS_PRIO )TASK2_TASK_PRIO,
(CPU_STK * )&TASK2_TASK_STK[0],
(CPU_STK_SIZE)TASK2_STK_SIZE/10,
(CPU_STK_SIZE)TASK2_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_CRITICAL_EXIT(); //Í˳öÁÙ½çÇø
OSTaskDel((OS_TCB*)0,&err); //ɾ³ýstart_taskÈÎÎñ×ÔÉí
}
//task1ÈÎÎñº¯Êý
void task1_task(void *p_arg)
{
u8 task1_num=0;
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
POINT_COLOR = BLACK;
OS_CRITICAL_ENTER();
LCD_DrawRectangle(5,110,115,314); //»Ò»¸ö¾ØÐÎ
LCD_DrawLine(5,130,115,130); //»Ïß
POINT_COLOR = BLUE;
LCD_ShowString(6,111,110,16,16,"Task1 Run:000");
OS_CRITICAL_EXIT();
while(1)
{
task1_num++; //ÈÎÎñ1Ö´ÐдÎÊý¼Ó1 ×¢Òâtask1_num1¼Óµ½255µÄʱºò»áÇåÁ㣡£¡
LED0= ~LED0;
printf("ÈÎÎñ1ÒѾִÐУº%d´Î\r\n",task1_num);
if(task1_num==5)
{
OSTaskSuspend((OS_TCB*)&Task2_TaskTCB,&err);//ÈÎÎñ1Ö´ÐÐ5´Îºó¹ÒÆðÈÎÎñ2
printf("ÈÎÎñ1¹ÒÆðÁËÈÎÎñ2!\r\n");
}
if(task1_num==10)
{
OSTaskResume((OS_TCB*)&Task2_TaskTCB,&err); //ÈÎÎñ1ÔËÐÐ10´Îºó»Ö¸´ÈÎÎñ2
printf("ÈÎÎñ1»Ö¸´ÁËÈÎÎñ2!\r\n");
}
LCD_Fill(6,131,114,313,lcd_discolor[task1_num%14]); //Ìî³äÇøÓò
LCD_ShowxNum(86,111,task1_num,3,16,0x80); //ÏÔʾÈÎÎñÖ´ÐдÎÊý
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //ÑÓʱ1s
}
}
//task2ÈÎÎñº¯Êý
void task2_task(void *p_arg)
{
u8 task2_num=0;
OS_ERR err;
CPU_SR_ALLOC();
p_arg = p_arg;
POINT_COLOR = BLACK;
OS_CRITICAL_ENTER();
LCD_DrawRectangle(125,110,234,314); //»Ò»¸ö¾ØÐÎ
LCD_DrawLine(125,130,234,130); //»Ïß
POINT_COLOR = BLUE;
LCD_ShowString(126,111,110,16,16,"Task2 Run:000");
OS_CRITICAL_EXIT();
while(1)
{
task2_num++; //ÈÎÎñ2Ö´ÐдÎÊý¼Ó1 ×¢Òâtask1_num2¼Óµ½255µÄʱºò»áÇåÁ㣡£¡
LED1=~LED1;
printf("ÈÎÎñ2ÒѾִÐУº%d´Î\r\n",task2_num);
LCD_ShowxNum(206,111,task2_num,3,16,0x80); //ÏÔʾÈÎÎñÖ´ÐдÎÊý
LCD_Fill(126,131,233,313,lcd_discolor[13-task2_num%14]); //Ìî³äÇøÓò
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //ÑÓʱ1s
}
}
任务 1 运行 5 次后调用 OSTaskSuspend()函数挂起任务 2。当任务 1 运行到第 10 次就调用函数 OSTaskResume()函数解挂任务 2。
总结
学了FreeRTOS之后在学ucos感觉很简单,其实都是相同的,只是用的函数不一样。