15016|8

117

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

RT-Thread/LPC17xx之网络协议栈 [复制链接]

RT-Thread优化的全功能型LwIP TCP/IP网络协议栈是RT-Thread RTOS引以为傲的组件,LwIP TCP/IP协议栈之全体现在:
  • 完善的IPv4、ARP、ICMP协议支持
  • 完善的UDP协议支持(还包括试验性质的UDP-lite扩展)
  • 完善的TCP协议支持,包括了拥塞控制、RTT估计、报文分段与重组和快速恢复/快速重传
  • 完善的DHCP、DNS协议支持
  • 完善的PPP协议支持
  • 于BSD Socket兼容的接口(兼容度非常高)

而RT-Thread针对LwIP优化体现在:
  • 更低的内存占用,这点是lwIP用于小型系统的最大障碍,因为原始的lwIP版本大约会用到20 - 30k的内存。而RT-Thread的版本仅使用5k左右的内存占用。
  • 采用发送与接收分离的方式处理lwIP底层的数据收发,更适合与RTOS的环境。
  • 整合BSD Socket API接口到RT-Thread线程模型中:原版的lwIP中的socket操作(也包括其他的一些API)只能用于lwIP创建的线程,整合后可以在任意RT-Thread线程中使用。
  • 其他一些lwIP问题修正。

在开源的TCP/IP网络协议中,另一著名的实现是uIP(lwIP作者Adam Dunkels的另一作品,大牛!),它是完全针对微小控制器准备的,但是小的体积也带来了功能上的损失,这也是RT-Thread并没选择支持uip的原因:
  • API上,如果应用的数据有错误产生,应用需要自己负责进行重传;lwIP在接收了应用的数据后就会自行进行错误处理及重发;
  • lwIP支持多个网络接口,并且也支持包转发;
  • uIP的TCP数据传输速度奇低:大约是5kB/s。相对应的,lwIP(在RT-Thread系统上测试得到)能够达到1MB/s

好了,开始说LPC1768的移植

如前一篇文章,RT-Thread已经包括了LPC1768的基本移植,通常RT-Thread的做法是,只提供独立的工程,并且在工程中力图把最多的特性都打开了,而不是类似一些做开发板的,循序渐进的提供一些例子。当然,在RT-Thread极为优秀的剪裁能力基础上,能够化繁为简,或层层叠加形成一个复杂的系统:
>>使能LwIP TCP/IP网络组件,仅需要在rtconfig.h中定义RT_USING_LWIP宏。

有了LwIP TCP/IP协议栈,当然还需要相应的网络驱动,LPC1768芯片内置EMAC,外围电路还需要一个PHY,我的开发板上使用DP83848C。

RT-Thread的网络驱动主要框架包括:
void ENET_IRQHandler(void);
这个是EMAC外设的中断处理函数。

static rt_err_t lpc17xx_emac_init(rt_device_t dev);
static rt_err_t lpc17xx_emac_open(rt_device_t dev, rt_uint16_t oflag);
static rt_err_t lpc17xx_emac_close(rt_device_t dev);
static rt_size_t lpc17xx_emac_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);
static rt_size_t lpc17xx_emac_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size);
static rt_err_t lpc17xx_emac_control(rt_device_t dev, rt_uint8_t cmd, void *args);
上面这些和SD卡的驱动很像,是RT-Thread的6大设备驱动接口。但是对于类似read/write这样的接口,它们的参数类型并不符合网络报文传输的需求,所以针对与以太网设备,额外定义了如下两个接口:
rt_err_t lpc17xx_emac_tx( rt_device_t dev, struct pbuf* p);
struct pbuf *lpc17xx_emac_rx(rt_device_t dev);

tx接口用于发送报文,它是阻塞性的,即如果底层容纳不下相应的报文,将阻塞调用这个函数的线程。当底层能够进行处理时,需要唤醒发送线程做下一步操作。入口参数p是lwIP用到的0拷贝的pbuf指针。
rx接口用于接收EMAC设备上的报文,返回的是pbuf类型报文,这个函数是非阻塞性的,即如果底层没有报文接收到时,将返回RT_NULL。

void lpc17xx_emac_hw_init(void);
这个函数用于注册一个网络设备驱动。

接口是这样,那么整个RT-Thread/LwIP的框架图最终会是:


tcp是lwIP协议栈的线程;erx和etx分别是面向底层以太网的两个收发线程;

当有EMAC接收到数据包时,中断被触发。在中断服务程序中将向erx线程通知一个设备就绪的消息;erx线程获得设备就绪的请求后,将主动去读取底层的网络报文。这里对系统做了一个优化,在中断服务程序中(如果是接收中断的情况下),它将先行关闭接收中断,而erx线程激活后将转为轮询方式poll设备(因为在读取报文的中间,即使有新的报文到达,erx也已经在服务了,新的中断新的设备就绪请求已经变成了一种浪费,所以这里直接转为轮询方式(仅针对于接收)),这对提高系统的吞吐量是非常有利的。erx线程会读空EMAC中接收到的报文,当EMAC发现已经没有报文需要向上层返回时,它将再行打开接收中断。

上面这个过程也就是lpc17xx_emac_rx函数的处理过程。

再来看lpc17xx_emac_tx函数。在lpc1768中,SRAM分成了两个部分,一段是常用的程序SRAM,地址位于0x10000000 - 0x10008000总计32KB。另一段是用于USB和ethernet的SRAM,地址位于0x2007C000 - 0x20084000。EMAC用的RAM放在了0x20080000 - 0x20084000,总计16K。

它是由两个ring构成的,一个是接收用的ring,一个是发送用的ring:
/* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
#define NUM_RX_FRAG         4           /* Num.of RX Fragments 4*1536= 6.0kB */
#define NUM_TX_FRAG         3           /* Num.of TX Fragments 3*1536= 4.6kB */
#define ETH_FRAG_SIZE       1536        /* Packet Fragment size 1536 Bytes   */

/* EMAC variables located in 16K Ethernet SRAM */
#define RX_DESC_BASE        0x20080000
#define RX_STAT_BASE        (RX_DESC_BASE + NUM_RX_FRAG*8)
#define TX_DESC_BASE        (RX_STAT_BASE + NUM_RX_FRAG*8)
#define TX_STAT_BASE        (TX_DESC_BASE + NUM_TX_FRAG*8)
#define RX_BUF_BASE         (TX_STAT_BASE + NUM_TX_FRAG*4)
#define TX_BUF_BASE         (RX_BUF_BASE  + NUM_RX_FRAG*ETH_FRAG_SIZE)

针对于发送,总计有3个 buffer 空间可用(每个buffer空间的大小是1536字节)。

就协议底层的etx线程而言,它需要调用lpc17xx_emac_tx函数把数据包写到tx ring上。但是写入到tx ring上并不代表着这个报文已经被成功发送出去,而需要等待EMAC的发送完成中断。这个过程与etx线程是异步的环境。如果etx线程等待EMAC发送完成无疑将会对系统的数据吞吐量造成巨大的影响,RT-Thread for LPC1768的做法是,建立一个计数器为NUM_TX_FRAG的semaphore,在每次发送报文到tx ring时,去获得这个semaphore;如果正确获得,那么表示tx ring的资源充足。如果获取失败,那么tx ring上已经全部放满了数据等待发送。当EMAC发送完成产生中断时,在中断服务例程中将释放一个semaphore,如果这个时候etx线程挂起在sempahore上,将把etx线程唤醒继续etx线程的发送动作。<这是一个最典型的把semaphore应用于资源计数的模型>

最后看看RT-Thread for LPC1768的一些配置说明:
1. EMAC初始化及lwIP初始化是在init线程中处理,因为默认采用PHY自动协商的方式去决定是10M还是100M,自动协商会需要一定的时间,放在init线程中能够把这部分时间用于其他线程继续执行。
2. rtconfig.h中能够配置lwip更多的选项,ip地址、网关等也是在这里进行配置。同样也能够在这里设置成DHCP自动获得IP地址、DNS服务器地址的方式。
3. RT-Thread同样包括一些基本的上层应用,例如telnet服务端,tftp client,NFSv3文件系统,GoAhead WebServer,ping小程序等,这些可以从RT-Thread的google svn服务器上或论坛上获得相应的源代码。

----
RT-Thread RTOS是一个国产的开源实时操作系统。RT-Thread/LPC17xx的代码已经放在Google SVN上,当前已经包括内核、shell、文件系统、以太网的支持。查看如下网址以获得最终的源代码。
http://code.google.com/p/rt-thread/source/checkout

目前仅支持Keil MDK编译器,欢迎使用。以上的完整代码请见bsp/lpc176x/emac.c

最新回复

请问lz有ksz8041的驱动头文件吗  详情 回复 发表于 2015-12-7 22:05
点赞 关注
个人签名RT-Thread:启动下一代RTOS演化

回复
举报

117

帖子

0

TA的资源

一粒金砂(高级)

沙发
 
今天才有空做一个1768的网络测试,测试下来结果惊人(和其他Cortex-M3芯片相比):
netio.exe -t 192.168.1.30

NETIO - Network Throughput Benchmark, Version 1.26
(C) 1997-2005 Kai Uwe Rommel

TCP connection established.
Packet size  1k bytes:  1014 KByte/s Tx,  5196 Byte/s Rx.
Packet size  2k bytes:  1015 KByte/s Tx,  3248 KByte/s Rx.
Packet size  4k bytes:  1016 KByte/s Tx,  3248 KByte/s Rx.
Packet size  8k bytes:  1017 KByte/s Tx,  3249 KByte/s Rx.
Packet size 16k bytes:  1018 KByte/s Tx,  3250 KByte/s Rx.
Packet size 32k bytes:  1020 KByte/s Tx,  158 KByte/s Rx.
Done.

可以看得出来,lpc1768接收速度一般,1MB/s,发送速度包超过1k以后基本上在3.2MB/s的样子。
 
个人签名RT-Thread:启动下一代RTOS演化
 

回复

117

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
32k大包则有些杯具了,因为lpc1768的可用内存实际只有32k。。。不过我还没搞明白最大可用内存是32k,为什么还能够发送、接收32k的大包。
 
个人签名RT-Thread:启动下一代RTOS演化
 
 

回复

91

帖子

0

TA的资源

一粒金砂(中级)

4
 

我要1768,没有操作系统的 lwIP, 特别是要求有tcp的socket部分。可以在keil上编译,运行,测试,mcb1700板

或者有操作系统,但能独立在keil 4.11下编译,在mcb1700里运行,检验socket

[ 本帖最后由 liwenz 于 2010-11-11 16:56 编辑 ]
 
 
 

回复

91

帖子

0

TA的资源

一粒金砂(中级)

5
 
你能把你的做测试的keil project给我吗?能够编译,能够运行在mcb1700上

email :  sv@liwensoft.com
qq:635477196
 
 
 

回复

92

帖子

0

TA的资源

一粒金砂(中级)

6
 

回复 5楼 liwenz 的帖子

RT-Thread是完全开源的,你可以从官方SVN服务器中获取代码。
 
 
 

回复

9

帖子

1

TA的资源

一粒金砂(初级)

7
 
不错,学习
 
 
 

回复

9

帖子

1

TA的资源

一粒金砂(初级)

8
 
学习学习
 
 
 

回复

6

帖子

0

TA的资源

一粒金砂(初级)

9
 
请问lz有ksz8041的驱动头文件吗
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表