在嵌入式运用中,运用RTOS的主要原因是为了进步体系的可靠性,其次是进步开发功率、缩短开发周期。uCOS-II是一个占先式实时多使命内核,运用对象是嵌入式体系,对源代码恰当削减,很简单移植到8~32位不同结构的微处理器上。但uCOS-II仅是一个实时内核,它不像其他实时操作体系(如嵌入式Linux)那样供给给用户一些API函数接口。在uCOS-II实时内核下,对外设的拜访接口没有一致完善,有许多作业需求用户自己去完结。串口通讯是单片机测控体系的重要组成部分,异步串行口是一个比较简单又很具代表性的中止驱动外设。本文以单片机中的串口为例,介绍uCOS—II下编写中止服务程序以及外设驱动程序的一般思路。
1 uCOS-II的中止处理及51系列单片机中止体系剖析
uCOS-II中止服务程序(ISR)一般用汇编语言编写。以下是中止服务程序的进程。
- 保存悉数CPU寄存器;调用OSIntEnter()或OSIntNesting(全局变量)直接加1;
- 履行用户代码做中止服务;
- 调用OSIntExit();
- 康复一切CPU寄存器;
- 履行中止回来指令。
uCOS-II供给两个ISR与内核接口函数;OSIntEnter()和OSIntExit()。OSIntEnter()告诉uCOS-II核,中止服务程序开端了。事实上,此函数做的作业是把一个全局变量OSIntNesting加1,此中止嵌套计数器能够保证一切中止处理完结后再做使命调度。另一个接口函数OSIntExit()则告诉内核,中止服务已完毕。依据相应状况,退回被中止点(可能是一个使命或者是被嵌套的中止服务程序)或由内核作使命调度。
用户编写的ISR有必要被装置到某一方位,以便中止发生后,CPU依据相应的中止号运转精确的服务程序。许多实时操作体系都供给了装置和卸载中止服务程序的 API接口函数,但uCOS-II内核没有供给相似的接口函数,需求用户在对CPU的移植中自己完成。这些接口函数与具体的硬件环境有关,接下来以51单片机下的中止处理对此具体阐明。
51单片机的中止根本进程如下:CPU在每个机器周期的S5P2时间采样中止标志,而在下一指令周期将对采样的中止进行查询。假如有中止请求,则依照优先级凹凸的准则进行处理。呼应中止时,先置相应的优先级激活触发器于相应位,封闭同级或初级中止,然后依据中止源类别,在硬件操控下,将中止地址压入仓库,并转向相应的中止向量进口单元。通常在进口单元处放一跳转指令,转向履行中止服务程序.当履行中止回来指令RETI时,把呼应中止时所置位的优先级激活触发器清零后,从仓库中弹出被维护的断点地址,装入程序计数器PC,CPU回来本来被中止处持续履行程序。
在移植的进程中,选用Keil C51作为编译环境。Keil C5l集成C编译和汇编器。中止子程序用汇编语言编写,放到移植uCOS-II后的OS_CPU_A.ASM汇编文件中。下面是以串行口中止为例的移植中止服务子程序代码。
CSEGAT0023H ;串口中止呼应进口地址
LJMPSerialISR;转移到串口中止子程序进口地址
RSEG?PR?SeriallSR?OS_CPU_A
SerialISR:
USINGO
CLR EA ;先关中止,以防中止嵌套
PUSHALL ;已界说的压栈宏,用于将
;CPU寄存器的值压入仓库
LCALL_?OSIntEnter ;监督中止嵌套
LCALL_?Serial ;串口中止服务程序
LCALL_?OSintExlt
SETBEA
POPALL;已界说的出栈宏,将CPU寄存器的值出栈
RETI
2 串口驱动程序
笔者已在5l单片机上成功移植了uCOS-II内核,移植进程在此不再评论。这儿要点剖析uC0S—II内核下串口驱动程序编写。
因为串行设备存在外设处理速度和CPU速度不匹配的问题,所以需求一个缓冲区.向串口发送数据时,只要把数据写到缓冲区中,然后由串口逐一取出往外发。从串口接纳数据时,往往等收到若干个字节后才需求CPU进行处理,所以这些预收的数据能够先存于缓冲区中。实践上,单片机的异步串口中只要两个彼此独立、地址相同的接纳、发送缓冲寄存器SBUF。在实践运用中,需求从内存中拓荒两个缓冲区,分别为接纳缓冲区和发送缓冲区。这儿把缓冲区界说为环形行列的数据结构。
uCOS-II内核供给了信号量作为通讯和同步的机制,引进数据接纳信号量、数据发送信号量分别对缓冲区两头的操作进行同步。串口的操作形式如下:用户使命想写,但缓冲区满时,在信号量上睡觉,让CPU运转其他使命,待ISR从缓冲区读走数据后唤醒此睡觉的使命;相同,用户使命想读,但缓冲区空时,也能够在信号量上睡觉,待外部设备有数据来了再唤醒。因为uCOS-II的信号量供给了超时等候机制,串口当然也具有超时读写能力。
图1是带缓冲区和信号量的串口接纳示意图。数据接纳信号量初始化为0,标明在环形缓冲区中无数据。
接纳中止到来后,ISR从UART的接纳缓冲器SBUF中读入接纳的字节(②),放入接纳缓冲区(③),然后经过接纳信号量唤醒用户使命端的读操作(④、 ①)。在整个进程中,能够查询记载缓冲区中当时字节数的变量值,此变量标明接纳缓冲区是否已满。UART收到数据并触发了接纳中止,但假如此刻缓冲区是满的,那么抛弃收到的字符。缓冲区的巨细应合理设置,下降数据丢掉的可能性,又要防止存储空间的糟蹋。
图2为带环形缓冲区和超时信号量的串口发送示意图。发送信号量初始值设为发送缓冲区的巨细,标明缓冲区已空,而且封闭发送中止。发送数据时,用户使命在信号量上等候(①)。假如发送缓冲区未满,用户使命向发送缓冲区中写入数据(②)。假如写入的是发送缓冲区中的第一个字节,则答应发送中止(②)。然后,发送ISR从发送缓冲区中取出最早写入的字节输出至UART(④),这个操作又触发了下一次的发送中止,如此循环直到发送缓冲区中最终一个字节被取走,从头封闭发送中止。在ISR向UART输出的一起,给信号量发信号(⑤),发送使命据此信号量计数值来了解发送缓冲区中是否有空间。