LwIP在uCOS_II上的移植.doc_第1页
LwIP在uCOS_II上的移植.doc_第2页
LwIP在uCOS_II上的移植.doc_第3页
LwIP在uCOS_II上的移植.doc_第4页
LwIP在uCOS_II上的移植.doc_第5页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

LwIP在uCOS_II上的移植1 与CPU或编译器有关的文件22 sys_arch操作系统相关部分3 LwIP 信号量的实现3 LwIP 消息队列的实现4 LwIP定时器的实现4 LwIP线程的创建5LwIP (Light - weight Internet Protocol) 是瑞士计算机科学院(Swedish Institute of Computer Science)的Adam Dunkels 等开发出来的一套用于嵌入式系统的开放源代码TCP/IP协议栈。一般情况下, LwIP既可移植到操作系统上, 又可在无操作系统的情况下独立运行。LwIP实现的主要优点是在保持了TCP/IP协议主要功能的基础上, 减少了其对RAM的占用。一般它只要几十KB的RAM和40KB左右的ROM就可以运行, 这使得LwIP协议非常适合在嵌入式系统中使用。目前最新版的LwIP已经发展到1.2.0版了。LwIP 的主要特点如下:支持多网络接口下的IP 转发; 支持网间控制报文协议ICMP ( Internet Control Messages Protocol);包含有实验性扩展的用户数据报协议UDP(User Datagram Protocol);包括阻塞控制、RTT 估算和快速恢复及快速转发的传输控制协议TCP (Transfer Control Protocol);具有专门提供的内部回调应用编程接口Raw API (Application Programming Interface),可用于提高应用程序性能;带有可选择的Berkeley接口API (多线程情况下);可在最新的版本中支持端对端协议PPP(Peer- Peer Protocol);新版本中增加了IP fragment 的支持;能支持动态主机配置协议(DHCP) 和动态分配IP地址。LwIP一般由几个模块组成, 除TCP/IP协议的实现模块外(IP, ICMP, UDP, TCP), 还有许多相关支持模块。这些支持模块包括: 操作系统模拟层、缓冲与内存管理子系统、网络接口函数、及一组Internet校验和计算函数, 此外, LWIP还包括一个API概要说明。LwIP的进程模型如图 3 所示Tftp_threadTcpecho_threadUDPTCPICMPIPIPpacketArp packet传输层网络层网络接口层应用层Tcpip_threadLwIP 协议在设计时为了适应不同的操作系统,没有在代码中使用和某一个操作系统相关的系统调用和数据结构,而是在LwIP 和操作系统之间增加了一个操作系统的封装层(sys_arch),该封装层主要用于把所有与硬件、操作系统和编译器相关的.c文件和.h头文件独立出来并按要求存放于/arch目录下。这样在移植LwIP到底层操作系统时,只需要改写这个接口里相关的文件即可。图3 LwIP进程模型1 与CPU或编译器有关的文件 与CPU或编译器有关的文件有cc. h、cpu. h和perf. h。在cc.h文件中主要是对数据类型的定义,要求它们与ARM处理器的要求相一致。具体数据定义如下:typedef unsigned char u8_t;typedef signed char s8_t;typedef unsigned short u16_t;typedef signed short s16_t;typedef unsigned int u32_t;typedef signed int s32_t;typedef u32_t mem_ptr_t;另外ARM系统默认以4字节对齐,在ADS编译环境中,结构体是4字节对齐的。但是处理网络数据包时,LwIP是根据结构体中不同数据的长度来读取相应的数据的,所以一定要在定义数据包结构体的时候使用_packed关键字,让编译器放弃原先的字节对齐。具体定义如下:#define PACK_STRUCT_FIELD(x) x#define PACK_STRUCT_STRUCT #define PACK_STRUCT_BEGIN _packed#define PACK_STRUCT_END 在cpu.h中主要是对字的大小端进行定义,再次定义为小端模式,定义语句为#define BYTE_ORDER LITTLE_ENDIAN,而在per.h文件中主要是定义#define PERF_START和#define PERF_STOP(x)。到此与 CPU 和编译器有关的文件就编写完成了。2 sys_arch操作系统相关部分 sys_arch.c和sys_arch.h中的内容是与操作系统相关的一些结构和函数,主要可以分为4部分: 信号量及相关函数、消息队列及相关函数、定时器相关函数以及创建新线程函数等,因此在sys_arch.c文件中需要把这四部分解决。 LwIP 信号量的实现LwIP中需要使用信号量进行通信,由于uCOS_II中已经实现了信号量OS_ EVENT的各种操作,并且可以满足LwIP 通信的各种要求,所以只需要定义结构struct sys_sem_t ,并把uCOS_II中的函数封装成以下函数供LwIP 调用:sys_sem_new() / 新建一个信号量;sys_sem_free () / 释放一个信号量;sys_sem_signal () / 发送一个信号量;sys_sem_wait () / 等待一个信号量; 对于sys_sem_new()、sys_sem_free ()和sys_sem_signal ()的实现相对较简单,因为uCOS_II提供了信号量,只需要直接调用建立信号量的相关函数进行封装就行了。sys_sem_wait ()的实现也需要调用uCOS_II底层函数OSSemPend(),但是打开uCOS_II中的OSSemPend()函数,发现它与我们要实现的函数还是有些差别的:其一、OSSemPend()函数没有返回值,它使用了一个结果参数err来代替返回值;其二、OSSemPend()函数的执行结果与sys_arch_sem_wait()函数的执行结果(返回值)不相同,OSSemPend()函数有5种执行结果,而sys_arch_sem_wait()函数只有两种结果;其三、timeout参数的时间单位不同,一个是时钟节拍数(OSSemPend()),另一个则是毫秒数(sys_arch_sem_wait())。这些差别的存在导致我们在调用OSSemPend()函数时必须根据需求作出相应的调整,经过调整后要实现的sys_sem_wait ()就完成了,这样信号量的部分就完成了。 LwIP 消息队列的实现LwIP 的消息队列是为了在传递各种消息供操作系统进行任务调度,uCOS_II中实现了消息队列结构OSQ 及其操作,但并没有对消息队列中的消息直接进行管理。LwIP 消息队列的实现需要定义以下结构和函数来完成:typedef struct OS EVENT *pQ; /C/ OS - II 指向事件控制块的指针;Void *pvQEntrieMAX_QUEUE_ ENTRIES;/ 消息队列;/MAX_ QUEUE_ ENTRIES 为最大消息数;TQ _DESCR ,*PQ_ DESCR;sys_mbox_new() / 创建一个消息队列;sys_mbox_free () / 释放一个消息队列;sys_mbox_post () / 向消息队列发送消息;sys_arch_mbox_fetch()/ 从消息队列中读取消息;uCOS_II同样实现了消息队列结构及其操作,只是uCOS_II没有对消息队列中的消息进行管理,我们可以通过在uCOS_II的基础上增加对消息的管理功能来实现LwIP对消息队列及其相关函数的调用。要实现消息的管理,就要从移植说明文中获得相关信息。在此可以让系统同事建立多个邮箱,这些邮箱通过一个单向链表链接在一起。每个邮箱一次可以接收多条信息,接收消息的最大数量由消息数组的大小决定。在系统初始化阶段即可完成建立邮箱和链表的工作,并把链表的首地址保存在一个全局变量指针中。申请建立一个新邮箱时,要先看看该全局变量是否为空值。如果为空则表明链表已经没有空闲节点,无法满足申请。不为空则立即将该全局变量指向的当前节点从链表中取出交给申请者使用,而该全局变量指向下一个空闲节点。 LwIP定时器的实现LwIP的每个协议控制块都有自己的超时等待属性,为每一个线程都分配一个超时等待时间的数据结构,并把这些数据结构存放在一个链表中,要返回的sys_timeouts结构保存了timeouts链表的首地址,且该函数在任何情况下都不能返回一个空值(NULL)。通过uCOS_II的任务查询机制来返回当前任务所对应的定时事件的结构指针。定义的结构和函数如下:struct sys_timeout struct sys_timeout *next ;/ 指向下一个定时结构u32_t time ;/ 定时时间sys_timeout_handler h ; / 执行的函数void *arg ;/ 定时时间到后执行函数的参数. ;struct sys_timeouts struct sys_timeout *next ; / 定时事件的链表struct sys_timeouts *sys_arch_timeouts(void)/返回当前线程定时的结构指针 这个函数的实现需要一定的技巧,LwIP内部线程优先级定义必须在1到LWIP_THREAD_MAX(含)之间。线程建立时,内部优先级号是先减1后再与LWIP_THREAD_START_PRIO相加的(参见实现sys_thread_new()函数一节)。这样,在sys_arch_timeouts()函数中,线程当前优先级减去LWIP_THREAD_START_PRIO,就可以直接作为sys_timeouts数组索引了。完成了sys_arch_timeouts()函数后,必须还要注意到sys_timeouts数组的初始化。每一个数组成员保存的链表首地址应该初始化为NULL,因为在系统初始化阶段,LwIP线程的timeouts链表还没有建立。因此需要在sys_init()函数内进行相应的初始化。 LwIP线程的创建LwIP可以单线程运行,即只有一个tcp_ip 线程负责处理所有的tcp/udp进程。LwIP也可以多线程运行以提高传输效率。这时就需要用sys_thread_new ( )函数创建新线程。由于uCOS_II中没有线程的概念而只有任务,所以LwIP中创建线程就是要调用uCOS_II中任务创建函数来进行封装。函数如下:sys_thread_t sys_thread_new(void(*fun)(void *arg),void *arg ,int prio)/fun为创建一个线程后的回调函数,arg传给fun 的参数,prio为线程优先级但要注意的是uCOS_II的任务是具有不同的优先级的,因此必须先明白LwIP调用这个函数时是如何指定的线程优先级。经过查看知道其优先级为1,按照uCO

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论