s3c2440的网卡接口扩展

发布者:爱笑的猫咪最新更新时间:2016-05-30 来源: eefocus关键字:s3c2440  网卡接口扩展 手机看文章 扫描二维码
随时随地手机看文章
网络对于嵌入式系统来说必不可少。可是s3c2440没有集成以太网接口,所以要想使s3c2440具备以太网的功能,就必须扩展网卡接口。在这里,我们外接DM9000,使其可以与以太网相连接。
 
       DM9000可以直接与ISA总线相连,也可以与大多数CPU相连。在这里,我们当然是要让DM9000与s3c2440相连接了。DM9000对外来说只有两个端口——地址口和数据口,地址口用于输入内部寄存器的地址,而数据口则完成对某一寄存器的读写。DM9000的CMD引脚用来区分这两个端口,当CMD引脚为0时,DM9000的数据线上传输的是寄存器地址,当CMD引脚为1时,传输的是读写数据。我们把DM9000的A8和A9接为高电平,把A4~A7接为低电平,并且把DM9000的AEN接到s3c2440的nGCS4引脚上,则DM9000的端口基址为0x20000300,如果再把DM9000的CMD引脚接到s3c2440的ADDR2引脚上,则我们就可以定义DM9000的这两个端口地址,它们分别为:
 
#define DM_ADDR_PORT          (*((volatile unsigned short *) 0x20000300))        //地址口
#define DM_DATA_PORT           (*((volatile unsigned short *) 0x20000304))        //数据口
 
如果要写入DM9000中的某个寄存器,则先把该寄存器的地址赋予DM_ADDR_PORT,然后再把要写入的数据赋予DM_DATA_PORT即可。读取DM9000中的某个寄存器也类似。下面的函数的作用分别是DM9000的读、写寄存器操作:
 
//写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;             //将数据从数据端口读出
}
      
       完成了对DM9000寄存器的读写函数的编写,下面我们就可以初始化DM9000,它的过程就是适当配置DM9000寄存器的过程。DM9000的内部寄存器在这里就不做介绍,而且DM9000的应用数据手册也有如何初始化DM9000的步骤,我们这里只给出具体的程序:
 
void dm_init(void)
{
       dm_reg_write(DM9000_NCR,1);         //软件复位DM9000
       delay(30);              //延时至少20μs
       dm_reg_write(DM9000_NCR,0);         //清除复位位
 
       dm_reg_write(DM9000_NCR,1);         //为了确保复位正确,再次复位
       delay(30);
       dm_reg_write(DM9000_NCR,0);
      
       dm_reg_write(DM9000_GPCR,1);       //设置GPIO0为输出
       dm_reg_write(DM9000_GPR,0);         //激活内部PHY
      
       dm_reg_write(DM9000_NSR,0x2c);           //清TX状态
       dm_reg_write(DM9000_ISR,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_PAR1,0x00);         //设置MAC地址:00-01-02-03-04-05
       dm_reg_write(DM9000_PAR2,0x01);        
       dm_reg_write(DM9000_PAR3,0x02);
dm_reg_write(DM9000_PAR4,0x03);
       dm_reg_write(DM9000_PAR5,0x04);
dm_reg_write(DM9000_PAR6,0x05);
   
       dm_reg_write(DM9000_NSR,0x2c);           //再次清TX状态
       dm_reg_write(DM9000_ISR,0xf);                     //再次清中断状态
 
       dm_reg_write(DM9000_IMR,0x81);           //打开接受数据中断
}
 
       DM9000内部有0x3FF大小的SRAM用于接受和发送数据缓存。在发送或接收数据包之前,数据是暂存在这个SRAM中的。当需要连续发送或接收数据时,我们需要分别把DM9000寄存器MWCMD或MRCMD赋予数据端口,这样就指定了SRAM中的某个地址,并且在传输完一个数据后,指针会指向SRAM中的下一个地址,从而完成了连续访问数据的目的。但当我们在发送或接受一个数据后,指向SRAM的数据指针不需要变化时,则要把MWCMDX或MRCMDX赋予数据端口。下面的程序为DM9000发送数据的函数,它的两个输入参数分别为要发送数据数组首地址和数据数组长度。在这里我们已经知道数据的宽为16位,它是由DM9000的硬件引脚设置实现的。
 
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);
 
dm_reg_write(DM9000_NSR, 0x2c);          //清除TX状态
dm_reg_write(DM9000_IMR, 0x81);          //打开DM9000接收数据中断
}
 
       发送数据比较简单,接收数据就略显复杂,因为它是有一定格式要求的。在接收到的一包数据中的首字节如果为0x01,则表示这是一个可以接收的数据包;如果为0x0,则表示没有可接收的数据包。因此在读取其他字节时,一定要先判断首字节是否为0x01。数据包的第二个字节为数据包的一些信息,它的高字节的格式与DM9000的寄存器RSR完全一致。第三个和第四个字节为数据包的长度。后面的数据就是真正要接收的数据了。下面就是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)                     //判断是否有数据要接受
       {
              rx_ready = dm_reg_read(DM9000_MRCMDX);         //先读取一个无效的数据
              rx_ready = (unsigned char)DM_DATA_PORT;            //真正读取到的数据包首字节
             
              if(rx_ready == 1)                 //判读首字节是否为1或0
              {
                     DM_ADDR_PORT = DM9000_MRCMD;           //连续读取数据包内容
 
                     rx_status = DM_DATA_PORT;                           //状态字节
                    
                     rx_length = DM_DATA_PORT;                          //数据长度
                    
                     if(!(rx_status & 0xbf00) && (rx_length < 10000))     //判读数据是否符合要求
                     {
                            for(i=0; i                             {
                                   delay(50);
                                   temp = DM_DATA_PORT;
                                   datas[i] = temp & 0x0ff;
                                   datas[i + 1] = (temp >> 8) & 0x0ff;
                            }
                     }
              }
              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;
}
 
       关于DM9000的设置我们就介绍到这里,下面就是s3c2440的设置。在这里,网卡发送数据利用的是查询方式,接收数据利用的是中断方式,因此我们把DM9000的INT引脚连接到了s3c2440的EINT7上。另外我们还是用UART0接口来控制和显示网卡数据。这两个接口的初始化为:
 
//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);
rINTMSK &= ~(1<<4);
pISR_EINT4_7 = (U32)DM9000ISR;
 
下面就利用DM9000来进行简单的网卡传输数据的测验。由于以太网传输数据都是基于某种协议的,因此要传输数据,必须遵循一定的协议格式。这里我们实现较为简单的ARP协议。用于以太网的ARP请求/应答分组格式为:14个字节的以太网首部+28个字节ARP请求/应答。以太网首部的格式为:6个字节的以太网目标地址+6个字节以太网源地址+2个字节帧类型,对于ARP来说,帧类型为0x0806。ARP请求/应答的格式为:2个字节的硬件类型+2个字节的协议类型+1个字节的硬件地址长度+1个字节的协议地址长度+2个字节的操作码+6个字节的发送端以太网地址+4个字节的发送端IP地址+6个字节的目标以太网地址+4个字节的目标IP地址。硬件类型为1表示的是以太网,协议类型为0x0800表示的是IP地址,硬件地址长度和协议地址长度分别为6和4,它们都是以字节为单位的,操作码为1表示的是ARP请求,为2表示的是ARP应答。
 
在下面的测试程序中,我们用交叉网线把开发板与PC机(操作系统为Windows XP,网卡的IP地址为192.168.1.120)相连接,我们通过UART发出一个命令,让开发板发出一个ARP请求数据包,然后接收来自PC机的应答,并把该应答信息通过UART显示出来。其中UART的中断复位程序为:
 
void __irq uartISR(void)
{
       char ch;
       rSUBSRCPND |= 0x1;
       rSRCPND |= 0x1<<28;
       rINTPND |= 0x1<<28;
       ch=rURXH0;
       if(ch == 0x33)
              comm=3;               //表示发送一个ARP数据请求包
      
       rUTXH0=ch;
}
 
另外我们还要事先定义一个遵循ARP协议格式的数组:
 
unsigned char arpsendbuf[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,        //接收端以太网硬件地址
       192, 168, 1, 120                                 //接收端IP协议地址
};
 
其中发送端硬件地址,即以太网源地址(00-01-02-03-04-05)是我们初始化DM9000时定义的。而发送端IP协议地址是我们任意定义的。
 
该测试程序的主程序为:
 
void Main(void)
{
……   ……
//一些必要的初始化
 
       comm=0;               //命令
       flag=0;                  //发送ARP请求包标识
      
       dm_init();              //DM9000初始化
             
       while(1)
       {
              if(comm.==3)
              {    
                     comm=0;
                     dm_tran_packet(arpsendbuf, 42 );               //发送ARP请求包
                     flag=1;           //置标识
              }
}
}
 
接收网络上的数据是通过外部中断方式的,在这个中断处理程序中,主要完成的是接收网卡数据,并把接收到的数据发送到UART,让其显示到PC机上。这里我们还需解决一个问题,那就是当我们发送一个ARP请求包的时候,XP系统并不会应答一个ARP数据包,而是应答一个IP协议数据包,当再多次发出ARP请求包后,才会得到ARP应答包。因此当s3c2440发送ARP请求包后,它首先要检查所接收到的数据包,如果不是ARP应答包,它就要再次发送ARP请求包,直到得到ARP应答包为止。因此中断处理程序为:
 
void __irq DM9000ISR(void)
{
       int i;
      
       rSRCPND = rSRCPND | (0x1<<4);
       rINTPND = rINTPND | (0x1<<4);
 
       if(rEINTPEND&(1<<7))
       {
              rEINTPEND = rEINTPEND | (0x1<<7);
 
              packet_len = dm_rec_packet(buffer);                  //接收网卡数据
 
              if((buffer[12]==0x08)&&(buffer[13]==0x06))          //是ARP协议
              {           
                     //通过UART显示出来
                     for(i=0;i                      {
                            while(!(rUTRSTAT0 & 0x2)) ;
                            rUTXH0 = buffer[i];
                     }
 
                     flag=0;                  //清标志
              }
              else if(flag==1)             //如果在发出ARP请求包后,接收到的数据不是ARP协议
              {
                     comm=3;               //继续发送ARP请求包
              }
       }
}
 
       这样,整个网卡程序就编写完毕。为了使大家对程序的因果关系认识得更加清晰,我们再叙述一遍程序的流程:首先初始化UART0,使其用中断方式接收数据,查询方式发送数据;初始化EINT7,这是因为DM9000的数据中断引脚INT是连接到s3c2440的外部中断7引脚上的;然后初始化DM9000,主要是配置一些它的寄存器,并使其用中断方式接收网卡数据,查询方式发送数据,这与UART0相似,最后是死循环等待UART0接收中断服务程序中得到的发送ARP请求包命令。当得到发送ARP请求包命令后,调用DM9000发送数据命令,发送事先准备好的一组数据。在发送完ARP数据后,PC机会应答该请求,从而引发s3c2440外部中断7中断,在该中断服务程序中,主要是完成接收ARP应答包的任务,并把它通过UART0显示出来。
 
       当程序被执行完,并在PC机上通过串口调试软件显示出了一个正确的ARP应答包后,我们还可以通过下列方法来进一步验证该程序的正确性:打开Windows XP系统只带的“命令提示符”小软件,在提示符下输入:arp –a,会出现我们所设置的开发板的MAC地址(00-01-02-03-04-05)和IP地址(192.168.1.50),则说明Windows XP系统已经把我们开发板上的网卡信息添加到了它的静态列表中。
 
       我们对该系统进一步分析还会发现,当开发板上电并且DM9000初始化完成后,Windows XP系统会向该开发板发送一些目标地址为广播地址(FF-FF-FF-FF-FF-FF)的ARP数据包和IP数据包,只要我们正确读取它们,就可以在开发板上电后,自动知道与其相连的系统的MAC地址和IP地址了。另外,如果对这一部分感兴趣,还可以编写ICMP协议的数据包,这样就可以让PC机ping通我们的开发板了。
关键字:s3c2440  网卡接口扩展 引用地址:s3c2440的网卡接口扩展

上一篇:s3c2440对nandflash的操作
下一篇:s3c2440的摄像接口应用

推荐阅读最新更新时间:2024-03-16 14:55

S3C2440中断体系结构:外部中断实验
1 SUBSRCPND和SRCPND表明有哪些中断被触发了 INTSUMMSK和INTMSK寄存器用于屏蔽某些中断 2 中断触发→SUBSRCPND相应位置1→INTSUBMSK未屏蔽→SRCPND相应位置1→ ↑ 中断触发 →若是FIQ中断:INTMOD相应位置1(同一时间,只能有一位置1) →INTMSK未屏蔽→INTPND相应位置1(同一时间,只能有一位置1) 3 读取INTPND或INTOFFSET可以确定中断源 4 清除中断的顺序:SUBSRCPND(相应位写1)→SRCPND(相应位写1)→INTPND
[单片机]
S3C2440和S5PV210的声卡对比
IIS(Inter-IC Sound)由飞利浦公司开发,是一种常用的音频设备接口,主要用于CD、MD、MP3等设备。 1.播放音频的过程: IIS接口发送声音 DDR—— S5PV210—————————— 解码芯片WM8960(DAC的过程)—— 耳机 2.录音的过程: IIS接收声音数据 MIC—— 编码芯片WM8960(ADC的过程)——————————— S5PV210—— DDR 3.IIS接口(共有5个引脚用于IIS): LRCK----------------------------------左右声道控制信号 SCLK-------------
[单片机]
<font color='red'>S3C2440</font>和S5PV210的声卡对比
Uboot在S3C2440上的移植详解(一)
一、移植环境 主 机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-boot:u-boot-2009.08.tar.bz2 二、移植步骤 本次移植的功能特点包括: 支持Nand Flash读写 支持从Nor/Nand Flash启动 支持CS8900或者DM9000网卡 支持Yaffs文件系统 支持USB下载(还未实现) 1.了解u-boot主要的目录结构和启动流程,如下图。 u-boot的stage1代码通常放在cpu/xxxx
[单片机]
Uboot在<font color='red'>S3C2440</font>上的移植详解(一)
s3c2440裸机-代码重定位(1.重定位的引入,为什么要代码重定位)
1.重定位的引入(为什么要代码重定位) 我们知道s3c2440的cpu从0地址开始取指令执行,当从nor启动时,0地址对应nor,nor可以像内存一样读,但不能像内存一样写。我们能够从nor上取指令执行。 例子1:当nand启动的时候,我们nand中的前4K指令会变自动加载到sram中去,这时的0地址对应sram。 那么我们的程序如果大于4K,要从nand启动,sram只拷贝了nand中的前4K代码,那么如何解决这个问题呢? 那么就需要重定位代码到sdram中去,sdram的容量较大,又可以直接被cpu访问。 例子2:我们知道,程序含有: 代码段(.text) 数据段(.data):存放初始值不为0的全局变量/静态变量
[单片机]
<font color='red'>s3c2440</font>裸机-代码重定位(1.重定位的引入,为什么要代码重定位)
基于S3C2440的UART传输小结
这里简单地介绍一下通过寄存器来控制S3C2440的UART传输。 查看S3C2440的芯片手册可以发现UART有着发送和接收的缓存区,在缓存区有数据后其便一个字节一个字节地将数据传输到对应端口处。 这里介绍其中使用到的几个寄存器。 ULCONx:用于设置数据的数据位、校验位、停止位之类的信息。 UCONx:设置查询方式以及UART的时钟源。 UFCONx:是否使用FIFO之类的方式。 UMCONx:是否使用流控 UBRDIVx:设置UART的波特率, 一般有两类:一种是标准的串口波特,为921600的约数,如300、600、1200、2400、4800、9600、19200、38400、43000、
[单片机]
基于<font color='red'>S3C2440</font>的UART传输小结
s3c2440 K9F2G08 nandflash支持硬件ECC校验
S3c2440的nandflash K9F2G08是支持硬件ECC的,NandFlash的每一页分为main区和spare区,S3C2440的NandFlash控制器支持这两个区的硬件ECC,这里我们实现main区的硬件ECC。在include/configs/fl2440.h文件中,如果我们定义了nandflash的硬件ECC校验,那么我们就可以控制相应的nandflash寄存器,实现硬件ECC。 nandflash的每一页有两区:main区和spare区,main区用于存储正常的数据,spare区用于存储其他附加信息,其中就包括ECC校验码。 当我们在写入数据的时候,我们就计算这一页数据的ECC校验码,然后把校验码
[单片机]
ARM Linux S3C2440 之UART分析
在分析ARM-Linux s3c2440中UART的时有必要先了解 s3c2440A中串口的硬件知识。 硬件篇: S3c2440A串口提供三个独立的异步串行通信I/O端口(asynchronousserial I/O ports)。每一个串口均可以以普通中断方式或者DMA方式进行数据收发。采用系统时钟时,最大速率为115.2kbps.如果采用外部时钟(UEXTCLK),UART速度可以更快。每个串口包含有2个64-byte的FIFO缓存区用来发送或传输数据。S3c2440A 串口具有可编程波特率,红外(IR)收发数据,1或者2 位的停止位(stop),5/6/7/8 位数据宽度和奇偶校验功能(parity checking)。
[单片机]
ARM Linux <font color='red'>S3C2440</font> 之UART分析
S3C2440的camera接口特性及WinCE 下的驱动
S3C2440是应用十分广泛且适用于嵌入式系统的一款嵌入式处理器。winCE 5.0/6.O是微软公司开发的一款专用于嵌入式系统的实时操作系统。其模块化设计使开发人员可以根据需求定制设备。目前,国内大部分OEM商都提供了对S3C2440的camera接口在WinCE5.O/6.0下的驱动支持。遗憾的是,目前国内OEM商提供的驱动仅限于对几款微型摄像头(如ov9650等)的驱动支持。当用户采用CCD摄像头作为图像采集的前端设备时,原来的驱动已经不能使用了,而CCD摄像头因其优越的性能,在监控领域扮演着主力军角色。本文从分析S3C2440的camera接口特性出发,详细介绍当摄像设备为CCD摄像头时,在WinCE 5.O/6.0操
[单片机]
<font color='red'>S3C2440</font>的camera<font color='red'>接口</font>特性及WinCE 下的驱动
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved