如何在嵌入式实时操作系统uC/0SII上移植实现LwIP
,所以,在它的结构体定义中有几个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的以太网芯片,
- 嵌入式Linux内核移植相关代码分析(04-21)
- 在Ubuntu上建立Arm Linux 开发环境(04-23)
- 蓝牙无线耳机设计及VxWorks移植方法(07-21)
- U-Boot的编译与移植到QT-S3C44B0X开发板上(03-08)
- LPC2292的μC/OS-II硬件抽象层构建(04-26)
- μC/OS-Ⅱ在MSP430F149上的移植(03-01)