首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

基于Nios软核CPU的uC/OS-II和LwIP移植 02

基于Nios软核CPU的uC/OS-II和LwIP移植 02

3.1 与CPU或编译器相关的include文件
  
        在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);
返回列表