分类:
2010-04-17 15:17:17
任何一个操作系统都会提供大量的API供程序员使用,μC/OS-Ⅱ也不例外。由于μC/OS-Ⅱ面向的是嵌入式开发,并不要求大而全,所以内核提供的API也就大多和多任务息息相关。本文通过分析μC/OS-Ⅱ中提供的API来引出μC/OS-Ⅱ中API的设计思路和实现机制。
API全称Application Programming Interface,中文是应用程序编程接口的意思。API是操作系统提供给用户的一组函数,供用户在编写应用程序时调用,可以完成应用程序对操作系统的各种调用,包括进程调度、存储管理、图形设备接口及文件管理等。μC/OS-Ⅱ作为一个嵌入式操作系统,相对于其他操作系统,有很多自己的特色,在设计思路和实现机制上都和一般操作系统有很大的不同。
1. 简介
任何一个操作系统都会提供大量的API供程序员使用,μC/OS-Ⅱ也不例外。由于μC/OS-Ⅱ面向的是嵌入式开发,并不要求大而全,所以内核提供的API也就大多和多任务息息相关。μC/OS-Ⅱ的API主要分以下几类:(1)任务类、(2)消息类、(3)同步类、(4)时间类、(5)临界区与事件类等。下面分别从这几类API分析各自的设计思路和实现机制。
2. 任务类API的设计思路和实现机制
μC/OS-Ⅱ可以管理多达64个任务,并从中保留了四个最高优先级和四个最低优先级的任务供自己使用,所以用户可以使用的只有56个任务。任务类API包括如何在用户的应用程序中建立任务、删除任务、改变任务的优先级、挂起和恢复任务,以及获得有关任务的信息等。
2.1 建立任务API
想让μC/OS-Ⅱ管理用户的任务,用户必须要先建立任务。用户可以通过传递任务地址和其它参数到以下两个函数之一来建立任务:OSTaskCreate() 或 OSTaskCreateExt()。
OSTaskCreate()与μC/OS是向下兼容的,OSTaskCreateExt()是OSTaskCreate()的扩展版本,提供了一些附加的功能。用两个函数中的任何一个都可以建立任务。任务可以在多任务调度开始前建立,也可以在其它任务的执行过程中被建立。在开始多任务调度(即调用OSStart())前,用户必须建立至少一个任务。任务不能由中断服务程序(ISR)来建立。
OSTaskCreate()的函数定义如下。从中可以知道,OSTaskCreate()需要四个参数:task是任务代码的指针,pdata是当任务开始执行时传递给任务的参数的指针,ptos是分配给任务的堆栈的栈顶指针,prio是分配给任务的优先级。
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio) |
用OSTaskCreateExt()函数来建立任务会更加灵活,但会增加一些额外的开销。
OSTaskCreateExt()需要九个参数!前四个参数(task,pdata,ptos和prio)与OSTaskCreate()的四个参数完全相同,连先后顺序都一样。这样做的目的是为了使用户能够更容易地将用户的程序从OSTaskCreate()移植到OSTaskCreateExt()上去。函数的定义如下:
INT8U OSTaskCreateExt (void (*task)(void *pd), |
void *pdata, |
OS_STK *ptos, |
INT8U prio, |
INT16U id, |
OS_STK *pbos, |
INT32U stk_size, |
void *pext, |
INT16U opt) |
2.2 删除任务API
有时候删除任务是很有必要的。删除任务,是说任务将返回并处于休眠状态,并不是说任务的代码被删除了,只是任务的代码不再被μC/OS-Ⅱ调用。通过调用OSTaskDel()就可以完成删除任务的功能。OSTaskDel()一开始应确保用户所要删除的任务并非是空闲任务,因为删除空闲任务是不允许的。不过,用户可以删除statistic任务。接着,OSTaskDel()还应确保用户不是在ISR例程中去试图删除一个任务,因为这也是不被允许的。调用此函数的任务可以通过指定OS_PRIO_SE
INT8U OSTaskDel (INT8U prio) |
2.3 改变任务优先级API
在用户建立任务的时候会分配给任务一个优先级。在程序运行期间,用户可以通过调用OSTaskChangePrio()来改变任务的优先级。换句话说,就是μC/OS-Ⅱ允许用户动态的改变任务的优先级。函数定义如下:
INT8U OSTaskChangePrio (INT8U oldprio, INT8U ne |
用户不能改变空闲任务的优先级,但用户可以改变调用本函数的任务或者其它任务的优先级。为了改变调用本函数的任务的优先级,用户可以指定该任务当前的优先级或OS_PRIO_SE
2.4 挂起任务和恢复任务API
有时候将任务挂起是很有用的。挂起任务可通过调用OSTaskSuspend()函数来完成。被挂起的任务只能通过调用OSTaskResume()函数来恢复。任务挂起是一个附加功能。也就是说,如果任务在被挂起的同时也在等待延时的期满,那么,挂起操作需要被取消,而任务继续等待延时期满,并转入就绪状态。任务可以挂起自己或者其它任务。
OSTaskSuspend()函数的函数定义如下:
INT8U OSTaskSuspend (INT8U prio) |
恢复任务OSTaskResume()函数定义为:
INT8U OSTaskResume (INT8U prio) |
被挂起的任务只有通过调用OSTaskResume()才能恢复。因为OSTaskSuspend()不能挂起空闲任务,所以必须得确认用户的应用程序不是在恢复空闲任务。注意,这个测试也可以确保用户不是在恢复优先级为OS_PRIO_SE
2.5 获得任务信息API
用户的应用程序可以通过调用OSTaskQue
void MyTask (void *pdata) |
函数参数为一指针变量,指向对应任务的OS_TCB结构地址。本函数是有用的调试工具。
3. 消息和同步类API的设计思路和实现机制
μC/OS-Ⅱ中有三种方法实现消息通信和同步:信号量、邮箱和消息队列。一个任务或者中断服务子程序可以通过事件控制块ECB(Event Control Blo
μC/OS-II中的信号量由两部分组成:一个是信号量的计数值,它是一个16位的无符号整数(0 到65,535之间);另一个是由等待该信号量的任务组成的等待任务表。用户要在OS_
邮箱是μC/OS-II中另一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量。该指针指向一个包含了特定“消息”的数据结构。为了在μC/OS-II中使用邮箱,必须将OS_
消息队列是μC/OS-II中另一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送以指针方式定义的变量。因具体的应用有所不同,每个指针指向的数据结构变量也有所不同。为了使用μC/OS-II的消息队列功能,需要在OS_
μC/OS-Ⅱ提供一系列API函数供用户调用,实现各个任务之间的通信和同步功能。下面以信号量为例说明各个API的实现。
μC/OS-II提供了5个对信号量进行操作的函数。它们是:OSSemCreate(),OSSemPend(),OSSemPost(),OSSemA