1. 网卡硬件结构(DM9000A)

网卡的实质就是MAC通过MII接口控制PHY的过程。

MAC主要负责数据帧的构建、数据差错检查、传送控制等。

PHY是物理接口收发器,属于物理层,当它收到MAC过来的数据时,它会去加上校验码,然后按照物理层的规则进行数据编码,再发送到传输介质上,接收过程则相反。

MII:媒体独立接口, “媒体独立”表明MAC一定情况下,任何类型的PHY设备都可以正常工作。

2. DM9000A硬件接口

由上图得到以下信息:

dm9000的片选信号CS#接到Xm0CSn1,Xm0CSn1选择的是Bank1,那么片选的起始地址为0x18000000;cmd引脚接到Xm0ADDR2,那么数据端口地址为0x18000004。

3. 软件设计

3.1 设置SROM Register

读写时序控制

3.2 设置DM9000A相关参数(初始化)

参考uboot

3.3 初步测试

测试结果与设置的一样,说明读写操作正常。

测试代码:

 //各种初始化...包括串口初始化等等
//下面是读取一些芯片的出厂信息
tmp = (unsigned char)ior(0x2c);
printf("CHIP Revision:%2x\n\r", tmp);
tmp = (unsigned char)ior(0x28);
printf("Vendor ID_L:%2x \n\r", tmp);
tmp = (unsigned char)ior(0x29);
printf("Vendor ID_H:%2x \n\r", tmp);
tmp = (unsigned char)ior(0x2a);
printf("Product ID_L:%2x \n\r", tmp);
tmp = (unsigned char)ior(0x2b);
printf("Product ID_H:%2x \n\r", tmp);

4. ARP协议实现

4.1 基础知识

4.1.1 以太网的格式

目的MAC地址:接收者的物理地址;MAC地址:发送者的物理地址;类型:标明高层的数据使用的协议类型;数据:高层的数据;CRC:校验码

4.1.2 ARP功能

在以太网络中,每台计算机的唯一身份标示是MAC地址(物理层的地址),两台计算机要进行通讯,也必须知道对方的MAC地址,但是用户通常只知道对方的IP地址,这个时候,就可以利用ARP(地址解析协议)来向局域网中的所有计算机发送ARP请求包,收到请求包且满足条件的计算机将回复ARP应答包,告知其MAC地址。所以ARP协议是一种利用IP地址或者MAC地址的协议.

4.1.3 ARP格式

ARP包分为请求包和应答包,通过OP字段来区别。

4.2 ARP收发

注意字节序!

5. 代码

 #include "arp.h"

 #define HON(n) ((((u16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))

 /*1.发送arp请求包*/
void arp_request()
{
/*1.构成arp请求包*/
memcpy(arpbuf.ethhdr.d_mac,host_mac_addr,);
memcpy(arpbuf.ethhdr.s_mac,mac_addr,);
arpbuf.ethhdr.type = HON(0x0806); arpbuf.hwtype = HON();
arpbuf.protocol = HON(0x0800); arpbuf.hwlen = ;
arpbuf.protolen = ; arpbuf.opcode = HON(); memcpy(arpbuf.smac,mac_addr,);
memcpy(arpbuf.sipaddr,ip_addr,);
memcpy(arpbuf.dipaddr,host_ip_addr,); packet_len = +; /*2.调用dm9000发送函数,发送应答包*/
dm9000_tx(buffer,packet_len);
} /*2.解析arp应答包,提取mac*/
u8 arp_process()
{ u32 i; if (packet_len<)
return ; memcpy(host_ip_addr,arpbuf.sipaddr,);
printf("host ip is : ");
for(i=;i<;i++)
printf("%03d ",host_ip_addr[i]);
printf("\n\r"); memcpy(host_mac_addr,arpbuf.smac,);
printf("host mac is : ");
for(i=;i<;i++)
printf("%02x ",host_mac_addr[i]);
printf("\n\r"); }

arp.c

 #include "dm9000.h"
#include "printf.h"
#include "arp.h" // SROM Controller
#define SROM_BW (*((volatile unsigned long*)0x70000000))
#define SROM_BC1 (*((volatile unsigned long*)0x70000008)) #define IOADDR (*((volatile unsigned short*)0x18000000))
#define IODATA (*((volatile unsigned short*)0x18000004)) u8 *buffer = &arpbuf; u8 host_mac_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
u8 mac_addr[] = {,,,,,};//随意
u8 ip_addr[] = {,,,};
u8 host_ip_addr[] = {,,,};
u16 packet_len; void delay(int n)
{
int i,j;
for(i=;i<;i++)
{
for(j=;j<n;j++)
;
}
}
void iow(u16 reg,u16 data)
{
IOADDR = reg;
IODATA = data;
} u8 ior(u16 reg)
{
IOADDR = reg;
return IODATA;
} void dm9000_reset()
{
iow(DM9000_GPCR, GPCR_GPIO0_OUT);
// power on the dm9000
iow(DM9000_GPR, );
//dm9000_reset
iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
iow(DM9000_NCR, );
delay();//second reset
iow(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST)); iow(DM9000_NCR, );
delay();
} int dm9000_probe(void)
{
u32 id_val;
id_val = ior(DM9000_VIDL);
id_val |= ior(DM9000_VIDH) << ;
id_val |= ior(DM9000_PIDL) << ;
id_val |= ior(DM9000_PIDH) << ;
if (id_val == DM9000_ID) {
printf("dm9000 is found !\n\r");
return ;
} else {
printf("dm9000 not found !\n\r");
return -;
}
} #define Tacs 2
#define Tcos 2
#define Tacc 3
#define Tcoh 2
#define Tcah 2
#define Tacp 0
int dm9000_init()
{
int i;
//设置SROM Register
SROM_BW &= (~(0xf<<));
SROM_BW |= (<<);
SROM_BC1 = (Tacs << ) | (Tcos << ) | \
(Tacc << ) | (Tcoh << ) | \
(Tcah << ) | (Tacp << ); dm9000_reset();
dm9000_probe(); //MAC初始化
/* Program operating register, only internal phy supported */
iow(DM9000_NCR, 0x0);
/* TX Polling clear */
iow(DM9000_TCR, );
/* Less 3Kb, 200us */
iow(DM9000_BPTR, BPTR_BPHW() | BPTR_JPT_600US);
/* Flow Control : High/Low Water */
iow(DM9000_FCTR, FCTR_HWOT() | FCTR_LWOT());
/* SH FIXME: This looks strange! Flow Control */
iow(DM9000_FCR, 0x0);
/* Special Mode */
iow(DM9000_SMCR, );
/* clear TX status */
iow(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
/* Clear interrupt status */
iow(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS); /* fill device MAC address registers */
for (i = ;i < ; i++)
iow(DM9000_PAR+i, mac_addr[i]); /* Activate DM9000 */
/* RX enable */
iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* Enable TX/RX interrupt mask */
iow(DM9000_IMR, IMR_PAR);
} void dm9000_tx(u8 *data,u32 length)
{
int i;
/*禁止中断*/
iow(DM9000_IMR,0x80); /*写入发送数据的长度*/
iow(DM9000_TXPLH, (length >> ) & 0xff); //高8位
iow(DM9000_TXPLL, length & 0xff); //低8位 /*写入待发送的数据*/
IOADDR = DM9000_MWCMD; for(i=;i<length;i+=)
{
IODATA = data[i] | (data[i+]<<);
} /*启动发送*/
iow(DM9000_TCR, TCR_TXREQ); /*等待发送结束*/
while()
{
u8 status;
status = ior(DM9000_TCR);
if((status&0x01)==0x00)
break;
} /*清除发送状态*/
iow(DM9000_NSR,0x2c); /*恢复中断使能*/
iow(DM9000_IMR,0x81);
} #define PTK_MAX_LEN 1522
u32 dm9000_rx(u8 *data)
{
u8 status,len;
u16 tmp;
u32 i; /*判断是否产生中断,且清除*/
if(ior(DM9000_ISR) & 0x01)
iow(DM9000_ISR,0x01);
else
return ; /*空读*/
ior(DM9000_MRCMDX); /*读取状态*/
status = ior(DM9000_MRCMD); /*读取包长度*/
len = IODATA; /*读取包数据*/
if(len<PTK_MAX_LEN)
{
for(i=;i<len;i+=)
{
tmp = IODATA;
data[i] = tmp & 0x0ff;
data[i+] = (tmp>>)&0x0ff;
}
}
} void dm9000_arp()
{
while()
{
arp_request();
delay();
}
} //初步测试
void dm9000_test(void)
{
char buf[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
char c; printf("DM9000 test :\n\r");
printf("press q to exit\n\r"); while( )
{
scanf("%c",&c);
if (c == 'q' || c == 'Q')
{
printf("%s line %d\n\r", __FUNCTION__, __LINE__);
return ;
}
unsigned char tmp; //各种初始化...包括串口初始化等等
//下面是读取一些芯片的出厂信息
tmp = (unsigned char)ior(0x2c);
printf("CHIP Revision:%2x\n\r", tmp);
tmp = (unsigned char)ior(0x28);
printf("Vendor ID_L:%2x \n\r", tmp);
tmp = (unsigned char)ior(0x29);
printf("Vendor ID_H:%2x \n\r", tmp);
tmp = (unsigned char)ior(0x2a);
printf("Product ID_L:%2x \n\r", tmp);
tmp = (unsigned char)ior(0x2b);
printf("Product ID_H:%2x \n\r", tmp); printf("%s line %d\n\r", __FUNCTION__, __LINE__);
//dm9000_tx( buf, sizeof(buf) );
printf("%s line %d\n\r", __FUNCTION__, __LINE__);
}
}

dm9000.c

 #if 0
#define EXT_INT_0_CON (volatile unsigned long*)0x7f008900
#define EXT_INT_0_MASK (volatile unsigned long*)0x7f008920
#define VIC0INTENABLE (volatile unsigned long*)0x71200010
#define EINT0_VECTADDR (volatile unsigned long*)0x71200100
#define EXT_INT_0_PEND (volatile unsigned long*)0x7f008924
#define VIC0ADDRESS (volatile unsigned long*)0x71200f00
#endif #define GPNCON (*((volatile unsigned long*)0x7F008830))
#define GPNDAT (*((volatile unsigned long*)0x7F008834)) #define EINT0CON0 (*((volatile unsigned long*)0x7F008900))
#define EINT0MASK (*((volatile unsigned long*)0x7F008920))
#define EINT0PEND (*((volatile unsigned long*)0x7F008924))
#define VIC0INTENABLE (*((volatile unsigned long*)0x71200010))
#define EINT7_VECTORADDR (*((volatile unsigned long*)0x71200104))
#define EINT0_VECTADDR (*((volatile unsigned long*)0x71200100)) #define VIC0ADDRESS (*((volatile unsigned long*)0x71200F00))
#define VIC1ADDRESS (*((volatile unsigned long*)0x71300F00)) #include "arp.h" void key1_handle()
{
__asm__( "sub lr,lr,#4\n"
"stmfd sp!,{r0-r12,lr}\n"
:
:
); led_rol(); EINT0PEND = ~0x0;
VIC0ADDRESS = ; __asm__(
"ldmfd sp!,{r0-r12,pc}^ \n"
:
:
); } void dm9000_int_issue()
{ __asm__(
"sub lr,lr,#4\n"
"stmfd sp!,{r0-r12,lr}\n"
:
:
); packet_len = dm9000_rx(buffer);
arp_process(); EINT0PEND = ~0x0;
VIC0ADDRESS = ;
//VIC1ADDRESS = 0;
__asm__(
"ldmfd sp!,{r0-r12,pc}^ \n"
:
:
);
} void init_irq()
{
EINT0CON0 |= 0B010;
EINT0MASK = ;
VIC0INTENABLE |= 0X01;
EINT0_VECTADDR = (unsigned long)key1_handle; //arp
GPNCON &= (~(0x2<<));
GPNCON |= (0x2<<);
EINT0CON0 &= (~(0x7<<));
EINT0CON0 |= (0x1<<);
EINT0MASK = ;
VIC0INTENABLE |= (<<);
EINT7_VECTORADDR = (unsigned long)dm9000_int_issue; __asm__(
"mrc p15,0,r0,c1,c0,0\n"
"orr r0,r0,#(1<<24)\n"
"mcr p15,0,r0,c1,c0,0\n" "mrs r0,cpsr\n"
"bic r0, r0, #0x80\n"
"msr cpsr_c, r0\n"
:
:
);
}

interrupt.c

6. 参考资料:

http://www.codeforge.cn/read/243433/dm9000.c__html?go_blog_box=1

http://blog.csdn.net/lzjsqn/article/details/42170375

6410实现网卡(DM9000A)收发功能及ARP协议实现的更多相关文章

  1. ARP协议与ARP攻击入门

    一 ARP协议 ARP协议是一个年代相当"久远"的网络协议.ARP协议制定于1982年11月,英文全称:Address Resolution Protocol,即"地址解 ...

  2. Lvs原理及部署之ARP协议

    1.什么使ARP协议 ARP协议,全称"Address Resolution Protocol" ,中文名是地址解析协议,使用ARP协议可实现通过IP地址获得对应的物理地址(MAC ...

  3. 关于ARP协议

    什么是arp协议: arp协议是地址解析协议,英文是address resolution protocol 通过IP地址可以获得mac地址 两个主机的通信归根到底是MAC地址之间的通信 在TCP/IP ...

  4. 什么是ARP协议?

    ARP协议,全称“Address Resolution Protocol”,中文名是地址解析协议, 使用ARP协议可实现通过IP地址获得对应主机的物理地址(MAC地址). 在TCP/IP的网络环境下, ...

  5. TX2平台CAN总线收发功能的测试

    前言 项目实现过程中需要将获取的数据信息通过CAN总线传输到控制规划模块,本文主要介绍如何在TX2平台测试CAN总线的收发功能. TX2是英伟达旗下为嵌入式平台人工智能应用开发出的一个硬件平台,TX1 ...

  6. ARP协议的基础知识

          关于ARP协议的基础知识 1.ARP的工作原理 本来我不想在此重复那些遍地都是的关于ARP的基本常识,但是为了保持文章的完整性以及照顾初学者,我就再啰嗦一些文字吧,资深读者可以直接跳过此节 ...

  7. ARP协议详解RARP

    简单来说,ARP协议是IP地址转换成MAC地址的协议.链路层协议.过程如下: 1:首先,每个主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址之间的对应关系. 2:当源主机要 ...

  8. 从零开始学安全(四十二)●利用Wireshark分析ARP协议数据包

    wireshark:是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用WinPCAP作为接口,直接与网卡进行数据报文交换,是目前 ...

  9. 图解ARP协议(三)ARP防御篇-如何揪出“内鬼”并“优雅的还手”

    一.ARP防御概述 通过之前的文章,我们已经了解了ARP攻击的危害,黑客采用ARP软件进行扫描并发送欺骗应答,同处一个局域网的普通用户就可能遭受断网攻击.流量被限.账号被窃的危险.由于攻击门槛非常低, ...

随机推荐

  1. Apache Nutch build文件解析

    本文目的:分析Apache Nutch 1.9的build.xml文件,从而让读者了解nutch的build全部流程

  2. and 与 && or 与 || 的差异之处

    其实就是比较他们的优先级 // --------------------// "||" 比 "or" 的优先级高 // 表达式 (false || true)  ...

  3. linux下bom头导致的php调用php接口 返回的json字符串 无法转成 数组,即json字符串无法解码的问题

    今天很是郁闷,写了一个php接口,返回的是标准的json字符串,但是调用的php 就是无法json_decode(),返回错误码为4,最后终于找到原因,原来是蒙一个文件中有bom头,最后采用一个命令 ...

  4. Linux Pthread 深入解析(转-度娘818)

    Linux Pthread 深入解析   Outline - 1.线程特点 - 2.pthread创建 - 3.pthread终止         - 4.mutex互斥量使用框架         - ...

  5. {part2}DFN+LOW(tarjan)割边

    首先非树边肯定不是割边,因为去掉它DFS树不受影响,只要还能生成一棵DFS树那么图就是连通的. 然后割掉一条树边只可能造成一个点与它的父亲不连通. 那好办,也就是说这个以这个点为根的子树就是上面所说的 ...

  6. About SQLite

    About SQLite See Also... Features When to use SQLite Frequently Asked Questions Well-known Users Boo ...

  7. struct2的structs.xml文件配置There is no Action mapped for action name 问题

    很久没写过博客,今天重新开始写,新技术太多,只有通过博客才可以不断积累,本人水平有限,如有错误,欢迎指正,谢谢 今天在MAVEN上配置web project的struct2,发现自己忽略了很多问题,再 ...

  8. Servlet执行流程和生命周期【慕课网搬】

    Servlet执行流程(GET方式为例) 首先用户客户端浏览器发出Get方式(点击超链接方式)向浏览器发出请求. 服务器接收到客户端点击超链接,接收到GET请求之后,服务器到WEB.xml中<s ...

  9. 格式化xml

    在程序代码开发过程中,我们可能有时候需要将xml报文进行格式化一下,整理了一下,大概有两种方法: public String formatXml(String inputXml){ SAXReader ...

  10. VR定制 AR定制 就找北京动软VR开发团队(VR案例 AR案例)

    我们长期承接丰交互软件.游戏项目外包: VR/AR内容应用定制.VR.AR游戏项目外包(有主流测试硬件设备) VR全景应用.视频外包 请提供贵公司的信息,我们将提供高大上的VR案例欢迎联系我们给您提供 ...