首页 > 代码库 > 给Hi3518e的Uboot添加UDP广播收发功能

给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

 1 #include <common.h> 2 #include <watchdog.h> 3 #include <command.h> 4 #include <net.h> 5 #include <miiphy.h> 6 #include "udp.h" 7  8 void 9 UdpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len)  //这个函数是处理包,先放下,有空再写10 {11     //printf("handler udp packet\n");12     printf("Receive udp packet: %s\n",pkt);13 }14 15 void  16 udpSend(void)  17 {  18     uchar *pkt;19     pkt = (uchar *)NetTxPacket;20     pkt += NetSetEther(pkt, UdpServerEther, PROT_IP);21     NetSetIP (pkt, UdpServerIP, UdpServerPort, UdpOurPort, data_len);22     pkt += IP_HDR_SIZE;23     memcpy(pkt, pkt_data, data_len);24     (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + data_len);25 }26 27 void28 UdpStart(const uchar *remoteeth, char *remoteip, int remoteport,int thisport, const char *data, int datalength)29 {30     UdpServerEther = remoteeth;31     UdpServerIP = string_to_ip(remoteip);32     UdpServerPort = remoteport;33     UdpOurPort = thisport;34     pkt_data =http://www.mamicode.com/ data;35     data_len = datalength;36 37     udpSend();38     printf("Send,ready to receive...\n");39 }

udp.h

 1 #ifndef __UDP_H__ 2 #define __UDP_H__ 3  4 static uchar *UdpServerEther; 5 static IPaddr_t UdpServerIP; 6 static int UdpServerPort;/* The UDP port at their end 7 */ 8 static int UdpOurPort;/* The UDP port at our end 9 */10 static uchar *pkt_data;11 static int data_len;12 13 void UdpHandler(uchar *pkt, unsigned dest, unsigned src, unsigned len);14 15 #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.  From31     * here on, this code is a state machine driven by received32     * 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 until50     * someone sets `NetState‘ to a state that terminates.51     */52     for (;;) {53         /*54         * Check the ethernet for a new packet.  The ethernet55         * 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广播包屏蔽了。

技术分享

那么我们修改\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收发小工具,源码就不发了,很简单的小工具。

技术分享

 

参考链接:

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

https://segmentfault.com/a/1190000005273491

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

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