[国嵌攻略][065][DM9000驱动程序设计]

移植代码:通过已有的可用的代码修改到新环境下运行。

代码编写:

初始化网卡

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
}
原文地址:https://www.cnblogs.com/d442130165/p/4997778.html