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

📄 cs8900if.c

📁 lwip在ucos上的移植代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 /** @file * *  Ethernet network driver for IP *//* * Copyright (c) 2001-2004 Swedish Institute of Computer Science. * All rights reserved.  *  * Redistribution and use in source and binary forms, with or without modification,  * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, *    this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, *    this list of conditions and the following disclaimer in the documentation *    and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission.  * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY  * OF SUCH DAMAGE. * * This file is part of the lwIP TCP/IP stack. *  * Author: Adam Dunkels <adam@sics.se> * *//* This file is part of the lwIP TCP/IP stack. * * This is a device driver for the Crystal Semiconductor CS8900 * chip in combination with the lwIP stack. * * This is work under development. Please coordinate changes * and requests with Leon Woestenberg <leon.woestenberg@axon.tv> * * The Swedish Institute of Computer Science and Adam Dunkels * are specifically granted permission to redistribute this * source code under any conditions they seem fit. * * A quick function roadmap: * * cs8900_*() are low level, cs8900 hardware specific functions. * These are declared static in the device driver source and * SHOULD NOT need to be called from outside this source. * * cs8900if_*() are the lwIP network interface functions. * * cs8900_interrupt() is an early interrupt service routine (ISR). * It merely sets a flag to indicate the cs8900 needs servicing. * (This function MAY be tied to an interrupt vector, IF present). * * cs8900_service() is the actual interrupt event service routine. * It must be called whenever the cs8900 needs servicing. It MAY * be polled safely (so, you do NOT NEED interrupt support.) * * cs8900_init() sets up the cs8900, using its register set. When * using the driver on your particular hardware platform, make sure * the register setups match. * Function is called from cs8900if_init(). * * cs8900_input() transfers a received packet from the chip. * Function is called from cs8900if_input(). * * cs8900_output() transfers a packet to the chip for transmission. * Function is called from cs8900if_output(). * * cs8900if_init() initializes the lwIP network interface, and * calls cs8900_init() to initialize the hardware. * Function is called from lwIP. * * cs8900if_service() is the service routine, which must be called * upon the need for service, or on a regular basis, in order to * service the Ethernet chip. * * cs8900if_input() calls cs8900_input() to get a received packet * and then forwards the packet to protocol(s) handler(s). * Function is called from cs8900_service(). * * cs8900if_output() resolves the hardware address, then * calls cs8900_output() to transfer the packet. * Function is called from lwIP. * * Future development: * * Split the generic Ethernet functionality (a lot of the * cs8900if_*() functions) and the actual cs8900a dependencies. * * Enhance the interrupt handler to service the Ethernet * chip (to decrease latency); support early packet * inspection (during reception) to early drop unwanted * packets, minimize chip buffer use and maximize throughput. * * Statistics gathering, currently under development. * SNMP support, currently under development. * */  /*  *		今天终于找出了取数据(DataAbort)出错的问题,原因是CS8900A的外部中断引起的。先用轮询法读取数据。  				2007.2.24 千杯不醉  */     /* *	cs8900a驱动程序,工作于16位I/O模式,采用中断方式收发数据 *	After a hardware or a software reset,the CS8900A will be in 8-bit mode.Provide a HIGH  *	to LOW and then LOW to HIGH transition on the /SBHE signal before any 16-bit IO or Memory access is done  *	to the CS8900A. * *  INT1--------P0.3 *	INT2--------P0.7 *	IOR---------P1.19 *	IOW---------P1.23 *  A3-A1-------P1.18-P1.16 *	SEL0--------P1.21	:active low *	SEL1--------P1.22 *	D15-D10-----P0.30-P0.25 *	D9-D0-------P0.23-P0.14 * *	千杯不醉 2007.1.20  */#include "lwip/debug.h"#include "lwip/opt.h"#include "lwip/def.h"#include "lwip/mem.h"#include "lwip/pbuf.h"#include "lwip/stats.h"#include "lwip/sys.h"#include "netif/etharp.h"#include "arch/sys_arch.h"//LPC2138头文件#include "LPC2294.h"#include "cs8900if.h"#include "cs8900a.h"/* Define those to better describe your network interface. */#define IFNAME0 'e'#define IFNAME1 '0'struct cs8900if {  struct eth_addr *ethaddr;  /* Add whatever per-interface state that is needed here. */};//CS8900A引脚宏定义#define 	IOR  		(1 << 19)         #define 	IOW  		(1 << 23)#define 	SEL0 		(1 << 21)#define 	SEL1 		(1 << 22)#define 	A3_1 		(7 << 16)#define 	D15_10 		(0x3f << 25)#define 	D9_0 		(0x3ff <<14)// typedefs:对cs8900a寄存器的访问先写入地址再写入数据typedef struct {                               	u16_t addr;      	//CS8900A寄存器地址  	u16_t data;			//要写入寄存器的数据} TInitSeq;/** * Dependend on physical layer. This is a safe minimum for 802.3 10base5/T. * @sa RFC1042 */#define ETH_MIN_FRAME_LEN 76static const struct eth_addr ethbroadcast = {{0xffU,0xffU,0xffU,0xffU,0xffU,0xffU}};//定义MAC地址#define ETHADDR0 0x00#define ETHADDR1 0x01#define ETHADDR2 0x02#define ETHADDR3 0x03#define ETHADDR4 0x04#define ETHADDR5 0x05//cs8900a的配置信息,寄存器地址和写入值成对出现static TInitSeq InitSeq[] ={  		{PP_IA,       ETHADDR0 | (ETHADDR1 << 8)},     // set MAC Address  	{PP_IA + 2,   ETHADDR2 | (ETHADDR3 << 8)},  	{PP_IA + 4,   ETHADDR4 | (ETHADDR5 << 8)},  	{PP_TestCTL,  0x0099},										//Test Control:DisableLT  XXX OBS   	/*   	 *	enable:receiver,transmitter	  	 */  	{PP_LineCTL,  0x0013U | 0x0080U/*SerTxOn*/ | 0x0040U/*SerRxOn*/},   	/*   	 *	accept valid unicast or broadcast frames  	 */  	{PP_RxCTL,    0x0005U | 0x0800U | 0x0400U | 0x0100U},  	{PP_RxCFG,		0x0003U | 0x0100U},		// enable receive interrupt  	{PP_TxCFG,		0x0007U | 0},					// disable transmit interrupt (is default)  	{PP_CS8900_ISAINT,		0x0000U},							// use interrupt number 0  	  	/* generate interrupt event on:  		 - the RxMISS counter reaches 0x200, or       - a received frame is lost       */  	{PP_BufCFG,		0x000bU},  	  	{PP_BusCTL,		0x0017U | 0x8000U}// enable interrupt generation};   static struct netif *cs8900if_netif;//向cs8900a内部寄存器地址写入一个16位半字,访问方式为小端模式static void cs8900a_write(u16_t addr, u16_t data){	u32_t addr32 = 0,data32 = 0;	addr32 = (u32_t)addr;	data32 = (u32_t)data;/* CS8900的片先低有效	*/	IO1SET = SEL0;	//禁止CS8900A0	IO1CLR = SEL1;	//使能CS8900A1  IO0DIR |= D15_10 | D9_0;                              // Data port to output  IO1SET = IOR | IOW | ((addr32<<15) & A3_1);						// Put address on bus  IO1CLR = (~(addr32<<15)) & A3_1;                      IO0SET = ((data32<<14) & D9_0) | ((data32<<15) & D15_10);		//put 16bit data on data bus  IO0CLR = ((~(data32<<14)) & D9_0) | ((~(data32<<15)) & D15_10);  IO1CLR = IOW;  IO1SET = IOW;}// Reads a word in little-endian byte order from a specified port-addressstatic u16_t cs8900a_read(u16_t addr){  u32_t value;  u16_t tmp;  u32_t addr32;	addr32 = (u32_t)addr;    /* CS8900的片先低有效	*/	IO1SET = SEL0;	//禁止CS8900A0	IO1CLR = SEL1;	//使能CS8900A1	IO0DIR &= ~(D15_10 | D9_0);		// data port to input		                         	IO1SET = IOR | IOW | ((addr32<<15) & A3_1);		// Put address on bus  IO1CLR = (~(addr32<<15)) & A3_1;                    IO1CLR = IOR;                            // IOR-signal low    value = IO0PIN;    IO1SET = IOR;    tmp = (u16_t)(((value & D9_0)>>14) | ((value & D15_10)>>15));    return tmp;}/**----------------------------------------* * 说明:	SKIP_1:when set,this bit causes the last committed revieved frame to be *			deleted from the receive buffer.并且一置位就立即执行(Act at once)。 **---------------------------------------*/static void cs8900a_skip_frame(void){  // No space avaliable, skip a received frame and try again  cs8900a_write(ADD_PORT, PP_RxCFG);  cs8900a_write(DATA_PORT, cs8900a_read(DATA_PORT) | SKIP_1);}static sys_sem_t rxSem = NULL;/* 我建立了一个接收进程来处理网络数据包的接收,也可以用轮询的方式,前者更符合lwip的设计原则,并且  工作效率更高。此进程的优先级应该更高,不至于使数据丢失,但系统繁忙时可能需要更多的内存。 * */void cs8900a_rxThread(void *pdata){	u16_t irq_status = 0x0000U;  	pdata = pdata;			/* Block for ever. */  rxSem = sys_sem_new(0); 		while(1)	{		//接收到信号量		sys_sem_wait(rxSem);		//读取8900的中断状态寄存器判断中断来源      		irq_status = cs8900a_read(ISQ_PORT);    	/* ISQ interrupt event, and allowed to service in this loop? */ 		while (irq_status != 0x0000U)  		{    		/* investigate event */    		if ((irq_status & 0x003fU) == 0x0004U/*Receiver Event*/)    		{      			/* correctly received frame, either broadcast or individual address */      			/* TODO: think where these checks should appear: here or in cs8900_input() */      			if ((irq_status & 0x0100U/*RxOK*/) && (irq_status & 0x0c00U/*Broadcast | Individual*/))      			{      			         			        			/* read the frame from the cs8900a */        			cs8900if_input(cs8900if_netif);      			}      			else cs8900a_skip_frame();    		}    		/* read ISQ register */   	 		irq_status = cs8900a_read(ISQ_PORT);  		}	}}/*u16_t ptr[1024];u16_t cs8900a_rev_test(){	u16_t len = 0;	u16_t i = 0;	  // Check receiver event register to see if there are any valid frames avaliable  cs8900a_write(ADD_PORT, PP_RxEvent);  if ((cs8900a_read(DATA_PORT) & 0xd00) == 0)    return 0;    // Read frame length  len = cs8900a_read(RX_FRAME_PORT);  len = cs8900a_read(RX_FRAME_PORT);  for(i = 0 ;i < (len/2); ++i)  {  	ptr[i] = cs8900a_read(RX_FRAME_PORT);  }  return len;}*//** * 		cs8900a的接收中断服务程序 * * 		接收到数据包时触发,用信号量通知接收子进程把数据提交给上层。 * * * *		千杯不醉		2007.1.30 */void cs8900a_rxIsr(void){         OS_ENTER_CRITICAL();	    //cs8900a_rev_test();    if((EXTINT & 0x04) == 0x04)    {      		    	sys_sem_signal(rxSem);                    // 通知接收任务    }    EXTINT |= 0x04;	//清除中断源,电平模式下当电平无效时执行    VICVectAddr = 0;            // 通知中断控制器中断结束        OS_EXIT_CRITICAL();}// cs8900_init()//// initializes the CS8900A chipvoidcs8900a_init(struct netif *netif){  struct cs8900if *cs8900if; // u16_t dummy;  u8_t i = 0;  // the meaning of "netif->state" can be defined in drivers, here for MAC address! cs8900if = netif->state;   /* maximum transfer unit */  netif->mtu = 1500;  /* broadcast capability */  netif->flags = NETIF_FLAG_BROADCAST;  /* hardware address length */  netif->hwaddr_len = 6;    /* make up an MAC address. */  cs8900if->ethaddr->addr[0] = (u8_t)ETHADDR0;  cs8900if->ethaddr->addr[1] = (u8_t)ETHADDR1;  cs8900if->ethaddr->addr[2] = (u8_t)ETHADDR2;  cs8900if->ethaddr->addr[3] = (u8_t)ETHADDR3;  cs8900if->ethaddr->addr[4] = (u8_t)ETHADDR4;  cs8900if->ethaddr->addr[5] = (u8_t)ETHADDR5;/**	初始化cs8900a引脚配置和中断控制器	 *******INT1***INT2**** * *  INT1--------P0.3 *	INT2--------P0.7 * *********GPIO********* *	IOR---------P1.19 *	IOW---------P1.23 *  A3-A1-------P1.18-P1.16 *	SEL0--------P1.21	:active low *	SEL1--------P1.22 *	D15-D10-----P0.30-P0.25 *	D9-D0-------P0.23-P0.14 ************************** */  PINSEL0 |= 0x0000c000;    //cs8900's INTRQ1 active high  //EXTMODE |= 0x04;		//INT2边沿触发  EXTMODE = 0x00;  EXTPOLAR |= 0x04;  PINSEL1 = 0x00000000;  PINSEL2 |= 0x04;  IO0DIR |= D15_10 | D9_0;  IO1DIR |= IOR | IOW | SEL0 | SEL1 | A3_1;    IO1SET = SEL0 | SEL1 | IOR | IOW;	   //以太网控制器cs8900a1的中断:外部中断2  //VICVectAddr10 = (u32_t)cs8900a_rxIsr;  //VICVectCntl10 = (0x20 | 0x10);  //VICIntEnable |= 1 << 16;  IO1SET = SEL0;	//禁止CS8900A0  IO1CLR = SEL1;	//使能CS8900A1   /**

⌨️ 快捷键说明

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