分类: 嵌入式
2011-01-05 14:28:28
基于RTL8019的以太网应用系统
以太网接口模块是构造一给通用的基于网络的嵌入式Linux系统的基础,该接口模块的主要任务就是完成与外界信息的交互,以达到网络监控的目的。
使用RTL8019作为以太网的物理层接口,它的基本工作原理:是在收到由主机发来的数据报后(从目的地址域到数据域),侦听网络线路。如果线路忙,就等到线路空闲为止,否则,立即发送数据桢。
RTL8019为台湾芯片生产商Realtek公司第三代快速以太网连接而设计,它支持多种嵌入式处理器芯片,内置FIFO缓存器用于发送和接受数据。
系统硬件电路结构图:
系统工作流程图:
网络数据的发送流程:
网络数据的接收:
RTL8019工作代码:
//RTL8019.c
#include "GloblDef.h"
#include "MMenage.h"
#include "RTL8019.h"
extern BYTE MemAllocation(WORD size);
extern void FreePage(BYTE page);
extern BYTE xdata *MemPageToPoint(BYTE page);
extern BYTE WriteQueue(BYTE page,struct Queue xdata * pQueue);
BYTE xdata LocalMACAddr[6]={0x52,0x54,0x4c,0x30,0x2e,0x2f};
struct Queue xdata QueueNetPacketIn;
BYTE StartPageOfPacket;
/* 接收头文件信息 */
struct RTLReceiveHeader
{
BYTE ReceiveStatus;
BYTE NextPacketStartPage;
BYTE PacketSizeLow;
BYTE PacketSizeHigh;
}Head; Head 须为全局变量.
BYTE xdata Head[4];
/* 上一次传输起始页*/
BYTE LastSendStartPage;
sbit RTLResetPin = RTL_RESET_PIN;
/* 读rtl8019 寄存器端口*/
BYTE ReadReg(WORD port)
{
BYTE xdata * p;
p = (BYTE xdata *)port;
return *p;
}
/* 写寄存器*/
void WriteReg(WORD port,BYTE value)
{
BYTE xdata * p;
p = (BYTE xdata *)port;
*p = value;
}
/* 选择寄存器页使用*/
void RTLPage(BYTE Index)
{
/* 设置 CR, CR_TXP 7-6位为 0(为 1 ,包重传) */
BYTE temp;
temp = ReadReg(CR);
temp = temp & 0x3B; /*set 7-6 and 3 bit to 0*/
Index = Index<<6;
temp = temp | Index;
WriteReg(CR,temp);
}
/* PRA 为物理地址 */
void RTLInitial()
{
BYTE temp;
int i;
/* 硬件重启 */
RTLResetPin = 1;
for(i = 0;i<255;i++);
RTLResetPin = 0;
/* 如果硬件重启时延很大, rtl自我初始化 */
for(i=0;i
WriteReg(PSTART_WPAGE0, RECEIVE_START_PAGE); /* Pstart */
WriteReg(PSTOP_WPAGE0, RECEIVE_STOP_PAGE); /* Pstop */
WriteReg(BNRY_WPAGE0, RECEIVE_START_PAGE); /* BNRY */
WriteReg(TPSR_WPAGE0, SEND_START_PAGE0); /* TPSR */
WriteReg(RCR_WPAGE0, 0xCE); /*RCR: 在Rtl8019as.h定义 */
WriteReg(TCR_WPAGE0, 0xE0); /* TCR: 在Rtl8019as.h定义*/
WriteReg(DCR_WPAGE0, 0xC8); /* DCR: 在Rtl8019as.h定义*/
WriteReg(IMR_WPAGE0,0); /* RTL 接收中断使能 */
WriteReg(ISR_WPAGE0, 0xFF); /* 写FF 清除所有中断标志*/
RTLPage(1);
WriteReg(CURR_WPAGE1,RECEIVE_START_PAGE + 1);
/* MAR0 */
WriteReg(0x08,0x00);
WriteReg(0x09,0x41);
WriteReg(0x0a,0x00);
WriteReg(0x0b,0x80);
WriteReg(0x0c,0x00);
WriteReg(0x0d,0x00);
WriteReg(0x0e,0x00);
WriteReg(0x0f,0x00)
/* 设置物理地址*/
WriteReg(PRA0_WPAGE1,LocalMACAddr[0]);
WriteReg(PRA1_WPAGE1,LocalMACAddr[1]);
WriteReg(PRA2_WPAGE1,LocalMACAddr[2]);
WriteReg(PRA3_WPAGE1,LocalMACAddr[3]);
WriteReg(PRA4_WPAGE1,LocalMACAddr[4]);
WriteReg(PRA5_WPAGE1,LocalMACAddr[5]);
/* 传输起始页*/
LastSendStartPage = SEND_START_PAGE0;
StartPageOfPacket = RECEIVE_START_PAGE + 1;
/* 初始化结束 */
WriteReg(CR,(CR_PAGE0 | CR_ABORT_COMPLETE_DMA | CR_STOP_COMMAND));
}
/* 写 buffer 到 rlt ram */
void RTLWriteRam(WORD address, WORD size, BYTE xdata * buff)
{
WORD i;
BYTE PrePage; /* store page */
PrePage = ReadReg(CR);
RTLPage(0);
WriteReg(RSARH_WPAGE0,(BYTE)((address>>8)&0x00ff));
WriteReg(RSARL_WPAGE0,(BYTE)address);
WriteReg(RBCRH_WPAGE0,(BYTE)((size>>8)&0x00ff));
WriteReg(RBCRL_WPAGE0,(BYTE)size);
WriteReg(CR,(0x00 | CR_REMOTE_WRITE | CR_START_COMMAND));
for(i=0;i
WriteReg(REMOTE_DMA_PORT,buff[i]);
}
/* 完成dma */
WriteReg(RBCRH_WPAGE0,0);
WriteReg(RBCRL_WPAGE0,0);
WriteReg(CR,((PrePage&0xC0) | CR_ABORT_COMPLETE_DMA | CR_START_COMMAND));
}
/* 读rlt ram 数据到 buffer */
void RTLReadRam(WORD address,WORD size,BYTE xdata * buff)
{
WORD i;
BYTE PrePage; /* 存储页 */
PrePage = ReadReg(CR);
RTLPage(0);
WriteReg(RSARH_WPAGE0,(BYTE)((address>>8)&0x00ff));
WriteReg(RSARL_WPAGE0,(BYTE)address);
WriteReg(RBCRH_WPAGE0,(BYTE)((size>>8)&0x00ff));
WriteReg(RBCRL_WPAGE0,(BYTE)size);
WriteReg(CR,(0x00 | CR_REMOTE_READ | CR_START_COMMAND));
for(i=0;i
buff[i] = ReadReg(REMOTE_DMA_PORT);
}
/* 完成dma */ WriteReg(RBCRH_WPAGE0,0);
WriteReg(RBCRL_WPAGE0,0);
WriteReg(CR,((PrePage&0xC0) | CR_ABORT_COMPLETE_DMA | CR_START_COMMAND));
}
BYTE RTLSendPacket(BYTE xdata * buffer,WORD size)
{
BYTE StartPage;
/* 存储页 */
BYTE PrePage;
PrePage = ReadReg(CR);
/* 检查包大小*/
if(size < MIN_PACKET_SIZE || size > MAX_PACKET_SIZE)
return FALSE;
/* 写包到ram */
if(LastSendStartPage == SEND_START_PAGE0)
{
StartPage = SEND_START_PAGE1;
LastSendStartPage = SEND_START_PAGE1;
}
else
{
StartPage = SEND_START_PAGE0;
LastSendStartPage = SEND_START_PAGE0;
}
RTLWriteRam(((WORD)StartPage)<<8,size,buffer);
/* 等待上一次传输结束*/
while((ReadReg(CR) & CR_TXP) == CR_TXP);
/* 写传输起始页和大小*/
RTLPage(0);
WriteReg(TPSR_WPAGE0,StartPage); /* TPSR */
WriteReg(TBCRL_WPAGE0,(BYTE)size); /*low */
WriteReg(TBCRH_WPAGE0,(BYTE)((size>>8)&0x00ff)); /*high*/
WriteReg(CR,((PrePage&0xC0) | CR_ABORT_COMPLETE_DMA | CR_TXP | CR_START_COMMAND));
return TRUE;
}
void RTLReceivePacket()
{
BYTE curr,bnry;
WORD address;
WORD PacketSize;
BYTE MemPage;
struct MemHeader xdata *pMemHead;
RTLPage(1);
curr = ReadReg(CURR_RPAGE1);
RTLPage(0);
/*在接收缓存中读所有包*/
while(TRUE)
{
/* 检验起始页是否未知错误*/
if(StartPageOfPacket >= RECEIVE_STOP_PAGE || StartPageOfPacket < RECEIVE_START_PAGE)
{
/* 用curr作为 StartPageOfPacket */
StartPageOfPacket = curr;
break;
}
/*检查是否有包读到 */
if(StartPageOfPacket == curr)
break;
/*读一个包 */
/* 读包头信息 */
address = ((WORD)StartPageOfPacket)<<8;
RTLReadRam(address,4,Head);
/* 校验rsr */
if(Head[0] & RSR_RECEIVE_NO_ERROR)
{
/*好包 */
/* 得到MAC校验和*/
PacketSize = ((WORD)Head[3])*256 + Head[2] - 4;
/* 分配 buffer , 读包到 buffer */
MemPage = MemAllocation(PacketSize);
if(MemPage != PAGE_NOT_FOUND)
{
pMemHead = (struct MemHeader xdata *)MemPageToPoint(MemPage);
pMemHead->StartPos = (BYTE xdata *)pMemHead + sizeof(struct MemHeader);
/* pos起始有效地址 */
pMemHead->StopPos = pMemHead->StopPos + PacketSize;
/* 停止pos */
address += 4;
if(StartPageOfPacket > Head[1] && Head[1] != RECEIVE_START_PAGE)
{
RTLReadRam(address,(((WORD)RECEIVE_STOP_PAGE)<<8) - address,pMemHead->StartPos); /* 读rtl */
RTLReadRam(((WORD)RECEIVE_START_PAGE)<<8,PacketSize - ((((WORD)RECEIVE_STOP_PAGE)<<8) - address),
pMemHead->StartPos + ((((WORD)RECEIVE_STOP_PAGE)<<8) - address)); /* 读rtl */
}
else
{
RTLReadRam(address,PacketSize,pMemHead->StartPos);
/ * 读rtl */
}
if(WriteQueue(MemPage,&QueueNetPacketIn) == PAGE_NOT_FOUND) /* 写到对列 */
{
/* 对列满 */
#ifdef DEBUG
printf("\n-------queue full-------");
#endif
FreePage(MemPage);
break;
}
}
else
{
/* 结束 */
#ifdef DEBUG
printf("\n-------mem over-------");
#endif
break;
}
}
/* 得到下一包的起始页 */
StartPageOfPacket = Head[1];
}
/* 重置 bnry */
bnry = StartPageOfPacket - 1;
if(bnry < RECEIVE_START_PAGE)
bnry = RECEIVE_STOP_PAGE - 1;
WriteReg(BNRY_WPAGE0,bnry);
}
系统调试代码:
//main.c
void main(void)
{
BYTE temp;
WORD port = 1001;
LocalMACAddr[0]=0x52;
LocalMACAddr[1]=0x54;
LocalMACAddr[2]=0x4c;
LocalMACAddr[3]=0x30;
LocalMACAddr[4]=0x2e;
LocalMACAddr[5]=0x2f;
LocalIPAddress = 0xc0a8020d; /* 本地地址192.168.2.14*/
ServerIPAddress = 0xc0a8020e; /* 目的地址192.168.2.13*/
/*初始化 */
SerialInitial();
MemInitial();
NetInInitial();
RTLInitial();
Start8019();
InterruptInitial();
// 建立一个ARP包
p[0] =0xff;
p[1] =0xff;
p[2] =0xff;
p[3] = 0xff;
p[4] = 0xff;
p[5] = 0xff;
p[6] = 0x52;
p[7] =0x54;
p[8] =0x4c;
p[9] =0x30;
p[10] =0x2e;
p[11] =0x2f;
p[12] = 0x08;
p[13] = 0x06;
p[14] = 0x00;
p[15] = 0x01;
p[16] = 0x08;
p[17] = 0x00;
p[18] = 0x06;
p[19] = 0x04;
p[20] = 0x00;
p[21] = 0x01;
// 发送ARP包
RTLSendPacket(p,60);
while(1);
#ifdef DEBUG
printf("\n-------bigine-------");
#endif
/* 处理 */
TCPBind(port);
if(TCPConnect(ServerIPAddress,1001) == TRUE)
{
while(UserFunc());
}
/* 延时 */
for(temp;temp<255;temp++);
#ifdef DEBUG
printf("\n run over!");
#endif
/* 存储 */
Stop8019();
while(1);
}