📄 eth.c
字号:
//-------------------------eth.c----------------
#include <absacc.h>
#include<string.h>
#include"includes.h"
uchar txbuf=0; //发送缓冲区选择0,1
/*****************************************
8019热复位
******************************************/
void rtl8019_reset()
{
REG1f=0x0f;
delay_us(DY200MS);
}
/*****************************************
8019寄存器换页
******************************************/
void page(uchar pgnum)
{
uchar temp;
temp=REG00;
temp=temp&0x3B ;//高两位清零
pgnum=pgnum <<6;
temp=temp | pgnum;
REG00=temp;
}
/*****************************************
写8019MAC地址
******************************************/
void write_mac()
{
page(1);
REG01=mymac[0];
REG02=mymac[1];
REG03=mymac[2];
REG04=mymac[3];
REG05=mymac[4];
REG06=mymac[5];
page(0);
}
/*****************************************
8019初始化
*****************************************/
void init_8019()
{
delay_us(DY10MS);
rtl8019_reset();
REG00=0x21; //选择页0寄存器,8019停止运行
delay_us(DY10MS); //延时10毫秒,确保芯片进入停止模式
page(0);
REG0a=0x00; //清远程DMA计数器RBCR0,RBCR1
REG0b=0x00;
REG0c= 0xe0; //RCR接收配置 只检查数据不存入缓存
REG0d= 0xe2; //TCR传输配置 back mode 使芯片处于mon和loopback模式,跟外部网络断开
//使用0x40-0x4B为网卡的发送缓冲区,共12页,刚好可以存储2个最大的以太网包。
REG01=0x4c; //PSTART 接收缓存环开始页地址
REG02=0x80; //PSTOP 接收缓存环结束页地址
REG03=0x4c; //BNRY
//使用0x4c-0x7f为网卡的接收缓冲区,共52页。
REG04=0x40; //TPSR 要发送包的起始页
REG07=0xff; //清除所有中断标志位
REG0f=0x00; //设置中断屏蔽寄存器,屏蔽所有中断
REG0e=0xc8; //DCR数据配置 使用FIFO缓存,普通模式,8位数据DMA
page(1);
REG07=0x4d; //CURR初始化当前页寄存器,指向当前正在写的页的下一页
REG08=0x00; //08-0F组播地址
REG09=0x00;
REG0a=0x00;
REG0b=0x00;
REG0c=0x00;
REG0d=0x00;
REG0e=0x00;
REG0f=0x00;
write_mac();
page(0);
REG0c=0xcc; //设置接收配置寄存器,使用接收缓冲区,仅接收自己地址的数据包(以及广播地址数据包)和多点播送地址包,小于64字节的包丢弃,校验错的数据包不接收
REG0d=0xe0; //设置发送配置寄存器,启用CRC自动生成和自动校验,工作在正常模式
REG00=0x22; //这时让芯片开始工作
REG07=0xff;
}
/*****************************************
发送以太网帧 最小为60字节,最大1514字节
*****************************************/
void frame_send(uchar xdata * outbuf, uint len)
{
uchar i;
uint cnt;
page(0);
if(len<60)
len=60;
REG09=(0x40 + txbuf*6); //RSAR1 设置远程DMA起始地址的高字节
REG08=0x00; //RSAR0 设置远程DMA起始地址的低字节
REG0b=len>>8; //RBCR1 设置远程DMA计数器高字节
REG0a=len&0xff; //RBCR0 设置远程DMA计数器低字节
REG00=0x12; //write dma, page0
for(cnt=0;cnt<len;cnt++)
REG10=*(outbuf+cnt);
REG0b=0x00; //read count high 中止DMA操作
REG0a=0x00; //read count low;
REG00=0x22; //complete dma page 0
REG04=(0x40 + txbuf*6); //TPSR 设置发送包起始页
REG06=len>>8; //TBCR1 设置要发送包长度高字节
REG05=len&0xff; //TBCR0 设置要发送包长度低字节
REG07=0xff;
REG00=0x3e; //to sendpacket;
for(i=0;i<16;i++) //最多重发16次
{
for(cnt=0;cnt<1000;cnt++) //检查txp为是否为低
{
if ((REG00&0x04)==0)
break;
}
if ((REG04&0x01)!=0) //PTX=1表示发送成功
break;
REG00=0x3e;
}
REG07=0xff; //清除所有中断标志位
clean_buf(outbuf,len);
}
/*****************************************
接收以太网帧,如果收到一个有效的数据包,
返回收到的数据,否则返回NULL
*****************************************/
uint frame_receive(uchar xdata * inbuf)
{
uchar bnry,curr,next_page,temp;
uint len, cnt;
page(0);
bnry=REG03; //读页指针指向已被主机读取了的那页的下页
page(1);
curr=REG07; //写页指针,指向所接收包的第一页地址
page(0);
if ((curr==0)) //读的过程出错
return(0);
next_page=bnry;
bnry=bnry + 1;
if (bnry>0x7f)
bnry=0x4c;
if (bnry!=curr) //此时表示有新的数据包在缓冲区里
{
//读取一包的前4个字节:4字节的8019头部
page(0);
REG09=bnry; //RSAR1设置远程DMA起始地址 high
REG08=0x00; //RSAR0设置远程DMA起始地址 low
REG0b=0x00; //RBCR1 设置远程DMA计数器高字节
REG0a=4; //RBCR1read count low;
REG00=0x0a; //read dma
temp = REG10; //接收状态
temp = REG10; //下一页指针
next_page = temp-1; //next page start-1
len = REG10; //帧长度2BYTE
temp = REG10;
len += temp<<8;
REG0b=0x00;
REG0a=0x00;
REG00=0x22;//complete dma page 0
if(len == 0)
{
page(1);
curr=REG07; //page1
page(0);
bnry = curr -1;
if(bnry < 0x4c)
bnry =0x7f;
REG03=bnry; //write to bnry
REG07=0xff; //清除中断状态
return(0);
}
REG09=bnry; //read page address high
REG08=4; //read page address low
REG0b=len>>8; //read count high
REG0a=len&0xff; //read count low;
REG00=0x0a; //read dma
for(cnt=0;cnt<len;cnt++)
{
inbuf[cnt]=REG10;
}
REG0b=0x00;
REG0a=0x00;
REG00=0x22;
//dma complete page0
bnry=next_page;
if (bnry<0x4c) bnry=0x7f;
REG03=bnry; //write to bnry
REG07=0xff;
return (len);
}
return (0);
}
/*****************************************
查询标志位,判断是否有新数据
*****************************************/
uchar query_8019(void)
{
uchar bnry,curr;
page(0);
bnry=REG03; //bnry page have read 读页指针
page(1);
curr=REG07; //curr writepoint 8019写页指针
page(0);
if ((curr==0))
return(0);
bnry++;
if (bnry>0x7f)
bnry=0x4c;
if (bnry!=curr) //此时表示有新的数据包在缓冲区里
return(1);
REG0b=0x00;
REG0a=0x00;
REG00=0x22; //complete dma page 0
return(0);
}
/*****************************************
发送以太网帧,加上帧头
*****************************************/
void eth_send(uchar xdata * outbuf, uchar * macaddr, uint frame_type, uint len)
{
Eth_Header xdata * eth;
LED=0; //指示灯亮
eth = (Eth_Header xdata *)outbuf;
memcpy(eth->dest_macaddr, macaddr, 6);
memcpy(eth->source_macaddr, mymac, 6);
eth->frame_type = frame_type;
frame_send(outbuf, len + 14);
// TRACE("SEND > ETH_FRAME",NULL,0,0);
LED=1; //指示灯
}
/*****************************************
接收以太网帧,转相应的处理程序
*****************************************/
void eth_process(uchar xdata * Databuf)
{
Eth_Header xdata * eth;
eth = (Eth_Header xdata *)Databuf;
if (eth->frame_type < 1518)//小于1518表示为长度,否则表示使用上层协议
return;
switch (eth->frame_type)
{
case ARP_PACKET:
TRACE("ARP_PACKET",NULL,0,0);
arp_receive(Databuf);
break;
case IP_PACKET:
TRACE("IP_PACKET",NULL,0,0);
ip_receive(Databuf);
break;
default:
TRACE("UNKNOW_PACKET",NULL,0,0);
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -