绪、jeanjlabrosse的故事80年代末,我设计了一个基于(编辑修改稿)内容摘要:

问共享资源结束以后,释放信号量,调用该函数。 先检查是否有等待该信号量的任务。 没有,信号量计数器加 1,有,则调用调度器 OS_Sched()。 32  删除信号量 OS_EVENT *OSSemDel( OS_EVENT * pevent, INT8U opt, INT8U *err) opt OS_DEL_NO_PEND 没有等待任务删除 OS_DEL_ALLWAYS 立即删除 只能任务执行,不能在中断服务程序中删除  查询信号量的状态 INT8U OSSemQuery( OS_EVENT * pevent OS_SEM_DATA *pdata) pdata是一个结构指针,存储信号量的状态。 33 ( 3)消息邮箱管理 消息邮箱是 uC/OSII中的一种通信机制,通常使用时要先定义一个指针型的变量该指针指向一个包含了消息内容的特定数据结构。 发送消息的任务或中断服务子程序把这个变量送往邮箱,接收消息的任务从邮箱中取出该指针变量,完成信息交换。 uC/OSII提供 6种对消息邮箱的操作,它们通过以下函数实现: 创建 OS_EVENT * OSMoxCreate( void * msg) Msg为消息指针,一般初始为 NULL。 34  向消息邮箱发送消息 INT8U OSMboxPost( OS_EVENT * pevent, void * msg) 发送广播消息 INT8U OSMboxPostOpt( OS_EVENT * pevent, void * msg, INT8U opt) opt: OS_POST_OPT_BROADCAST 广播消息 OS_POST_OPT_NONE 最高优先级 35  请求消息邮箱 void * OSMboxPend( OS_EVENT * pevent, INT16U timeout, INT8U *err)  查询邮箱状态 INT8U OSMboxQuery( OS_EVENT * pevent, OS_MBOX_DATA *pdata)  删除邮箱 OS_EVENT *OSMboxDel( OS_EVENT * pevent, INT8U opt, INT8U *err) 36 ( 4)消息队列管理 消息队列是 uC/OSII的另一种通信机制,它可以使一个任务或中断服务子程序向另一个任务发送以指针定义的变量。 uC/OSII提供了 9个对消息队列进行操作的函数。  创建 先创建一个指针数组,然后用该数组来创建消息队列 OS_EVENT OSQCreate( void ** start,INT16U size)  请求消息队列 void* OSQPend( OS_EVENT * pevent, INT16U timeout,INT8U *err) 37  向消息队列发送消息 INT8U OSQPost( OS_EVENT * pevent,void * msg) 工作方式 FIFO INT8U OSQPostFront( OS_EVENT * pevent,void * msg) 工作方式 LIFO 发送广播消息 INT8U OSQPostOpt( OS_EVENT * pevent,void * msg, INT8U opt) 38  清空消息队列 INT8U OSQFlush ( OS_EVENT * pevent )  删除消息队列 OS_EVENT * OSQDel( OS_EVENT * pevent )  查询消息队列 INT8U OSuery( OS_EVENT * pevent, OS_Q_DATA *pdata) 39 4. 181。 C/ OSII操作系统的文件系统 181。 C/ OSII操作系统的文件体系结构如图 2所示 , 其核心主要可分为以下 3部分: ( 1) 应用软件层 , 指的是基于 181。 C/ OSII的应用程序代码。 ( 2) 内核的核心代码层 , 主要包括 8个源代码文件。 这 8个源代码文件为 、 、 、 、 、 ,其主要实现的功能分别是核心管理 、 事件管理 、 存储管理 、 消息队列管理 、 定时管理 、 信号量处理 、 消息管理和任务调度等 , 这部分代码与处理器无关。 ( 3) 系统设置与移植层。 系统设置部分的代码由两个头文件。 其主要功能是用来配置事件控制块的数目以及是否包含消息管理的相关代码等。 与处理器相关的移植代码部分包括:一个头文件 、 一个汇编文件 C代码文件。 系统设置与移植层与具体应用和处理器相关 , 在随后的 181。 C/ OSII的移植和开发过程中 , 用户所需要关注的就是这部分文件。 40 图 2 181。 C/ OSII文件体系结构 41 181。 C/ OSII 操作系统的初始化 在调用 181。 C/ OSII操作系统的其他服务之前 , 181。 C/ OSII操作系统要求用户首先调用系统初始化函数 OSInit()。 执行 OSInit()函数后将初始化 181。 C/ OSII所有的变量和数据结构 , 另外 OSInit()会建立空闲任务 , 并且这个任务总是处于就绪状态的。 空闲任务OSTaskldle()函数的优先级总是设置成为最低级别 , 即OS_LOWEST_PRIO。 多任务的启动是用户通过调用 OSStart()函数来实现的。 然而 ,在启动 181。 C/ OSII之前 , 用户至少要建立一个应用任务 , 例如: void main() { OSInit()。 .. 通过 OSTaskCreate()或 OSTaskCreateExt()创建至少一个任务 .. OSStart()。 /*开始多任务调度 , OSStart()永远都不会返回 */ } 42 181。 C/ OSII系统在 ARM系统中的移植 所谓移植,就是指使一个实时操作系统能够在其他的微处理器平台上进行运行。 由于 181。 C/OSII的主要代码都是由标准的 C语言写成的,所以,一般来说移植过程并不复杂。 181。 C/ OSII移植条件 虽然 181。 C/ OSII的大部分源代码是用 C语言写成的 ,但是 , 仍需要用汇编语言完成一些与微处理器相关的代码。 例如 , 181。 C/ OSII在读写微处理器 、寄存器时只能通过汇编语言来实现。 这是因为 181。 C/ OSII在设计的时候就已经充分考虑了可移植性。 为了要使 181。 C/ OSII可以正常工作 , 处理器必须要满足如下要求: 43 1). 微处理器的 C编译器能产生可重入代码 可重入的代码指的是一段代码 (如一个函数 )可以被多个任务同时调用 , 而不必担心会破坏其内部的数据。 也就是说 , 可重入型函数在任何时候都可以被中断执行 , 也不会因为在函数中断的时候被其他的任务重新调用 , 影响函数中的数据。 可重入代码或者只使用局部变量 , 即变量保存在 CPU寄存器中或堆栈中;或者使用全局变量 ,则要对全局变量予以保护。 通常的 C编译器 , 把局部变量分配在栈中。 所以 , 多次调用同一个函数 , 可以保证每次的局部变量互不受影响。 而全局变量 , 在多次调用函数的时候 , 必然受到影响。 代码的可重入性是保证完成多任务的基础 , 除了在 C程序中使用局部变量以外 , 还需要 C编译器的支持。 基于ARM的 SDT、 ADS等集成开发环境 , 都可以生成可重入的代码。 44 2). 在程序中可以使用 c语言打开或者关闭中断 在 181。 C/ OSII中 , 可以通过进入中断屏蔽的宏定义OS_ENTER_CRITICAL()或者退出中断屏蔽的宏定义 OS EXIT_CRITICAL()来控制系统关闭中断或者打开中断 ,这需要微处理器的支持。 在目前的 ARM系列的微处理器上 , 都可以设置相应的寄存器来关闭或者打开系统的所有中断。 3) . 微处理器支持中断 , 并且能产生定时中断 (通常在10Hz1000Hz之间 )。 181。 C/ OSII是通过微处理器产生定时的中断来实现多任务之间的调度的。 4) . 微处理器支持能够容纳一定量数据的硬件堆栈 ,并具有将堆栈指针和其他 CPU寄存器读写到堆栈 (或者内存 )的指令。 5) 181。 C/ OSII进行任务调度的时候 , 会把当前任务的 CPU内部寄存器的内容存放到此任务的堆栈中。 然后 , 再从另一个任务的堆栈中恢复原来的工作寄存器 , 继续运行另一个任务。 所以 , 寄存器中内容的入栈和出栈是 181。 C/ OSII多任务调度的基础。 45 181。 C/ OSII的移植步骤 在的移植过程中 , 使用的是基于 ARM公司架构的软件开发工具作为编译器 , 所值得关注的问题是与微处理器相关的代码 , 这部分主要包括一个头文件 、 一个汇编文件 个 C代码文件。 1) . 设置头文件 ( 1) 与编译器相关的数据类型 define INT8U unsigned char define INTl6U unsigned short define INT32U unsigned long define OS_STK unsigned long define BOOLEAN int define OS_CPU_SR unsigned long define INT8S char 因为不同的微处理器有不同的字长,所以 181。 C/ OSⅡ 的移植包括了一系列的类型定义以确保其可移植性。 46 用户必须将任务堆栈的数据类型定义到 181。 C/ OSII操作系统中 ,这个过程是通过为 OS_STK声明正确的 C语言数据类型来完成的。 由于使用的微处理器上的堆栈成员是 16位的 , 所以将 OS_TSK声明为无符号整形数据类型。 值得注意的是 , 所有的任务堆栈都必须使用 OS_STK声明数据类型。 ( 2) 进入中断屏蔽的宏定义 OS_ENTER_CRITICAL()和退出中断屏蔽的宏定义 OS_EXIT_CRITICAL() extern int INTS_OFF(void); extern void INTS_ON(void); define OS_ENTER_CRITICAL() {cpu_sr = INTS_OFF(); } define OS_EXIT_CRITICAL() {if(cpu_sr==0) INTS_ON(); } 与所有的实时内核一样 , 181。 C/ OSII操作系统在进行任务切换时需要先禁止中断在访问代码的临界区 , 并且在访问完毕后重新允许中断。 这就使得 181。 C/ OSII能够保护临界区代码免受多任务或中断服务例程 (ISR)的破坏。 在 S3C44B0微处理器上是通过OS_ENTER_CRITICAL()和 OS_EXIT_CRITICAL()两个函数来实现开 、关中断的。 47 ( 3) 栈增长方向标 OS_STK_GROWTH define OS_STK_GROWTH 1 define STACKSIZE 256 绝大多数的微处理器的堆栈是从高地址向低地址增长的 , 但是有些微处理器是采用相反方式工作的。 鉴于这种情况 181。 C/ OSII操作系统被设计成为这两种情况都可以处理 , 只要在结构常量OS_STK_GROWTH中指定堆栈的生长方式就可以了。 例如: 设 OS_STK_GROWTH为 0表示堆栈从下往上增长。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。