给Hi3518e的Uboot添加UDP广播收发功能
2016-09-30 11:22
246 查看
基于个人兴趣,决定实现一个和方案公司提供的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
4. 给common目录的makefile添加
COBJS-$(CONFIG_CMD_UDP) += cmd_udp.o5. 在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);
#endif5.
修改net目录的net.c,在最下面加入NetLoop_UDP函数,并添加udp.h头文件引用 #include "udp.h"
int
NetLoop_UDP(const uchar* remorteth, char* remoteip, int remoteport, int thisport, const char* data, int datalength)
{
bd_t *bd = gd->bd;
/* XXX problem with bss workaround */
NetTxPacket = NULL;
if (!NetTxPacket){
int i;
/*
* Setup packet buffers, aligned correctly.
*/
NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
for (i = 0; i < PKTBUFSRX; i++) {
NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
}
}
eth_halt();
if (eth_init(bd) < 0) {
eth_halt();
return(-1);
}
restart:
eth_getenv_enetaddr("ethaddr", NetOurEther);
/*
* Start the ball rolling with the given start function. From
* here on, this code is a state machine driven by received
* packets and timer events.
*/
NetInitLoop(TFTP);
switch (net_check_prereq (TFTP)) {
case 1:
/* network not configured */
eth_halt();
return (-1);
case 0:
NetSetHandler(UdpHandler);
UdpStart(remorteth,remoteip, remoteport, thisport, data, datalength);
break;
}
/*
* Main packet reception loop. Loop receiving packets until
* someone sets `NetState' to a state that terminates.
*/
for (;;) {
/*
* Check the ethernet for a new packet. The ethernet
* receive routine will process it.
*/
eth_rx();
NetSetHandler(UdpHandler);
/*
* Abort if ctrl-c was pressed.
*/
if (ctrlc()) {
eth_halt();
puts ("\nAbort by Ctrl+C\n");
return (-1);
}
}
}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
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
#include <common.h> #include <command.h> #include <net.h> char _ctoi(char c) { if(c>='0'&&c<='9')return c-'0'; if(c>='a'&&c<='f')return c-'a'+10; return 0; } int _atoi(char* s) { unsigned int a=0; unsigned int b=0; int i=0; while(s[i]){ a*=10; a+=_ctoi(s[i]); i++; } return a; } int _atox(char* s) { unsigned int a=0; unsigned int b=0; int i=0; while(s[i]){ a<<=4; a|=_ctoi(s[i]); i++; if(i>=8)break; } return a; } int _strlen(char*s) { int i=0; while(s[i]){ i++; } return i; } void _getmac(char* s,char* eth) { unsigned char a=0; int i=0; while(s[i]){ a<<=4; a|=_ctoi(s[i]); if((i&1)==1){ eth[i>>1]=a; a=0; } i++; } } int do_udp_broadcast(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { uchar eth[6]= {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; char* UdpServerIP="255.255.255.255"; int dest_port = 25500, src_port =25300; uchar *str; int len; switch(argc){ case 1: puts("Params error, try again\nusage: [udp_b] [string] or [udp_b] [dest_port] [src_port] [string]\n"); return 1; break; case 2: str = argv[1]; len = strlen(str); break; case 4: dest_port = _atoi(argv[1]); src_port = _atoi(argv[2]); str = argv[3]; len = strlen(argv[3]); break; default: return 1; break; } printf("len=%d\n",len); show_boot_progress(80); if(NetLoop_UDP(eth,UdpServerIP,dest_port,src_port,str,len)<0){ show_boot_progress(-81); return 1; } return 0; } U_BOOT_CMD( udp_b, 4, 1, do_udp_broadcast, "Send or receive UDP broadcast to/from server using UDP protocol", "[udp_b] [string] or [udp_b] [dest_port] [src_port] [string]" );
4. 给common目录的makefile添加
COBJS-$(CONFIG_CMD_UDP) += cmd_udp.o5. 在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);
#endif5.
修改net目录的net.c,在最下面加入NetLoop_UDP函数,并添加udp.h头文件引用 #include "udp.h"
int
NetLoop_UDP(const uchar* remorteth, char* remoteip, int remoteport, int thisport, const char* data, int datalength)
{
bd_t *bd = gd->bd;
/* XXX problem with bss workaround */
NetTxPacket = NULL;
if (!NetTxPacket){
int i;
/*
* Setup packet buffers, aligned correctly.
*/
NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
for (i = 0; i < PKTBUFSRX; i++) {
NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
}
}
eth_halt();
if (eth_init(bd) < 0) {
eth_halt();
return(-1);
}
restart:
eth_getenv_enetaddr("ethaddr", NetOurEther);
/*
* Start the ball rolling with the given start function. From
* here on, this code is a state machine driven by received
* packets and timer events.
*/
NetInitLoop(TFTP);
switch (net_check_prereq (TFTP)) {
case 1:
/* network not configured */
eth_halt();
return (-1);
case 0:
NetSetHandler(UdpHandler);
UdpStart(remorteth,remoteip, remoteport, thisport, data, datalength);
break;
}
/*
* Main packet reception loop. Loop receiving packets until
* someone sets `NetState' to a state that terminates.
*/
for (;;) {
/*
* Check the ethernet for a new packet. The ethernet
* receive routine will process it.
*/
eth_rx();
NetSetHandler(UdpHandler);
/*
* Abort if ctrl-c was pressed.
*/
if (ctrlc()) {
eth_halt();
puts ("\nAbort by Ctrl+C\n");
return (-1);
}
}
}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
相关文章推荐
- 为 uboot 添加 wince 唤醒功能
- S3C6410移植u-boot-2010.3(4)uboot的dnw功能添加
- spring boot 添加aop功能
- 【代码练习8】UDP协议实现局域网屏幕广播功能
- SpringBoot 为MapperScan添加动态扫描(占位符)功能
- c# UDP通过广播实现群发功能
- SpringBoot添加Email发送功能及常见异常详解
- 第14章 UDP编程(3)_利用UDP实现广播功能
- springboot实现添加邮件发送及压缩功能
- c# UDP通过广播实现群发功能
- uboot1.1.6移植到jz2440上(添加DM9000(ping命令)/SDRAM/NOR/NAND功能)
- spring-boot 添加JSP页面功能
- iOS 飞屏功能的实现(UDPSocket协议广播机制)
- SpringBoot添加Email发送功能及常见异常
- U-Boot-2010.06添加烧写yaffs根文件系统功能
- u-boot-2010.3 添加usb下载功能支持 ( for mini2440)
- c# UDP通过广播实现群发功能
- 使用Spring Boot日志框架在已有的微服务代码中添加日志功能
- spring boot 添加aop功能
- Python+Socket实现基于UDP协议的局域网广播功能示例