移植代码:通过已有的可用的代码修改到新环境下运行。
代码编写:
初始化网卡
1.选中网卡
nLAN_CS BWSCON(0x48000000) DW4:01 16bit
BANKCON4(0x48000014)
(0x0<<13)|(0x0<<11)|(0x7<<8)|(0x1<<6)|(0x0<<4)|(0x0<<2)|(0x0<<0)
2.初始化中断
中断源EIN7
GPFCON GPF7:10
设置触发方式(高电平触发)
EXTINT0 0x1<<28
设置中断掩码寄存器
INTMSK ~(1<<4)
EINTMASK ~(1<<7)
3.复位网卡
4.捕获网卡
5.初始化MAC
6.初始化MAC地址
7.启动网卡
发送数据
1.禁止中断
2.写入待发送的数据
3.写入发送数据的长度
4.启动发送
5.等待发送结束
6.清除发送转态
7.恢复中断
接收数据
1.判断是否产生中断,并清除
2.空读
3.读取状态
4.读取包长度
5.读取数据
/******************************************************************** *名称:dm9000.c *作者:D *时间:2015.11.24 *功能:网卡驱动 *********************************************************************/ /******************************************************************** *宏定义 *********************************************************************/ #define BWSCON ( *((volatile unsigned long *)0x48000000) ) //总线宽度与等待状态寄存器 #define BANKCON4 ( *((volatile unsigned long *)0x48000014) ) //Bank4控制寄存器 #define GPFCON ( *((volatile unsigned long *)0x56000050) ) //GPF组控制寄存器,注意该寄存器只有16位 #define SRCPND ( (*(volatile unsigned long *)0X4A000000) ) //中断源请求寄存器 #define INTMSK ( (*(volatile unsigned long *)0x4A000008) ) //中断掩码寄存器 #define INTPND ( (*(volatile unsigned long *)0X4A000010) ) //中断请求寄存器 #define EXTINT0 ( *((volatile unsigned long *)0x56000088) ) //外部中断0控制寄存器 #define EINTMASK ( (*(volatile unsigned long *)0x560000A4) ) //外部中断掩码寄存器 #define EINTPEND ( (*(volatile unsigned long *)0x560000A8) ) //外部中断掩码寄存器 #define DM9000_IO ( (*(volatile unsigned short *)0x20000300) ) //DM9000索引端口 #define DM9000_DATA ( (*(volatile unsigned short *)0x20000304) ) //DM9000数据端口 //DM9000寄存器 #define DM9000_NCR 0x00 //网络控制寄存器 #define DM9000_NSR 0x01 //网络状态寄存器 #define DM9000_TCR 0x02 //发送控制寄存器 #define DM9000_RCR 0x05 //接收控制寄存器 #define DM9000_BPTR 0x08 //背压门限寄存器 #define DM9000_FCTR 0x09 //流量控制门限寄存器 #define DM9000_FCR 0x0A //接收流量门限寄存器 #define DM9000_PAR 0x10 //物理地址寄存器 #define DM9000_GPCR 0x1E //GPIO控制寄存器 #define DM9000_GPR 0x1F //GPIO状态寄存器 #define DM9000_SMCR 0x2F //特殊模式寄存器 #define DM9000_MRCMDX 0xF0 //地址固定的存储数据读寄存器 #define DM9000_MRCMD 0xF2 //地址递增的存储数据读寄存器 #define DM9000_MWCMD 0xF8 //地址递增的存储数据写寄存器 #define DM9000_TXPLL 0xFC //传输帧长度低8位 #define DM9000_TXPLH 0xFD //传输帧长度高8位 #define DM9000_ISR 0xFE //中断状态寄存器 #define DM9000_IMR 0xFF //中断掩码寄存器 //DM9000 NCR配置 #define NCR_LBK (0x1<<1) //MAC internal loopback #define NCR_RST (1<<0) //Software reset //DM9000 NSR配置 #define NSR_WAKEST (1<<5) //Clear #define NSR_TX2END (1<<3) //Clear #define NSR_TX1END (1<<2) //Clear //DM9000 TCR配置 #define TCR_TXREQ (1<<0) //Tx request //DM9000 BPTR配置 #define BPTR_BPHW (0x3<<4) //3KB #define BPTR_JPT (0xF<<0) //600us //DM9000 FCTR配置 #define FCTR_HWOT (0x3<<4) //3KB #define FCTR_LWOT (0x8<<0) //3KB //DM9000 GPCR配置 #define GPCR_GPIO0 (1<<0) //GPIO0:output //DM9000 ISR配置 #define ISR_ROOS (1<<3) //Clear #define ISR_ROS (1<<2) //Clear #define ISR_PTS (1<<1) //Clear #define ISR_PRS (1<<0) //Clear //DM9000 RCR配置 #define RCR_DIS_LONG (1<<5) //1522Byte #define RCR_DIS_CRC (1<<4) //CRC #define RCR_RXEN (1<<0) //Enable //DM9000 IMR配置 #define IMR_PAR (1<<7) //Enable #define IMR_PRM (1<<0) //Enable //DM9000 网卡ID #define DM9000_ID 0x90000A46 //DM9000 网卡ID #define DM9000_VIDL 0x28 //DM9000 Vender ID低8位控制寄存器 #define DM9000_VIDH 0x29 //DM9000 Vender ID高8位控制寄存器 #define DM9000_PIDL 0x2A //DM9000 Product ID低8位控制寄存器 #define DM9000_PIDH 0x2B //DM9000 Product ID高8位控制寄存器 #define DM9000_PKT_MAX 1536 //接收数据包最大长度 /******************************************************************** *全局变量声明 *********************************************************************/ unsigned char mac_addr[6] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}; //MAC地址 unsigned char buffur[1024]; //接收数据缓存 /******************************************************************** *函数原型声明 *********************************************************************/ void init_dm9000(); void init_cs(); void init_int(); void reset_dm9000(); void probe_dm9000(); void launch_dm9000(); int tx_dm9000(unsigned char *buffur, int length); int rx_dm9000(unsigned char *buffur); unsigned char ior8_dm9000(int reg); void iow8_dm9000(int reg, unsigned char value); unsigned short ior16_dm9000(int reg); void iow16_dm9000(int reg, unsigned short value); void rx_dm9000_irq(); /******************************************************************** *名称:init_dm9000 *参数: * none *返回: * none *功能:初始化网卡 *********************************************************************/ void init_dm9000(){ //设置片选 init_cs(); //设置中断 init_int(); //重置网卡 reset_dm9000(); //捕获网卡 probe_dm9000(); //启动网卡 launch_dm9000(); } /******************************************************************** *名称:init_cs *参数: * none *返回: * none *功能:设置片选 *********************************************************************/ void init_cs(){ //设置数据宽度 BWSCON &= ~(0x3<<16); BWSCON |= (0x1<<16); //DW4:16bit //设置片选控制 //Tacs:0clk, Tcos:0clk, Tacc:14clk, Tcoh:1clk, Tcah:0clk, Tacp:2clk, PMC:normal BANKCON4 = (0x0<<13)|(0x0<<11)|(0x7<<8)|(0x1<<6)|(0x0<<4)|(0x0<<2)|(0x0<<0); } /******************************************************************** *名称:init_int *参数: * none *返回: * none *功能:设置中断 *********************************************************************/ void init_int(){ //配置中断引脚 GPFCON &= ~(0x3<<14); GPFCON |= 0x2<<14; //GPF7:EINT[7] //设置触发方式 EXTINT0 &= ~(0x7<<28); EXTINT0 |= 0x1<<28; //EINT7:High level // 设置外部中断掩码 EINTMASK &= ~(1<<7); //EINT7:enable interrupt // 设置中断掩码 INTMSK &= ~(1<<4); //EINT4_7:Service available } /******************************************************************** *名称:reset_dm9000 *参数: * none *返回: * none *功能:重置网卡 *********************************************************************/ void reset_dm9000(){ //打开PHY电源 iow8_dm9000(DM9000_GPCR, GPCR_GPIO0); iow8_dm9000(DM9000_GPR, 0); //第一次重置 iow8_dm9000(DM9000_NCR, (NCR_LBK|NCR_RST)); iow8_dm9000(DM9000_NCR, 0); //第二次重置 iow8_dm9000(DM9000_NCR, (NCR_LBK|NCR_RST)); iow8_dm9000(DM9000_NCR, 0); } /******************************************************************** *名称:probe_dm9000 *参数: * none *返回: * none *功能:捕获网卡 *********************************************************************/ void probe_dm9000(){ unsigned long id = 0; //网卡ID //获取网卡ID id |= ior8_dm9000(DM9000_VIDL)<<0; id |= ior8_dm9000(DM9000_VIDH)<<8; id |= ior8_dm9000(DM9000_PIDL)<<16; id |= ior8_dm9000(DM9000_PIDH)<<24; //判断网卡ID if(id == DM9000_ID){ printf("DM9000 is found!"); }else{ printf("DM9000 is not foun!"); } } /******************************************************************** *名称:launch_dm9000 *参数: * none *返回: * none *功能:启动网卡 *********************************************************************/ void launch_dm9000(){ int i; unsigned char temp_addr; //以太网地址临时变量 //配置网卡 iow8_dm9000(DM9000_NCR, 0); //Program operating register, only internal phy supported iow8_dm9000(DM9000_TCR, 0); //TX Polling clear iow8_dm9000(DM9000_BPTR, BPTR_BPHW|BPTR_JPT); //Less 3Kb, 600us iow8_dm9000(DM9000_FCTR, FCTR_HWOT|FCTR_LWOT); //Flow Control : High/Low Water iow8_dm9000(DM9000_FCR, 0); //SH FIXME: This looks strange! Flow Control iow8_dm9000(DM9000_SMCR, 0); //Special Mode iow8_dm9000(DM9000_NSR, NSR_WAKEST|NSR_TX2END|NSR_TX1END); //clear TX status iow8_dm9000(DM9000_ISR, ISR_ROOS|ISR_ROS|ISR_PTS|ISR_PRS); //IOMODE:16bit, Clear interrupt status //配置MAC地址 for(i = 0; i < 6; i++){ iow8_dm9000(DM9000_PAR+i, mac_addr[i]); } //回读MAC地址 printf("MAC address is "); for(i = 0; i < 6; i++){ temp_addr = ior8_dm9000(DM9000_PAR+i); printf("%02X:",temp_addr); } printf("! "); //启动网卡 iow8_dm9000(DM9000_RCR, RCR_DIS_LONG|RCR_DIS_CRC|RCR_RXEN); //RX enable iow8_dm9000(DM9000_IMR, IMR_PAR); //Disable all interrupt } /*----------------------------------------分割线----------------------------------------*/ /******************************************************************** *名称:rx_dm9000 *参数: * buffur 数据缓存 *返回: * return 0 成功 * 1 失败 *功能:接收数据 *********************************************************************/ int rx_dm9000(unsigned char *buffur){ int i; unsigned short temp; //临时数据 unsigned short status; //数据状态 unsigned short length; //数据长度 //判断接收中断 if( !(ior8_dm9000(DM9000_ISR)&ISR_PRS) ){ //如果没有产生中断,那么返回 return 1; } //清除接收中断 iow8_dm9000(DM9000_ISR, ISR_PRS); //空读接收数据 ior16_dm9000(DM9000_MRCMDX); //读取接收状态 status = ior16_dm9000(DM9000_MRCMD); //读取接收长度 length = ior16_dm9000(DM9000_MRCMD); if(length > DM9000_PKT_MAX){ printf("rx length too big! "); return 1; } //读取接收数据 for(i = 0; i < length; i = i+2){ temp = ior16_dm9000(DM9000_MRCMD); buffur[i] = (temp>>0)&0xFF; buffur[i+1] = (temp>>8)&0xFF; } return 0; } /******************************************************************** *名称:tx_dm9000 *参数: * buffur 数据缓存 * length 数据长度 *返回: * return 0 成功 * 1 失败 *功能:发送数据 *********************************************************************/ int tx_dm9000(unsigned char *buffur, int length){ int i; unsigned short temp; //临时数据 //关闭接收中断 iow8_dm9000(DM9000_IMR, IMR_PAR); //写入发送长度 iow8_dm9000(DM9000_TXPLL, (length>>0)&0xff); iow8_dm9000(DM9000_TXPLH, (length>>8)&0xff); //写入发送数据 for(i = 0; i < length; i = i+2){ temp = (buffur[i+1]<<8)|(buffur[i]<<0); iow16_dm9000(DM9000_MWCMD, temp); } //打开发送请求 iow8_dm9000(DM9000_TCR, TCR_TXREQ); //等待发送结束 while( (ior8_dm9000(DM9000_TCR)&TCR_TXREQ) ); //如果发送请求为1,那么等待 //清除发送状态 iow8_dm9000(DM9000_NSR, NSR_WAKEST|NSR_TX2END|NSR_TX1END); //打开接收中断 iow8_dm9000(DM9000_IMR, IMR_PAR|IMR_PRM); return 0; } /*----------------------------------------分割线----------------------------------------*/ /******************************************************************** *名称:ior8_dm9000 *参数: * reg 索引端口 *返回: * value 读取数据 *功能:从网卡IO端口读取一个字节 *********************************************************************/ unsigned char ior8_dm9000(int reg){ unsigned char value; DM9000_IO = reg; value = DM9000_DATA; return value; } /******************************************************************** *名称:iow8_dm9000 *参数: * reg 索引端口 * value 写入数据 *返回: * none *功能:写一个字节到网卡IO端口中 *********************************************************************/ void iow8_dm9000(int reg, unsigned char value){ DM9000_IO = reg; DM9000_DATA = value; } /******************************************************************** *名称:ior16_dm9000 *参数: * reg 索引端口 *返回: * value 读取数据 *功能:从网卡IO端口读取两个字节 *********************************************************************/ unsigned short ior16_dm9000(int reg){ unsigned short value; DM9000_IO = reg; value = DM9000_DATA; return value; } /******************************************************************** *名称:iow16_dm9000 *参数: * reg 索引端口 * value 写入数据 *返回: * none *功能:写两个字节到网卡IO端口中 *********************************************************************/ void iow16_dm9000(int reg, unsigned short value){ DM9000_IO = reg; DM9000_DATA = value; } /*----------------------------------------分割线----------------------------------------*/ /******************************************************************** *名称:rx_dm9000_irq *参数: * none *返回: * none *功能:接收数据中断服务 *********************************************************************/ void rx_dm9000_irq(){ //接收数据 rx_dm9000(buffur); //清除外部中断请求 EINTPEND |= (1<<7); //EINT8:cleard //清除中断源请求 SRCPND |= (1<<4); //EINT4_7:cleard //清除中断请求 INTPND |= (1<<4); //EINT4_7:cleard }