天天看点

嵌入式实时操作系统ucosii原理及应用(任哲)

本文是《嵌入式实时操作系统ucosii原理及应用(任哲)》一书第三章的阅读笔记,知识点多为摘录,若希望深入了解,请购买该书认真研读。由于一些知识比较零散,记起来不大方便,又习惯画图辅助记忆,刚好想起一款比较好用的思维导图,就顺手拿来用一用了(绝非打广告),导图中包含部分备注。

嵌入式实时操作系统ucosii原理及应用(任哲)

脑图链接及密码:http://naotu.baidu.com/file/c550d674fa54bd29588c31c5bd682f4f?token=8e71f5732699f4b6 密码: v6um

嵌入式实时操作系统ucosii原理及应用(任哲)

可以看出:A)任务必须先从睡眠状态进入就绪状态,才能在合适的时机被运行;B)只能从运行状态进入中断服务状态;C)只能从运行状态进入等待状态。

前面一章我们已经讲过:大多数任务(尤其是用户任务)是一个无限循环结构,在这个循环中,系统响应中断请求,进入中断服务函数进行其他操作。但是,有时任务中的一些操作是不允许被中断打断的,为此,我们可以在任务函数程序代码中添加关中断函数和开中断函数,则在这两个函数之间的代码,执行过程不会被打断,该段代码称为临界段。ucosii中用两个宏:OS_ENTER_CRITICAL( )、OS_EXIT_CRATICAL( )分别实现关中断和开中段。从程序设计角度看,一个ucosii任务的代码就是一个C语言函数,为了可以传递各种不同类型的数据甚至是函数,ucosii把任务参数定义成了一个void类型的指针。

用户应用程序的一般结构:

在ucosii中,main函数与任务函数的地位是平等的,虽然任务是在main函数中初始化的,但是任务和main的运行与中断是由操作系统调度的,也就是说,作为程序运行的入口函数,main函数必须完成操作系统的初始化、任务的创建、操作系统的启动,最后把系统的调度权交回给操作系统。

void MyTask1(void *pdata)

{

for( ; ; )

{

//这上面的代码执行时可以被打断

OS_ENTER_CRITICAL( );

//临界段

//这中间执行的代码不可以被打断

OS_ENTER_CRITICAL( );

}

}

void MyTask2(void *pdata)

{

for( ; ; )

{

//这上面的代码执行时可以被打断

OS_ENTER_CRITICAL( );

//临界段

//这中间执行的代码不可以被打断

OS_ENTER_CRITICAL( );

}

}

void main(void)

{

OS_Init( );

OSTaskCreate(MyTask1,...);

OSTaskCreate(MyTask2,...);

OS_Start( );

}

操作系统运行时,一定有某段时间处于空闲状态,但是CPU是不可以停下来的,除非断电。为此,ucosii定义了两个系统任务:空闲任务和统计任务。空闲任务是用户应用程序必须使用的,统计任务是用户程序可选择使用的。

//操作系统定义的空闲任务

void OS_TaskIdle(void *pdata)

{

#if(OS_CRITICAL_METHOD == 3)

OS_CPU_SR cpu_sr;

#endif

//部分C编译器会对定义了却没有使用的变量报错

pdata = pdata;

for( ; ; )

{

OS_ENTER_CRITICAL( );

OSIdleCtr++; //记录空闲任务运行次数

OS_EXIT_CRITICAL( );

//一般还会加上下面这个函数,用户可以在该函数中写用户希望执行的代码

//一般函数内写的是让CPU进入低功耗模式的指令

//该函数总是处于就绪状态的

OSTaskIdleHook( );

}

}

至于统计任务,该任务每秒计算一次CPU在单位时间内被使用的时间,并把计算结果以百分比的形式存放在变量OSCPUsage中,从而使得应用程序可以了解CPU的利用率。

当不同任务同时需要运行时,系统利用优先级判断哪个先执行,由于大多数情况下任务数少于64个,用户可以通过修改OS_CFG.h文件的OS_LOWEST_PRIO来确定最低优先级(优先级为:0~OS_LOWEST_PRIO)。OS_LOWEST_PRIO赋给空闲任务,如果用户使用了统计任务,系统还会把(OS_LOWEST_PRIO-1)赋给统计任务,用户可以使用的优先级范围为:0~OS_LOWEST_PRIO-2,在创建任务时,用户必须指定任务的优先级(指定OSTaskCreate( )第四个参数)。

任务堆栈:任务的运行环境,在程序设计上体现为一数组,出栈入栈遵循LIFO后进先出的原则。任务堆栈的定义:宏定义设置堆栈存储单位(可理解为数据类型)type、宏定义设置堆栈大小size、用type定义大小为size的数组用作任务堆栈。

任务的定义:使用系统函数OSTaskCreate(指向任务代码的指针,传递给任务的参数,任务堆栈的栈顶指针,任务优先级),需要提醒的是,处理器不同,栈的生长方向不同,stm32f103的栈生长方向是从高地址到低地址,所以栈顶指针是堆栈数组的最后一个成员的地址。

int 16位;unsigned int 位数与操作系统相关。

任务堆栈的初始化:由于任务的运行前,CPU的各个寄存器需要预置一些原始数据,包括指向任务的指针、程序状态字PSW等,因为它们因任务不同而有差异,所以存储在任务堆栈中,创建任务时将这些值放入堆栈中称为堆栈的初始化。堆栈的初始化由OSTaskCreat( )函数调用OSTaskStkInit( )实现,用户除了在移植操作系统时修改它,基本不会接触到这个函数。

附上一篇的脑图链接及密码:http://naotu.baidu.com/file/8910fc6778b390b730a755e610790477?token=86bdf5ad5bee75c3 密码: SC2h