微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 如何在嵌入式实时操作系统uC/0SII上移植实现LwIP

如何在嵌入式实时操作系统uC/0SII上移植实现LwIP

时间:10-10 来源:互联网 点击:

,所以,在它的结构体定义中有几个PACKED_FIELD_xxx宏,默认的时候这几个宏都是空的,可以在移植的时候添加不同的编译器所对应的_packed关键字。比如在Skyeye(ARM7)上对应gcc编译器的定义:

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

#define PACK_STRUCT_STRUCT __attribute__((packed))

#define PACK_STRUCT_BEGIN

#define PACK_STRUCT_END

4.3 sys_arch操作系统相关部份

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

(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/0SII已经实现了信号量OS_EVENT的各种操作,并且功能和LwIP上面几个函数的目的功能是完全一样的,所以只要把uC/0SII的函数重新包装成上面的函数,就可以直接使用了。

(2) sys_mbox_t 消息

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

sys_mbox_new() //创建一个消息队列

sys_mbox_free() //释放一个消息队列

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

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

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

typedef struct {

OS_EVENT* pQ;

void* pvQEntries[MAX_QUEUE_ENTRIES];

} sys_mbox_t;

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

(3) sys_arch_timeout 函数

LwIP中每个与外界网络连接的线程都有自己的timeout属性,即等待超时时间。这个属性表现为每个线程都对应一个sys_timeout结构体队列,包括这个线程的timeout时间长度,以及超时后应调用的timeout函数,该函数会做一些释放连接,回收资源的工作。如果一个线程对应的sys_timeout为空(NULL),说明该线程对连接做永久的等待。

timeout结构体已经由LwIP自己在sys.h中定义好了,而且对结构体队列的数据操作也由LwIP负责,我们所要实现的是如下函数:

struct sys_timeouts * sys_arch_timeouts(void)

这个函数的功能是返回目前正处于运行态的线程所对应的timeout队列指针。timeout队列属于线程的属性,因此是OS相关的函数,只能由用户实现。

(4) sys_thread_new 创建新线程

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

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

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

4.4 lib_arch中库函数的实现

LwIP协议栈中用到了8个外部函数,这些函数通常与用户使用的系统或编译器有关,因此留给用户自己实现。如下:

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

u16_t ntohs(u16_t n);

u32_t htonl(u32_t n); //32位数据大小头对调

u32_t ntohl(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); //内存中指定长度的数据块清零

前四个函数通常由用户自己实现。Skyeye(ARM7)中,由于使用了gCC编译器,gcc的lib库里已经有了后四个函数。而ez80的编译器函数库中缺少bcopy和bzero两个,需要自己编写。用户在其它CPU上实现时应根据自己的编译器来决定。

4.5 网络设备驱动程序

ez80开发板自带的网络芯片为ReaLTEk的8019as芯片,这是ISA 10BASE-T的以太网芯片,

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top