?? 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 + -