这几天一直在调试DM9000,所以关于ARM9的PWM定时器,以及看门狗定时器的操作的笔记一直也没有整理,等抽出时间来再整理吧,DM9000的调试还是费了一些精力,不过总算能够正常的收发数据了。对于这一块的具体操作,我就不细写了,给大家推荐两篇文章,写的非常的详细,我在这给出链接:
本文引用地址:https://www.eepw.com.cn/article/201611/322174.htm单片机驱动DM9000网卡芯片(详细调试过程):http://hi.baidu.com/mikenoodle/blog/item/dda3a4cc034e871800e9287a.html
s3c2440的网卡接口扩展:
http://blog.csdn.net/zhaocj/article/details/5672588
这两篇文章对我的帮助很大,我想对刚刚开始调DM9000的朋友来说会有点帮助,下面我就说一下我在这个过程中觉得应该注意的问题。
一 DM9000的的基地址设置,因为扩展网卡接口要将2440的nGCSn连接到DM9000的片选引脚,所以要想选中DM9000就必须要访问nGCSn指定的内存区域以激活nGCSn信号,我的板子连接的是nGCS4,所以访问0x20000000开始的区域可以激活nGCS4。因为DM9000由CMD引脚区分输入的是数据还是地址,一般将CMD引脚连接在2440的addr2引脚,所以可以通过访问addr2分别为0和1指定的内存区域控制addr2为0还是1,这样就能区分输入的是数据还是命令了,所以可以将DM9000的数据口地址和地址口地址都可以确定了。
二如果PC机网络连接不正常的话应该是我们的初始化有问题,我们可以将DM9000初始化后的寄存器的值通过串口打印出来,看看是不是正确。
三如果进入不了中断,说明是MMU的设置问题,因为我们用到了nGCS4,所以要设置MMU。如果我们没有考虑MMU而通过仿真运行时肯定进入不了中断的,这时我们可以将程序烧写到flash中,看看程序的运行情况(在这种情况下可能有时候收到的数据是正常的,而有时候收到的数据却不正确)。
四能够收到数据,也就是能够激发2440的外部中断进入中断的话,但收到的数据却不正确,这是可以试一下在MMU的设置中:
解决办法是:
在MMU_SetMTT(0x20000000,0x27f00000,0x20000000,RW_CNB); //bank4 for dm9000
把RW_CNB 改为RW_NCNB//cache_off,WR_BUF 以关闭cache
五 关于数据的传输,我相信看了上面的这两篇文章大家都应该对ARP数据有了一定的了解,当我们的DM9000初始化成功后,PC机就会开发板发送ARP请求信号(我的是发送了3次),这个数据是一个广播数据,里面有PC机的MAC和IP地址,所以如果我们数据接收正常的话我们可以获得这些信息,因为我的程序中将收到的数据进行区分,如果是ARP数据的话通过串口进行打印。当我们向PC机发送ARP请求的话(发送的数据中必须是有PC机的IP),PC机会发送一个ARP应答信号,里面包括PC机的MAC和IP,也包括开发板的MAC和IP。
六关于数据的读取,因为收到的数据刚开始会有一个无效数据,ARP数据的这个数据一般为0,我们必须将其读出,然后接下来的数据会是1,表示有可以接收的数据,在接下来是ARP数据的状态为,再接下来两个字节是是数据的长度,然后后面才是真正的数据,包括地址信息等。
上面这些就是我在这个过程中遇到的一些问题,下面我给出实验的截图:


这就是我收到的数据的效果图,里面有我电脑的MAC和我设置的IP。
下面是程序代码及分析:
#include"2440addr.h"
#include"dm9000.h"
#include"def.h"
#define DM_ADDR_PORT(*((volatile unsigned short *) 0x20000300))//地址口3为0也行
#define DM_DATA_PORT(*((volatile unsigned short *) 0x20000304))//数据口3为0也行
extern void Uart_Printf(char *fmt,...);
int tran;
unsigned char arpsendbuf1[42]={//请求信号
0xff,0xff,0xff,0xff,0xff,0xff,//以太网目标地址,全1表示为广播地址
0x00,0x01,0x02,0x03,0x04,0x05,//以太网源地址
0x08,0x06,//帧类型:ARP帧
0x00,0x01,//硬件类型:以太网
0x08,0x00,//协议类型:IP协议
0x06,//硬件地址长度:6字节
0x04,//协议地址长度:4字节
0x00,0x01,//操作码:ARP请求
0x00,0x01,0x02,0x03,0x04,0x05,//发送端以太网硬件地址
192, 168, 1, 50,//发送端IP协议地址
0x00,0x00,0x00,0x00,0x00,0x00,//接收端以太网硬件地址,发送请求时不用设置,为0即可,可根据IP地址转换为相应的硬件地址,即MAC
192, 168, 1, 120//接收端IP协议地址
};
int packet_len;
U8*buffer;
extern void ChangeRomCacheStatus(int attr);
//写DM9000寄存器
void __inline dm_reg_write(unsigned char reg, unsigned char data)
{
DM_ADDR_PORT = reg;//将寄存器地址写到地址端口
DM_DATA_PORT = data;//将数据写到数据端口
}
//读DM9000寄存器
unsigned char __inline dm_reg_read(unsigned char reg)
{
DM_ADDR_PORT = reg;
return DM_DATA_PORT;//将数据从数据端口读出
}
void delay(U32 t)
{
U32 i;
for(;t>0;t--)
{
for(i=0;i<100;i++){}
}
}
void dm_init(void)
{
//int i;
dm_reg_write(DM9000_NCR,3);//1//软件复位DM9000
delay(30);//延时至少20μs
dm_reg_write(DM9000_NCR,0);//清除复位位
dm_reg_write(DM9000_NCR,3);//1//为了确保复位正确,再次复位
delay(30);
dm_reg_write(DM9000_NCR,0);
dm_reg_write(DM9000_GPCR,1);//设置GPIO0为输出
delay(50);
dm_reg_write(DM9000_GPR,0);//激活内部PHY
delay(50);/////////////////////////////////////
dm_reg_write(DM9000_NSR,0x2c);//清TX状态
dm_reg_write(DM9000_ISR,0x3f); //0xf//清中断状态
dm_reg_write(DM9000_RCR,0x39);//设置RX控制
dm_reg_write(DM9000_TCR,0);//设置TX控制
dm_reg_write(DM9000_BPTR,0x3f);
dm_reg_write(DM9000_FCTR,0x3a);
dm_reg_write(DM9000_FCR,0xff);
dm_reg_write(DM9000_SMCR,0x00);
dm_reg_write(DM9000_PAR0,0x00);//设置MAC地址:00-01-02-03-04-05
dm_reg_write(DM9000_PAR1,0x01);
dm_reg_write(DM9000_PAR2,0x02);
dm_reg_write(DM9000_PAR3,0x03);
dm_reg_write(DM9000_PAR4,0x04);
dm_reg_write(DM9000_PAR5,0x05);
dm_reg_write(DM9000_NSR,0x2c);//再次清TX状态
dm_reg_write(DM9000_ISR,0x3f); //0xf//再次清中断状态
dm_reg_write(DM9000_IMR,0x81);//打开接受数据中断
}
void dm_tran_packet(unsigned char *datas, int length)
{
int i;
dm_reg_write(DM9000_IMR, 0x80);//在发送数据过程中禁止网卡中断
dm_reg_write(DM9000_TXPLH, (length>>8) & 0x0ff);//设置发送数据长度
dm_reg_write(DM9000_TXPLL, length & 0x0ff);
DM_ADDR_PORT = DM9000_MWCMD;//发送数据缓存赋予数据端口
//发送数据
for(i=0;i
{
delay(50);
DM_DATA_PORT = datas[i]|(datas[i+1]<<8);//8位数据转换为16位数据输出
}
dm_reg_write(DM9000_TCR, 0x01);//把数据发送到以太网上
while((dm_reg_read(DM9000_NSR) & 0x0c) == 0)
;//等待数据发送完成
delay(50);
评论