功能
- 帮助初学者初识UCOSIII
- 掌握UCOSIII的基本知识,具体包括任务的创建与删除、任务的挂起与恢复、软件定时器、信号量和互斥信号量、消息的传递等
一、简介
μC/OS-II由Micrium公司提供,是一个可移植、可固化的、可裁剪的、占先式多任务实时内核,它适用于多种微处理器,微控制器和数字处理芯片(已经移植到超过100种以上的微处理器应用中)。同时,该系统源代码开放、整洁、一致,注释详尽,适合系统开发。 μC/OS-II已经通过联邦航空局(FAA)商用航行器认证,符合航空无线电技术委员会(RTCA)DO-178B标准。现在最新版的是μC/OS-III。
μC/OS-II可以大致分成核心、任务处理、时间处理、任务同步与通信,CPU的移植等5个部分。
- 核心部分(OSCore.c)
是操作系统的处理核心,包括操作系统初始化、操作系统运行、中断进出的前导、时钟节拍、任务调度、事件处理等多部分。能够维持系统基本工作的部分都在这里。 - 任务处理部分(OSTask.c)
任务处理部分中的内容都是与任务的操作密切相关的。包括任务的建立、删除、挂起、恢复等等。因为μC/OS-II是以任务为基本单位调度的,所以这部分内容也相当重要。 - 时钟部分(OSTime.c)
μC/OS-II中的最小时钟单位是timetick(时钟节拍)。任务延时等操作是在这里完成的。 - 任务同步和通信部分
为事件处理部分,包括信号量、邮箱、邮箱队列、事件标志等部分;主要用于任务间的互相联系和对临界资源的访问。 - 与CPU的接口部分
是指μC/OS-II针对所使用的CPU的移植部分。由于μC/OS-II是一个通用性的操作系统,所以对于关键问题上的实现,还是需要根据具体CPU的具体内容和要求作相应的移植。这部分内容由于牵涉到SP等系统指针,所以通常用汇编语言编写。主要包括中断级任务切换的底层实现、任务级任务切换的底层实现、时钟节拍的产生和处理、中断的相关处理部分等内容。
二、基础知识
1、任务的创建
①定义相关参数
#define LED1_TASK_PRIO 5
#define LED1_STK_SIZE 128
OS_TCB Led1TaskTCB;
CPU_STK LED1_TASK_STK[LED1_STK_SIZE];
void led1_task(void *p_arg);
②创建任务
OSTaskCreate((OS_TCB * )&Led1TaskTCB,
(CPU_CHAR * )"led1 task",
(OS_TASK_PTR )led1_task,
(void * )0,
(OS_PRIO )LED1_TASK_PRIO,
(CPU_STK * )&LED1_TASK_STK[0],
(CPU_STK_SIZE)LED1_STK_SIZE/10,
(CPU_STK_SIZE)LED1_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);
③编写任务函数
void led1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED1=~LED1;
OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err);
}
}
2、任务的挂起与恢复
在这里插入代码片
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++;
LED0= ~LED0;
printf("任务1已经执行:%d次\r\n",task1_num);
if(task1_num==5)
{
OSTaskSuspend((OS_TCB*)&Task2_TaskTCB,&err);
printf("任务1挂起了任务2!\r\n");
}
if(task1_num==10)
{
OSTaskResume((OS_TCB*)&Task2_TaskTCB,&err);
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);
}
}
3、任务同步
①定义信号量
OS_SEM MY_SEM;
②在开始任务中创建信号量
OSSemCreate ((OS_SEM* )&MY_SEM,
(CPU_CHAR* )"MY_SEM",
(OS_SEM_CTR)1,
(OS_ERR* )&err);
③使用信号量
void led0_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
OSSemPend(&MY_SEM,0,OS_OPT_PEND_BLOCKING,0,&err);
LED0=~LED0;
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err);
}
}
void led1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED1=~LED1;
OSSemPost (&MY_SEM,OS_OPT_POST_1,&err);
OSTimeDlyHMSM(0,0,2,0,OS_OPT_TIME_HMSM_STRICT,&err);
}
}
4、消息传递
①定义消息队列
#define KEYMSG_Q_NUM 1
#define DATAMSG_Q_NUM 4
OS_Q KEY_Msg;
OS_Q DATA_Msg;
②创建消息队列
OSQCreate ((OS_Q* )&KEY_Msg,
(CPU_CHAR* )"KEY Msg",
(OS_MSG_QTY )KEYMSG_Q_NUM,
(OS_ERR* )&err);
OSQCreate ((OS_Q* )&DATA_Msg,
(CPU_CHAR* )"DATA Msg",
(OS_MSG_QTY )DATAMSG_Q_NUM,
(OS_ERR* )&err);
③任务函数
void tmr1_callback(void *p_tmr,void *p_arg)
{
u8 *pbuf;
static u8 msg_num;
OS_ERR err;
pbuf = mymalloc(SRAMIN,10);
if(pbuf)
{
msg_num++;
sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
OSQPost((OS_Q* )&DATA_Msg,
(void* )pbuf,
(OS_MSG_SIZE)10,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
if(err != OS_ERR_NONE)
{
myfree(SRAMIN,pbuf);
OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err);
tmr1sta = !tmr1sta;
LCD_ShowString(10,150,100,16,16,"TMR1 STOP! ");
}
}
}
void main_task(void *p_arg)
{
u8 key,num;
OS_ERR err;
u8 *p;
while(1)
{
key = KEY_Scan(0);
if(key)
{
OSQPost((OS_Q* )&KEY_Msg,
(void* )&key,
(OS_MSG_SIZE)1,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
}
num++;
if(num%10==0) check_msg_queue(p);
if(num==50)
{
num=0;
LED0 = ~LED0;
}
OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);
}
}
void Keyprocess_task(void *p_arg)
{
u8 num;
u8 *key;
OS_MSG_SIZE size;
OS_ERR err;
while(1)
{
key=OSQPend((OS_Q* )&KEY_Msg,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err);
switch(*key)
{
case WKUP_PRES:
LED1 = ~LED1;
break;
case KEY2_PRES:
BEEP = ~BEEP;
break;
case KEY0_PRES:
num++;
LCD_Fill(126,111,233,313,lcd_discolor[num%14]);
break;
case KEY1_PRES:
tmr1sta = !tmr1sta;
if(tmr1sta)
{
OSTmrStart(&tmr1,&err);
LCD_ShowString(10,150,100,16,16,"TMR1 START!");
}
else
{
OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err);
LCD_ShowString(10,150,100,16,16,"TMR1 STOP! ");
}
break;
}
}
}
void msgdis_task(void *p_arg)
{
u8 *p;
OS_MSG_SIZE size;
OS_ERR err;
while(1)
{
p=OSQPend((OS_Q* )&DATA_Msg,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err);
LCD_ShowString(5,270,100,16,16,p);
myfree(SRAMIN,p);
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);
}
}
欢迎一起讨论技术问题,求关注!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)