码迷,mamicode.com
首页 > Web开发 > 详细

U-Boot中如何添加自定义网络通信

时间:2016-07-08 16:12:14      阅读:249      评论:0      收藏:0      [点我收藏+]

标签:

U-boot没有TCP协议栈,不支持TCP(提出要在U-boot里面支持基于TCP的协议的项目经理你给我出去)。但是UDP还是有的。使用U-boot配合UDP可以做很多底层的功能。甚至我们规划在生产的时候使用U-boot来烧写Nand-Flash呢。

这篇U-boot教程没啥参考资料,完全是看着U-Boot的代码然后写出来的

 

准备用于NetLoop的软件程序

要给U-Boot添加一个UDP处理工具,那么首先应该准备用于这个程序的.c.h文件。比如我就写了amc_udp.camc_udp.h

准备UDP send函数

如何构建发送函数和接口视需求决定。但最终都是需要在函数内调用这个U-Boot API:

NetSendUDPPacket(uchar   *ether,

                 IPaddr_t dest,

                 int      dport,

                 int      sport,

                 int      len);

以下是各参数说明:

 

ether:目标的以太网地址。如果是广播,则使用全局变量NetBroadcastAddr;如果未知,则指定全零的char[6]={0,0,0,0,0,0}

 

 

dest:目标的IP地址。如果是广播,则指定0;如果是单播,则制定一个ulong值。可以指定已经设置好了的全局变量NetServerIP

 

 

dport:包发送的目的端口,即远端端口

 

 

sport:不是“sport”,而是“source-port”。包发送的源端口

 

 

lenUDP包正文的长度。发送之前需要事先设置好正文,参见下文说明

 

上面提到了发送之前必须设置好正文,那么正文在哪呢?正文在net.c的一个全局变量中,应这样获得:

uchar *context = (uchar *)(NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE);

准备UDP Timeout的处理函数

超时函数貌如static void amc_udp_timeout()。主要做一些超时时需要处理,然后设置

NetState = NETLOOP_FAIL

然后返回,这样NetLoop会提示错误退出。

准备接收处理函数

接收函数形式如:

static void amc_udp_handler(uchar *pkt, unsigned dest, unsigned srt, unsigned len);

下面列出可以在函数中获得的信息:

 

IP报头:
IP_t *ipPky = pkt - (IP_HDR_SIZE);
这一句将pkt所代表的正文前推一段距离,以获得IP报文头,此时你可以完整获取报文信息,比如:
IPAddr_t ipFrom = ipPkg->ip_src; // 可以用于UDP response
而其他的一些信息,参见IP报文的格式可知。

 

 

端口信息:
dest表示目标port,可就是远端发往本地的port;相对应地,src代表远端port

 

 

IP报文正文:
pkt本身就是,使用len获得长度

 

 

完成处理:NetLoop的完成处理是看全局变量NetState的。一般设置为NETLOOP_FAILNETLOOP_SUCCESS都导导致NetLoop()结束。其他的暂时未研究。

 

准备NetLoop()调用接口

撰写一个诸如void amc_udp_start()的函数,开始整个功能。在开始之前,需要以下两句:

NetSetHandler(amc_udp_handler);

NetSetTimeout(AMC_UDP_TIMEOUT_SEC * CFG_HZ, amc_udp_timeout);

配置好handlertimeout回调之后,就可以send udp了。

另:传输过程中,建议设置NetBootFileXferSize代表传输大小,也就是NetLoop的返回值。

 

修改net.cnet.h

首先要在net.h中添加一个协议名,如下“AMCUDP”

typedef enum {

    BOOTP, RARP, ARP, TFTP, DHCP, PING, DNS, NFS,

    CDP, NETCONS, SNTP, AMCUDP

} proto_t;

然后在NetLoop中添加执行分支:

......

    switch (protocol) {

        case TFTP:

            ...

            break;

        

        ......

        

        case AMCUDP:

            amc_udp_start();

            break;

        

        default:

            break;

    }

......

后面U-boot自然会按照你写的函数处理网络接收和相应的动作。

 

修改UDP checksum

net.c中搜索if(0 == strcmp(getenv("udpsum"), "on")),或者是直接搜udpsum可以找到UDP校验的开关。这里建议改为强制打开。

有一些U-boot是这样写的:

ip->xsum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);

 

 

启动自定义网络通信

NetLoop()函数的传入参数非常少,所以经常需要使用别的方法/函数或者是全局变量来配置。配置完成之后再开始NetLoop()。调用NetLoop监听的方法为:

netLoopRet = NetLoop(AMCUDP);

返回值小于0代表失败,可以重试

 

关于ARP

理论上,当调用NetSendUDPPacket时,如果传入的MAC地址为全0的话,U-boot会自动完成ARP过程之后再发出自定义的ARP包。但我手头项目的U-Boot代码不是这样的,它直接获得MAC地址之后就什么都不做了,这可能是一个未完成的bug

 

 

 

原文来自:segmentfault 

U-Boot中如何添加自定义网络通信

标签:

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
jiangjie190
加入时间:2016-02-19
  关注此人  发短消息
文章分类
jiangjie190”关注的人------(0
jiangjie190”的粉丝们------(0
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!