Jarvis's Blog

白帽子、全栈、IoT安全专家、嵌入式系统专家

TI DSP TMS320F28335上的TCP/IP协议栈

最近接了学校一个项目,需要在TMS320F28335+RTL8019AS平台上实现一个TCP/IP协议栈,网上找了大半圈,并没有发现相关实现,在嵌入式领域用的比较多的uip和lwip感觉体系太过于庞大,移植工作量较大,而且这两个协议栈目前都适合搭配操作系统使用,且bug不少,对于DSP28335这样性能一般的DSP来说,有点杀鸡用牛刀了。

后来,我找到了ZlIP(详细介绍:http://www.zlmcu.com/project/ZLIP/zlip.htm),一个原来在8051+RTL8019平台实现的一个轻量级TCP/IP协议栈,这个协议栈只实现了TCP/IP的协议,且ICMP协议只实现了echo,以及并不支持UDP和一些常用的应用层协议比如HTTP,不过这些正好不需要,这个实现可以满足项目的需求,又不至于过于庞大,所以就打算将其移植到TMS320F28335平台上。另外好像这个协议栈的0.2版本是开源的,1.0版本已经作为商业用途,说明稳定性应该还可以,至于我,只需要开源版本就可以了。

当然,移植过程并不轻松,在这个过程中,我总算是发现为什么DSP28335上一直没有一个像样的协议栈了,主要原因是28335的总线宽度是16位的,一个char指针指向的是2个字节,一个Int也是2个字节,而且char无法拆开,这就蛋疼了,也就是说,传统协议栈通常会采用结构体的方式去解析TCP数据包,比如像这样:

IP的头部通常是这样定义的:

 struct SIPHead
 {
 /* Version 4 bits, HeadLength 4 bits. typical value is 0x45 */
 BYTE Ver_HeadLen;

/* Precedence(priority) 3 bits, Delay, Throughput, Reliability
 , reserved 2 bits. typical value 0x00 */
 BYTE ServeType;

WORD TotalLen; /* all size of IP packet inlcude IPHead. 16 bits */
 WORD FragmentID; /* 16 bits */

/* Reserved 1 bit, May be fragmented 1 bit, Last fragment 1 bit,
 Fragment offset 13 bits. typical 0x00 */
 #define IP_FRAGMENT_OFFSET_MASK 0x1FFF
 WORD FragmentFlag_Offset;

BYTE LifeLength; /* ttl */
 BYTE Protocol; /* eg. IP_PROTOCAL_TCP*/
 WORD CheckSum; /* 16 bits */
 IP_ADDR IPScr; /* 32 bits */
 IP_ADDR IPDest;
 };

其中的IPSrc和IP_Dest都是4个字节,若直接使用Long指针去转化,他只能包含2个28335总线地址,也就是说,sizeof运算的结果会是这样:

sizeof(char) = 1

sizeof(int) = 1

sizeof(long)  = 2

也就是说和我们一般意义上的平台完全不同,因此会造成错乱,无法直接正常运行。于是,最后实在没办法,只好把结构体所有属性全部拆成单字节(也就是说浪费了高8位,2个字节大小的char只使用最低的字节位),所以代码就变成这样了:

struct SIPHead
{
 /* Version 4 bits, HeadLength 4 bits. typical value is 0x45 */
 BYTE Ver_HeadLen;

 /* Precedence(priority) 3 bits, Delay, Throughput, Reliability
 , reserved 2 bits. typical value 0x00 */
 BYTE ServeType;

 BYTE TotalLenH; /* all size of IP packet inlcude IPHead. 16 bits */
 BYTE TotalLenL;
 BYTE FragmentIDH; /* 16 bits */
 BYTE FragmentIDL;

 /* Reserved 1 bit, May be fragmented 1 bit, Last fragment 1 bit,
 Fragment offset 13 bits. typical 0x00 */
#define IP_FRAGMENT_OFFSET_MASK 0x1FFF
 BYTE FragmentFlag_OffsetH;
 BYTE FragmentFlag_OffsetL;

 BYTE LifeLength; /* ttl */
 BYTE Protocol; /* eg. IP_PROTOCAL_TCP*/
 BYTE CheckSumH; /* 16 bits */
 BYTE CheckSumL;
 BYTE IPScrH; /* 32 bits */
 BYTE IPScrh;
 BYTE IPScrl;
 BYTE IPScrL;
 BYTE IPDestH;
 BYTE IPDesth;
 BYTE IPDestl;
 BYTE IPDestL;
};

我将所有大于1个字节的成员对象,全部拆成H和L各1个字节,其中4个字节的拆成了H h l L这4个,然后,对于取出对象,自己使用了2个merge函数:

Uint32 MergeNetDword(BYTE H,BYTE h,BYTE l,BYTE L)
{
 DWORD out;
 out = htonl(((DWORD)H<<24)|((DWORD)h<<16)|((DWORD)l<<8)|(DWORD)L);
 return out;
}

Uint16 MergeNetWord(BYTE H,BYTE L)
{
 BYTE out;
 out = htons(((DWORD)H<<8)&0xFF00|(DWORD)L);
 return out;
}

在比较值的时候,再将其中的成员属性合并。最后写的非常蛋疼。不过好在程序还是正常跑起来了,TCP/IP协议也正常工作,当然蛋疼的细节还远不止上面这些。

在移植过程中,还发现了原作者留下的一些bug和坑,ARP协议还是错的,我也是醉,虽然这个不影响正常工作。

如果你对整个协议栈代码感兴趣,代码我已经放在github上以MIT协议开源了,大家可以戳这里:
https://github.com/zjlywjh001/DSP28335_ZlIP_Stack

CC2640/2650 IAR环境编译报错Error while running "D:\ti\xdctools_3_31_01_33_core\xs"原因分析

上一篇

CAN Omega 1.1版本开发笔记(一)

下一篇
评论
发表评论 说点什么
还没有评论
2629
2

    浙公网安备 33011002014706号