给Hi3518e的Uboot添加UDP广播收发功能

基于个人兴趣,决定实现一个和方案公司提供的uboot收发广播的功能。记录笔记如下。

SDK版本:Hi3518E_V100R001C01SPC081

1. 由于我手头的板子的Phy是RMII模式,因此先按这篇帖子进行将uboot默认的网络驱动改为RMII模式。

http://blog.csdn.net/skdkjzz/article/details/39931915

2. 然后设置好Phy的CONFIG_PHY_ADDR_U和CONFIG_PHY_ADDR_D,这个我不太懂是为什么,估计和硬件有关,各位看官可能这里不能完全照抄,我有空翻一翻Phy的规格书。编辑 u-boot-2010.06\include\configs\hi3518e.h

3. 在common目录下新建文件cmd_udp.c,新建一个uboot cmd

1 #include <common.h>
  2 #include <command.h>
  3 #include <net.h>
  4 
  5  char _ctoi(char c)
  6 {
  7     if(c>='0'&&c<='9')return c-'0';
  8     if(c>='a'&&c<='f')return c-'a'+10;
  9     return 0;
 10 }
 11 
 12 int _atoi(char* s)
 13 {
 14     unsigned int  a=0;
 15     unsigned int  b=0;
 16     int i=0;
 17     while(s[i]){
 18         a*=10;
 19         a+=_ctoi(s[i]);
 20         i++;    
 21     }
 22     return a;
 23 }
 24 
 25 int _atox(char* s)
 26 {
 27     unsigned int  a=0;
 28     unsigned int  b=0;
 29     int i=0;
 30     while(s[i]){
 31         a<<=4;
 32         a|=_ctoi(s[i]);
 33         i++;    
 34         if(i>=8)break;
 35     }
 36     return a;
 37 }
 38 
 39 int _strlen(char*s)
 40 {
 41     int i=0;
 42     while(s[i]){
 43         i++;
 44     }
 45     return i;
 46 }
 47 
 48 void _getmac(char* s,char* eth)
 49 {
 50     unsigned char  a=0;
 51     int i=0;
 52     while(s[i]){
 53         a<<=4;
 54         a|=_ctoi(s[i]);            
 55         if((i&1)==1){
 56             eth[i>>1]=a;
 57             a=0;            
 58         }
 59         i++;
 60     }
 61 }
 62 
 63 int do_udp_broadcast(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 64 {
 65     uchar eth[6]= {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
 66     char* UdpServerIP="255.255.255.255";
 67     int dest_port = 25500, src_port =25300;
 68     uchar *str;
 69     int len;
 70 
 71     switch(argc){
 72     case 1:
 73         puts("Params error, try again\nusage: [udp_b] [string] or [udp_b] [dest_port] [src_port] [string]\n");
 74         return 1;
 75         break;
 76     case 2:
 77         str = argv[1];
 78         len = strlen(str);
 79         break;
 80     case 4:
 81         dest_port = _atoi(argv[1]);
 82         src_port = _atoi(argv[2]);
 83         str = argv[3];
 84         len = strlen(argv[3]);
 85         break;
 86     default:
 87         return 1;
 88         break;
 89     }
 90 
 91     printf("len=%d\n",len);
 92     show_boot_progress(80);
 93     if(NetLoop_UDP(eth,UdpServerIP,dest_port,src_port,str,len)<0){
 94         show_boot_progress(-81);
 95         return 1;
 96     }
 97 
 98     return 0;
 99 }
100 
101 U_BOOT_CMD(
102     udp_b, 4, 1, do_udp_broadcast,
103     "Send or receive UDP broadcast to/from server using UDP protocol",
104     "[udp_b] [string] or [udp_b] [dest_port] [src_port] [string]"
105 );

4. 给common目录的makefile添加

COBJS-$(CONFIG_CMD_UDP) += cmd_udp.o

5. 在net目录新建文件udp处理函数,udp.c和udp.h

udp.c

#include <common.h>
 #include <watchdog.h>
 #include <command.h>
 #include <net.h>
 #include <miiphy.h>
 #include "udp.h"
 
 void
 UdpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len)  //这个函数是处理包,先放下,有空再写
 {
     //printf("handler udp packet\n");
     printf("Receive udp packet: %s\n",pkt);
 }
 
 void  
 udpSend(void)  
 {  
     uchar *pkt;
     pkt = (uchar *)NetTxPacket;
     pkt += NetSetEther(pkt, UdpServerEther, PROT_IP);
     NetSetIP (pkt, UdpServerIP, UdpServerPort, UdpOurPort, data_len);
     pkt += IP_HDR_SIZE;
     memcpy(pkt, pkt_data, data_len);
     (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + data_len);
 }
 
 void
 UdpStart(const uchar *remoteeth, char *remoteip, int remoteport,int thisport, const char *data, int datalength)
 {
     UdpServerEther = remoteeth;
     UdpServerIP = string_to_ip(remoteip);
     UdpServerPort = remoteport;
     UdpOurPort = thisport;
     pkt_data = data;
     data_len = datalength;
 
     udpSend();
     printf("Send,ready to receive...\n");
 }

udp.h

#ifndef __UDP_H__
 #define __UDP_H__
 
 static uchar *UdpServerEther;
 static IPaddr_t UdpServerIP;
 static int UdpServerPort;/* The UDP port at their end
 */
 static int UdpOurPort;/* The UDP port at our end
 */
 static uchar *pkt_data;
 static int data_len;
 
 void UdpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len);
 
 #endif

5. 修改net目录的net.c,在最下面加入NetLoop_UDP函数,并添加udp.h头文件引用 #include "udp.h"

1 int
 2 NetLoop_UDP(const uchar* remorteth, char* remoteip, int remoteport, int thisport, const char* data, int datalength)
 3 {
 4     bd_t *bd = gd->bd;
 5 
 6     /* XXX problem with bss workaround */
 7     NetTxPacket = NULL;
 8 
 9     if (!NetTxPacket){
10         int i;
11         /*
12         * Setup packet buffers, aligned correctly.
13         */
14         NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
15         NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
16         for (i = 0; i < PKTBUFSRX; i++) {
17             NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
18         }
19     } 
20 
21     eth_halt();
22     if (eth_init(bd) < 0) {
23         eth_halt();
24         return(-1);
25     }
26 
27     restart:
28     eth_getenv_enetaddr("ethaddr", NetOurEther);
29     /*
30     * Start the ball rolling with the given start function.  From
31     * here on, this code is a state machine driven by received
32     * packets and timer events.
33     */
34     NetInitLoop(TFTP);
35 
36     switch (net_check_prereq (TFTP)) {
37         case 1:
38         /* network not configured */
39         eth_halt();
40         return (-1);
41 
42         case 0:
43         NetSetHandler(UdpHandler);
44         UdpStart(remorteth,remoteip, remoteport, thisport, data, datalength);
45         break;
46     }
47 
48     /*
49     * Main packet reception loop.  Loop receiving packets until
50     * someone sets `NetState' to a state that terminates.
51     */
52     for (;;) {
53         /*
54         * Check the ethernet for a new packet.  The ethernet
55         * receive routine will process it.
56         */
57         eth_rx();
58         NetSetHandler(UdpHandler);
59 
60         /*
61         * Abort if ctrl-c was pressed.
62         */
63         if (ctrlc()) {
64             eth_halt();
65             puts ("\nAbort by Ctrl+C\n");
66             return (-1);
67         }
68     }
69 }

6. 修改net目录下的makefile,添加

COBJS-$(CONFIG_CMD_NET)  += udp.o

7. 这样操作后可以通过udp_b命令发送和接收UDP广播了。实际跑在板子上能发送UDP广播,但接收不到UDP广播包。

经过查看芯片规格书之后,发现有寄存器可以屏蔽广播包,我们查看uboot网络驱动源码之后发现确实默认将UDP广播包屏蔽了。

给Hi3518e的Uboot添加UDP广播收发功能

那么我们修改\drivers\net\hisfv300下的glb.c

将
hieth_writel_bits(ld, 0, GLB_MACTCTRL, BITS_BROAD2CPU_UP);
修改为
hieth_writel_bits(ld, 1, GLB_MACTCTRL, BITS_BROAD2CPU_UP);

8. 修改部分到此结束,现在我们进行测试。我采用的测试工具是我自己用c#写的udp收发小工具,源码就不发了,很简单的小工具。

给Hi3518e的Uboot添加UDP广播收发功能

参考链接:

http://blog.csdn.net/skdkjzz/article/details/39931915

https://segmentfault.com/a/1190000005273491

http://www.ithao123.cn/content-10639610.html

相关推荐