基于Nios软核CPU的uCOS-II和LwIP移植(2)

2019-09-01 16:21

在LwIP/src/arch/include/arch目录下,cc.h、cpu.h、perf.h中有一些与CPU或编译器相关的定义,如数据长度、字的高低位顺序等。这应该与用户实现uC/OS-II时定义的参数一致。通常,c语言的结构体(struct)是4字节对齐的,但是在处理数据包的时候,LwIP是通过结构体中不同数据的长度来读取相应的数据的,所以,一定要在定义struct的时候使用_packed关键字,让编译器放弃struct的字节对齐。LwIP也考虑到了这个问题,所以,在它的结构体定义中有几个PACK_STRUCT_xxx宏,在移植的时候添加编译器所对应的_packed关键字。比如在nios-eft-gcc上对应的定义为:

#define PACK_STRUCT_FIELD(x) x_attribute_((packed)) #define PACK_STRUCT_STRUCT _attribute_((packed)) 3.2 sys_arch操作系统相关部分

sys_arch.h[c]中的内容是与OS相关的一些结构和函数,主要可以分为四个部分:

3.2.1 sys_sem_t 信号量

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

struct sys_sem_t

sys_sem_new() //创建一个信号量结构 sys_sem_free() //释放一个信号量结构 sys_sem_signal() //发送信号量 sys_arch_sem_wait() //请求信号量

由于uC/OS-II已经实现了信号量OS_EVENT的各种操作,并且功能和LwIP上面几个函数的功能是完全一样的,所以只要把uC/OS-II的函数重新封装成上面的函数就可以了。 3.2.2 sys_mbox_t消息

LwIP使用消息队列来缓冲、传递数据报文,因此要在sys_arch中实现消息队列结构

sys_mbox_t以及相应的操作函数: sys_mbox_new() //创建一个消息队列 sys_mbox_free() //释放一个消息队列 sys_mbox_post() //向消息队列发送消息 sys_arch_mbox_fetch() //从消息队列中获取消息

uC/OS-II虽然实现了消息队列结构OS_Q及其操作,但是uC/OS-II没有对消息队列中的消息进行管理,因此不能直接使用,必须在uC/OS-II的基础上重新实现。为了实现对消息的管理,我们定义了以下结构: typedef struct{ OS_EVENT *pQ:

void *pvQEntries[MAX_QUEUE_ENTRIES]; }sys_mbox_t;

typedef PQ_DESCR sys_mbox_t; //LwIP中的mbox是UCOS的消息队列

该结构包括OS_EVENT类型的队列指针(pQ)和队列内的消息(pvQEntries)两部分,对队列本身的管理利用uC/OS-II自己的消息队列相关函数来完成,然后使

用uC/OS-II中的内存管理模块实现对消息的创建、使用和删除,两部分综合起来便实现了LwIP的消息队列功能。 3.2.3 sys_arch_timeout函数

LwIP中每个与外界网络连接的线程都有自己的timeout属性,即等待超时时间。这个属性表现为每个线程都对应一个sys_timeout结构体队列,它包括这个线程的timeout时间长度,以及超时后应调用的timeout函数,该函数会做一些释放连接、回收资源的工作。timeout结构体已经在sys.h中定义好了,而且对结构体队列的数据操作也由LwIP负责,我们所要实现的是如下函数: struct sys_timeouts *sys_arch_timeouts(void)

这个函数的功能是返回目前正处于运行状态的线程所对应的timeout队列指针。timeout队列属于线程的属性,因此是与操作系统相关的函数,只能由用户实现。 3.2.4 sys_thread_new创建新线程函数

LwIP可以是单线程运行,即只有一个tcpip线程(tcpip_thread),负责处理所有的TCP(Transmission Control Protocol:传输控制协议)或UDP(User Datagram Protocol:用户数据报协议)连接,各种网络程序都通过tcpip线程与网络交互。它也可以多线程运行,以提高效率。这时就需要用户实现创建新线程的函数: void sys_thread_new(void(*thread)(void *arg),void *arg);

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

3.3 lib_arch中库函数的实现

LwIP用到8个外部函数,这些函数通常与用户使用的系统或编译器有关,因此要求用户实现。

u16_t htons(u16_t n);//16位数据高低字节交换 u16_t ntons(u16_t n);

u32_t htonl(u32_t n);//32位数据大小端对调 u32_ t ntonl(u32_t n); int strlen(const char *str);

int strncmp(const char *str1,const char *str2,int len); void bcopy(const void *src,void dest,int len); void bzero(void *data,int n); 4 网络设备驱动程序

我们采用的网络芯片为Cirrus Logic公司的CS8900芯片。LwIP的网络驱动有一定的模型,/src/netif/ethernetif.c文件即为驱动的模板,用户为自己的网络设备实现驱动时应参照此模板。在LwIP中可以有多个网络接口,每个网络接口都对应了一个netif结构,该结构体包含了相应网络接口的属性、收发函数。LwIP调用netif的函数netif->input()及netif->output()进行以太网packet的收、发等操作。在驱动中主要做的就是实现网络接口的收、发、初始化以及中断处理函数。

void ethernetif_init(struct netif *netif) //网卡初始化函数 void ethernetif_input(struct netif *netif) //网卡接收函数 err_t ethernetif_output(struct netif *netif,struct pbuf *p,struct ip_addr *ipaddr) //网卡发送函数

void ethernetif_isr(void);//网卡中断处理函数

5 测试

完成上面的移植修改工作后,就可以在uC/OS-II中初始化LwIP,并创建TCP或UDP任务进行测试了。这部分是用c语言实现的。关键部分的代码和说明如下: main(){ OSInit();

OSTaskCreate(lwip_init_task,&task1_data,&lwip_init_stk[TASK_STK_SIZE-1],0);

OSTaskCreate(user_task,&task2_data,&user_stk[TASK_STK_SIZE-1],1); OSStart(); }

主程序中,创建了Lwip_init_task初始化LwIP任务(优先级0)和user_task用户任务(优先级1)。lwip_init_task任务中除了初始化硬件时钟和LwIP之外,还创建了tcpip_thread(优先级3)和tcpecho_thread(优先级4)。实际上tcpip_thread才是LwIP的主线程,多线程的Berkley API也是基于这个线程实现的,即上面的tcpecho_thread线程也要依靠tcpip_thread线程来与外界通信。tcpecho_thread是一个TCP echo服务,监听7号端口。程序框架如下: void tcpecho_thread(void arg){

conn = netconn_new(NETCONN_TCP); //建立新的连接 netconn_bind(conn,NULL,7); //绑定到7号端口 netconn_listen(conn); //监听7号端口 while(1){

newconn = netconn_accept(conn); //接收外部连接 bur=netconn_recv(newconn) //获取数据 …… //处理数据

netconn_write(newconn,data,len,NETCONN_COPY);//发送数据 netconn_delete(newconn);//释放本次连接

} }

编译下载运行,用ping ip地址命令可以得到ICMP reply响应,用telnet ip地址7(登录7号端口)命令可以看到echo server的回显效果。说明ARP、IP、ICMP、TCP协议都已正确运行。 6 结论

本文提出了在Nios软核CPU上移植嵌入式实时操作系统uC/OS-II,并且在uC/OS-II上移植LwIP,以构建嵌入式网络开发平台。在该网络平台的设计中,一方面,由于采用Nios软核CPU,而Nios开发软件SOPC Builder开发环境的完备功能使得硬件设计简单而快捷;另一方面,由于uC/OS-II和LwIP都是开放源代码的,并且在设计时就已经考虑了移植问题,因此使得移植很方便。通过测试,证明这种方案切实可行。


基于Nios软核CPU的uCOS-II和LwIP移植(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:2017年高中化学竞赛模拟考试五试题(12.16)解析版

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: