第1章μC/OS-II微小内核分析本章导读•为了方便初学者学习嵌入式实时操作系统的基本原理,作者将μC/OS-IIV2.52由小到大裁减为几个只具备基本功能的微小内核。•通过分析仅仅418行的操作系统最小内核,带领初学者尽快入门。•作者建议在学习或教授本章的过程中,初学者或教师要边阅读原码,边画图,深刻理解过程,因为“过程比结论更重要!”。目录概述最小内核临界区与中断管理任务的结束信号量删除信号量目录概述最小内核临界区与中断管理任务的结束信号量删除信号量1.1概述•μC/OS-II微小内核简介μC/OS-II体系结构µC/OS-II与处理器无关的代码OS_Q.COS_CORE.COS_SEM.COS_FLAG.COS_TASK.COS_MBOX.COS_TIME.COS_MEM.CuCOS_H.COS_MUTEX.CuCOS_H.HCPU定时器硬件软件µC/OS-II与处理器相关的代码(移植时需要修改)OS_CPU.HOS_CPU_A_ASMOS_CPU_C.CµC/OS-II与应用程序相关的代码OS_CFG.HINCLUDES.H用户应用程序µC/OS-IIμC/OS-II嵌入式实时操作系统的源代码可以分成三部分:与硬件无关的内核代码、与处理器有关的移植代码和用户配置文件。1.1概述•μC/OS-II微小内核简介-内核代码内核代码位于source目录下,提供了4个微小内核。它们分别位于source\SOURCE1(包含建立任务和延时功能)、source\SOURCE2(增加删除任务功能)、source\SOURCE3(增加信号量文件)和source\SOURCE4(增加删除信号量功能)。它们的功能依次增强,代码也依次增大。以上代码并没有完全裁减到最小,还包含了一些参数校验代码等非必需代码,μC/OS-II的代码裁减功能也同时保留,这些代码大约50多行。1.1概述•μC/OS-II微小内核简介-移植代码本书提供基于ARM的移植代码,位于arm目录下,分别为OS_CPU_C.C(移植代码C语言部分)、OS_CPU_a.S(移植代码汇编语言部分)、OS_CPU.H(移植代码头文件)和IRQ.INC(移植代码与芯片无关的中断处理接口程序)4个文件。1.1概述•μC/OS-II微小内核简介-配置文件配置文件是每个μC/OS-II程序必备的文件,而且不同的程序一般不一样,但大小基本上相同。配置文件范例位于H目录下,分别为INCLUDES.H(内核需要的头文件,对于特定的移植,一般不需要改变)和OS_CFG.H(内核配置的头文件,一般需要根据程序的需求修改其常量的内容)文件。一般来说,每个应用程序都有自己的配置文件拷贝,并很可能与范例不同。1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSInit函数。函数名称OSInit所属文件OS_CORE.C函数原型voidOSInit(void)功能描述初始化μC/OS-Ⅱ,无函数参数和返回值特殊说明必须在调用OSStart()函数之前调用OSInit(),而只有在调用OSStart()函数之后,μC/OS-Ⅱ才真正开始运行多任务1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSStart函数。函数名称OSStart所属文件OS_CORE.C函数原型voidOSStart(void)功能描述启动μC/OS-II的多任务环境,无函数参数和返回值特殊说明在调用OSStart()之前必须先调用OSInit()。在用户程序中OSStart()只能被调用一次,第二次调用OSStart()将不执行任何操作1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSTaskCreate函数。函数名称OSTaskCreate所属文件OS_TASK.C函数原型INT8UOSTaskCreate(void(*task)(void*pd),void*pdata,OS_STK*ptos,INT8Uprio)功能描述建立一个新任务。既可以在多任务环境启动之前,也可以在正在运行的任务中创建任务函数参数task:指向任务代码的指针(函数指针)pdata:传递给任务的参数(一个变量指针)ptos:指向任务堆栈栈顶的指针prio:任务的优先级特殊说明任务堆栈必须声明为OS_STK类型。注意:在中断处理程序中不能建立任务。在任务中必须调用μC/OS提供的下述过程之一:延时等待、任务挂起、等待事件发生(等待信号量,消息邮箱、消息队列),以便其它任务也能获得CPU的使用权1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSTimeDly函数。函数名称OSTimeDly所属文件OS_TIME.C函数原型voidOSTimeDly(INT16Uticks)功能描述将一个任务延时若干个时钟节拍,无函数返回值。延时时间的长度可从0到65535个时钟节拍,延时时间0表示不进行延时,函数将立即返回调用者,延时的具体时间依赖于系统每秒钟有多少时钟节拍(由文件OS_CFG..H中的常量OS_TICKS_PER_SEC设定)函数参数ticks:要延时的时钟节拍数特殊说明延时时间0表示不进行延时操作,而立即返回调用者。为了确保设定的延时时间,建议用户设定的时钟节拍数加1。例如,希望延时10个时钟节拍,可设定参数为111.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSTimeTick函数。函数名称OSTimeTick所属文件OS_CORE.C函数原型voidOSTimeTick(void)功能描述在每次时钟节拍中断服务程序中被调用,无函数参数和返回值。OSTimeTick()检查处于延时状态的任务是否达到延时时间,或正在等待事件的任务是否超时特殊说明OSTimeTick()的运行时间和系统中的任务数直接相关,在任务或中断中都可以调用。如果在任务中调用,任务的优先级应该很高(优先级数字很小),这是因为OSTimeTick()负责所有任务的延时操作1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSTaskDel函数。函数名称OSTaskDel所属文件OS_TASK.C函数原型INT8UOSTaskDel(INT8Uprio)功能描述删除一个指定优先级的任务。被删除的任务将回到休眠状态,任务被删除后可以用函数OSTaskCreate()重新建立函数参数prio:指定要删除任务的优先级,如果为OS_PRIO_SELF则删除自身函数返回值OS_NO_ERR:函数调用成功OS_TASK_DEL_IDLE:错误,试图删除空闲任务(Idletask)OS_TASK_DEL_ERR:错误,指定要删除的任务不存在OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIOOS_TASK_DEL_ISR:错误,试图在中断处理程序中删除任务1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSIntEnter函数。函数名称OSIntEnter所属文件OS_CORE.C函数原型voidOSIntEnter(void)功能描述通知μC/OS-Ⅱ一个中断服务已开始执行,这有助于μC/OS-Ⅱ掌握中断嵌套的情况。通常OSIntExit()和OSIntEnter()联合使用,无函数参数和返回值特殊说明在中断服务程序中,如果保证直接递增OSIntNesting“原子操作”,中断服务程序使用直接递增OSIntNesting的方法而不调用OSIntEnter()函数何为原子操作?在一个任务的执行过程中,如果有某些操作不希望在执行过程中被别的任务或中断打断,那么这些不希望被打断的操作就是原子操作1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSIntExit函数。函数名称OSIntExit所属文件OS_CORE.C函数原型voidOSIntExit(void)功能描述通知μC/OS-Ⅱ一个中断服务已执行完毕,这有助于μC/OS-Ⅱ掌握中断嵌套的情况。通常OSIntExit()和OSIntEnter()联合使用。当最后一层嵌套的中断执行完毕后,如果有更高优先级的任务准备就绪,μC/OS-Ⅱ会调用任务调度函数,在这种情况下,中断返回到更高优先级的任务而不是被中断了的任务。无函数参数和返回值特殊说明在任务级不能调用该函数。即使中断服务程序使用直接递增OSIntNesting的方法(没有调用OSIntEnter()),也必须调用OSIntExit()函数1.1概述•函数说明μC/OS-II微小内核SOURCE4提供禁止/允许中断函数。函数名称OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()所属文件移植代码函数原型由移植代码决定功能描述一般来说,OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()为定义的宏,用来禁止、打开CPU的中断,无函数参数和返回值特殊说明OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()必须成对使用1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSSemCreate函数。函数名称OSSemCreate所属文件OS_SEM.C函数原型OS_EVENT*OSSemCreate(INT16Ucnt)功能描述建立并初始化一个信号量函数参数cnt:建立的信号量的初始值,可以取0到65535之间的任何值函数返回值正常:指向分配给所建立的信号量的事件控制块的指针NULL:没有可用的事件控制块特殊说明必须先建立信号量,然后使用1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSSemPend函数。函数名称OSSemPend所属文件OS_SEM.C函数原型voidOSSemPend(OS_EVENT*pevent,INT16Utimeout,INT8U*err)功能描述等待信号量:当任务调用OSSemPend()函数时,如果信号量的值大于零,那么OSSemPend()函数对该值减一并返回:如果调用时信号量等于零,那么OSSemPend()函数将任务加入该信号量的等待列表,任务将等待直到获得信号量或超时函数参数cnt:建立的信号量的初始值,可以取0到65535之间的任何值特殊说明必须先建立信号量,然后使用,不允许在中断中调用该函数,因为中断不能被挂起1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSSemPost函数。函数名称OSSemPost所属文件OS_SEM.C函数原型INT8UOSSemPost(OS_EVENT*pevent)功能描述发送信号量:如果指定的信号量是零或大于零,OSSemPost()函数递增该信号量并返回。如果有任务在等待信号量,则最高优先级的任务将得到信号量并进入就绪状态。然后进行任务调度,决定当前运行的任务是否仍然为处于最高优先级的就绪态的任务函数参数pevent:指向信号量的指针,OSSemCreate()的返回值函数返回值OS_NO_ERR:发送信号量成功OS_SEM_OVF:信号量的值溢出OS_ERR_EVENT_TYPE:pevent不是指向信号量的指针OS_ERR_PEVENT_NULL:错误,pevent为NULL特殊说明必须先建立信号量,然后使用1.1概述•函数说明μC/OS-II微小内核SOURCE4提供OSSemDel函数。函数名称OSSemDel所属文件OS_SEM.C函数原型OS_EVENT*OSSemDel(OS_EVENT*pevent,INT8Uopt,INT8U*err)功能描述删除信号量:在删除信号量之前,应当删除可能会使用这个信号量的任务函数参数pevent:指向信号量的指针,OSSemCreate()的返回值opt:定义信号量删除条件-OS_DEL_NO_PEND:没有任何任务等待信号量才删除-OS_DEL_ALWAYS:立即删除err:用于返回错误码特殊说明(1)使用这个函数调用时,必须特别小心,因为其它任务可能还要用这个信号量(2)当挂起任务就绪