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

📄 cs8900.c

📁 cs8900网卡在嵌入式系统中的驱动,网上很少有此网卡驱动的源代码,并且cs8900的datasheet写的非常乱,这个网卡驱动是我用了快2个星期弄出来的,分享给大家,希望大家少走弯路.
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "cs8900.h"
#include "2410lib.h"
#include "string.h"
#include "2410addr.h"

#define printf Uart_Printf

int cs8900_reset(void);
unsigned short ReadPPRegister(unsigned short regOffset);
void WritePPRegister(unsigned short regOffset, unsigned short val);

extern unsigned char gRxDataBuf[1520];
extern unsigned char gTxDataBuf[1520];
extern int ack_flag;
//源地址
static char EtherAddr[6] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x66};
//目的地址
static char EtherDesAddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};

static int gPrevTxBidFail = 0; /* The flag to know if the previous bid for Tx is failed. */



/***************************************************************************************/
/* ReadPPRegister(): Read value from the Packet Pointer register at regOffset */
/***************************************************************************************/
unsigned short ReadPPRegister(unsigned short regOffset)
{
	 CS8900_PPTR = regOffset; 
	return CS8900_PDATA;
}

/****************************************************************************************/
/* WritePPRegister(): write value to the Packet Pointer register at regOffset           */
/****************************************************************************************/
void WritePPRegister(unsigned short regOffset, unsigned short val)
{	
	CS8900_PPTR = regOffset;
	CS8900_PDATA = val;
}

/**************************************************************************/
/*   cs8900_poll_init( ): start up CS8900 for Poll Mode                   */
/**************************************************************************/
int cs8900_poll_init(unsigned short duplexMode) 
{

	unsigned short chip_type, chip_rev,/* chip_status,*/ tmpAddr0, tmpAddr1, tmpAddr2;
    	unsigned short *ptr;
	int status;

	/* Information: read Chip Id and Revision */
 	chip_type = ReadPPRegister(PP_ChipID);
    	chip_rev = ReadPPRegister(PP_ChipRev);
    	if ( chip_type != 0x630e )
    	{
		printf ("Chip ID Error\n");
		return -1;
	}
    /****** step 1: software reset the chip ******/
	status = cs8900_reset();
	if (status != 0 ) 
	{
	      printf("CS8900 Error: Reset Failed!\n");
	      return -1;
	}
 
	/****** step 2: Set up Ethernet hardware address ******/
	ptr = (unsigned short *)EtherAddr;
	tmpAddr0=*ptr;
 	tmpAddr1=*(ptr+1);
 	tmpAddr2=*(ptr+2);
 	
    /* Write 2 bytes of Ethernet address into the Individual Address register at a time */
    WritePPRegister(PP_IA, tmpAddr0 );
    WritePPRegister(PP_IA+2, tmpAddr1 );
    WritePPRegister(PP_IA+4, tmpAddr2 );
    
    /****** step 3: Configure RxCTL to receive good frames for Indivual Addr, Broadcast, and Multicast.*/  
    /*WritePPRegister(PP_RxCTL, PP_RxCTL_RxOK | PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_Multicast);*/
    
    /****** step 3: or set to Promiscuous mode to receive all network traffic ******/
                                                       //任意地址接收             //网卡设置成接收correct CRC & valid length(64--1518)
 WritePPRegister(PP_RxCTL, PP_RxCTL_Promiscuous|PP_RxCTL_RxOK); 
    

    /****** step 4: Configure TestCTL (DuplexMode) ******/
	/* defualt: 0:half duplex;  0x4000=Full duplex*/
	
	//duplexMode由参数传递过来
 //   WritePPRegister(PP_TestCTL, duplexMode);

  //全双工
    WritePPRegister(PP_TestCTL, PP_TestCTL_FDX);
    /****** step 5: Set SerRxOn, SerTxOn in LineCTL ******/
    //使接收下一桢成为可能
    WritePPRegister(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);
  	return 0;
}

//初始化中断
void interrupt_init(void)
{
	U16 val;
	int int_stat;
	
	//mcu相关的设定使之响应中断
	pISR_EINT8_23 = (int)interrupt_done; //中断入口函数
		
	
	WritePPRegister(PP_IntReg, PP_IntReg_IRQ0);//选择pin0
	WritePPRegister(PP_RxCFG, PP_RxCFG_RxOK);//接收产生中断
	
//	WritePPRegister(PP_TxCFG, PP_TxCFG_TxOK);//发送产生中断
	
	Uart_Printf("RxCFG = %x\n", ReadPPRegister(PP_RxCFG));
	
	val = ReadPPRegister(PP_LineCTL)|PP_LineCTL_Rx|PP_LineCTL_Tx;
	WritePPRegister(PP_LineCTL, val);
		
	val = ReadPPRegister(PP_BusCtl);
	val |= PP_BusCtl_EnableIRQ;
	
	rEXTINT1 |= 1<<4; //使eint9高电平有效
	rEINTMASK &= ~(1<<9);//开外部屏蔽中断
	rINTMSK &= ~(1 << 5);//开内部中断屏蔽	
	
	WritePPRegister(PP_BusCtl, val);//受理中断使能	
}

//中断服务程序
void __irq interrupt_done(void)
{
	U16 int_stat;	
	U8 isdata;

	int_stat = CS8900_ISQ;// ReadPPRegister(0x0008);
	Uart_Printf("%x\n", int_stat);
	switch (int_stat & 0x003f)  {
		case 4:
			Uart_Printf("接收中断!\n");
			
			if ((int_stat & PP_RER_RxOK)) {
				Uart_Printf("接收!\n");
				Uart_Printf("int_stat = %x\n", int_stat);
				cs8900a_rev(gRxDataBuf);
				
				//是数据就发送确认桢
				if (data_is(gRxDataBuf)) 
					if (get_frame_num(gTxDataBuf) == get_frame_num(gRxDataBuf)) {
						send_ack(gTxDataBuf);
						Uart_Printf("ack send!\n");
						ack_flag = 1;
					}
					
				ShowReceiveFrame();				
				return;
			}
			
		/*case 8:
			Uart_Printf("发送中断!\n");
			if (int_stat & PP_TER_TxOK) {
				creat();
				cs8900_poll_send(gTxDataBuf);				
			}*/
	
	}
	
/*	Uart_Printf("响应!\n");
	//把中断队列的内容全部处理
	while (((int_stat = CS8900_ISQ)& 0xffc0) != 0) {
		if (int_stat & PP_RER_RxOK) {
				cs8900a_rev(gRxDataBuf);
				
				//是数据就发送确认桢
				if (data_is(gRxDataBuf)) 
					if (get_frame_num(gTxDataBuf) == get_frame_num(gRxDataBuf)) {
						send_ack(gTxDataBuf);
						ack_flag = 1;
					}
					
				ShowReceiveFrame();				
				return;
		}		
		return ;
	} */
	/*
	if (int_stat & 0x003f) {
		if (int_stat & PP_TER_TxOK){
		Uart_Printf("产生中断\n");
		creat();
		cs8900_poll_send(gTxDataBuf);
		}
		if (int_stat & PP_RER_RxOK) {
		 Uart_Printf("接收中断!\n");
		}
		
	}*/
			
	rSRCPND = BIT_EINT8_23;       //Clear pending bit
    rINTPND = BIT_EINT8_23;
    rINTPND;
    rEINTPEND = 1<<9;//Clear externt pending bit
    rEINTPEND;
}

//发送数据桢
int cs8900a_send(unsigned char *pTxData)
{
	 int total_len, len, i;
	 unsigned short *sdata;
	 U16 stat;
	 	
	 total_len = get_frame_len(pTxData) + 14;
	 
	
	 CS8900_TxCMD =  (unsigned short) PP_TxCmd_TxStart_Full | PP_TxCmd_Force;
	 CS8900_TxLEN  = total_len;
	 
	 sdata = (unsigned short *)pTxData;
	
    len = total_len;
    if (len > 0) 
    {
        /* Output contiguous words, two bytes at a time. */
        while (len > 1) 
	{
	       CS8900_RTDATA = *sdata ++;
	       len -= 2;
	       printf(".");
        }
        
        

        /* If Odd bytes, copy the last one byte to chip.*/
        if (len == 1) 
	{
		    CS8900_RTDATA = (*sdata) & 0x00ff;
        }
    }
printf("\nEnding  Translate\n");

    /****** Step 5.1: enable interrupts at processor level if it is disabled in step 0.******/
    /*enable( );   */


	/****** Step 6: Poll the TxEvent Reg for the TX completed status */
	/* This step is optional. If you don't wait until Tx compelete, the next cs8900_poll_send() 
	  Bid For Tx may encounter Not Ready For Tx because CS8900 is still Tx'ing.*/
	for ( i=0; i<30000; i++) 
	{
	        stat = ReadPPRegister(PP_TER);
	        
	        if ( stat != 0x0008 ) 
		{
	            break;
	        }
	}
	
	Uart_Printf("***%x\n", stat);
	/* Tx compelete without error, return total_length Tx'ed */
	if ( (stat & PP_TER_TxOK) || (stat == 0x0008) ) 
	{
		printf("Translate successful \n");
		 printf("----------End Translate-------\n");
		 Uart_Printf("***\n%x\n", ReadPPRegister(PP_TER));
            return total_len; /* return successful*/
	} 
	/* Tx with Errors */
	printf("Tx Error! TxEvent=%x \n", stat);
	printf("----------End Translat--------\n");
	Uart_Printf("***\n%x\n", ReadPPRegister(PP_TER));
	return -1; /* return failed*/
}

//判定是不是数据桢,如果是,创建确认桢,发送,不是则采取动作
/*
在桢中数据长度后面的1bit来标记数据桢还是确认桢
1 表示数据桢,
0 表示确认桢,
位置在gRxDataBuf中的14个单元的第一个bit
*/
int data_is(unsigned char *pRxData)
{
	unsigned char *ptr = pRxData;
	ptr += 14;
	
	*ptr >> 7;
	return *ptr;	
}

//Ack的桢的发送
int send_ack(unsigned char *pTxData, unsigned char *pRxData)
{
	unsigned char *ptr;
	U16 *tptr;
	ptr = pTxData;
	
	//创建确认桢
	memcpy(ptr,(unsigned char*)EtherDesAddr, 6);
	ptr += 6;
	
	memcpy(ptr,  EtherAddr, 6);
	ptr += 6;
	
	tptr = (U16 *)ptr;
	*tptr = 2;
	
	ptr += 2;
	*ptr = 0x0;
	
	*ptr << 7;  //设置ack桢标志
	
	ptr ++;
	
	*ptr = get_frame_num(pRxData);//接收桢的编号,封装在确认桢中
	
	cs8900_poll_send(pTxData);			
}

//获取接收到桢的编号
int get_frame_num(unsigned char *pRxData)
{
	unsigned char *ptr = pRxData;
	
	return *(ptr + 15);
}

//数据接收
int cs8900a_rev(unsigned char *dataBuf)
{
	U16 *data;
	 unsigned short totalLen, leftLen,val;
	 unsigned char *cp;
	 
	 totalLen = ReadPPRegister(PP_Rx_LENGTH);
	 
//	 Uart_Printf("rxlenth = %d\n", totalLen);
	 
	 data = (U16 *)dataBuf;
	  leftLen = totalLen;
	  
	  /* read 2 bytes at a time */
    while (leftLen >= 2) 
    {
	   *data++ = CS8900_RTDATA;
          leftLen -= 2;
    }

	/* if odd bytes, read the last byte from chip*/
    if (leftLen == 1) 
    {
	/* Read the last byte from chip*/
		val = CS8900_RTDATA;
        /* point to the last one byte of the user buffer*/
        	cp = (unsigned char *)data;

	   /* truncate the word (2-bytes) read from chip to one byte */
      		 *cp = (unsigned char)(val & 0xff);
    }
	return (int)totalLen;
}


/**************************************************************************/
/*   cs8900_reset( ): software reset the CS8900 chip                          */
/**************************************************************************/
int cs8900_reset(void) 

⌨️ 快捷键说明

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