微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于 LWIP 的嵌入式网络系统设计和实现

基于 LWIP 的嵌入式网络系统设计和实现

时间:12-20 来源:互联网 点击:

,主要包括数据类型 的重新定义、堆栈单位和增长方向的设定,以及开关中断的宏定义和任务切换的宏 定义。

OS_CPU_C.C 文件 :当 C/OS-II 进行任务切换或中断时要保护 CPU 的寄存器 到任务堆栈,在这个文件中定义了该堆栈的初始化函数,即设定了要保护的每一个 寄存器在堆栈中,使堆栈如同中断刚发生过一样。此外还有一些 HOOK 函数,必须 声明。

OS_CPU_A.S 文件:C/OS-II 是多任务实时操作系统,在进行任务调度时需要切换任务上下文,这些和处理器相关的任务切换函数在这个文件中定义,此外还有时 钟中断处理函数和进退临界区宏指令也需要在此文件中实现。

2.3 LWIP 在 C/OS-II 上的移植

LWIP是独立的TCP/IP协议栈,代码中没有使用和操作系统及硬件相关的函数与数据结构,而是当需要这样的函数时,通过操作系统模拟层加以使用。操作系统模拟层向诸如定时 器、处理同步、消息传送机制等的操作系统服务提供一套统一的接口。原则上,移植LWIP 到其他操作系统时,仅仅需要实现适合该操作系统的操作系统模拟层,它包括以下这些函数[2]:

sys_init() //初始化接口函数

sys_arch_timeouts() //定时器接口函数

sys_sem_new() //创建信号量接口函数

sys_sem_signal() //发送信号量接口函数

sys_arch_sem_wait() //等待信号量接口函数

sys_sem_free() //释放信号量接口函数

sys_mbox_t sys_mbox_new() //创建消息邮箱接口函数

sys_mbox_post() //发送消息接口函数

sys_arch_mbox_fetch() //取得消息接口函数

sys_mbox_free() //释放消息邮箱接口函数

sys_thread_new() //创建线程接口函数

这些函数的实现,基本上是根据 ?C/OS-II 操作系统的相关数据结构,重定义这些函数 中的数据结构如 sys_sem_t、sys_mbox_t 等,再封装 ?C/OS-II 操作系统相应的系统调用函 数来完成的。以接口函数 sys_sem_new()为例,其实现如下:

sys_sem_t sys_sem_new(u8_t count)

{

sys_sem_t pSem;

pSem = OSSemCreate((u16_t)count );

return pSem;

}

在 LWIP 中使用的这个信号量创建函数,可以看到是通过封装 ?C/OS-II 操作系统的信号 量创建函数 OSSemCreate()来完成的,其中使用的数据结构 sys_sem_t 也被重定义如下:

typedef OS_EVENT* sys_sem_t;

其中数据结构 OS_EVENT 同样为 C/OS-II 操作系统所有,其它函数的实现与此类似,不再重复。

此外,为支持操作系统模拟层,还需要建立 cc.h 、perf.h 文件,完成与 CPU 或编译器 相关的定义,如数据长度、字的高低位顺序等,这些应该与实现 C/OS-II 时相一致。

2.4 CS8900A 芯片驱动程序对 LWIP 的支持对于 LWIP 来说,它同样为网络驱动提供了一个移植接口,它使用 netif 数据结构代表 网络驱动层,此数据结构部分如下:

struct netif {

struct netif *next;

err_t (* input)(struct pbuf *p, struct netif *inp);

err_t (* output)(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr);

err_t (* linkoutput)(struct netif *netif, struct pbuf *p);

……

};

LWIP 和网络驱动程序会共用一个这样的数据结构,从而实现了两者的联系。其中

output( )函数提供给 LWIP 的 IP 模块,linkoutput( )函数提供给 LWIP 的 ARP 模块。LWIP 的

驱动编写 示例 [3] 指出, output( ) 函封装 了 LWIP 中 ARP 模块的数据 发送函 数 etharp_output( ),此函数最终会调用到 linkoutput( )函数,即 linkoutput( )函数是实际的数 据发送函数(这个函数由网络驱动程序实现)。另一方面,当网络驱动的中断处理函数接收到一个数据包后,也会调用此结构中的 input( )函数(这个函数由 LWIP 实现),将数据转交给 LWIP。接口结构[4]如图 2 所示:

具体在为 LWIP 编写网络驱动程序时我们要实现以下函数:

初始化函数:init( )

在这个函数里,主要的任务就是初始化数据结构 netif,包扩硬件地址、最大传输 单元 mtu 和 state(指向设备驱动中网络接口的特定状态)以及 output( )函数、linkoutput( )函数和 input( )函数等。

数据发送函数:output( )

此函数只是简单的封装了 LWIP 中 ARP 模块的数据发送函数 etharp_output( )。

数据发送函数:linkoutput( )

这是真正的网卡数据发送函数,output( )函数最终会调用到此函数。它将上层传递 来的数据转移到 CS8900A 网卡芯片上,使网卡将数据发送到网络上。

中断函数:net_isr( )

CS8900A 芯片将其要求的所有中断事件放在中断状态队列寄存器 ISQ 中,所以当 其产生中断

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

网站地图

Top