基于LPC2210的RTL8019AS以太网驱动系统设计(二)

    技术2022-05-20  58

    基于LPC2210RTL8019AS以太网驱动系统设计(二)

    ---------------------------------------------------------

    Author             :tiger-johnWebSite            :blog.csdn.net/tigerjb

    Email               jibo.tiger@gmail.com

    开发环境         硬件环境:LPC2200

                                操作系统:UC/OS-II操作系统

                                编译环境:ADS1.2

    Tiger声明:本人鄙视直接复制本人文章而不加出处的个人或团体,

    但不排斥别人转载tiger-john的文章,只是请您注明出处并和本人

    联系或留言给我3Q

    ---------------------------------------------------------

    .发送数据包模块

    5.1发送数据包模块功能

    发送数据包时,先将待发送数据包通过远程DMA写入芯片RAM,给出发送缓冲区首地址和数据包长度,即可实现RTL8019AS的数据发送。RTL8019AS会自动按以太网协议完成发送并将结果写入状态寄存器。

    5.2发送数据包模快的数据结构

     

    1>_pkst

    struct _pkst{

    struct _pkst *STPTR;//前一个结构数组

    unsigned int        length;//以太网帧报头长度长度14字节

    unsigned char      *DAPTR;//报头的指针

                                };

    2>ipethernet

    typedef struct  { 

    uint8        DestMacId[6];          /*目的网卡地址*/

    uint8        SourceMacId[6];      /*源网卡地址*/

    int16        NextProtocal;       /*下一层协议*/

                                       } ipethernet;

    3>定义数据结构:

    struct _pkst  * TxdData

    struct _pkst *ExPtr;

    5.3发送数据包模块组成

    第一部分:ARM LPC2210把数据写到RTL8019AS RAM

    该过程涉及以下几个寄存器:

    Ø  RBCR0,RBCR1:远程DMA数据字节技术器

    Ø  RSAR0,RSAR1:远程DMA起始地址

    Ø  CR:发出远程DMA开始命令

     

    1>计算发送包帧的长度

    2>设置远程DMA起始地址寄存器(RSAR0,RSAR1),使远程DMA起始地址寄存器为发送缓冲区首地址

    3>设置远程DMA字节计数器寄存器为发送数据帧的长度

    >启动远程DMA

    设置CR命令寄存器使DMA开始远程写。

    5>将数据写到远程DMA 0x10号寄存器处

    6>清零远程DMA字节计数器为0,并终止远程DMA

    7>清除所有中断标志

    第二部分:RTL8019AS将数据发送到以太网

    ARM LPC2210把数据通过远程DMA写到RTL8019AS RAM之后,RTL8019AS芯片通过本地DMA将数据发送到以太网。

    该过程涉及以下寄存器:

    Ø  TPSR:设置传输数据包开始页面地址

    Ø  TBCR0,TBCR1:设置传输数据包的字节计数。

    Ø  CR:发出发送数据包的指令。

    设置寄存器结束后,RTL8019AS会自动用本地DMA发数据。

    1>  设置要发送包的起始页

    配置TPSR(发送开始页寄存器):把发送缓冲区首地址赋值给TPSR.

    2>  判断数据包长度,若小于60字节,补足60字节

    3>  设置传输数据包的字节计数

    设置TBCR0,TBCR1为数据包长度

    4>发送数据前先清除所有中断源

    5>启动本地DMA发送数据包

    配置CR命令寄存器为3E发送数据包

    6>包发送完后,判断是否出错,若发送错误则进行重发,但只重发六次

    Ø  读取命令寄存器(CR)中的TXP位:判断数据包是否发送完毕。没有发送完,则循环等待包发送完。

     

    Ø  TSR(传输状态寄存器):判断PTX位是否为1,若为1说明传输正确,退出程序。否则启动DMA重新传输数据。

    5.4发送数据包模块的接口

    发送包模块调用了写数据子模块,读数据子模块和页面切换子模块

    Ø  读数据子模块: RTL8019AS芯片中把数据读出。

    Ø  写数据子模块:将数据写入RTL8019AS芯片中

    Ø  页面切换子模块:可选择Page0,Page1,Page3三个页面。

    5.5发送数据包模块程序

    /****************************Copyright(c)********************

    **                                   西安邮电学院

    **                                   graduate school

    **                                                                 XNMS实验室

    **                                  Author:冀博

    **                                                                 Time:2011221

    **                                 http://blog.csdn.net/tigerjb

    **

    **--------------FileInfo---------------------------------------------------------------------

    ****************************Copyright(c)******************** /

    /***************************************************

    **函数原型:void    Send_Packet(struct _pkst *TxdData)

    **入口参数:struct _pkst *TxdData   :指向要发送数据的结构指针            

    **出口参数:                    

    **    明:       发送数据包,以太网底层驱动程序,所有的数据发送都要通过该程序

    ***************************************************/

    void Send_Packet(struct _pkst *TxdData)// 

    {

           static uint8 Tx_Buff_Sel=0;

           struct _pkst *ExPtr;

           uint8 *TEPTR;

           union send_temp{

                                                     uint16 words;

                                                     uint8    bytes[2];

                                               }send_buff;

           uint16 ii,length=0;

           //切换至第0

           page(0);

           length=length+TxdData->length;

           ExPtr=TxdData->STPTR;

           //计算出要发送的数据的总长度

           while(ExPtr!=NULL)

           {     

                  length=length+ExPtr->length;

                  ExPtr=ExPtr->STPTR;

           }

           ii=length;

           //发送缓冲区的切换

           Tx_Buff_Sel=Tx_Buff_Sel^1;

      //设置远程DMA起始地址寄存器(RSAR0,RSAR1)

           if(Tx_Buff_Sel)

           {

                  WriteToNet(0x09,0x40);                       

           }                   

           else

           {     

                  WriteToNet(0x09,0x46);                

           }

           WriteToNet(0x08,0x00);

           //设置远程DMA字节计数器寄存器为发送数据帧的长度

           WriteToNet(0x0b,ii>>8);         

           WriteToNet(0x0a,ii&0x00ff); 

           //启动远程DMA开始写

           WriteToNet(0,0x12);  

           /*******将数据写到远程DMA 0x10号寄存器处*****/       

           //TEPTR指向IPthernet

           TEPTR=TxdData->DAPTR;

           //发送数据结构IPthernet数据,每次发送两个字节

           for(ii=0;ii<(((TxdData->length)+1)/2);ii++)

           {

                  send_buff.bytes[0]=*TEPTR;

                  TEPTR++;

                  send_buff.bytes[1]=*TEPTR;

                  TEPTR++;

                  WriteToNet(0x10,send_buff.words);

           }

           ExPtr=TxdData->STPTR;//把下一个结构体指针给Exptr

           while(ExPtr!=NULL)

           {

                  TEPTR=ExPtr->DAPTR;

                  for(ii=0;ii<((ExPtr->length+1)/2);ii++)

                  {

                         send_buff.bytes[0]=*TEPTR;

                         TEPTR++;

                         send_buff.bytes[1]=*TEPTR;

                         TEPTR++;

                         WriteToNet(0x10,send_buff.words);

                  }

           ExPtr=ExPtr->STPTR;

           }

           //清零远程DMA字节计数器为0

           WriteToNet(0x0b,0x00);

           WriteToNet(0x0a,0x00);

           //终止DMA写操作

           WriteToNet(0x00,0x22);  

           //清除所有中断标志

           WriteToNet(0x07,0xff);

           //设置要发送包的起始页

           if(Tx_Buff_Sel)

                  {

                         WriteToNet(0x04,0x40);  

                  }

           else

                  {

                         WriteToNet(0x04,0x46); 

              }

           //判断数据包长度,若小于60字节,补足60字节

       ii=length;

           if(length<60)

                  {

                         //如果数据长度<60字节,设置长度为60字节

                         ii=60;

                  }

           //设置TBCR0,TBCR1为数据包长度

           WriteToNet(0x06,ii>>8);  

           WriteToNet(0x05,ii&0x00ff);

           //发送数据前先清除所有中断标志

           WriteToNet(0x07,0xff);

           //启动本地DMA发送数据包

           WriteToNet(0x00,0x3e);  

           //检测是否发错,若发错重发,但只重发六次

           for(length=0;length<6;length++) //最多重发6

           {

                  for(ii=0;ii<1000;ii++)

                  {

                                if((ReadFromNet(0X00)&0x04)==0) 

                                {

                                       break;

                                }

          }

                                if((ReadFromNet(0X04)&0x01)!=0)

                                {

                                       break;

                                }

                  WriteToNet(0x00,0x3e);       //to sendpacket;

          }

    }

     

     


    最新回复(0)