📄 etherdev.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 + -