?? udp.c
字號(hào):
/******************************
將數(shù)據(jù)報(bào)讀取到packetRAM[]中
********************************/
static void readpacket(int i)
{
packetRAM[i]=low2high(CS8900_RTDATA);
}
/******************************
計(jì)算校驗(yàn)和
從packetRAM[start]開(kāi)始
計(jì)算len長(zhǎng)度的和,然后把
進(jìn)位位也加,最后取補(bǔ)碼。
********************************/
int inet_chksum(int start,int len)
{
long acc=0;
for(i=0;i<len;i++)
acc=acc+packetRAM[start+i];
// 對(duì)于本程序校驗(yàn)和不會(huì)超過(guò)4個(gè)字節(jié)所以就不需要使用循環(huán)
while(acc >> 16)
{
acc = (acc & 0xffff) + (acc >> 16);
}
return ~(acc & 0xffff);
}
/******************************
交換 IP 地址
********************************/
void IpResp()
{
packetRAM[ip_dst+0]=packetRAM[ip_src+0];
packetRAM[ip_dst+1]=packetRAM[ip_src+1];
packetRAM[ip_src]=IP12;
packetRAM[ip_src+1]=IP34;
packetRAM[ip_cksum]=0x0000;
packetRAM[ip_cksum]=inet_chksum(ip_VerLen,10);
}
/******************************
交換以太頭地址
********************************/
void EthResp()
{
packetRAM[pktDest12]=packetRAM[pktSrc12];
packetRAM[pktDest34]=packetRAM[pktSrc34];
packetRAM[pktDest56]=packetRAM[pktSrc56];
packetRAM[pktSrc12]=MAC12;
packetRAM[pktSrc34]=MAC34;
packetRAM[pktSrc56]=MAC56;
}
/******************************
發(fā)送數(shù)據(jù)報(bào)文的函數(shù)
********************************/
void sendpacket()
{
//寫(xiě)發(fā)送命令字
TxCMD=0x00C0;
//寫(xiě)入發(fā)送數(shù)據(jù)報(bào)文的長(zhǎng)度
TxLEN=packetRAM[pktLen];
//等待線路空閑的時(shí)候發(fā)送
while(!(get_reg(PP_BusSTAT)&PP_BusSTAT_TxRDY));
//寫(xiě)入需要發(fā)送的數(shù)據(jù)
for(i=1;i<=packetRAM[pktLen]/2;i++)
RTDATA=low2high(packetRAM[i]);
}
/******************************
發(fā)送tftp的ack信號(hào)
********************************/
void tftpack()
{
//ack 用0004
packetRAM[tftp_op]=tftp_opack;
//ack Number
packetRAM[tftp_blk]=tftpNo;
//交換udp 端口
packetRAM[u_src]=tftpARMport;
packetRAM[u_dst]=tftpSPort;
//忽略校驗(yàn)和
packetRAM[u_cksum]=0x0000;
//ack幀 是定長(zhǎng)度的 46 個(gè)字節(jié)
packetRAM[pktLen]=46;
packetRAM[ip_Len]=32;
packetRAM[u_len]=12;
EthResp();
IpResp();
sendpacket();
}
void C_vMain(void)
{
/*******************************
初始化以太網(wǎng)口
*********************************/
put_reg(PP_SelfCTL,PP_SelfCTL_Reset);
while(get_reg(PP_SelfSTAT)&PP_SelfSTAT_InitD!=PP_SelfSTAT_InitD);
put_reg(PP_RxCTL,PP_RxCTL_RxOK |PP_RxCTL_Broadcast|PP_RxCTL_IA|PP_RxCTL_Promiscuous);
put_reg(PP_RxCFG,PP_RxCFG_RxOK| PP_RxCFG_BufferCRC|PP_RxCFG_Stream);
put_reg(PP_LineCTL,PP_LineCTL_Rx|PP_LineCTL_Tx|PP_LineCTL_AutoAUI10BT);
put_reg(PP_TxCFG,PP_TxCFG_TxOK);
put_reg(PP_TestCTL,PP_TestCTL_FDX);
put_reg(PP_IA_65,MAC56_);
put_reg(PP_IA_43,MAC34_);
put_reg(PP_IA_21,MAC12_);
/******************************
開(kāi)始接受數(shù)據(jù)
******************************/
for(;;){
while( get_reg(PP_RER)&PP_RER_RxOK )
{
packetRAM[0]=get_reg(PP_RxLENGTH);
//收取前面的74個(gè)字節(jié),如果是ICMP正好包括了最后一個(gè)字符 14+20+8+32
for (i=pktDest12;i<=23; i++)
{
packetRAM[i]=low2high(RTDATA);
}
//檢查幀的類(lèi)型 如果是 0806 表示arp
if (packetRAM[pktType]==0x0806)
{
//*******************************
//發(fā)現(xiàn)ARP數(shù)據(jù)報(bào)文就開(kāi)始發(fā)送RARP
//*********************************
//判斷arp是否合法
if (packetRAM[arp_hwtype]!=0x0001)
return;
if (packetRAM[arp_prtype]!=0x0800)
return;
if (packetRAM[arp_hwlen]!=0x0604)
return;
if (packetRAM[arp_op]!=0x0001)
return;
if (packetRAM[arp_tpa]!=IP12)
return;
if (packetRAM[arp_tpa+1]!=IP34)
return;
//判斷結(jié)束 如果沒(méi)有返回說(shuō)明需要發(fā)送RARP //******************************
// 發(fā)送arp request
//********************************
//修改arp操作碼為rarp
packetRAM[arp_op]=0x0002;
//交換以太Mac
EthResp();
//源mac 寫(xiě)到目的mac
packetRAM[arp_tha]=packetRAM[arp_sha];
packetRAM[arp_tha+1]=packetRAM[arp_sha+1];
packetRAM[arp_tha+2]=packetRAM[arp_sha+2];
//源ip 寫(xiě)到目的ip
packetRAM[arp_tpa]=packetRAM[arp_spa];
packetRAM[arp_tpa+1]=packetRAM[arp_spa+1];
//重寫(xiě)源mac
packetRAM[arp_sha]=MAC12;
packetRAM[arp_sha+1]=MAC34;
packetRAM[arp_sha+2]=MAC56;
//重寫(xiě)源IP
packetRAM[arp_spa]=IP12;
packetRAM[arp_spa+1]=IP34;
//發(fā)送rarp報(bào)文
sendpacket();
}
//如果幀的類(lèi)型是 0800 表示 IP 幀
if(packetRAM[pktType]==0x0800)
{
//檢查IP幀的類(lèi)型 01 表示 ICMP , 11 表示UDP
if((packetRAM[ip_proto]&0x00ff)==0x0001)
{
//當(dāng)幀的類(lèi)型是 0800 表示ICMP請(qǐng)求
if(packetRAM[ic_type]==0x0800)
{
EthResp();
IpResp();
//改變ICMP 為 0000 表示應(yīng)答
packetRAM[ic_type]=0x0000;
packetRAM[ic_cksum]=0x0000;
packetRAM[ic_cksum]=inet_chksum(ip_data,20);
sendpacket();
}
}
if((packetRAM[ip_proto]&0x00ff)==0x0011)
{
//判斷UDP的目的地址是否是本機(jī)地址,如果不是就不處理
if(packetRAM[ip_dst+1]!=IP34||packetRAM[ip_dst]!=IP12)
return;
//檢查目的端口是否是69 和tftpARMport
if(packetRAM[u_dst]!=0x0045 && packetRAM[u_dst]!=tftpARMport)
return;
//然后檢查 tftp_op 操作碼 0002 表示寫(xiě)請(qǐng)求
if(packetRAM[tftp_op]==0x0002)
{
tftpNo=0;
tftpSPort=packetRAM[u_src];
sdrampoint=0;pktcount=0;
tftpack();tftpack();
}
// tftp_op 操作碼 0003 表示數(shù)據(jù)
if(packetRAM[tftp_op]==0x0003)
{
tftpNo=packetRAM[tftp_blk];
//得到這一幀的長(zhǎng)度
pktlength=(packetRAM[ip_Len]-32)/2;
for(i=tftp_data;i<tftp_data+pktlength;i++)
{
packetRAM[i]= RTDATA&0xffff;
put_char((packetRAM[i])&0x00ff);
put_char((packetRAM[i]>>8)&0x00ff);
}
if (packetRAM[ip_Len]&0x0001==1)
{
packetRAM[i]= RTDATA&0xffff;
}
//處理數(shù)據(jù)
//將數(shù)據(jù)寫(xiě)到ram中
for(j=0;j<i-tftp_data;j+=2)
{
RAM_WORD(sdrampoint)=((packetRAM[tftp_data+j+1]<<16)|packetRAM[tftp_data+j]);
sdrampoint=sdrampoint+4;
}
tftpack();
//計(jì)算文件的長(zhǎng)度 以字為單位
pktcount=pktcount+pktlength;
//如果幀的數(shù)據(jù)的長(zhǎng)度 在 0-511個(gè)字節(jié) pktlength是字長(zhǎng)所以和256比較 表示已經(jīng)是最后一個(gè)報(bào)文就開(kāi)始向flash中寫(xiě)入數(shù)據(jù)
if(pktlength<256)
{
ramtoflash(pktcount);
put_char('!');
}
}
if(packetRAM[tftp_op]==0x0005) //清空所有的標(biāo)記
{
sdrampoint=0;pktcount=0;
return;
}
}
}
//不滿(mǎn)足條件就跳過(guò)這一幀
put_reg(PP_RxCFG,PP_RxCFG_Skip1);
}
}
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -