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

📄 dm9000.c

📁 uCOS-II下实现的lwip协议栈实现Ping功能
💻 C
字号:
#define __DM9000
#include "uCOS_II/SOURCE/API/os_api.h"
#include "uCOS_II/include/ucos_ii.h"
#include "uCOS_II/include/OS_CPU.h"

#include "dm9000.h"
#undef __DM9000

#define rTCNTO4			(*(volatile unsigned *)0x51000040)
#define IPaddr_t		unsigned long
#define NSR_TX2END      (1<<3)
#define NSR_TX1END      (1<<2)
unsigned long timestamp;
unsigned long lastdec;		// 上次所得计数值. 用于换算CPU运行时间.
int timer_load_val ;		// 定时器装载值

//********************** Global Variable **********************

// 网络数据缓冲区
volatile u_char * NetTxPacket;				// 发送包	/* THE transmit packet	*/
volatile u_char * NetRxPackets[PKTBUFSRX];	// 接收包	/* Receive packets	*/

// 网卡参数
char MACAddr[] = {8, 1, 62, 38, 10, 91};	// MAC地址
IPaddr_t IPAddr = 0x0A0A0A76;				// 自身IP地址: 10.10.10.118
IPaddr_t GateAddr = 0x0a0a0afe;				// 网关: 10.10.10.254
IPaddr_t MaskAddr = 0xffffff00;				// 子网掩码: 255.255.255.0
IPaddr_t ServerAddr = 0x0A0A0A1A;			// 服务器地址: 10.10.10.26

//*************************************************************



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 取DM9000ID.
// 描述: packet page register access functions.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
u32_t  GetDM9000ID (void)
{
	u32_t 	id_val;
	DM9000_PPTR = DM9000_PID_H;
	id_val = (DM9000_PDATA & 0xff) << 8;
	DM9000_PPTR = DM9000_PID_L;
	id_val+= (DM9000_PDATA & 0xff);
	id_val = id_val << 16;
	DM9000_PPTR = DM9000_VID_H;
	id_val += (DM9000_PDATA & 0xff) << 8;
	DM9000_PPTR = DM9000_VID_L;
	id_val += (DM9000_PDATA & 0xff);
	return id_val;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网卡I/O写.
//
// [参数表]
//	reg: 寄存器号.
//	value: 写入值.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static void dm9000_iow(int reg, u8_t    value)
{
	DM9000_PPTR  = reg;
	DM9000_PDATA = value & 0xff;  //value & 0xff = value ;00001110&11111111=00001110
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网卡I/O读.
//
// [参数表]
//	reg: 寄存器号.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static unsigned char dm9000_ior(int reg)
{
	DM9000_PPTR = reg;
	return DM9000_PDATA & 0xff;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网卡复位.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static void eth_reset (void)
{
	int IoMode,i;
	
	dm9000_iow(0, 1);	/* register 0 set 1 in order to reset, auto clean after 10us*/
	for( i=0; i<1000; i++ );	// 延时
	
	IoMode = dm9000_ior(0xfe) >> 6; 	/* ISR bit7:6 keeps I/O mode */

	dm9000_iow(0x1e, 0x01);	/* Let GPIO0 output */
	dm9000_iow(0x1f, 0x00);	/* Enable PHY , Let GPIO0 output value =  0*/
	dm9000_iow(0xff, 0x80);	/* disable interrupt and sram read/write point auto return*/
	dm9000_iow(0x01, 0xc);		/* clear TX status */
	dm9000_iow(0x05, 0x33);	/* enable rx fuction, note: must set promiscuous mode */
	dm9000_ior(0x06);
	dm9000_iow(0x02, 1);   	/* enable tx fuction */

	IoMode = dm9000_ior(0x01);
}

//Eint9中断服务程序
//__irq void  Eint9_ISR(void)
 void irqDM9000ISR(void)
{		
    //extern HANDLER hEthernetInput;
    U16  ulIntStatus, ulReceiveStatus;
	U32 len,i, tx_status;
	OSPrintf("\nEnter interrupt\n");
	OSIntEnter();
	{
	    //U16  ulIntStatus, ulReceiveStatus;
		//* 获取中断状态
		ulIntStatus = dm9000_ior(0xfe);
		//*清除中断
		dm9000_iow(0xfe, ulIntStatus);
		
		
		if (ulIntStatus & 0x01) {
			OSPrintf("\nEnter rx interrupt\n");
			//OSAPISemSend(hEthernetInput);
		}	
		//ulReceiveStatus = dm9000_ior(0x06);
		
		if (ulIntStatus & 0x02)	{
			OSPrintf("\nEnter tx interrupt\n");
			tx_status = dm9000_ior(0x01);/* Got TX status */
			//if(tx_status & (NSR_TX2END | NSR_TX1END))
			//{			
			//}
		}
		//len = eth_rx();
		//len = receivepacket(Buffer);
		//OSPrintf("接收数据长度:%d <--->",len);
		//OSPrintf("\r\n数据接收\r\n");
		//ClearPending(BIT_EINT4_7);
		rSRCPND   |= 0x1<<5;
		rINTPND   |= 0x1<<5 ;
		rEINTPEND |= 1<<9;
	}
	OSIntExit();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 初始化网卡.
// 描述: 初始化DM9000.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void DM9k_init(void)
{
	//extern HANDLER hEthernetInput;
	#if OS_CRITICAL_METHOD == 3                     
    	OS_CPU_SR  		cpu_sr = 0;
	#endif
	int i=0, oft;
	UBYTE ubDelaySeconds = 0;
	u32_t ID = 0;

	//ID = GetDM9000ID();	// 取网卡ID号
	//if ( ID != DM9000_ID)	// 若ID验证失败, 则跳出
	//	return;
	OSPrintf("Intialize dm9000!\r\n");
	
	while ((ID != DM9000_ID)&&(i++<3)) {
		// 若ID验证失败, 则反复读取
		eth_reset ();	// 网卡重置
		ID = GetDM9000ID();		// 取网卡ID号
		OSTimeDlyHMSM(0, 0, ubDelaySeconds, 0);
	}
	
	OSPrintf("Success to read dm9000 id which is %x\n", ID);
	//eth_reset ();	// 网卡重置
	
	//hEthernetInput = OSAPISemNew(0);
	
	for( i=0, oft=0x10; i<6; i++, oft++) {
		// 写入MAC地址
		dm9000_iow(oft, MACAddr[i]);
	}
		
	// 设置dm9000中断	
	OS_ENTER_CRITICAL()
	{
		//GPG1设置为EINT9,DM9000的INT连接EINIT9 [3:2]=10
		rGPGCON = (rGPGCON & (~(0x03<<2))) | (0x02<<2);	       
		//rEXTINT0 = (rEXTINT0 & (~(0x07<<28))) | (0x01<<28);
		rEXTINT1 = (rEXTINT1 & (~(0x07<<4))) | (0x01<<4);
		//EINIT9中断使能
		rEINTMASK = rEINTMASK & (~(0x01<<9));         
		//rINTMOD |= 0x01<<5;
		//ChearPending()清除SCRPND和INTPND对应的位,rSRCPND = bit;rINTPND = bit;rINTPND;
		//ClearPending(BIT_EINT4_7);             //BIT_EINT4_7 (0x1<<4)                  
		rSRCPND |= 0x1<<5;
		rINTPND |= 0x1<<5 ;
		//pISR_EINT8_23 = (U32)Eint9_ISR;
		pISR_EINT8_23 = (U32)irqDM9000ISR;
		rINTMSK = rINTMSK & (~(BIT_EINT4_7));
	}
	OS_EXIT_CRITICAL()
	// dm9000中断使能
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络接收一个数据包.
// 描述: Get a data block via Ethernet.
//
// 返回: 数据包长度.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int eth_rx (void)
{
	int i;
	unsigned short rxlen;
	unsigned short *addr;
	unsigned short status;
	u8_t    RxRead;
	
	RxRead = dm9000_ior(0xf1);
	RxRead = dm9000_ior(0xf0);
	RxRead = (DM9000_PDATA) & 0xff;
	RxRead = (DM9000_PDATA) & 0xff;
	
	if (RxRead != 1)  /* no data */ 
		return 0;

	DM9000_PPTR = 0xf2;		/* set read ptr ++ */

	status = DM9000_PDATA;		/* get status */
	rxlen  = DM9000_PDATA;		/* get len */
	
	// 数据包长度溢出, 返回
	if (rxlen > PKTSIZE_ALIGN + PKTALIGN)
		return 0;
	
	// 接收数据包
	for( addr=(unsigned short *)NetRxPackets[0], i=rxlen>>1; i>0; i--)
		*addr++ = DM9000_PDATA;

	if (rxlen & 1) {
		*addr = DM9000_PDATA;
    }
    
	//NetReceiveProcess (NetRxPackets[0], rxlen);	// 网络接收数据包处理
  	rGPFDAT ^= (0x01 << 4);
  	
	return rxlen;	// 返回数据包长度
}//eth_rx()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//函数:函数拷贝缓冲池里的数据,传给low_level_input函数使用.
//描述:for the function low_level_input ,need to know ,if it is not usefull 

//[参数表]:

//len :数据包长度.间接从eth_rx()函数里读取

//返回:数据包首地址

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

u8_t *revc_frame(u16_t len)
{
	u8_t *ptr ; 
	//ptr = pbuf_alloc(PBUF_RAW,len,PBUF_POOL) ; 
	memcpy(ptr,NetRxPackets,len) ; 
	return ptr ;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函数: 网络发送一个数据包.
// 描述: Send a data block via Ethernet.
//
// [参数表]
//	packet: 数据包地址.
//	length: 数据包长度.
//
// 返回: 数据包长度.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int eth_send (volatile void *packet, int length)
{
   volatile unsigned short	*addr;
   int 	tmo;
   u8_t    	TxStatus;
   int	length1 = length;
   int 	IoMode, TryTimes=0, TryTimes1=0;

   while (1) {
      TryTimes++;
      if (TryTimes > 5) {	// 试5次
         break;
 	  }
 	  
      TxStatus = dm9000_ior( 0x01);
      TxStatus = TxStatus & 0xc;

      /*if(!TxStatus)		// 发送完成置零,要判是否连接OK
      {
         TryTimes1 = 0;
         for( tmo = get_timer(0)+CFG_HZ; get_timer(0)< tmo; )
         {
            TryTimes1++;
            if( TryTimes1>5000 )
            {
               eth_reset ();
               return 1;
            }
         }
 
         IoMode = dm9000_ior( 0x01);
         if(IoMode & 0x40)		// 没有连接, 重新复位再试
            eth_reset ();
      }
      else
         break;*/
       if (TxStatus) {
       	  break;
       }
       
       TryTimes1 = 0;
       for (tmo = get_timer(0)+CFG_HZ; get_timer(0)< tmo; ) {
           TryTimes1++;
           if (TryTimes1>5000) {
               eth_reset ();
               return 1;
           }
       }
 
       IoMode = dm9000_ior( 0x01);
       if (IoMode & 0x40) {		// 没有连接, 重新复位再试
           eth_reset ();         
       }
   }

   DM9000_PPTR = 0xf8;		/* data copy ready set */

   /* copy data */
   for (addr = packet; length > 0; length -= 2)
      DM9000_PDATA = *addr++;

   dm9000_iow(0xfd, (length1 >> 8) & 0xff);  /*set transmit leng */
   dm9000_iow(0xfc, length1 & 0xff);
   /* start transmit */
   dm9000_iow(0x02, 1);  
   rGPFDAT ^= (0x01 << 5); 
   return 0;
}//eth_send()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//自己添加一个函数.函数get_timer
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
u_long get_timer(int t)
{
	
	unsigned long now;
	now = rTCNTO4;	// 读出当前定时器计数值
	
	if (lastdec >= now)	// 根据上次所得计数值与本次所得计数值之间的大小关系换算出CPU运行时间
	{
		// normal mode
		timestamp += lastdec - now;
	} 
	else 
	{
		// we have an overflow ...
		timestamp += lastdec + timer_load_val - now;
	}
	lastdec = now;	// 用本次采用的定时器计数值更新上次所得计数值
	return timestamp-t;
}

⌨️ 快捷键说明

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