• [国嵌攻略][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
    }
    
  • 相关阅读:
    「搬运」影魔
    「不会」斯特林数
    「不会」二项式反演
    「不会」插头dp
    「不会」主定理
    「不会」网络流
    接口和抽象类的区别
    TestNG常用注解
    九九乘法表-Java
    冒泡排序和选择排序--Java
  • 原文地址:https://www.cnblogs.com/d442130165/p/4997778.html
Copyright © 2020-2023  润新知