基于uC/OS-II的LwIP网络协议移植

2011-10-26 03:27杨辉
中国科技信息 2011年7期
关键词:网络协议线程队列

杨辉

中北大学电子与计算机科学技术学院多核实验室 太原 030051

基于uC/OS-II的LwIP网络协议移植

杨辉

中北大学电子与计算机科学技术学院多核实验室 太原 030051

LwIP是一款优秀的开源TCP/IP协议栈,应用各个嵌入式应用,用于简化接入互联网设备的网络协议栈应用开发。uC/OS-II是一款优秀的开源嵌入式实时操作系统。本文深入讲解了LwIP移植到uC/OS-II的方法,并进行相应测试。

LwIP移值;uC/OS-II;AT91SAM7

引言

随着互联网的普及度越来越高,能够接入互联网的设备越来越多,互联网已经成为人们工作生活中不可或缺的通信渠道之一。在嵌入式操作系统中加入网络协议栈是一项重要的研究内容。uC/OS-II是一款优秀的、开源的嵌入式实时操作系统内核,实现了实时任务调度、任务间通信及其管理系统内存,但是缺少文件系统,图形界面,以及网络协议的支持。本文介绍了uC/OS-II嵌入式实时操作系统中加入LwIP网络协议栈的方法,从而使得嵌入式系统能够接入互联网。

1 uC/OS-II嵌入式实时操作系统概述

uC/OS II 是Labrosse设计的一款完整的、开源的抢占式实时多任务嵌入式操作系统内核。代码绝大部分采用标准C语言编写,小部分底层硬件代码采用汇编语言编写,因此具有良好的移植性及裁剪性,从8位到64位处理器,已经成功移植到超过40种不同构架的微处理上。uC/OS II已经广泛应用在诸多领域,如手机、工控设备、医疗设备,甚至是飞行器等要求极高的应用。

uC/OS II是第一个支持ARM Cortex内核的嵌入式操作系统,其大部分代码是用标准C语言编写,这样对于移植工作很方便。在移植时,只需要用汇编语言及C语言编写一些与处理器相关的代码即可。uC/OS II代码设计的结构清晰,层次分明,代码总体来说分为三个层次:处理器无关代码层,处理器相关代码层,以及应用程序相关代码层。

2 开源TCP/IP网络协议LwIP简介

LwIP是由瑞士计算机科学院Adam Dunkels等人开发的专门用于嵌入式系统的开源TCP/IP协议栈[1]。LwIP可以移植到操作系统上,也可以在无操作系统的情况下独立运行。LwIP是一种轻型的TCP/IP协议栈,在实现TCP/IP基本功能的基础上,减少自身代码容量,并且在运行时,减少对RAM的占用。LwIP需要20KB的RAM空间和40KB左右的ROM空间即可运行,这样使得 LwIP协议栈适合在低端嵌入式系统中使用。

LwIP协议栈的特性如下:

支持多网络接口下的 IP转发;

支持 ICMP协议;

包括实验性扩展的 UDP(用户数据报协议);

包括阻塞控制、RTT估算、快速恢复和快速转发的 TCP(传输控制协议);

提供专门的内部回调接口(Raw API),用于提高应用程序性能;

可选择的 Berkeley 接口 API(多线程情况下)。

3 LwIP在uC/OS下的移植

本文所用到的嵌入式操作系统uC/OS-II版本为V2.5.4.,本文在移植时所用到的开发环境为RVMDK4.0。首先我们获取LwIP代码,只需到LwIP的官方网站下载。将代码文件添加至所建立的工程中即可。LwIP协议栈在最初设计时就考虑到移植问题,将硬件接口代码、OS接口代码、编译器相关代码独立分开出来,放在/src/arch目录下面。在LwIP移植到uC/OS-II中时,只需修改这个目录下的文件即可移植后的功能框图如图1所示。下面是具体的移植过程。

图1 系统示意图

3.1 移植CPU及编译器相关头文件

在/src/arch/include/arch目录下面,是关于CPU及编译器相关的头文件。这些文件里面定义了数据长度,字高低位顺序等,这些应该与用户实现uC/OS-II时定义的数据长度一致。我们这里主要涉及cc.h,cpu.h,perf.h这三个文件。下面定义为:

#define BYTE_ORDER LITTLE_ENDIAN //小端存储类型

typedef unsigned char u8_t; //关于数据类型长度的定义,下同

typedef signed char s8_t;

typedef unsigned short u16_t;

typedef signed short s16_t;

注意,C语言的结构体是4字节对齐的,但是在处理数据包时,则是根据结构体中不同数据长度来读取相应数据的,所以在定义struct的时候要加上_packed关键字。在LwIP代码中,结构体中定义了几个PACKED_FIELED_xxx宏,缺省的情况下是空的,可以在移植的时候添加不同的编译器所对应的_packed关键字。下面是对应的宏定义代码:

#define PACK_STRUCT_FIELD(x)x __attribute__((packed))

#define PACK_STRUCT_STRUCT__attribute__((packed))

3.2 与操作系统相关文件移植

sys_arch.[ch]文件中的内容是与移植的操作系统相关的一些结构和函数,下面是相应的移植内容。

3.2.1 sys_sem_t信号量

LwIP在操作系统中需要使用相应的信号量进行通信,所以在sys_arch中,应实现相关的信号量结构体和处理函数:

sys_ sem _send signal() //发送信号量

sys_ arch_sem _req() //请求信号量

在uC/OS-II中已经实现了OS_EVENT信号量的各种操作,在功能上同LwIP上的几个函数的目标功能是完全一样的,因此,只要把uC/OS-II的函数进行重新封装成上面的函数即可。

3.2.2 sys_thread_new 创建新线程LwIP可以是单线程运行,即只有一个tcpip线程(tcpip_thread),负责处理所有的 tcp/ucp连接,各种网络程序都通过tcpip线程与网络交互。但LwIP也可以多线程运行,以提高效率,降低编程复杂度。这时需要用户实现创建新线程的函数:

void sys_thread_new(void (* thread)(void *arg),void *arg);

在uC/OS-II中,没有线程的概念,只有任务。它已经提供了创建新任务的系统API调用OSTaskCreate,因此,只要把OSTaskCreate封装一下,就可以实现sys_thread_new。需要注意的是,LwIP中的thread并没有uC/OS-II中优先级的概念,实现时,要由用户事先为 LwIP中创建的线程分配好优先级。

3.2.3 sys_mbox_t 消息

LwIP要使用消息队列来进行缓冲、传递数据报文,因此,要在sys_arch中实现消息队列结构sys_mbox_t及其相应的发送和获取操作函数:

sys_mbox_post() //向队列发送消息

sys_arch_mbox_fetch() //从队列中获取消息

uC/OS-II同样实现了消息队列结构OSQ及其操作,但是,uC/OS-II 没有对消息队列中的消息进行管理,因此不能直接使用,必须在uC/OS-II的基础上进行重新实现。为了实现对消息的管理,我们定义一个结构体积。

包括OS_EVENT类型的指针(pQ)和队列内的消息两部分。对队列本身的管理利用uC/OS-II自己的 OSQ操作完成,然后使用uC/OS-II中的内存管理模块实现对消息的创建、使用、删除回收,两部分综合起来形成了 LwIP的消息队列功能。

3.3 网络设备驱动程序

LwIP可以有多个相应的网络接口,每个网络接口都有一个对应的 struct netif结构, 此netif包含了其属性、收发函数等。LwIP中的代码通过调用netif的函数netif->input()及netif->output()进行以太网的包收发操作。我们在驱动程序中主要做的移植工作是实现对应网络接口的初始化、接收、发送及对应中断处理函数。网络驱动程序工作在IP协议模型的网络接口层

3.4 lib_arch中库函数实现

LwIP协议栈需要实现8个外部函数,这些函数都是与CPU和用户编译器相关的,需要用户去实现。

4 移植功能测试

在完成上面的移植工作后,就可以对移植代码进行应用程序测试。测试工作主要为初始化LwIP协议栈,并创建TCP或者UDP等任务进行测试。

正确编译运行后,用ping ip地址命令可以得到ICMP reply 响应。用 telnet ip地址 7(登录 7号端口)命令可以看到echo server 的回显效果。说明 ARP、ICMP、IP、TCP协议都已正确运行,说明网络协议已经成功移植。总之,LwIP作为的开源TCP/IP协议栈,在带网络嵌入式设备开发中可以比较广泛的的使用。

[1] 张翠, 邓志良.LwIP协议栈在uC/OS-Ⅱ上的移植和应用.微计算机信息.2010,23(2):43-45

[2] 胡俐蕊.基于LwIP的uC/OS-Ⅱ网络应用程序设计方法.计算机应用与软件.2010,19(1):145-148

10.3969/j.issn.1001-8972.2011.07.054

猜你喜欢
网络协议线程队列
基于C#线程实验探究
队列里的小秘密
基于多队列切换的SDN拥塞控制*
基于国产化环境的线程池模型研究与实现
线程池调度对服务器性能影响的研究*
在队列里
一种蓝牙多跳网络协议的设计与研究
丰田加速驶入自动驾驶队列
基于载波技术的多点温度测量系统设计
基于DPI技术的语音视频流量监控系统设计与实现