⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udp.c

📁 arm嵌入式常用模块的程序源代码
💻 C
字号:
/******************************
	将数据报读取到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()
{
										//写发送命令字
	TxCMD=0x00C0;
									//写入发送数据报文的长度
	TxLEN=packetRAM[pktLen];
									//等待线路空闲的时候发送
	while(!(get_reg(PP_BusSTAT)&PP_BusSTAT_TxRDY));
										//写入需要发送的数据

	for(i=1;i<=packetRAM[pktLen]/2;i++)
		
		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)
{
/*******************************
	初始化以太网口
*********************************/
	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_);
/******************************
	开始接受数据
******************************/
for(;;){
	while( get_reg(PP_RER)&PP_RER_RxOK )
		{
		packetRAM[0]=get_reg(PP_RxLENGTH);
					//收取前面的74个字节,如果是ICMP正好包括了最后一个字符 14+20+8+32
		for (i=pktDest12;i<=23; i++)
		{
				packetRAM[i]=low2high(RTDATA);		
		}
					//检查帧的类型 如果是 0806 表示arp
		if (packetRAM[pktType]==0x0806)
		{
			//*******************************
					//发现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();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]= RTDATA&0xffff;
						put_char((packetRAM[i])&0x00ff);
						put_char((packetRAM[i]>>8)&0x00ff);
					}
					if (packetRAM[ip_Len]&0x0001==1)
					{
						packetRAM[i]= RTDATA&0xffff;

					}
					//处理数据
					//将数据写到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 + -