⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 etherdev.c

📁 STC51系列的源码
💻 C
字号:
/********************************************************************************/
/* filename: ethernet.c                                                         */
/* version : v1.00                                                              */
/* created : hw-chen                                                            */
/********************************************************************************/
#include "../CPU/CPU.h"
#include "../CFG/CFG.h"
#include "../UART/UART.h"
#include "uip.h"
#include "uipopt.h"
#include "uip_arch.h"
#include "etherdev.h"
unsigned char pkts_start_page=0x0;
unsigned char pkts_sends_page=0x0;

/********************************************************************************/
/* function : net_delay_ms()                                                    */
/* recension: hw-chen                                                           */
/* descript : 延时函数                                                          */
/********************************************************************************/
void net_delay_ms(unsigned char time)
{   unsigned int i;
    while(time)
    {   for(i=0;i<1000;i++)
        {   _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
            _nop_();
        }
        time--;
    }
}

/********************************************************************************/
/* function : rtl8019_set_pages                                                 */
/* created  : hw-chen                                                           */
/* descript : RTL8019更换页面                                                   */
/********************************************************************************/
void rtl8019_set_pages(unsigned char page)
{   unsigned char mdata;
    mdata =DEV_NET_COMMAND;
    mdata&=0x3B;
    page  =page<<6;
    mdata =mdata|page;
    DEV_NET_COMMAND=mdata;
}

/********************************************************************************/
/* function : rtl8019_initialize()                                              */
/* created  : hw-chen                                                           */
/* descript : RTL8019初始化                                                     */
/*  RTL8019AS内部有16kB SRAM,分为64页,256字节/页,组成环形队列作为           */
/*  收发缓冲区,只能按页操作,页地址从0x4000~0x7FFF。可以通过相关的            */
/*  寄存器读写操作,可以对缓冲区进行设置及状态的读取。由于接收缓冲区            */
/*  是按页即256B来操作的,与缓冲区地址有关的寄存器中只需存储缓冲区的            */
/*  高16位地址即可。在本设计中,将前52页(0x4C00-0x8000)作为接收缓冲区           */
/*  将后12页(0x4000~0x4B00)作为发送缓冲区。                                    */
/********************************************************************************/
void rtl8019_initialize(void)
{   unsigned char mdata;
    net_delay_ms(10);
    DEV_NET_COMMAND= NET_PAGE0+NET_NODMA+NET_STOP;  //* 选择页0寄存器,网卡停止 运行
    
    UART_printf("A-0x%bx.\r\n",DEV_NET_ID1);
    UART_printf("B-0x%bx.\r\n",DEV_NET_ID0);
    
    DEV_NET_PSTART = RX_START_PAGE;     //* 接收缓冲区范围
    DEV_NET_PSTOP  = RX_STOP_PAGE;      //* PSTOP,构造缓冲环:0x4C-0x80.   
    DEV_NET_BNRY   = RX_START_PAGE;     //* BNRY是读指针,指向用户已经读走的页
    DEV_NET_TPSR   = TX_START_PAGE;     //* 发送缓冲区的指针
    DEV_NET_TCR    = 0xE2;              //* 发送配置寄存器,loop back mode 使芯片处于mon和loopback模式,跟外部网络断开
    DEV_NET_RCR    = 0xE4;              //* 接收配置寄存器,monitor mode (no packet receive)
    DEV_NET_ISR    = 0xFF;              //* Interrupt Status Register,it must be clear after power up
    DEV_NET_IMR    = 0x00;              //* Interrupt Mask Register,disable all interrrupt
    DEV_NET_DCR    = 0xC8;              //* 数据配置寄存器:设置为使用FIFO缓存,普通模式,8位数据传输模式
    mdata=DEV_NET_ISR;
    
    DEV_NET_COMMAND= NET_PAGE1+NET_NODMA+NET_STOP;
    DEV_NET_CURR   = RX_START_PAGE+0x1; //* CURR是网卡写缓冲区的指针,指向此时要写的页
    DEV_NET_MAR0   = 0x0;               //* 接收所有的组包
    DEV_NET_MAR1   = 0x0;
    DEV_NET_MAR2   = 0x0;
    DEV_NET_MAR3   = 0x0;
    DEV_NET_MAR4   = 0x0;
    DEV_NET_MAR5   = 0x0;
    DEV_NET_MAR6   = 0x0;
    DEV_NET_MAR7   = 0x0;  
    DEV_NET_PAR0   = UIP_ETHADDR0;
    DEV_NET_PAR1   = UIP_ETHADDR1;
    DEV_NET_PAR2   = UIP_ETHADDR2;
    DEV_NET_PAR3   = UIP_ETHADDR3;
    DEV_NET_PAR4   = UIP_ETHADDR4;
    DEV_NET_PAR5   = UIP_ETHADDR5;
    
    DEV_NET_COMMAND= NET_PAGE0+NET_NODMA+NET_START;
    DEV_NET_RCR = 0xC4;     //* 接收配置寄存器,仅接收自己地址和广播地址的数据包,小于64字节和校验错误的数据包不被接收
    DEV_NET_TCR = 0xE0;     //* 发送配置寄存器,工作在正常模式,启用CRC自动生成和自动校验
    DEV_NET_ISR = 0xFF;
    DEV_NET_IMR = 0x00;     //* RST  RDC  CNT  OVW  TXE  RXE  PTX  PRX
    pkts_start_page= RX_START_PAGE;
}

/********************************************************************************/
/* fun_name : NET_RESET_set()                                                   */
/* version  : v1.00                                                             */
/* created  : xillinx                                                           */
/* descript : 网络模块的复位                                                    */
/********************************************************************************/
void NET_RESET_set(void)
{   c51_U07_latch|=0x20;  
    c51_hc138_cs_keyw[0x0]=c51_U07_latch;
}

/********************************************************************************/
/* fun_name : NET_RESET_clr()                                                   */
/* version  : v1.00                                                             */
/* created  : xillinx                                                           */
/* descript : 网络模块的复位                                                    */
/********************************************************************************/
void NET_RESET_clr(void)
{   c51_U07_latch&=0xDF;  
    c51_hc138_cs_keyw[0x0]=c51_U07_latch;
}

/********************************************************************************/
/* function : rtl8019_reset()                                                   */
/* created  : hw-chen                                                           */
/* descript : RTL8019复位                                                       */
/********************************************************************************/
void rtl8019_reset(void)
{   unsigned char mdata;
    NET_RESET_set();
    net_delay_ms(100);
    NET_RESET_clr();
    net_delay_ms(100);
    mdata=DEV_NET_RESET;
    DEV_NET_RESET=mdata;
    net_delay_ms(100);
}

/********************************************************************************/
/* function : rtl8019_read_mdata()                                              */
/* created  : hw-chen                                                           */
/* descript : 读取RTL8019缓冲区的数据                                           */
/********************************************************************************/
void rtl8019_read_mdata(unsigned char page, unsigned char addr, unsigned int size, unsigned char * buffer)
{   unsigned char preb_page;
    unsigned int  i;
    preb_page=DEV_NET_COMMAND&0xC0;
    rtl8019_set_pages(0x0);     //* 设置成为PAGE0
    DEV_NET_RSAR1  = page;      //* read pages address high
    DEV_NET_RSAR0  = addr;      //* read pages address low
    DEV_NET_RBCR1  = size>>8;   //* read count high
    DEV_NET_RBCR0  = size&0xFF; //* read count low
    DEV_NET_COMMAND= NET_PAGE0+NET_REM_READ+NET_START;
    for(i=0x0;i<size;i++)
    {   buffer[i]=DEV_NET_PORT;
    }
    DEV_NET_ISR    = 0x40;      //* set when remote DMA operation been completed
    DEV_NET_RBCR1  = 0x0;
    DEV_NET_RBCR0  = 0x0;                    
    DEV_NET_COMMAND= preb_page+NET_NODMA+NET_START;
}

/********************************************************************************/
/* function : rtl8019_write_mdata()                                             */
/* created  : hw-chen                                                           */
/* descript : 读取RTL8019缓冲区的数据                                           */
/********************************************************************************/
void rtl8019_write_mdata(unsigned char page, unsigned char addr, unsigned int size, unsigned char * buffer)
{   unsigned char preb_page;
    unsigned int  i;
    preb_page=DEV_NET_COMMAND&0xC0;
    rtl8019_set_pages(0x0);     //* 设置成为PAGE0
    DEV_NET_COMMAND= NET_PAGE0+NET_NODMA+NET_START;
    DEV_NET_RSAR1  = page;      //* read pages address high
    DEV_NET_RSAR0  = addr;      //* read pages address low
    DEV_NET_RBCR1  = size>>8;   //* read count high
    DEV_NET_RBCR0  = size&0xFF; //* read count low
    DEV_NET_COMMAND= NET_PAGE0+NET_REM_WRITE+NET_START;
    for(i=0x0;i<size;i++)
    {   DEV_NET_PORT=buffer[i];
    }
    DEV_NET_COMMAND= preb_page+NET_NODMA+NET_START;
}
/********************************************************************************/
/* function : etherdev_write()                                                  */
/* created  : hw-chen                                                           */
/* descript : 给RTL8019写发送数据区                                             */
/********************************************************************************/
unsigned int etherdev_send(void)
{   unsigned char preb_page;
    unsigned char pages;
    unsigned int  status=0x0;
    unsigned char * buffer;
    unsigned int length;
    
    buffer=uip_buf;
    length=uip_len;
    preb_page=DEV_NET_COMMAND&0xC0;
    rtl8019_set_pages(0);
    DEV_NET_IMR = 0x0;          //* 屏蔽8019中断
    
    if(pkts_sends_page==0x0)
    {  pkts_sends_page=0x1;
    }
    else
    {  pkts_sends_page=0x0;
    }
    if(pkts_sends_page==0x1)    //* 选择RTL8019发送缓冲区
    {  pages=0x40;
    }
    else
    {  pages=0x46;
    }
    if(length<60)               //* 填充数据
    {  length=60;
    }
    UART_printf("eths:0x%bx,len:%d.\r\n",pages,length);
    rtl8019_write_mdata(pages,0x0,length,buffer);   //* 发送数据
    while((DEV_NET_COMMAND&NET_TXP)==NET_TXP);      //* 等待上一次的数据发送完毕
    rtl8019_set_pages(0x0);     //* 设置成为PAGE0
    DEV_NET_TPSR   = pages;     //* txd packet start;
    DEV_NET_TBCR1  = length>>8;
    DEV_NET_TBCR0  = length&0xFF;   
    DEV_NET_COMMAND= preb_page+NET_NODMA+NET_REM_READ+NET_TXP+NET_START;
    return status;
}

/********************************************************************************/
/* function : etherdev_read()                                                   */
/* created  : hw-chen                                                           */
/* descript : 读取RTL8019缓冲区的数据                                           */
/********************************************************************************/
unsigned int etherdev_read(void)
{   unsigned char page_wr, page_rd, next_frame;
    unsigned char head[0x4];
    unsigned int  size;
    unsigned int  seg_length;

    rtl8019_set_pages(0x0);
    page_rd=DEV_NET_BNRY;       //* 我最后一次已经读取的缓冲区指针
    rtl8019_set_pages(0x1);
    page_wr=DEV_NET_CURR;       //* RTL8019当前已经写到的位置
    rtl8019_set_pages(0x0);
    
    page_rd+=0x1;               //* 指向还未读取的第一帧数据
    if(page_rd>=RX_STOP_PAGE)
    {  page_rd=RX_START_PAGE;
    }
    if(page_rd==page_wr)        //* 没有数据可读取
    {  return 0x0;
    }

    rtl8019_read_mdata(page_rd,0x0,0x4,&head[0x0]); //* 读取四字节的数据
    if((head[0x0]&0xF)!=RSR_RECV_NO_ERR)            //* 接收头部错了,丢弃所有的数据
    {  DEV_NET_BNRY=RX_START_PAGE;
       rtl8019_set_pages(0x1);
       DEV_NET_CURR=RX_START_PAGE+0x1; 
       rtl8019_set_pages(0x0);
       return 0x0;
    }
    
    size=head[0x3];
    size<<=0x8;
    size +=head[0x2];   
    size -=0x4;             //* 去掉MAC的CRC
    
    next_frame=page_rd+0x1+((size+4)>>8);    //* 计算出下一个数据包的缓冲区位置
    
    if((head[0x1]!=next_frame)&&(head[0x1]!=next_frame+0x1)&&(head[0x1]!=next_frame-(RX_STOP_PAGE-RX_START_PAGE))&&(head[0x1]!=next_frame+0x1-(RX_STOP_PAGE-RX_START_PAGE)))
    {  DEV_NET_BNRY=RX_START_PAGE;
       rtl8019_set_pages(0x1);
       DEV_NET_CURR=RX_START_PAGE+0x1; 
       rtl8019_set_pages(0x0);
       return 0x0;
    }
    
    if(size>=UIP_BUFSIZE)   //* 长度不正确,只丢弃这一帧数据
    {  DEV_NET_BNRY=RX_START_PAGE;
       rtl8019_set_pages(0x1);
       DEV_NET_CURR=RX_START_PAGE+0x1; 
       rtl8019_set_pages(0x0);
       return 0x0;
    }

    /****************************************************************************/
    /*  START-PAGE --- HEAD[0x1] ---------- PKTS-START-PAGE  ----- STOP-PAGE    */
    /*  ++++++++++++++++++++++++            ++++++++++++++++++++++++++++++++    */
    /*  这段数据需要读取                    这段数据需要读取                    */           
    /****************************************************************************/
    if((page_rd>head[0x1])&&(head[0x1]!=RX_START_PAGE))
    {  seg_length=(RX_STOP_PAGE<<0x8)-((page_rd<<0x8)+0x4);
       rtl8019_read_mdata(page_rd, 0x4, seg_length, &uip_buf[0x0]);
       rtl8019_read_mdata(RX_START_PAGE, 0x0, size-seg_length, &uip_buf[seg_length]);
    }
    else
    {  rtl8019_read_mdata(page_rd,0x4,size,&uip_buf[0x0]);
    }

    if(next_frame==RX_START_PAGE)
    {  DEV_NET_BNRY=RX_STOP_PAGE-0x1;
    }
    else
    {  DEV_NET_BNRY=next_frame-0x1;
    }
    DEV_NET_ISR =0xFF;
    
    return size;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -