?? tftpflash.c
字號:
#include "ioregs.h"
#include "cs8900.h"
#include "net.h"
#include "flash.h"
#include "put.h"
static int sdrampoint=0; //SDRAM的地址指針
static int i,j,pktlength=0,pktcount=0;
static int tftpNo,tftpSPort=0; //保存接收tftp數據的序號和源端口
static int packetRAM[280]; //定義幀的存儲數組 按照字從低到高排列
/******************************
把ram中的數據寫到flash中
********************************/
void ramtoflash(int length)
{
int point=0,t=0,k;
for(t=0;t<length*2;t=t+0x20000) //每次寫一個block
{
FLASH_BYTE(t)=0x50;
FLASH_BYTE(t)=0x20;
FLASH_BYTE(t)=0xD0;
while(FLASH_WORD(t)!=0x00800080);
for(j=0;j<0x20000;j+=32)
{
FLASH_BYTE(t)=0x50;
FLASH_BYTE(t)=0xE8;
while(FLASH_WORD(t)!=0x00800080);
FLASH_BYTE(t)=0x0F0F;
for(k=0;k<8;k++)
{
FLASH_WORD(point)=RAM_WORD(point);
point=point+4;
}
FLASH_BYTE(t+j)=0xD0;
while(FLASH_WORD(t+j)!=0x00800080);
if(point>2*length) return;
}
}
}
/******************************
交換高低字節
********************************/
int low2high(int i)
{
return ((i>>8)&0x00ff)+((i<<8)&0xff00);
}
/******************************
將數據報讀取到packetRAM[]中
********************************/
/*
static void readpacket(int i)
{
packetRAM[i]=low2high(CS8900_RTDATA);
}
*/
/******************************
計算校驗和
從packetRAM[start]開始
計算len長度的和,然后把
進位 位也加到地位,最后
取補碼。
********************************/
int inet_chksum(int start,int len)
{
long acc=0;
for(i=0;i<len;i++)
acc=acc+packetRAM[start+i];
// 對于本程序校驗和不會超過4個字節所以就不需要使用循環
// 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;
}
/******************************
發送數據報文的函數
********************************/
void sendpacket()
{
//寫發送命令字
//CS8900_PP_TxCommand=0x00C0;
CS8900_TxCMD=0x00C0;
//寫入發送數據報文的長度
//CS8900_PP_TxLength=packetRAM[pktLen];
CS8900_TxLEN=packetRAM[pktLen];
//等待線路空閑的時候發送
while(!(get_reg(PP_BusSTAT)&PP_BusSTAT_TxRDY));
//寫入需要發送的數據
for(i=1;i<=packetRAM[pktLen]/2;i++)
//CS8900_(PP_TxBASE+2*i-2)=low2high(packetRAM[i]);
CS8900_RTDATA=low2high(packetRAM[i]);
}
/******************************
發送tftp的ack信號
********************************/
void tftpack()
{
//ack 用0004
packetRAM[tftp_op]=tftp_opack;
//ack Number
packetRAM[tftp_blk]=tftpNo;
//交換udp 端口
packetRAM[u_src]=tftpARMport;
packetRAM[u_dst]=tftpSPort;
//忽略校驗和
packetRAM[u_cksum]=0x0000;
//ack幀 是定長度的 46 個字節
packetRAM[pktLen]=46;
packetRAM[ip_Len]=32;
packetRAM[u_len]=12;
EthResp();
IpResp();
sendpacket();
}
void C_vMain(void)
{
/*******************************
初始化CS8900A
*********************************/
//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);設置接收數據包,接收廣播和符合目標地址的數據包
//put_reg(PP_RxCFG,PP_RxCFG_RxOK| PP_RxCFG_BufferCRC);接收到事件引發中斷,CRC校驗信息記入數據幀總長度
//put_reg(PP_LineCTL,PP_LineCTL_Rx|PP_LineCTL_Tx);接收使能,發送使能,均設置能,
//put_reg(PP_TxCFG,PP_TxCFG_TxOK);數據發送完后引發中斷
//put_reg(PP_IA_65,MAC56_);從0158h開始寫MAC地址,MAC12_ 0x2301,#define MAC34_ 0x6745,#define MAC56_ 0xAB8
//put_reg(PP_IA_43,MAC34_);
//put_reg(PP_IA_21,MAC12_);
/******************************
開始接受數據
******************************/
for(;;){
while( get_reg(PP_RER)&PP_RER_RxOK )//pp_rer為接收幀狀態寄存器,此句為檢測數據無錯接收
{
packetRAM[0]=get_reg(PP_RxLENGTH);//rxlength為接收長,只讀寄存器,當RXOK置位時自動生成接收幀長度,但注意包不包括CRC的長度
//收取前面的74個字節,如果是ICMP正好包括了最后一個字符 14+20+8+32
for (i=pktDest12;i<=23; i++)//pktDest12=1,目的地址
{
readpacket(i);
//packetRAM[i]=low2high(CS8900_RTDATA);//交換CS8900_RTDATA即為PORT0口的高低字節,PORT0在16位模式下存放CPU和8900交換的數據幀
}//交換是因為大小斷不一樣
//檢查幀的類型 如果是 0806 表示arp
if (packetRAM[pktType]==0x0806)//pktType =7 幀類型 0800 IP 0806 ARP
{
//*******************************
//發現ARP數據報文就開始發送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;
*/
//判斷結束 如果沒有返回說明需要發送RARP
//******************************
// 發送arp request
//********************************
//修改arp操作碼為rarp
packetRAM[arp_op]=0x0002;
//交換以太Mac
EthResp();
//源mac 寫到目的mac
packetRAM[arp_tha]=packetRAM[arp_sha];
packetRAM[arp_tha+1]=packetRAM[arp_sha+1];
packetRAM[arp_tha+2]=packetRAM[arp_sha+2];
//源ip 寫到目的ip
packetRAM[arp_tpa]=packetRAM[arp_spa];
packetRAM[arp_tpa+1]=packetRAM[arp_spa+1];
//重寫源mac
packetRAM[arp_sha]=MAC12;
packetRAM[arp_sha+1]=MAC34;
packetRAM[arp_sha+2]=MAC56;
//重寫源IP
packetRAM[arp_spa]=IP12;
packetRAM[arp_spa+1]=IP34;
//發送rarp報文
sendpacket();
}
//如果幀的類型是 0800 表示 IP 幀
if(packetRAM[pktType]==0x0800)
{
//檢查IP幀的類型 01 表示 ICMP , 11 表示UDP
if((packetRAM[ip_proto]&0x00ff)==0x0001){
//當幀的類型是 0800 表示ICMP請求
if(packetRAM[ic_type]==0x0800){
EthResp();
IpResp();
//改變ICMP 為 0000 表示應答
packetRAM[ic_type]=0x0000;
packetRAM[ic_cksum]=0x0000;
packetRAM[ic_cksum]=inet_chksum(ip_data,20);
sendpacket();
}
}
if((packetRAM[ip_proto]&0x00ff)==0x0011){
//判斷UDP的目的地址是否是本機地址,如果不是就不處理
//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 表示寫請求
if(packetRAM[tftp_op]==0x0002)
{
tftpNo=0;
tftpSPort=packetRAM[u_src];
sdrampoint=0;pktcount=0;
tftpack();
}
// tftp_op 操作碼 0003 表示數據
if(packetRAM[tftp_op]==0x0003)
{
tftpNo=packetRAM[tftp_blk];
//得到這一幀的長度
pktlength=(packetRAM[ip_Len]-32)/2;
for(i=tftp_data;i<tftp_data+pktlength;i++)
{
packetRAM[i]=CS8900_RTDATA&0xffff;
// put_char((packetRAM[i])&0x00ff);
// put_char((packetRAM[i]>>8)&0x00ff);
}
if (packetRAM[ip_Len]&0x0001==1)
{
packetRAM[i]=CS8900_RTDATA&0xffff;
}
//for(j=0;j<i-tftp_data;j+=2)
//{
//}
//處理數據
//將數據寫到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();
//計算文件的長度 以字為單位
pktcount=pktcount+pktlength;
//如果幀的數據的長度 在 0-511個字節 pktlength是字長所以和256比較 表示已經是最后一個報文就開始向flash中寫如數據
if(pktlength<256)
{
ramtoflash(pktcount);
put_char('!');
}
}
if(packetRAM[tftp_op]==0x0005) //清空所有的標記
{
sdrampoint=0;pktcount=0;
return;
}
}
}
//不滿足條件就跳過這一幀
put_reg(PP_RxCFG,PP_RxCFG_Skip1);
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -