硬件准备
ADSP-EDU-BF533:BF533开发板
AD-HP530ICE:ADI DSP仿真器
软件准备
Visual DSP++软件
硬件链接
硬件设计原理图
功能介绍
BF533说实话用来做LAN的应用有些许勉强,因为他自己不带网口,要做的话,需要在总线上挂,那么真实来讲,我何不直接用一个自带网口的DSP呢?比如BF537?BF548?BF609?因为我在做BF533的项目的时候,其他的DSP都还没有推出,ADI没有什么带网口的DSP,所以强行用533+一个DM9000来实现的,当下如果让我再去做这个方案的设计,芯片选型会有更多的选择。
20年前那会,我们真的是没条件也得创造条件。。。
这个程序只是打通了底层的硬件链路,并没有去写怎么移植TCP/IP协议的,后面有时间我再单独开一章,好好说一说怎么在嵌入式DSP上去移植TCP/IP协议。
ADSP-EDU-BF533开发板上的网卡模块采用 DM9000EP 实现, DM9000EP 为 DAVICOM 公司生产的网络芯片,它集成了网卡的 MAC 和 PHY,支持 10M/100M 速度。支持 16Bit/32Bit 总线访问带宽。
ADSP-BF533 通过 EBIU 总线采用 16Bit 总线方式与 DM9000EP 连接,其映射地址为 ADSP-BF53x 的 BANK2地址,其映射寄存器如下:
DM9000_PPTR 寄存器(写唯一):
DM9000_PPTRT 寄存器地址:0x20200000
DM9000_PPTR 寄存器是 DM9000EP 的指令寄存器,用于为 DM9000EP 写入指令。
DM9000_PDATA 寄存器(读写):
DM9000_PDATA 寄存器地址:0x20200020
DM9000_PDATA 寄存器是 DM9000EP 的数据寄存器,通过该寄存器读取和发送数据包。
硬件连接示意图
代码实现功能
代码实现了通过网络接口发送数据包的功能,没有包含任何网络协议。通过网线与计算机连接,使用计算机上的抓包工具,抓取数据包可以查看数据包的数据内容。
调试步骤
通过抓包软件 Commview.exe 的 Pack 窗口可以看到抓取的数据包的数据信息。
计算机端打印的网卡信息
使用 COMMVIEW 软件抓取的数据包信息。
程序源码
#include
#include “dm9000e.h”
#define CONFIG_DRIVER_DM9000
#define CONFIG_COMMANDS 1
#define CFG_CMD_NET 1
#ifdef CONFIG_DRIVER_DM9000
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#define PKTALIGN 32
#define PKTSIZE_ALIGN 1536
#define CFG_HZ 1000
#define DM9000_VID_L 0x28
#define DM9000_VID_H 0x29
#define DM9000_PID_L 0x2A
#define DM9000_PID_H 0x2B
#define DM9000_ID 0x90000A46
#define DM9000_int32_MII 0x00
#define DM9000_10MHD 0x1
#define DM9000_10MFD 0x2
#define DM9000_100MHD 0x3
#define DM9000_100MFD 0x4
#define LOOP_MAC 0x1
#define LOOP_PHY100M 0x2
unsigned short NetRxPackets[PKTSIZE_ALIGN+PKTALIGN];
unsigned char env_enetaddr[6];
#define DM9000_PPTR *(volatile unsigned short *)(0x20200000)
#define DM9000_PDATA *(volatile unsigned short *)(0x20200020)
/****************************************************************************
名称 : GetDM9000ID
功能 : 读取DM9000E ID并打印
入口参数 :无
出口参数 :id_val ID值
****************************************************************************/
unsigned int GetDM9000ID(void)
{
unsigned int id_val;
id_val = ior(DM9000_PID_H);
printf(“DM9000E ID is %x”,id_val);
id_val = ior(DM9000_PID_L);
printf(“%x”,id_val);
id_val = ior(DM9000_VID_H);
printf(“%x”,id_val);
id_val = ior(DM9000_VID_L);
printf(" %x\n\r",id_val);
return id_val;
}
/****************************************************************************
名称 : iow
功能 : 将值写入指定的寄存器
入口参数 :reg,value
出口参数 :无
/
static void iow(int reg, unsigned char value)
{
DM9000_PPTR = reg;
asm(“ssync;”);
asm(“ssync;”);
asm(“ssync;”);
DM9000_PDATA = value & 0xff;
asm(“ssync;”);
asm(“ssync;”);
asm(“ssync;”);
}
/
名称 : ior
功能 : 送入要读取的寄存器地址返回当前寄存器值
入口参数 :reg
出口参数 :DM9000_PDATA & 0xff
/
static unsigned char ior(int reg)
{
DM9000_PPTR = reg;
asm(“ssync;”);
asm(“ssync;”);
asm(“ssync;”);
return DM9000_PDATA & 0xff;
}
/
名称 : eth_reset
功能 : 复位,初始化dm9000E并打印相关设置
入口参数 :无
出口参数 :无
****************************************************************************/
void eth_reset (void)
{
int IoMode;
unsigned char tmp;
iow(0, 1); // 复位
delay(50); // delay 100us
IoMode = ior(0xfe) >> 6; //读取io模式
if(!IoMode)
printf(“DM9000 work in 16 bus width\r\n”);
else if(IoMode == 2)
printf(“DM9000 work in 8 bus width\r\n”);
else if(IoMode == 1)
printf(“DM9000 work in 32 bus width\r\n”);
else
printf(“DM9000 work in wrong bus width, error\r\n”);
iow(0x1e, 0x01);
iow(0x1f, 0x00); // 使能 PHY
iow(0xff, 0x80);
iow(0x01, 0xc); // 清除 TX 状态
iow(0x5, 0x33); // 使能 RX
ior(0x6);
iow(0x2, 1); // 使能TX
delay(100);
IoMode = ior(0x01);
if(IoMode & 0x40)
printf(“Link on ethernet at:%d Mbps\r\n”, (IoMode & 0x80) ? 10:100);
}
/****************************************************************************
名称 : eth_rx
功能 : 读取网络传输数据
入口参数 :addr
出口参数 :rxlen
****************************************************************************/
int eth_rx (unsigned short *addr)
{
int i;
unsigned short rxlen;
unsigned short status;
unsigned char RxRead;
unsigned char *tmp;
RxRead = ior(0xf0);
RxRead = (DM9000_PDATA) & 0xff;
RxRead = (DM9000_PDATA) & 0xff;
if (RxRead != 1)
return 0;
status = ior(0xf2);//获得状态
rxlen = DM9000_PDATA; //获得长度
asm(“ssync;”);
if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
printf (“packet too big! %d %d\r\n”, rxlen, PKTSIZE_ALIGN + PKTALIGN);
for ( i =0; i
asm(“ssync;”);
return rxlen;
}
unsigned char txCmd;
/****************************************************************************
名称 : eth_send
功能 : 向网络发送数据包
入口参数 :packet,length
出口参数 :0
****************************************************************************/
void eth_send (volatile void *packet, int length)
{
int i;
volatile unsigned short *addr;
int tmo;
unsigned char TxStatus;
int length1 = length>>1;
int IoMode;
TxStatus = ior(0x01);
TxStatus = TxStatus & 0xc;
DM9000_PPTR = 0xf8;
for(i=0;i<2;i++) //延时匹配时序。
asm(“ssync;”);
for (addr = packet; length1 > 0; length1 --)
{
DM9000_PDATA = *addr++;
for(i=0;i<3;i++) //延时匹配84nS延时时序。
asm(“ssync;”);
}
iow(0xfd, (length >> 8) & 0xff); //set transmit leng
iow(0xfc, length & 0xff);
/* start transmit */
iow(0x02, txCmd|0x1);
return 0;
}
/****************************************************************************
名称 : phy_read
功能 : 读取DM9000E物理寄存器
入口参数 :reg
出口参数 :( ior( 0xe) << 8 ) | ior( 0xd)
/
static unsigned short phy_read(int reg)
{
iow( 0xc, DM9000_PHY | reg);
iow( 0xb, 0xc);
delay(100);
iow(0xb, 0x0);
return ( ior( 0xe) << 8 ) | ior( 0xd);
}
/
名称 : phy_write
功能 : 写DM9000E物理寄存器
入口参数 :reg,value
出口参数 :无
/
static void phy_write( int reg, unsigned short value)
{
iow( 0xc, DM9000_PHY | reg);
iow( 0xd, (value & 0xff));
iow(0xe, ( (value >> 8) & 0xff));
iow(0xb, 0xa);
delay(100);
iow(0xb, 0x0);
}
/
名称 : set_PHY_mode
功能 : 设置网卡工作模式 10M:100M
入口参数 :op_mode
出口参数 :无
****************************************************************************/
static void set_PHY_mode(op_mode)
{
int phy_reg4,phy_reg0;
switch(op_mode)
{
case DM9000_10MHD:
phy_reg4 = 0x21;
asm(“ssync;”);
phy_reg0 = 0x0000;
asm(“ssync;”);
break;
case DM9000_10MFD:
phy_reg4 = 0x41;
asm(“ssync;”);
phy_reg0 = 0x1100;
asm(“ssync;”);
break;
case DM9000_100MHD:
phy_reg4 = 0x81;
asm(“ssync;”);
phy_reg0 = 0x2000;
asm(“ssync;”);
break;
case DM9000_100MFD:
phy_reg4 = 0x101;
asm(“ssync;”);
phy_reg0 = 0x3100;
asm(“ssync;”);
break;
} // end of switch
phy_write( 0, phy_reg0);
phy_write( 4, 0x0400|phy_reg4);
}
/****************************************************************************
名称 : loopback
功能 : 网卡环路测试,设置网卡工作于何种环路测试模式
入口参数 :mode
出口参数 :无
****************************************************************************/
void loopback(int mode)
{
switch(mode)
{
case LOOP_MAC:
iow(DM9000_NCR, 0x02);
phy_write( 0, 0x40);
break;
case LOOP_PHY100M:
iow(DM9000_NCR, 0x04);
phy_write( 0, 0x40);
break;
}
}
#endif
#endif
unsigned short pack[1024];
unsigned short packLen=0;
void main()
{
int i;
Set_PLL(16,4);
Init_EBIU();
Init_SDRAM();
GetDM9000ID();
set_PHY_mode(DM9000_100MHD);
eth_reset();
delay(100);
for(i=0;i<1024;i++)
pack[i] = i;
while(1)
{
for(i=0;i<1000000;i++)
{
packLen = 512;
eth_send(pack,packLen);
}
eth_rx(NetRxPackets);
}
}