对于任何一个硬件模块的设计,首先第一步都是要先了解硬件本身后,再开始程序的软件设计。而由于DM9000的芯片文档内容很多,要驱动好网卡,需要很长时间,特别对于新手比较困难,所以可以参考linux内核代码中的网卡驱动程序,将其移植到裸机程序当中。下面将就ok6410,介绍DM9000裸机程序驱动的详细过程,并且完成arp协议的程序设计。

1.       DM9000硬件接口

  打开ok6410的底板原理图可以看到DM9000和ok6410的硬件接口,通过DM9000的文档大概浏览可知一些比较重要的引脚接口,如图:

再参考ok6410的核心板原理图可以很清楚的知道硬件接口对应的管脚:

SD0~SD15:DATA0~DATA15:XM0DATA0~XM0DATA15

CMD:ADDR2:XM0ADDR2

INT:IRQ_LAN:GPN7

IOR:OEN:XM0OEN

IOW:WEN:XM0WEN

CS:CSN1:XM0CSN1

  从上面一些管脚的对应关系,可能很难理解控制的方式,这和GPIO等一些模块的裸机程序时有很大的不同。在6410芯片手册中搜索关键字,对于初学者,也很难了解到各个引脚的关系。但是通过网上的资料还是可以知道DM9000接口,接在了ROM1的控制模块中,ok6410并没有接ROM。这样就可以很清楚的知道以下的关系

DATA0~DATA15:ROM1的数据总线

ADDR2:ROM1的地址总线的第二位

IRQ_LAN:中断接口

OEN:nOE

WEN:nWE

CSN1:XM0CSn

这样对DM9000模块的读写相当于对ROM的读写了,关键的是CMD的引脚即ADDR2。

当CMD为1时DATA0~DATA15为数据总线

当CMD为0时DATA0~DATA15为地址总线。

通过ok6410手册可以得出ROM1的起始地址为:0x18000000

2.       DM9000程序设计

2.1    初始化读写时序

通过时序图配置以下寄存器

void cs_init()

{

SROM_BW &= (~(0xf<<4));

SROM_BW |=  (0x1<<4);

SROM_BC1 =(0<<0)|(0x2<<4)|(0x2<<8)|(0x2<<12)|(0x2<<16)|(0x2<<24)|(0x2<<28);

}

2.2    读写操作函数

#define DM_ADD (*((volatile unsigned short *)0x18000000))

#define DM_DAT (*((volatile unsigned short *)0x18000004))

void dm9000_reg_write(u16 reg,u16 data)

{

DM_ADD = reg;

DM_DAT = data;

}

u8 dm9000_reg_read(u16 reg)

{

DM_ADD = reg;

return DM_DAT;

}

由硬件接口分析可知CMD即ROM1的地址总线的第二位,为1时为数据总线,为0是为地址总线,从而可以按上宏定义进行读写。

2.3    DM9000初始化

参考linux内核的DM9000驱动程序,可以清楚了解初始化的具体步骤

void dm9000_reset()

{

dm9000_reg_write(DM9000_GPCR, GPCR_GPIO0_OUT);

dm9000_reg_write(DM9000_GPR, 0);

dm9000_reg_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));

dm9000_reg_write(DM9000_NCR, 0);

dm9000_reg_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));

dm9000_reg_write(DM9000_NCR, 0);

}

void dm9000_probe(void)

{

u32 id_val;

id_val  = dm9000_reg_read(DM9000_VIDL);

id_val |= dm9000_reg_read(DM9000_VIDH) << 8;

id_val |= dm9000_reg_read(DM9000_PIDL) << 16;

id_val |= dm9000_reg_read(DM9000_PIDH) << 24;

if (id_val == DM9000_ID)

{

printf("dm9000 is found !\n");

return ;

}

else

{

printf("dm9000 is not found !\n");

return ;

}

}

void dm9000_init()

{

u32 i;

//设置片选

cs_init();

//复位设备

dm9000_reset();

//捕获dm9000

dm9000_probe();

//MAC初始化

//Program operating register, only internal phy supported

dm9000_reg_write(DM9000_NCR, 0x0);

//TX Polling clear

dm9000_reg_write(DM9000_TCR, 0);

//Less 3Kb, 200us

dm9000_reg_write(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);

// Flow Control : High/Low Water

dm9000_reg_write(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));

//SH FIXME: This looks strange! Flow Control

dm9000_reg_write(DM9000_FCR, 0x0);

//Special Mode

dm9000_reg_write(DM9000_SMCR, 0);

//clear TX status

dm9000_reg_write(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);

// Clear interrupt status

dm9000_reg_write(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);

//填充MAC地址

for (i = 0; i < 6; i++)

dm9000_reg_write(DM9000_PAR+i, macc_addr[i]);

//激活DM9000

dm9000_reg_write(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);

//Enable TX/RX interrupt mask

dm9000_reg_write(DM9000_IMR, IMR_PAR);

}

2.4    DM9000发送函数

void dm9000_tx(u8 *data,u32 length)

{

u32 i;

//禁止中断

dm9000_reg_write(DM9000_IMR,0x80);

//写入发送数据的长度

dm9000_reg_write(DM9000_TXPLL, length & 0xff);

dm9000_reg_write(DM9000_TXPLH, (length >> 8) & 0xff);

//写入待发送的数据

DM_ADD = DM9000_MWCMD;

for(i=0;i

{

DM_DAT = data[i] | (data[i+1]<<8);

}

//启动发送

dm9000_reg_write(DM9000_TCR, TCR_TXREQ);

//等待发送结束

while(1)

{

u8 status;

status = dm9000_reg_read(DM9000_TCR);

if((status&0x01)==0x00)

break;

}

//清除发送状态

dm9000_reg_write(DM9000_NSR,0x2c);

//恢复中断使能

dm9000_reg_write(DM9000_IMR,0x81);

}

2.5    DM9000接收函数

#define PTK_MAX_LEN 1522

u32 dm9000_rx(u8 *data)

{

u8 status,len;

u16 tmp;

u32 i;

//判断是否产生中断,且清除

if(dm9000_reg_read(DM9000_ISR) & 0x01)

dm9000_reg_write(DM9000_ISR,0x01);

else

return 0;

//空读

dm9000_reg_read(DM9000_MRCMDX);

//读取状态

status = dm9000_reg_read(DM9000_MRCMD);

//读取包长度

len = DM_DAT;

//读取包数据

if(len

{

for(i=0;i

{

tmp = DM_DAT;

data[i] = tmp & 0x0ff;

data[i+1] = (tmp>>8)&0x0ff;

}

}

}

DM9000裸机驱动程序设计的更多相关文章

  1. I2C裸机驱动程序设计

    ① I2C(Inter-Integrated Circuit)总线是由飞利浦公司开发的两线式串行总线,用于连接微控制器及其外围设备 ② I2C总线有两根双向信号线 (1)SDA:Serial Data ...

  2. SPI裸机驱动程序设计

    1. SPI(Serial Peripheral Interface)串行外设接口,是一种高速的.全双工.同步的通信总线.采用主从模式(Master Slave)架构,支持多个slave,一般仅支持单 ...

  3. 20145316&20145229实验四:驱动程序设计

    20145316&20145229实验四:驱动程序设计 结对伙伴:20145316 许心远 博客链接:http://www.cnblogs.com/xxy745214935/p/6130871 ...

  4. linux驱动程序设计的硬件基础,王明学learn

    linux驱动程序设计的硬件基础(一) 本章讲总结学习linux设备程序设计的硬件基础. 一.处理器 1.1通用处理器 通用处理器(GPP)并不针对特定的应用领域进行体系结构和指令集的优化,它们具有一 ...

  5. 信息安全系统设计基础实验四:外设驱动程序设计 20135211李行之&20135216刘蔚然

    北京电子科技学院(BESTI) 实 验 报 告 封面 课程:信息安全系统设计基础                                           班级:1352           ...

  6. Tiny6410之按键裸机驱动

    操作步骤: 第一步:查看开发板电路原理图 找到LED 和按键的管脚所对应的寄存器 LED:(见Tiny6410之LED裸机驱动) nLED_1 - GPK4 nLED_2 - GPK5 nLED_3 ...

  7. 2017-2018-1 20155214&20155216 实验四:外设驱动程序设计

    2017-2018-1 20155214&20155216 实验四:外设驱动程序设计 实验四外设驱动程序设计-1 实验要求: 学习资源中全课中的"hqyj.嵌入式Linux应用程序开 ...

  8. 基于μC/OS—III的CC1120驱动程序设计

    基于μC/OS—III的CC1120驱动程序设计 时间:2014-01-21 来源:电子设计工程 作者:张绍游,张贻雄,石江宏 关键字:CC1120   嵌入式操作系统   STM32F103ZE   ...

  9. 【驱动】DM9000网卡驱动分析

    Preface    内核源码版本:linux-2.6.18    网卡驱动·linux内核网络分层结构:http://infohacker.blog.51cto.com/6751239/122114 ...

随机推荐

  1. 20190926-02Redis五大数据类型之Set 000 028

  2. 20190923-06Linux文件权限类 000 014

    文件属性 Linux系统是一种典型的多用户系统,不同的用户处于不同的地位,拥有不同的权限.为了保护系统的安全性,Linux系统对不同的用户访问同一文件(包括目录文件)的权限做了不同的规定.在Linux ...

  3. Java网络通信 —— 序列化问题

    Java序列化的目的主要有两个: 1.网络传输 2.对象持久化 当选行远程跨迸程服务调用时,需要把被传输的Java对象编码为字节数组或者ByteBuffer对象.而当远程服务读取到ByteBuffer ...

  4. Spring-代理模式

    代理模式 目录 代理模式 1. 代理模式的分类 2. 静态代理 1. 角色分析 2. 代码步骤 3. 代理的好处 4. 进一步理解 3. 动态代理 1. 角色分析 2. 对动态代理的两个关键类的理解 ...

  5. Mybatis动态SQL配置

    使用 if where foreach标签对映射配置文件中sql语句进行动态配置 1.首先在dao接口中设置两个查询方法 package sun.dao; import sun.domain.Quer ...

  6. pytorch常用函数总结(持续更新)

    pytorch常用函数总结(持续更新) torch.max(input,dim) 求取指定维度上的最大值,,返回输入张量给定维度上每行的最大值,并同时返回每个最大值的位置索引.比如: demo.sha ...

  7. defer implement for C/C++ using GCC/Clang extension

    前述: go 中defer 给出了一种,延时调用的方式来释放资源.但是对于C/C++去没有内置的这种属性.对于经常手动管理内存的C/C++有其是C程序员这种特性显得无比重要.这里给出了一种基于GCC/ ...

  8. Django ContentType(ORM操作)

    ContentType-设计课程表 # 数据: """ 免费课:Python入门 学位课:Python全栈 价格策略: Linux入门 7 0 Python入门 7 0 ...

  9. spring的初认识

    spring的理解 1.spring是一个开源的免费框架(容器) 2.spring是一个轻量级的,非入侵式的框架 3.支持事务的处理,对框架的整合的支持 4.控制反转(ioc)和面向切口编程(aop) ...

  10. [SUCTF 2019]EasySQL1 及sql_mode

    (我被虐到了,呜呜呜) 当 sql_mode 设置了 PIPES_AS_CONCAT 时,|| 就是字符串连接符,相当于CONCAT() 函数 当 sql_mode 没有设置 PIPES_AS_CON ...