DM900的DMA数据传送方式

DM900的DMA数据传送方式

项目二期    2009-12-13 11:06    阅读6   评论0   
字号:  大   中  

DMA Direct Memory Access 直接存储器访问,在大部分的网络芯片中都使用该技术,例如RTL8019,8139等。

该技术适合数据顺序存储的读写环境中,所以非常适合以太网的数据帧收发。

DMA读写方式只需要提供 起始地址 和长度就可以完成顺序存储数据的一次访问。在访问过程,存储数据的地址指针根据数据总线宽度自动增加或减少(1个字节或一个字)。有效减少访问时,对地址的操作,提高访问速度。

针对DM9000的DMA访问内部RAM,则更有其本身的特性。由于其内部RAM特点有:

读写到顶端时自动返回到底端的功能。可以看作是一个循环队列,数据先进先出。

1、用户写数据到RAM,即发生数据包,只要连续写数据到 MWCMD (0xF8) ——数据写入地址增加寄存器,然后指定长度到TXPLH,TXPLL——发送包长度寄存器,就可以完成写入操作。

如代码:

io_mode=ior(ISR)>>7;//读出io宽度

DM9000_PPTR=MWCMD;//写MWCMD寄存器,选择地址自动增加写入方式

if(io_mode==byte_mode){ //字节传送

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

DM9000_PDATA=Tx_data[i];//连续写入MWCMD寄存器

}

else if(io_mode==word_mode){//字传送

(int) length_temp=(Tx_length+1)/2;//长度修改

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

DM9000_PDATA=Tx_data[i];//连续写入MWCMD寄存器

读出数据时,即读走接收数据包,只要用户从MRCMD——数据包读地址增加寄存器连续读出,数据包信息中接收状态Rx_status,及包长度Rx_length;就可以完成读出操作。

代码如下:

(uint8) io_mode=ior(ISR)>>7;//读出io宽度

DM9000_PPTR=MRCMD;//写MRCMD寄存器,选择地址自动增加读出方式

/*接收状态及包长度信息包含在接收数据包里面*/

if(io_mode==byte_mode){//字节读出

Rx_status=DM9000_PDATA+DM9000_PDATA<<8;//接受包首两个字节为状态

Rx_length=DM9000_PDATA+DM9000_PDATA<<8;//接受包次两个字节为长度

if(io_mode==word_mode){//字读出

Rx_status=DM9000_PDATA;//接受包首字为状态

Rx_length=DM9000_PDATA;//接受包次字为长度

if(io_mode==byte_mode){//字节读出

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

(uint8) Rx_data[i]=DM9000_PDATA;//保存到接收包数组 8位

}

else if(io_mode==word_mode){//字读出

(uint16) length_temp=(Rx_length+1)/2;//修改长度

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

(uint16) RX_data[i]=DM9000_PDATA;//保存到接收包数组 16位

}

由此可见,DMA传送方式的确是高效的传送方式。

附表:接收包的表示DM900的DMA数据传送方式_第1张图片

第一个字节一定为1,假如发现不是1,需要复位以太网连接,重新自动协商——DM9000提供的硬件功能。

第二个字节为状态位。

第三和第四个字节都是接收包长度。

DM9000寄存器的读写

项目二期    2009-12-13 10:24    阅读14   评论0   
字号:  大   中  

DM9000内部有64多个8位寄存器,常用的有40多个。还有12个特殊的16位PHY寄存器,其中常用的PHY寄存器有4个。对其寄存器的读写有别于前面的64个寄存器。其寄存器的功能请参看DM9000寄存器功能详解上下文(该空间有)。

如前面所说,DM9000是数据地址线复用的,即INDEX Port,DATA Port;DM9000访问的是地址端口,还是数据端口由A2信号线的电平决定。

那么可以做这样的宏定义:

#define DM9000_PPTR   *(volatile uint16 *)(DM9000_BASE) //地址端口
#define DM9000_PDATA  *(volatile uint16 *)(DM9000_BASE +4)  //数据端口

其中 DM9000_BASE 是基地址,由板子的设计决定。

对64个8位寄存器的读写代码如下:

uint8 ior(uint8 reg) //读寄存器
{
        DM9000_PPTR=reg;
        return DM9000_PDATA&0xff;
}

void iow(uint8 reg, uint8 value) //写寄存器
{
        DM9000_PPTR = reg;
        DM9000_PDATA  =  value & 0xff;
}

其中由于MCU 的处理速度和DM9000 的处理速度可能有差别,最好加入适当的延迟。

对PHY16位寄存器的读写由8位寄存器的操作完成,代码如下:

uint16 phy_read(uint8 reg) //读PHY寄存器
{
 uint16 val;
 iow(DM9KS_EPAR, DM9KS_PHY | reg); 
 iow(DM9KS_EPCR, 0x0c);
 iow(DM9KS_EPCR, 0x08);
 val = (ior(DM9KS_EPDRH) << 8) | ior(DM9KS_EPDRL);
 return val;
}

void phy_write(uint8 reg, uint16 value) //写PHY寄存器
{

iow(DM9KS_EPAR,DM9KS_PHY|reg);
 iow(DM9KS_EPDRL,(value&0xff));
 iow(DM9KS_EPDRH,((value>>8)&0xff));
 iow(DM9KS_EPCR,0xa);
 iow(DM9KS_EPCR, 0x08);
}

最后我们再一次读出DM9000的ID。

uint32 GetDM9000ID(void)
{
        uint32 id_val;

        DM9000_PPTR = DM9KS_PID_H;
        id_val = (DM9000_PDATA & 0xff) << 8;
        DM9000_PPTR = DM9KS_PID_L;
        id_val+= (DM9000_PDATA & 0xff);
        id_val = id_val << 16;
        
        DM9000_PPTR = DM9KS_VID_H;
        id_val += (DM9000_PDATA & 0xff) << 8;
        DM9000_PPTR = DM9KS_VID_L;
        id_val += (DM9000_PDATA & 0xff);

        return id_val;
}

你可能感兴趣的:(c,IO,网络,存储,Access,byte)