?? ip.c
字號:
/**********************************************************************
修改于07.7.27,在RST8019末尾加入延時,保證發送不丟包
************************************************************************/
#include "DSP28_Device.h"
extern Uint16 TxEthnetFrameBuffer[1518/2];
extern Uint16 RxEthnetFrameBuffer[100/2];
extern Uint16 IsAns;
const Uint16 MyMAC[] =
{0xE002,0xA04C,0x7C7E};
const Uint16 MyIP[] =
{0xA8C0,0x0301};
const Uint16 RemoteIP[] =
{0xA8C0,0x0101};
const Uint16 SubnetMask[] =
{0xFFFF,0x00FF};
const Uint16 GatewayIP[] =
{0xA8C0,0x0101};
Uint16 TxBufFlag;
Uint16 bnry,curr;
Uint16 UDPUserDataLenth;
Uint16 RemoteMAC[3]={0x1900,0x22E0,0x7802}; // 48 bit MAC,賦初值便于調試
//Uint16 RemoteMAC[3];
Uint16 RecdFrameMAC[3];
Uint16 RecdFrameIP[2];
Uint16 RecdIpFrameLenth;
Uint16 TxFrameSize;
Uint16 ARPAnswerSuccessFlag;
/**********************************************************************
**函數原型: void delay_ms(uint ms_number)
**入口參數: ms_number: 延時的毫秒數
**出口參數: 無
**返 回 值: 無
**說 明: 延時預定的時間,延時時間與特定的處理器有關
************************************************************************/
/*void Delay_MS(Uint16 ms_number)
{
Uint16 i;
Uint16 j;
for(j = 0;j < ms_number;j++)
for(i = 0;i < 10000;i++);
}*/
void Delay_MS(Uint16 ms_number)
{
Uint16 i;
Uint16 j;
Uint16 tepDlay;
for(j = 0;j < ms_number;j++)
{
for(i = 0;i < 227;i++)
{
tepDlay++;
if (tepDlay==100)
{
tepDlay=0;
}
}
}
}
/**********************************************************************
**函數原型: void page(uchar pagenumber)
**入口參數: Uint16 pagenumber: 要切換的頁
**出口參數: 無
**返 回 值: 無
**說 明: 選擇頁,可選擇0,1,2三頁,第四頁ne000兼容芯片保留
************************************************************************/
/*void page(Uint16 pagenumber)
{
Uint16 temp;
temp=Reg00&0x3b;
pagenumber=pagenumber<<6;
Reg00=temp | pagenumber;
}*/
void page(Uint16 pagenumber)
{
Uint16 temp;
temp = Reg00; //command register
temp = temp&0x3B ; //注意txp位不能要
pagenumber=pagenumber <<6;
temp=temp | pagenumber;
Reg00=temp;
}
/**********************************************************************
**函數原型: void RST8019(void)
**入口參數: 無
**出口參數: 無
**返 回 值: 無
**說 明: 復位8019AS
************************************************************************/
void RST8019(void)
{
Uint16 resetTmp;
Set8019RST;
Delay_MS(50);
Clr8019RST;
Delay_MS(100);
resetTmp=RegReset;
RegReset=resetTmp;
Delay_MS(100);//延遲10ms保證芯片復位成功;
}
/**********************************************************************
**函數原型: void Init8019()
**入口參數: 無
**出口參數: 無
**返 回 值: 無
**說 明: 對芯片的工作寄存器進行設置,各個寄存器的用法可參考文檔和
** 絡芯片的數據手冊
************************************************************************/
void Init8019()
{
Reg00=0x21; //使芯片處于停止模式,這時進行寄存器設置
Delay_MS(10); //延時10毫秒,確保芯片進入停止模式
page(0);
Reg0a=0x00; //清rbcr0
Reg0b=0x00; //清rbcr1
Reg0c= 0xee; //RCR,監視模式,不接收數據包,11101110
//Reg0c= 0xec; //RCR,監視模式,不接收數據包,11101100,小于64字節不接收
Reg0d= 0xe2; //TCR,loop back模式,Auto發送禁止,ENC module Loopback,Internal Lookback;11100010,rcr自動生成
Reg01=0x4c;//Pstart
Reg02=0x80;//Pstop
Reg03=0x4c;//BNRY
Reg04=0x40; //TPSR,發送起始頁寄存器
Reg07=0xff; //清除所有中斷標志位,中斷狀態寄存器,ISR
Reg0f=0x00; //中斷屏蔽寄存器清0,禁止中斷IMR
Reg0e=0xC9; // 數據配置寄存器,16位dma方式,LS位怎么回事?該位與TCR中的兩個LOOPBACK位是對應的,為何此處設置不一致?
//Reg0e=0xC1; //相對于上面設定了loopback模式??
page(1);
Reg07=0x4d;
Reg08=0x00;
Reg09=0x00;
Reg0a=0x00;
Reg0b=0x00;
Reg0c=0x00;
Reg0d=0x00;
Reg0e=0x00;
Reg0f=0x00;
//Reg00=0x22; //這時讓芯片開始工作,以上為loopback測試??
//page(1);
Reg01=0x02;
Reg02=0xE0;
Reg03=0x4C;
Reg04=0xA0;
Reg05=0x7E;
Reg06=0x7C;
page(0);
//Reg0e=0xC9;
Reg0c=0xcc; //將芯片設置成正常模式,跟外部網絡連接RCR
//Reg0c=0xde; //不要過濾小于64字節的數據,11011110,且物理地址不需要與自己的MAC相符
Reg0d=0xe0;//TCR:11100000CRC enable;
Reg00=0x22; //啟動芯片開始工作
Reg07=0xff; //清除所有中斷標志位
Reg0f=0x03;//僅限接受中斷
///test
IsAns=Reg07;
page(2);
IsAns=Reg01;
IsAns=Reg02;
IsAns=Reg04;
IsAns=Reg0c;
IsAns=Reg0d;
IsAns=Reg0e;
IsAns=Reg0f;
}
Uint16 CalcCheckSum(Uint16 *Start, Uint16 Count, Uint16 IsTCP, Uint16 IsUDP)
{
Uint32 Sum;
Sum = 0;
if ((IsTCP)||(IsUDP))
{
Sum += MyIP[0];
Sum += MyIP[1];
Sum += RemoteIP[0];
Sum += RemoteIP[1];
Sum += SwapWord(Count*2);
if(IsTCP)
Sum += SwapWord(PROTOCOL_TCP);
else
Sum += SwapWord(PROTOCOL_UDP);
}
while (Count > 0)
{
Sum += *Start;
Start ++;
Count --;
}
Sum = (Sum & 0xFFFF) + ((Sum >> 16)&0xFFFF);
if(Sum&0xFFFF0000)
Sum++;
return((Uint16)((~Sum)&0xFFFF));
}
/**********************************************************************
**函數原型: void SendFrame(Uint16 *TxdNetBuff,Uint16 length)
**入口參數: Uint16 *TxdNetBuff :指向發送緩沖區
** uint length :發送數據包的長度
**出口參數: 無
**返 回 值: 無
**說 明: 發送數據包,以太網底層驅動程序,所有的數據發送都要通過該程序
************************************************************************/
void SendFrame(Uint16 *TxdNetBuff,Uint16 length)
{
Uint16 i,ii;
if(length<46/2)
{
for(i=length;i<60/2;i++) TxEthnetFrameBuffer[i]=0;
length=60/2;
}
page(0); //切換至第0頁
length = length <<1;
TxBufFlag=!TxBufFlag; //設置兩個發緩區,提高發送效率
if(TxBufFlag)
{Reg09=0x40 ;} //設置發送頁地址,RSAR設置遠程DMA起始地址
else
{Reg09=0x46 ;} //設置發送頁地址
Reg08=0x00; //read page address low
Reg0b = length >>8; //寫發送長度高位,RBCR
Reg0a = length & 0x00ff; //寫發送長度低位
Reg00=0x12; //write dma, page0
for(i=0;i<length/2;i++)
{
Reg10 = TxEthnetFrameBuffer[i];
}
/***************************************/
//以下為終止DMA操作
Reg0b=0x00;
Reg0a=0x00;
Reg00=0x22; //結束或放棄DMA操作
/***************************************/
for(i=0;i<6;i++) //最多重發6次
{
for(ii=0;ii<1000;ii++)
{//檢查CR寄存器的txp位是否為低,為1說明正在發送,為0說明發完或出錯放棄
if((Reg00&0x04)==0)
{ break; }
}
if((Reg04&0x01)!=0)//表示發送成功,判斷發送狀態寄存器TSR,決定是否出錯
{break;};
Reg00=0x3e;
}
Reg07=0xff;//清除發送完標志
if(TxBufFlag)
{
Reg04=0x40; //txd packet start;
}
else
{
Reg04=0x46; //txd packet start;
}
Reg06=length>>8; //high byte counter
Reg05=length&0xff;//low byte counter
Reg07=0xff;//清除所有中斷標志位,等待發送完成中斷
Reg00=0x3e; //to sendpacket;
}
/**********************************************************************
**函數原型: Uint16 Rec_NewPacket()
**入口參數: 無
**出口參數: 無
**返 回 值: 0 沒有新數據包
** 1 接收到新數據包
**說 明: 查詢是否有新數據包并接收進緩沖區
************************************************************************/
Uint16 RecFrame()
{
Uint16 i,ii;
Uint16 Temp,length;
union{
Uint16 total;
struct{
Uint16 high:8;
Uint16 low:8;
}e;
}d;
page(0);
bnry = Reg03; //bnry page have read 讀頁指針
bnry = bnry & 0x00FF;
page(1);
curr = Reg07; //curr writepoint 8019寫頁指針
curr = curr & 0x00FF;
page(0);
if((curr==0))return(0); //讀的過程出錯
bnry++;
if(bnry>0x7f) bnry=0x4c;
if(bnry!=curr) //此時表示有新的數據包在緩沖區里
{
page(0);//在任何操作都最好返回page0
//=======================================
Reg09=bnry; //讀頁地址的高字節
Reg08=0x00; //讀頁地址的低字節
Reg0b=0x00; //讀取字節計數高字節
Reg0a=18; //讀取字節計數低字節
Reg00=0x0a; //啟動Remote DMA讀操作
for(i=0;i<9;i++) //讀取一包的前18個字節:4字節的8019頭部,6字節目的地址,6字節原地址,2字節協議
{
RxEthnetFrameBuffer[i]=Reg10;
}
//====================================中止DMA操作
Reg0b=0x00; //
Reg0a=0x00; //
Reg00=0x22; //結束或放棄DMA操作
//====================================
d.total = RxEthnetFrameBuffer[0];
length = RxEthnetFrameBuffer[1];
if(((d.e.high & 0x01)==0)||(d.e.low > 0x7f) || (d.e.low < 0x4c)||( length > 1517))
{//接收狀態錯誤或下一數據包的起始頁地址錯誤或接收的數據包長度>1500字節
page(1);
curr=Reg07; //page1
page(0); //切換回page0
bnry = curr -1;
if(bnry < 0x4c) bnry =0x7f;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -