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

📄 rtl8019.c

📁 TMS320VC5402开发板的超详细电路原理
💻 C
字号:
#include	"cpu_reg.h"
#include	"RTL8019.h"

struct	ipaddr   	server_ipaddr,nod_ipaddr,r_ipaddr;
struct 	mac      	MAC_server,MAC_broad,MAC_rec;
struct 	mac      	MAC_self,MAC_nod;
struct 	iphdr    	t_iphdr;
struct 	igmphdr  	t_igmphdr;
struct 	udphdr   	t_udphdr;
struct 	pre_udphdr  pre_udphdr1;

Uint16	TxNetBuf[1518/2];
Uint16	RxNetBuf[1518/2];
Uint16	TxBufFlag;
Uint16	bnry,curr;

extern	Uint16	ms;

void	InitProtocal(void);

/**********************************************************************
**函数原型:    void  	delay_ms(uint ms_number)
**入口参数:		ms_number: 延时的毫秒数
**出口参数:		无
**返 回 值:	无      
**说    明:	延时预定的时间,延时时间与特定的处理器有关
************************************************************************/
void	Delay_MS(Uint16	ms_number)
		{
			Uint16 i,j;
			for (i=0;i<ms_number;i++)
				{
					for(j = 0;j < ms_number;j++) { ; }
				}	
		}



//==============================================================================
/**********************************************************************
**函数原型:    void  page(uchar pagenumber)
**入口参数:   	Uint16	pagenumber: 要切换的页
**出口参数:		无
**返 回 值:	无      
**说    明:	选择页,可选择0,1,2三页,第四页ne000兼容芯片保留 
************************************************************************/
void	page(Uint16 pagenumber)
		{
			Uint16	temp;
			temp = Reg00;				//command register
			temp = temp&0x3B ; 			//注意txp位不能要
			pagenumber=pagenumber <<6;
			temp=temp | pagenumber;
			Reg00=temp;
		}

/**********************************************************************
**函数原型:     void 	Init8019()
**入口参数:		无
**出口参数:		无
**返 回 值:		无              
**说    明:		对芯片的工作寄存器进行设置,各个寄存器的用法可参考文档和
**				络芯片的数据手册
************************************************************************/
void	Init8019()
		{
			Delay_MS(10);
/**********************************************************************

1.Reg00命令寄存器: CR,命令寄存器,地址偏移量00H,为一个字节
  位:  7   6   5   4   3   2   1   0 
名字: PS1 PS0 RD2 RD1 RD0 TXP STA STP 
//============================================
2.
RD2,RD1,RD0: 这3个位代表要执行的功能。
 0   0   1 : 读网卡内存
 0   1   0 : 写网卡内存
 0   1   1 : 发送网卡数据包
 1   *   * : 完成或结束DMA的读写操作
//============================================
3.TXP位置1时发送数据包,发完自动清零
//============================================
4.
STA,STP:	这两个位用来启动命令或停止命令
 1   0 		启动命令
 0   1 		停止命令
//============================================
********************************************************/
			Reg00=0x21;   //使芯片处于停止模式,这时进行寄存器设置
			InitProtocal();
			
			Delay_MS(10); //延时10毫秒,确保芯片进入停止模式
			page(0);
			Reg0a= 0x00;   //清rbcr0
			Reg0b= 0x00;   //清rbcr1
			Reg0c= 0xe0;  //RCR,监视模式,不接收数据包
			Reg0d= 0xe2;  //TCR,loop back模式
			Reg01= 0x4c;   //pstart = 0x4c
			Reg02= 0x80;   //pstop = 0x80
			Reg03= 0x4c;   //bnry = 4c
			Reg04= 0x40;  //TPSR,发送起始页寄存器
			Reg07= 0xff;  //清除所有中断标志位,中断状态寄存器
			Reg0f= 0x00;  //中断屏蔽寄存器清0,禁止中断
			Reg0e= 0xc9;  // 数据配置寄存器,16位dma方式
			page(1);
			Reg07= 0x4d;
			Reg08= 0x00;
			Reg09= 0x00;
			Reg0a= 0x00;
			Reg0b= 0x00;
			Reg0c= 0x00;
			Reg0d= 0x00;
			Reg0e= 0x00;
			Reg0f= 0x00;

    		Reg01= MAC_self.addr2_1;
    		Reg02= MAC_self.addr2_1>>8;
    		Reg03= MAC_self.addr4_3;
    		Reg04= MAC_self.addr4_3>>8;
    		Reg05= MAC_self.addr6_5;
    		Reg06= MAC_self.addr6_5>>8;

			page(0);
			Reg0c= 0xce;  //将芯片设置成正常模式,跟外部网络连接
			Reg0d= 0xe0;
			Reg00= 0x22;  //启动芯片开始工作
//-----------------------------------
			Reg07= 0xff;  //清除所有中断标志位
			
		}

void 	InitProtocal(void)
		{
/*  server_ip=192.168.1.40  */

    		server_ipaddr.addr2_1  =192;
    		server_ipaddr.addr2_1 +=(Uint16)168<<8;
    		server_ipaddr.addr4_3  =1;
    		server_ipaddr.addr4_3 +=(Uint16)40<<8;

//192.168.1.1    
    		nod_ipaddr.addr2_1     =192;
    		nod_ipaddr.addr2_1    +=(Uint16)168<<8;
    		nod_ipaddr.addr4_3     =1;
    		nod_ipaddr.addr4_3    +=(1<<8);
    
    		t_iphdr.tos_version    =69;
    		t_iphdr.tos_version   +=(Uint16)0<<8;      //usally not use
    		t_iphdr.id =20;  //++IP_id;
    		t_iphdr.id +=(Uint16)52<<8;
    
    		t_iphdr.frag_off =0;
    		t_iphdr.protocal_ttl   =128;       //usally 32 or 64
    		t_iphdr.protocal_ttl +=(Uint16)17<<8;
    		t_iphdr.saddr =nod_ipaddr;
    		t_iphdr.daddr =server_ipaddr;
    //UDP PORT
    		t_udphdr.sport =1024; //1*256+0x08,9901
    		t_udphdr.dport =1025; //1*256+0x07,9901
    
    		pre_udphdr1.saddr=t_iphdr.saddr;
    		pre_udphdr1.daddr=t_iphdr.daddr;
    		pre_udphdr1.protocal_value  =0;
    		pre_udphdr1.protocal_value +=17<<8;  //UDP
// FF-FF-FF-FF-FF-FF    
    		MAC_broad.addr2_1   =255;
    		MAC_broad.addr2_1  +=(Uint16)255<<8;
    		MAC_broad.addr4_3   =255;
    		MAC_broad.addr4_3  +=(Uint16)255<<8;
    		MAC_broad.addr6_5   =255;
    		MAC_broad.addr6_5  +=(Uint16)255<<8;
    
//	02-E0-4C-A0-7E-7A    
    		MAC_self.addr2_1  =1<<1;
    		MAC_self.addr2_1  +=(Uint16)224<<8;
    		MAC_self.addr4_3  =76;
    		MAC_self.addr4_3  +=(Uint16)160<<8;
    		MAC_self.addr6_5  =126;
    		MAC_self.addr6_5  +=(Uint16)122<<8;

//  00-E0-4C-A0-7E-7A	    
	    	MAC_nod.addr2_1  =0;
    		MAC_nod.addr2_1  +=(Uint16)224<<8;
    		MAC_nod.addr4_3  =76;
    		MAC_nod.addr4_3  +=(Uint16)160<<8;
    		MAC_nod.addr6_5  =126;
    		MAC_nod.addr6_5  +=(Uint16)122<<8;
	}


//=============================================================================
/**********************************************************************
**函数原型:    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++)	TxNetBuf[i]=0;
          			length=60/2;
       			}
			
			page(0);						//切换至第0页
			length = length <<1;
			TxBufFlag=!TxBufFlag;			//设置两个发缓区,提高发送效率
			if(TxBufFlag)
				{Reg09=0x40 ;}				//设置发送页地址
			else
				{Reg09=0x46 ;}				//设置发送页地址
    
			Reg08=0x00; 					//read page address low
			Reg0b = length >>8;				//写发送长度高位
			Reg0a = length & 0x00ff;        //写发送长度低位  
			Reg00=0x12;						//write dma, page0

			for(i=0;i<length/2;i++)
				{
					Reg10 = TxNetBuf[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)			//此时表示有新的数据包在缓冲区里
    			{					//在任何操作都最好返回page0
     				page(0);
     //=======================================
     				Reg09=bnry;		//读页地址的高字节
     				Reg08=0x00; 	//读页地址的低字节
     				Reg0b=0x00;		//读取字节计数高字节
     				Reg0a=18;       //读取字节计数高字节
     				Reg00=0x0a;     //启动Remote DMA读操作
	 
	 
     				for(i=0;i<9;i++)	//读取一包的前18个字节:4字节的8019头部,6字节目的地址,6字节原地址,2字节协议
                    	{
                       		RxNetBuf[i]=Reg10;
                      	}
 //=======================================中止DMA操作
     				Reg0b=0x00;	//
     				Reg0a=0x00;	//
     				Reg00=0x22;	//结束或放弃DMA操作
 //=======================================
					
					d.total = RxNetBuf[0];
					length = RxNetBuf[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;
        					Reg03=bnry; 	//write to bnry     
        					Reg07=0xff;
							return(0);
              			}
//=============================================
            
     				else//表示数据包是完好的.读取剩下的数据
     					{
     						Temp = SwapByte(RxNetBuf[8]);		
        					if((Temp == IP_FRAME)||(Temp == ARP_FRAME))
								{ //协议为IP或ARP才接收
                					Reg09 = bnry;   				//read page address high
                					Reg08 = 4;      				//read page address low
                					Reg0b = length>>8;  //read count high
                					Reg0a = length & 0xff;//read count low;
                					
                					Reg00=0x0a;                             //read dma
						        	length=(length+1)/2;
                					for(ii=2;ii<length+2;ii++)
                						{
                							RxNetBuf[ii]=Reg10;
                						}
                        			//================终止DMA操作
                        			Reg0b=0x00;			//read count high   
                        			Reg0a=0x00;			//read count low;
                        			Reg00=0x22;			//结束或放弃DMA
                        			//============================
                        		}
                        		//=========================================
                        	d.total = RxNetBuf[0];
                        	bnry = d.e.low - 1;	
                			if(bnry<0x4c)	bnry=0x7f;
                			page(0);
	        				Reg03=bnry;      //write to bnry
                			Reg07=0xff;
                			return(1);   //have new packet
               			}
   				}
			else	
				return(0);
		}



//============================================================
void	LoadEnetHrd(Uint16	MAC_type,Uint16	PROTO_type)
		{       
       		if(MAC_type==0)              		//添加目的MAC地址
         		memcpy(TxNetBuf,&MAC_server,3);
       		else if(MAC_type==BroadCast)
         		memcpy(TxNetBuf,&MAC_broad,3);
       		else if(MAC_type==RequestArp)
         		memcpy(TxNetBuf,&MAC_broad,3);
         	else if(MAC_type==AnswerArp)
         		memcpy(TxNetBuf,&MAC_rec,3);	
       		else if(MAC_type==Nod)
         		memcpy(TxNetBuf,&MAC_nod,3);
         
       		memcpy(TxNetBuf+3,&MAC_self,3);   //添加源MAC地址

       		if(PROTO_type==UDP)          	  //协议类型
         		*(TxNetBuf+6)=8+(0<<8);   
       		else if(PROTO_type==ARP)
         		*(TxNetBuf+6)=8+(6<<8);   
       		else if(PROTO_type==LSS)          //协议类型
         		*(TxNetBuf+6)=8+(8<<8);   
		}
			
void	LoadArp(struct	ipaddr	*ip,Uint16	type)
		{
			struct 	arp  arp1;
         	arp1.hard_type  = (Uint16)1<<8;
         	arp1.proto_type = (Uint16)((2048<<8)+(2048>>8));
         	arp1.proto_hard_length = 6;
         	arp1.proto_hard_length += (Uint16)4<<8;
         
         	arp1.send_macaddr =MAC_self;
         	arp1.send_ipaddr  =nod_ipaddr;

			if (type==RequestArp)
				{
		           	arp1.op_code = 0x01<<8;
   					arp1.rec_macaddr.addr2_1  =0;
		   			arp1.rec_macaddr.addr4_3  =0;
   					arp1.rec_macaddr.addr6_5  =0;
         		}
         	else{
         			arp1.op_code = 0x02<<8;
		   			arp1.rec_macaddr =MAC_rec; 			
         		}	
         	arp1.rec_ipaddr   =*ip;         
         	memcpy(TxNetBuf+7,&arp1,sizeof(arp1));
		
		}
		
void	LoadIp(struct	ipaddr	*ip,Uint16	protocal)
		{
			struct	iphdr	tip;
    		tip.tos_version = 0x45;
    		tip.tos_version += (Uint16)0<<8;      //usally not use
    		tip.id =20;  //++IP_id;
    		tip.id +=(Uint16)52<<8;
    
    		tip.frag_off =0;
    		tip.protocal_ttl   =128;       //usally 32 or 64
    		tip.saddr =nod_ipaddr;
    		tip.daddr = *ip;
			if	(protocal==TCP)
  		  		t_iphdr.protocal_ttl +=(Uint16)6<<8;
  		  	else if (protocal==UDP)
  		  		t_iphdr.protocal_ttl +=(Uint16)17<<8;	
			else if (protocal==ICMP)
	    		t_iphdr.protocal_ttl +=(Uint16)1<<8;
			else if (protocal==IGMP)
	    		t_iphdr.protocal_ttl +=(Uint16)2<<8;
         	memcpy(TxNetBuf+7,&tip,sizeof(tip));	    		
		}
		
				
void	ArpRequest(struct	ipaddr *ip)
		{
			LoadEnetHrd(RequestArp,ARP);         	
			LoadArp(ip,RequestArp);
         	SendFrame(TxNetBuf,30);
		}

void	ArpAnswer(struct	ipaddr *ip)
		{
			LoadEnetHrd(AnswerArp,ARP);         	
			LoadArp(ip,AnswerArp);
         	SendFrame(TxNetBuf,30);
		}

Uint16	SwapByte(Uint16	value)
		{
    		Uint16	temp;
    		temp=(value<<8)|(value>>8);
    		return(temp);
		}								

		
//======================= END ===============================

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -