【Abstract】The paper introduces the transplantation of uC/OS-II to ARM at first. Basic on this, the hardware frame is designed according to the features of Ethernet Controller ENC28J60. Then it expatiates how to realize the transplantation of LwIP protol stack to the embedded RTOS(Real-Time Operating System) μC / OS-Ⅱ, and describes the software flow of ENC28J60 network card drive in detail, which makes uC/OS-II become a true RTOS with networking utilities.
【Keywords】Embedded System, Ethernet Network, ENC28J60, LwIP
随着计算机技术的发展,嵌入式系统已成为计算机领域的一个重要组成部分,实时操作系统的应用也越来越受到重视。uC/OS-II是专门为嵌入式应用设计的实时操作系统内核,它具有以下几个优点:源代码公开,代码结构清晰,注释详尽,组织有条理,具有良好的可扩展性和可移植性,最多可以管理60个任务。uC/OS-II采用了基于优先级的占先式实时内核,它包含了实时内核任务管理、时间管理、任务间的同步(信号量、邮箱、消息队列)和内存管理等功能。正适合嵌入式操作系统体积小、速度快、可裁减、可移植的特性。
嵌入式系统在网络化开发的过程中,如何解决与网络连接,即如何将通用处理器的网络连接装置应用于嵌入式网络的开发是十分重要的。目前市面上有许多以太网络控制芯片,其中大多功耗高、功能复杂,不适用于价格低廉的嵌入式系统之中。并且目前市场上的大部分以太网控制器采用的封装均超过80引脚,而符合IEEE802.3协议的ENC28J60只有28引脚,就能既提供相应的功能,又可以大大简化相关的设计,并减小占板空间,再加上由Microchip免费提供的用于单片机的TCP/IP软件堆栈,使之成为目前市面上最小的嵌入式应用以太网解决方案。
ARM是目前嵌入式领域中应用最广泛的RISC微处理器结构,以其低成本、低功耗、高性能等优点占据了嵌入式系统应用领域的领先地位[1]。uC/OS-II可以简单地看作是一个多任务调度器,在这个任务调度器上完善地添加了与多任务操作系统相关的一些系统服务,如信号量、邮箱等。其90%的代码是用C语言写的,可以直接移植到有C语言编译器的处理器上。移植工作主要都集中在多任务切换的实现上,因为这部分代码用来保存和恢复CPU现场(即写/读相关寄存器),不能用C语言,只能使用汇编语言完成。uC/OS-II的全部源代码量大约是6000-7000行,共15个文件[1]。将uC/OS-II移植到ARM处理器上,需要修改三个与ARM体系结构相关的文件,代码量大约是500行。以下是这个三个文件的移植工作:
1) OS_CPU. H 的移植
首先进行基本配置和数据类型定义,因为不同的编译器所提供的同一数据类型的数据长度并不相同。其次用#define 语句定义2 个宏开关中断:即
退出临界区宏定义: # define OS_EXITCRITICAL ( ) ARMDisable Int ( ) //关中断,
进入临界区宏定义# define OS_ENTERCRITICAL ( ) ARMEnableInt ( ) //开中断。
最后根据堆栈的方向定义OS_STK GROWTH。
2) OS_CPU.C的移植
OS_CPU.C的移植包括任务堆栈初始化和相应函数的实现.在这里共有6个函数[2]:OSTaskStkInit( ),OSSTaskCreateHook( ),OSTaskDelHook( ),OSTaskSwHook( ),OSTaskStatHook( ),OSTimeTickHook( )。其中后面的5个HOOK函数又称为钩子函数,主要是用来对uC/OS-II进行功能扩展。这些函数为用户定义函数,由操作系统调用相应的HOOK函数去执行,在一般情况下,他们都没有代码,所以实现为空函数即可。而函数OSTaskStkInit( )对堆栈进行初始化,在ARM系统中,任务堆栈空间由高到低依次为PC,LR,R12,R11,…,R1,R0,CPSR,SP,SR。在进行堆栈初始化以后,OSTaskStkInit( )返回新的堆栈栈顶指针。
3) OS_CPU A. S 的移植
uC/OS-II移植的最后还需要用户编写4个重要的汇编函数,包括OSStartHighRdy( )、OSCtxSw( )、OSIntCtxSw( )及OSTickISR( )。分别介绍如下:OSStartHighRdy( )函数由OSStart( )调用,用以运行优先级最高的就绪任务,其运行过程:调用用户定义的OSTaskSwHook( )函数→获取任务堆栈指针→置位全局;OSCtxSw( )函数,实时操作系统内任务级的切换是通过处理器的软中断实现的,并且软中断服务例程的向量地址必须指向OSCtxSw( )函数;OSIntCtxSw( )函数用于实现中断级任务切换,并用在最初清理堆栈(调整堆栈指针的位置);OSTicklSR( )函数实现任务切换,并使用内核定时器产生时钟节拍。
系统主要采用ENC28J60+LPC2212/LPC2214,其信息终端模块硬件系统框图,如图1所示。
图1 信息终端模块硬件系统框图
图2 网卡芯片的配置原理图部分电路图
硬件由以下几部分组成:
1) 单片机及其外围器件:LPC2214、PLL(10KHz晶体等)、LED指示灯;
2) 以太网控制器部分:ENC28J60、耦合变压器、RJ45插座、25MHz晶体;
3) 电源部分:由一片7805提供5V的直流电压,SPX1117M3-1.8 提供1.8V的直流电压 SPX1117M3-3.3提供3.3V的直流电压。
系统采用LPC2212/LPC2214单片机,LPC2212/LPC2214是一款基于16/32位ARM7TDMI-S,并支持实时仿真和跟踪的CPU,带有128/256 k字节(kB)嵌入的高速Flash存储器。128位宽度的存储器接口和独特的加速结构使32位代码能够在最大时钟速率下运行。对代码规模有严格控制的应用可使用16位Thumb模式将代码规模降低超过30%,而性能的损失却很小。
ENC28J60是Microchip Technology(美国微芯科技公司)近期推出的28引脚独立以太网控制器,它采用业界标准的SPI串行接口,具有10 Mbps SPI接口,符合IEEE802.3协议,内置了10 Mbps以太网物理层器件(PHY)及介质访问控制器(MAC),可按以太网协议可靠地收发信息包数据[3]。另外,它还具有可编程8 KB双端口SRAM缓冲器,此缓冲存储器具有灵活可靠的数据管理机制,以高效的方式进行信息包的存储、检索和修改,以减轻主控单片机的内存负荷。该系统用到的网卡芯片配置原理部分电路图,如上图2所示。
系统软件的核心是uC/OS-II 内核通过ENC28J60以太网控制器以TCP/IP协议栈LwIP为协议和以太网相连接,在该系统中主要完成以下三个方面的设置与实现:
1) TCP/IP协议栈的精简与实现;2) ENC28J60以太网控制器驱动程序的实现;3) 整个系统的流程图及实现。该系统的软件框图,如图3所示。
图3 系统软件框图 |
1) LwIP协议
嵌入式系统uC/OS-II只是一个实时的任务调度及通信内核,缺少对外围设备和接口的支持。以开放源代码的TCP/IP协议栈LwIP为原型,对嵌入式TCP/IP协议进行改造,可使uC/OS-II成为支持网络的RTOS。
LwIP协议栈在设计时就考虑到了将来的移植问题,它把所有的硬件、OS、编译器相关的部分独立出来,放在一个固定的目录下[4]。因此LwIP在uC/OS-II 上的实现就是修改这个目录下的文件,其他的文件一般不必修改。本系统的硬件平台是ENC28J60+LPC2212/LPC2214。uC/OS-II在LPC2214需要说明的一点是LwIP会为每个网络连接动态分配一些信号量(Semaphone)和消息队列(Message Queue),当连接断开时会删掉这些Semaphone和Queue。
2) 协议的实现
对嵌入式系统来说不需要实现所有的TCP/IP协议,本系统主要实现TCP/IP协议的TCP、UDP、IP、ICMP和 ARP等协议,主要实现的模块如图3中TCP/IP 协议栈的数据流向(虚线框的部分)。
ARP协议主要完成网络地址到物理地址的映射,该协议是网络中实现通信的基础。嵌入式系统中仅响应ARP请求,发送ARP回答包。ICMP协议负责传递差错报文以及其它需要注意的信息,且由ICMP首部8位的类型字段和8位的代码字段决定信息的种类。IP是TCP/IP协议族中最为核心的协议。IP协议主要是校验 IP 报文头和实现ICMP、TCP协议之间多路复用功能。为测试网络的连通情况,实现了ICMP中类型号为0、代码为0的Ping应答协议。传输层采用了面向连接的可靠数据传输协议TCP,以确保远程数据可靠性要求。UDP协议是一种面向无连接的不可靠的协议。该部分实现对输入包的处理,判断其端口号、检验和是否正确。正确则将其交给相应端口的应用程序,不正确则丢弃;对从应用程序接收到的输出包,设置响应的源端口号和目的端口号,再交给IP层发送。TCP协议提供可靠的面向连接的数据传输服务。
本系统采用ENC28J60以太网控制芯片,需要编写网络设备驱动程序,以实现低层网络接口及硬件函数驱动。本文针对ENC28J60芯片的特点,对该程序做一下预处理以便进行可靠性设计和应用。
对驱动程序进行预处理:
#define MAC_TX_BUFFER_SIZE (600) //定义发送缓冲区的大小
#define MAC_TX_BUFFER_COUNT (1) //定义发送缓冲区的个数
#define LPC2200_CS_ENC28J60 0x00000800 //ENC28J60的片选信号P0.8
#define LPC2200_RESET_ENC28J60 0x00000200 //ENC28J60的复位引脚
此驱动主要完成ENC28J60网络芯片的初始化过程,主要函数void LpcCtlEncCInit(void),完成在LPC2214控制器中加载ENC28J60网卡芯片的配置信息,并实现ENC28J60的自检功能。其核心流程图,如图4所示。注:在设置ENC28J60的物理地址时应该注意的是ENC28J60的地址顺序是倒序的。
图4 MacInit()程序流程图 |
图5 系统主函数TaskE( )的流程图
系统主任务主要完成申请动态IP地址,建立与远端中心的连接,以及数据的接收和发送等。首先对该主程序进行预处理:
定义SEVER服务器端和CLIENT客户端
定义协议特征字:其中包括uC/OS-II的任务ID号、uC/OS-II的任务优先级的分配和系统的事件操作指针,如:动态域名解析用到的信号量*DNSFlag;IP动态更新时用到的信号量*ConnectFlag,以及网络传输信息*EthNetMsgFlag等等。
系统工作主流程图,如上图5所示。
在这个流程图中主要调用的函数有:ModeSetTask()函数,完成系统通信接口的设置;EthNetTask()函数,完成主机与终端网口的通信任务;NetSetTask()函数,完成主机与终端串口的通信任务等。
μC/OS-II是近年来发展迅速的一个开放源码实时操作系统,但它只是一个实时的任务调度及通信内核,缺少对外围设备和接口的支持,如没有文件系统、网络协议、图形界面等。而随着以太网技术的深入发展,将嵌入式系统与网络结合,在嵌入式实时操作系统中引入TCP/IP协议栈,以支持嵌入式设备接入网络,成为嵌入式领域重要的研究方向,且对一些基于网络接口的数据采集系统与远程监控的任务系统都将具有广泛的应用前景。
本文作者的主要创新点:
1、 提出了在嵌入式系统中运用以太网控制器ENC28J60的硬件及软件的设计思路;
2、 将LwIP协议栈运用于ENC28J60+LPC2212/LPC2214的硬件平台上,同时该系统已经应用在LED显示等远程控制中,并取得了良好的效果。
参考文献
【1】 《ARM嵌入式处理器结构与应用基础》.马忠梅等编著. 北京航空航天大学出版社.2002年出版
【2】 朱华均. uC/OS-II 操作系统在ARM处理器上的移植 . 计算机工程, (软件技术与数据库)2004.12, 增刊 第30卷 64~124
【3】 祁树胜 SPI接口以太网控制器ENC28J60及其应用, 微计算机信息 (嵌入式与SOC)2006 年第22 卷第8-2 期 266~268
【4】 用TCP/IP进行网际互联第一卷:原理、协议与结构(第四版) [美]科默(Comer,D.E.)著;林瑶,蒋慧等 译 北京:电子工业出版社