UCOSIII(一)

  • 格式:pdf
  • 大小:288.42 KB
  • 文档页数:7

UCOSIII(⼀)

⼀,前后台系统和RTOS

1,前后台系统

早期嵌⼊式开发没有嵌⼊式操作系统的概念 ,直接操作裸机,在裸机上写程序,⽐如⽤51单⽚机基本就没有操作系统的概念。通常把程序分为

两部分:前台系统和后台系统。

简单的⼩系统通常是前后台系统,这样的程序包括⼀个死循环和若⼲个中断服务程序:

应⽤程序是⼀个⽆限循环,循环中调⽤API函数完成所需的操作,这个⼤循环就叫做后台系统。

中断服务程序⽤于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。

2,RTOS

RTOS全称为: Real Time OS,就是实时操作系统,强调的是: 实时性。实时操作系统⼜分为硬实时和软实时。

硬实时要求在规定的时间内必须完成操作 ,硬实时系统不允许超时,在软实时⾥⾯处理过程超时的后果就没有那么严格。

在实时操作系统中,我们可以把要实现的功能划分为多个任务,每个任务负责实现其中的⼀部分,每个任务都是⼀个很简单的程序,通常是⼀

个死循环。

RTOS操作系统: UCOS, FreeRTOS, RTX, RT-Thread, DJYOS等。

RTOS操作系统的核⼼内容在于: 实时内核。

3,可剥夺型内核

RTOS的内核负责管理所有的任务,内核决定了运⾏哪个任务,何时停⽌当前任务切换到其他任务,这个是内核的多任务管理能⼒。

多任务管理给⼈的感觉就好像芯⽚有多个CPU,多任务管理实现了CPU资源的最⼤化利⽤,多任务管理有助于实现程序的模块化开发,能够实

现复杂的实时应⽤。

可剥夺内核顾名思义就是可以剥夺其他任务的CPU使⽤权,它总是运⾏就绪任务中的优先级最⾼的那个任务

UCOS系统简介

UCOS是Micrium公司出品的RTOS类实时操作系统, UCOS⽬前有两个版本:

UCOSII和UCOSIII。

UCOSIII是⼀个可裁剪、可剥夺型的多任务内核,⽽且没有任务数限制。

UCOSIII提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。

UCOSIII是⽤C和汇编来写的,其中绝⼤部分都是⽤C语⾔编写的,只有极少数的与处理器密切相关的部分代码才是⽤汇编写的, UCOSIII结构

简洁,可读性很强!最主

要的是⾮常适合初次接触嵌⼊式实时操作系统学⽣、嵌⼊式系统开发⼈员和爱好者学习。

#include "sys.h"

#include "delay.h"

#include "usart.h"

#include "led.h"

#include "includes.h"

#include "dht.h"

#include "infra_red.h"

//任务1控制块

OS_TCB Task1_TCB;

void task1(void *parg);

CPU_STK task1_stk[128]; //任务1的任务堆栈,⼤⼩为128字,也就是512字节

//任务2控制块

OS_TCB Task2_TCB;

void task2(void *parg);

CPU_STK task2_stk[128]; //任务2的任务堆栈,⼤⼩为128字,也就是512字节

//主函数

int main(void)

{

OS_ERR err;

delay_init(168); //时钟初始化

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断分组配置

uart_init(9600); //串⼝初始化

LED_Init(); //LED初始化

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); //打开温湿度模块控制GPIOG的时钟 //OS初始化,它是第⼀个运⾏的函数,初始化各种的全局变量,例如中断嵌套计数器、优先级、存储器

OSInit(&err);

//创建任务1

OSTaskCreate( (OS_TCB *)&Task1_TCB, //任务控制块

(CPU_CHAR *)"Task1", //任务的名字

(OS_TASK_PTR)task1, //任务函数

(void *)0, //传递参数

(OS_PRIO)3, //任务的优先级

(CPU_STK *)task1_stk, //任务堆栈基地址

(CPU_STK_SIZE)128/10, //任务堆栈深度限位,⽤到这个位置,任务不能再继续使⽤

(CPU_STK_SIZE)128, //任务堆栈⼤⼩

(OS_MSG_QTY)0, //禁⽌任务消息队列

(OS_TICK)0, //默认时间⽚长度

(void *)0, //不需要补充⽤户存储区

(OS_OPT)OS_OPT_TASK_NONE, //没有任何选项

&err //返回的错误码

);

//创建任务2

OSTaskCreate( (OS_TCB *)&Task2_TCB, //任务控制块

(CPU_CHAR *)"Task2", //任务的名字

(OS_TASK_PTR)task2, //任务函数

(void *)0, //传递参数

(OS_PRIO)4, //任务的优先级

(CPU_STK *)task2_stk, //任务堆栈基地址

(CPU_STK_SIZE)128/10, //任务堆栈深度限位,⽤到这个位置,任务不能再继续使⽤

(CPU_STK_SIZE)128, //任务堆栈⼤⼩

(OS_MSG_QTY)0, //禁⽌任务消息队列

(OS_TICK)0, //默认时间⽚长度

(void *)0, //不需要补充⽤户存储区

(OS_OPT)OS_OPT_TASK_NONE, //没有任何选项

&err //返回的错误码

);

//启动OS,进⾏任务调度

OSStart(&err);

}

void task1(void *parg)

{

OS_ERR err;

uint8_t dht_data[5]={0};

printf("task1 is create ok\r\n");

//红外初始化

ir_init();

while(1)

{

if(dht11_read_data(dht_data)==0)

{

printf("temp=%d.%d\r\n",dht_data[2],dht_data[3]);

printf("humi=%d.%d\r\n",dht_data[0],dht_data[1]);

printf("\r\n");

}

delay_ms(500);

delay_ms(500);

OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s

}

}

void task2(void *parg)

{

OS_ERR err;

printf("task2 is create ok\r\n");

while(1)

{

//添加LED2闪烁

printf("task2 is running ...\r\n");

OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1s

}}

(1)假如任务1和任务2两个任务的优先级都是⼀样的,⽽且任务1⽐任务2创建更早,会出现什么结果?例如任务1和任务2的运⾏代码是⼀样

的。如下:

void task1(void *parg)

{

OS_ERR err;

printf("task1 is create ok\r\n");

while(1)

{

printf("task1 is running ...\r\n");

}

}

void task2(void *parg)

{

OS_ERR err;

printf("task2 is create ok\r\n");

while(1)

{

printf("task2 is running ...\r\n");

}

}

结果

task1 is running ...

task1 is running ...

task1 is running ...

task1 is running ...

task1 is running ...

......

当两个任务的优先级都是⼀样且最⾼,这个两个任务都没有任何的让出CPU的函数,在执⾏的时候,只执⾏创建最早的任务,任务1是⽐任务2

创建更早,只能执⾏任务1.

(2)任务1的优先级是⽐任务2⾼,代码如下:

void task1(void *parg)

{

OS_ERR err;

printf("task1 is create ok\r\n"); while(1)

{

printf("task1 is running ...\r\n");

OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时10ms

}

}

void task2(void *parg)

{

OS_ERR err;

printf("task2 is create ok\r\n");

while(1)

{

printf("task2 is running ...\r\n");

OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时10ms

}

}

结果:

task2task1 is running ...

is task1 is running ...

runntask1 is running ...

ing task1 is running ...

...

task1 is running ...

task1 is running ...

task2task1 is running ...

在任务2在打印的过程当中,打印数据时间超过10ms,所以在打印的中途ucos发现任务1已经就绪了,任务1就会抢夺CPU的使⽤权,任务2就

停⽌执⾏,等任务1执⾏完之后让出CPU,任务2才继续执⾏。

(三)临界区代码⽤于资源保护,以下有两种的编写⽅法,哪⼀种才是正确的?

1,

//进⼊临界区,保护以下的代码,关闭总中断,停⽌了ucos的任务调度,其他任务已经停⽌执⾏

OS_CRITICAL_ENTER();

printf("task1 is running ...\r\n");

//退出临界区,开启总中断,允许ucos的任务调度

OS_CRITICAL_EXIT();

OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1000ms

2,

//进⼊临界区,保护以下的代码,关闭总中断,停⽌了ucos的任务调度,其他任务已经停⽌执⾏

OS_CRITICAL_ENTER();

printf("task1 is running ...\r\n");

OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延时1000ms

//退出临界区,开启总中断,允许ucos的任务调度

OS_CRITICAL_EXIT();

只有例⼦1才是正确的,能够进⾏准确的延时,唯独只有例⼦2延时是失效的。

在进⼊临界区代码,因为它是关闭了总中断,所以跟阻塞相关、时间管理函数都会失效。

在ucos3,提供的最⼩毫⽶级别的延时是多少,依据是什么?