查看( 175 ) / 评论( 0 ) / 评分( 0 / 0 )
1.内存池地址对齐问题
timer tcon=00500000, tcnt dc7e, tcfg 00000200,00000000
uC/OS-II, The Real-Time Kernel ARM Ported version
Jean J. Labrosse/ (Ported by) Michael Anburaj
WEIYAN TECHNOLOGY
Task1 #1
TCP/IP initialized.
11111111111
1:0:16:13
2:0:16:13
3:0:16:13
1:1:16:13
Dabort exception!!!
跟踪一下,发现问题在memp_init初始化时memp->next访问的地址没有对齐。
memp_init(void)
{
……
memp = LWIP_MEM_ALIGN(memp_memory);
/* for every pool: */
for (i = 0; i < MEMP_MAX; ++i) {
memp_tab[i] = NULL;
/* create a linked list of memp elements */
for (j = 0; j < memp_num[i]; ++j) {if(i>12)CONSOL_Printf("1:%d:%d:%d\n",j,memp_num[i],i);
memp->next = memp_tab[i];
memp_tab[i] = memp;
memp = (struct memp *)((u8_t *)memp + MEMP_SIZE + memp_sizes[i]);
……
}
#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))
memp->next访问时需要4字节对齐的地址。而默认的MEM_ALIGNMENT为1,通过LWIP_MEM_ALIGN调整的地址为1字节对齐,故出现该错误。定义MEM_ALIGNMENT为4使调整的地址以4字节对齐,问题解决。
2.ip头部对齐
当接收到http访问的IP包时,再次出现Dabort exception!!!错误。
再次跟踪(幸好有个仿真器,不然累死…),发现在ip_input里
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
这一句有问题,iphdr->dest存放在2字节对齐的内存里,而ip_addr_cmp访问时一次读入4个字节,需4字节对齐。由iphdr = p->payload跟踪payload存放的地址,当驱动收到以太包上传时,payload是指向4字节对齐的地址。但进入ethernet_input,再传给ip_input后,payload的地址发生了变化,增加了14个字节,导致字节对齐出现问题。仔细一看,发现问题在这一句:
if(pbuf_header(p, -(s16_t)sizeof(struct eth_hdr))) {
当跳过已处理的物理地址时,sizeof(struct eth_hdr)恰好为14字节…
问题的解决也很简单,LWIP已经准备了硬件地址补齐的预定义,使用
#define ETH_PAD_SIZE 2
补齐2字节即可。
3.系统配置
UCOS默认配置的队列控制块OS_MAX_QS和事件控制块OS_MAX_EVENTS分别为4和10,当创建多个lwip进程时,会出现资源不足导致程序失败的,需增加这些系统资源。
//#define OS_MAX_EVENTS 32
#define OS_MAX_QS 10
4.全局字符变量的对齐问题
真佩服ADS的编译器,这次的问题还是字节对齐的问题。在http任务里,定义的两个全局字符数组,编译器生成的访问地址竟然在奇数开始的地址,当16位的网卡发送访问该地址时会出现data abort的错误。这回真的头都大了…使用__packet和align都没有效果。到时有2个办法可以使用,1是数组放到函数内,二是自己定义一个结构体,在第一个字节处自己填充一个0,第二个字节处存放真实的数据。
有关ARM平台字节对齐的一篇文章(感觉解析很透彻)
http://www.cpper.com/zweily/68.html
5.数据分包大小
移植好的HTTP server工作很正常,但修改一下输出的内容,发现又不能工作---__---
重复修改输出的内容,发现一超过128字节时,程序工作不正常。用Wireshark抓包,发现输出的内容被切割成多个小包。一把抓住一个,仔细一看,发现一个数字很熟悉,就是MSS=128。
查了下资料,MSS就是最大的分包大小。设为以太网可以接受的1450,一切OK。
当一切搞定后,现在来看看我们移植的成果:
ping 开发板的ip 192.168.1.174,返回正常。在UCOS心跳时间为5ms,dm9000驱动接收间隔为10ms的情况下,平均2ms的返回时间有点出乎意料。
下面是LWIP带的一个简单HTTP server,修改一下就能很好的工作。