打印

十一 ARM9(2440)的网卡接口扩展

[复制链接]
2344|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
mizhongqin|  楼主 | 2011-9-13 13:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这几天一直在调试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机的应答信号
     
    }
}

相关帖子

沙发
river_huang| | 2011-9-22 10:39 | 只看该作者
DAVICOM大陆技术支持。有关于DM9000   DM9161的问题可以相互探讨····

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

67

帖子

1

粉丝