这几天一直在调试DM9000,所以关于ARM9的PWM定时器,以及看门狗定时器的操作的笔记一直也没有整理,等抽出时间来再整理吧,DM9000的调试还是费了一些精力,不过总算能够正常的收发数据了。 对于这一块的具体操作,我就不细写了,给大家推荐两篇**,写的非常的详细,我在这给出链接:
单片机驱动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数据的状态为,再接下来两个字节是是数据的长度,然后后面才是真正的数据,包括地址信息等。
上面这些就是我在这个过程中遇到的一些问题,下面我给出实验的截图:
<IMG title="十一 ARM9(2440)的网卡接口扩展" height=278 alt="十一 ARM9(2440)的网卡接口扩展" src="http://s8.sinaimg.cn/middle/6c73c98dhaa5af1151917&690" width=252>
<IMG title="十一 ARM9(2440)的网卡接口扩展" height=273 alt="十一 ARM9(2440)的网卡接口扩展" src="http://s4.sinaimg.cn/middle/6c73c98dhaa5af1b6c603&690" width=221 name=image_operate_59081313209126750 real_src="http://s4.sinaimg.cn/middle/6c73c98dhaa5af1b6c603&690">
这就是我收到的数据的效果图,里面有我电脑的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<length;i+=2)
{
delay(50);
DM_DATA_PORT = datas|(datas[i+1]<<8); //8位数据转换为16位数据输出
}
dm_reg_write(DM9000_TCR, 0x01); //把数据发送到以太网上
while((dm_reg_read(DM9000_NSR) & 0x0c) == 0)
; //等待数据发送完成
delay(50);
dm_reg_write(DM9000_NSR, 0x2c); //清除TX状态
dm_reg_write(DM9000_IMR, 0x81); //打开DM9000接收数据中断
}
int dm_rec_packet(unsigned char *datas)
{
unsigned char int_status;
unsigned char rx_ready;
unsigned short rx_status;
unsigned short rx_length;
unsigned short temp;
int i;
int_status = dm_reg_read(DM9000_ISR); //读取ISR
if(int_status & 0x1) //判断是否有数据要接受
{
dm_reg_write(DM9000_ISR,0x01);//清除中断*******************F
rx_ready = dm_reg_read(DM9000_MRCMDX); //先读取一个无效的数据
Uart_Printf("ready1=%d\n",rx_ready);
rx_ready = (unsigned char)DM_DATA_PORT; //真正读取到的数据包首字节
Uart_Printf("ready2=%d\n",rx_ready);
if(rx_ready == 1) //判读首字节是否为1或0
{
DM_ADDR_PORT = DM9000_MRCMD; //连续读取数据包内容
rx_status = DM_DATA_PORT; //状态字节
rx_length = DM_DATA_PORT; //数据长度
Uart_Printf("\nlength=%d\n",rx_length);
for(i=0; i<rx_length; i+=2) //16位数据转换为8位数据存储
{
delay(20);
temp = DM_DATA_PORT;
datas = temp & 0x0ff;
datas[i + 1] = (temp >> 8) & 0x0ff;
}
if((datas[12]==8)&&(datas[13]==6))
{
if((datas[20]==0)&&(datas[21]==1))
Uart_Printf("ARP请求\n");
if((datas[20]==0)&&(datas[21]==2))
Uart_Printf("ARP应答\n");
for(i=1; i<=rx_length; i++)
{
Uart_Printf("%d ",datas[i-1]);
if(i%6==0)
Uart_Printf("\n");
}
}
}
}
else if(rx_ready !=0) //停止设备
{
//dm_reg_write(DM9000_IMR,0x80); //停止中断
//dm_reg_write(DM9000_ISR,0x0F); //清中断状态
//dm_reg_write(DM9000_RCR,0x0); //停止接收
//还需要复位系统,这里暂时没有处理
}
dm_reg_write(DM9000_ISR, 0x1); //清中断
return rx_length;
}
void __irq uartISR(void)
{
char ch;
rSUBSRCPND |= 0x1;
rSRCPND |= 0x1<<28;
rINTPND |= 0x1<<28;
ch=rURXH0;
if(ch == 's')
tran=1; //表示发送一个ARP数据请求包
while(!(rUTRSTAT0 & 0x2));
rUTXH0=ch;
//for(i=0;i<100;i++);
}
void __irq DM9000ISR(void)
{
DisableIrq(BIT_EINT4_7);
Uart_Printf("\nEINT7 Occured\n");
if(rEINTPEND&(1<<7))
{
rEINTPEND = rEINTPEND | (0x1<<7);
packet_len = dm_rec_packet(buffer); //接收网卡数据
}
rSRCPND = rSRCPND | (0x1<<4);
rINTPND = rINTPND | (0x1<<4);
EnableIrq(BIT_EINT4_7);
}
void init()
{
//uart0 port
rGPHCON = 0x00faaa;
rGPHUP = 0x7ff;
rULCON0 = 0x3;
rUCON0 = 0x5;
rUFCON0 = 0;
rUMCON0 = 0;
rUBRDIV0 = 26;
rSRCPND = (0x1<<27)|(0x1<<28);
rSUBSRCPND = 0x1;
rINTPND = (0x1<<27)|(0x1<<28);
rINTSUBMSK = ~(0x1);
rINTMSK = ~((0x1<<27)|(0x1<<28));
pISR_UART0 = (U32)uartISR;
//EINT7
rGPFCON = 2<<14;
rEXTINT0 = (rEXTINT0 & (~(0x07<<28))) | (0x01<<28);
rEINTMASK &= ~(1<<7);
rSRCPND = rSRCPND | (0x1<<4);
rINTPND = rINTPND | (0x1<<4);
rGPFCON = (rGPFCON & (~(0x03<<14))) | (0x02<<14); //GPF7设置为EINT7
rEXTINT0 = (rEXTINT0 & (~(0x07<<28))) | (0x01<<28);
rEINTMASK = rEINTMASK & (~(0x01<<7));
ClearPending(BIT_EINT4_7);
pISR_EINT4_7 = (U32)DM9000ISR;
rINTMSK &= ~(1<<4);
}
void Main(void)
{
tran=0;
MMU_Init();
init();
dm_init();
while(1)
{
if(tran==1)
{
dm_tran_packet(arpsendbuf1, 42 );//因为PC机不断向外发送数据,其中刚开始就有ARP数据包,
tran=0; //所以为了方便查看,PC机通过串口发送's'时,DM9000
}
//向PC机发送一个ARP数据请求,再收到的ARP数据就是PC机的应答信号
}
} |
|