手机操作系统 2016-09-30
基于个人兴趣,决定实现一个和方案公司提供的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广播包屏蔽了。

那么我们修改\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