ucos

来源:互联网 发布:java执行多个cmd命令 编辑:程序博客网 时间:2024/03/29 15:11

 重入与不可重入:

可重入函数指当一个函数在被调用时,同时还能被其他函数调用,且不会产生错误.
不可重入函数则不能同时被多次调用,多次调用可能会产生错误.

例子:某函数有一个变量为全局变量,则如果该函数有多个实例在交替运行的话,由于同时存取
同一全局变量,导致该变量被不同实例改变而引起错误.

信号量:
与同一共享数据打交道(可能是全局变量,也可能是共享资源如UART,打印机等)的任务调用等待
信号量函数OSSemPend(),处理完后调用释放信号量函数OSSemPost().
为防止无限等待可设置等待超时.

例子:
//任务Task要存取共享数据,如果该数据正在被其他任务使用,则任务Task只能等待别的任务用
//完,然后分配给任务Task使用.用完后释放该信号量,以供给其他任务使用(或者说将资源归还
//给操作系统).
void Task(void)
{
    OSSemPend(...);
    perform operation;    //porcess the data
    OSSemPost(...);
}

信号量也可能是隐藏的.如多任务共享UART时,信号量可隐藏在驱动函数中.

信号量操作:
初始化/建立 INITILIZE/CREATE
等待信号/挂起 WAIT/PEND
给信号 SIGNAL/POST

信号量类型:
二进制    0/1
计数型    0 ~ 2^width - 1
如果某种资源只有1个,可用二进制型信号量,如RS232接口.
如果资源有多个,可用计数型信号量,如系统缓冲区一般有多个.

死锁:
两个任务无限期相互等待对方控制的资源.可用信号量等待超时来化解.

事件标志(Event Flag)
用于任务与多个事件同步.
可用多个事件的组合发信号给多个任务.
可将8/16/32个事件标志组合在一起,当任务所需的事件都发生了,任务结束挂起,继续运行


任务间通讯(Intertask Communication)
两个途径:
1.通过全局变量.与中断函数进行通讯只能通过全局变量.
2.发送消息给另一个任务.

发送消息的方式有邮箱(Mail Box)和消息队列(Message Queue)

邮箱(Mail Box)
一个任务通过内核服务给另一个任务发消息.
内核提供的邮箱服务:
邮箱内消息内容初始化;
将消息放入邮箱(POST);
等待有消息进入邮箱(PEND);

例子:
TASK1 --(POST)--> MAIL BOX --(PEND)--> TASK2

可在主程序中创建邮箱,则在任务中就可直接使用.
疑问:也可在任务中创建邮箱,但此时,邮箱能否接收其他任务发送消息?能否发送消息给其他任务?

消息队列(Message Queue)
实际上是邮箱阵列.
任务或ISR可将消息放入消息队列(POST),一个或多个任务可从消息队列中得到消息.
传递的消息实际上是传递的指针指向的内容.消息队列的进出通常有规则,如FIFO.

例子:
ISR --(POST)--> MSG QUEUE --(PEND)--> TASK

疑问:消息队列属于某个任务?还是所有任务公用的?任务能从消息队列中取得消息,
并执行相应的操作.任务也可以向外发送消息,但是是否应该指明发送的消息是送给谁的?
在Windows系统的应用程序中,程序的运行是基于事件驱动,消息循环的.每个应用程序进程
都有自己的消息队列.如一个进程1发送消息给进程2,进程2收到消息便继续往下执行,否则
就挂起什么都不干.也即是没有事件的驱动,程序是不往下运行的.程序的运行就是依靠不
断的消息循环来进行下去,程序从消息队列中接收自己的消息,而发送消息时需指明将消息
送给哪个进程.

某一个进程发送一条消息,指明了需要送给哪个进程,该消息进入系统的消息队列,系统将
该则消息投递到目的进程的消息缓存中.而接收消息的进程则读取消息并处理消息.
在这个过程中,系统就像一个邮局,进程发送消息就像寄信,系统投递消息就像邮递员送信.

在uC/OS中,可以创建一个消息队列,并返回一个该消息队列的标识,用户任务就可以通过
这个标识向队列中发送消息或接收消息,这样看来不在发送消息时指定接收消息的任务是
可以的.但当任务较多,且创建了较多的消息队列后,多个任务使用消息队列时是否会产生
误发送或误接收等问题.对于uC/OS中的其他类型资源如Mail Box也是如此.


用户应用uC/OS系统的框架:

main()
{
    ...
    OSInit();
    ...
    OSTaskCreate();
    ...
    OSStart();
}

OSInit()会进行一些初始化,包括Mail Box,Queue,Memory Partition等的初始化.
并创建OS_Idle_Task.

OSTaskCreate()用来创建用户任务,uC/OS应该也支持动态创建任务,即在用户任务中来
创建其他任务,并可将其删除.不过uC/OS称任务被删除后,代码仍在,只是不再调度该任
务.而Linux则是将任务从内存中释放.这可能与CPU有关.如果是哈佛结构的(如51单片
机),代码是存放在ROM中的,无法删除,一般对于嵌入式系统而言,多数都是属于哈佛结
构的CPU吧.而PC机的CPU是普林斯顿结构,程序代码和数据都是存放于内存中的,当一个
任务不再运行了,就可释放其占据的内存空间,以供其他程序使用.

OSStart()开始进行调度.

原创粉丝点击