Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1002411
  • 博文数量: 81
  • 博客积分: 3308
  • 博客等级: 中校
  • 技术积分: 784
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-16 18:26
文章分类

全部博文(81)

文章存档

2014年(1)

2013年(5)

2011年(38)

2010年(37)

我的朋友

分类: 嵌入式

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 

                /* 写重启口 */
temp = ReadReg(RESET_PORT);
WriteReg(RESET_PORT,temp);

                /* 初始化RTL 寄存器*/
WriteReg(CR,(CR_PAGE0 | CR_ABORT_COMPLETE_DMA | CR_STOP_COMMAND)); 
              /* 设置page0, stop command */

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);
}

阅读(1125) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~