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

📄 mcpcan.c

📁 linux-2.6.12下的can总线mcp2510芯片的完整驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/unistd.h>#include <linux/module.h>//#include <asm-arm/arch-s3c2410/S3C2410.h>#include <asm-arm/arch-s3c2410/irqs.h>#include <linux/interrupt.h> //fla#include <asm/arch/regs-gpio.h>//fla#include <asm/arch/hardware.h> //fla#include <linux/slab.h>  //fla#include <asm/arch/irqs.h> //fla#if defined(CONFIG_SMP)#define __SMP__#endif#if defined(CONFIG_MODVERSIONS)#define MODVERSIONS#endif#include <linux/sched.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/errno.h> 	/* for -EBUSY *///#include <linux/malloc.h>#include <linux/slab.h>#include <linux/ioport.h>	/* for verify_area */#include <linux/mm.h>#include <linux/interrupt.h>//#include <linux/tqueue.h>#include <linux/timer.h>#include <linux/delay.h>#include <linux/types.h>#include <linux/init.h>		/* for module_init */#include <linux/module.h>#include <asm/io.h>#include <asm/segment.h>#include <asm/irq.h>#include <asm/signal.h>#include <asm/siginfo.h>#include <asm/uaccess.h>  	/* for get_user and put_user */#include <asm/fcntl.h>#include <asm/cache.h>#include <asm/atomic.h>#include <asm/arch-s3c2410/regs-irq.h>  //fla#include <asm/arch-s3c2410/regs-clock.h> //#include <asm-arm/arch-s3c2410/S3C2410_2.h>//#include <sys/syscall.h>//#include <asm-arm/arch-s3c2410/S3C2410_2.h>//#include	<asm-arm/arch-s3c2410/S3C2410_2.h>//#include "S3C2410_2.h"#include "mcpcan.h"#include	"spi_cmd.h"#include    "spi.h"#define	MCP2510_FLAG#define BUF_SIZE sizeof(struct MCP_device) * 100unsigned long eintmask,spcon0,spsta0,sppin0,sppre0,sptdat0,sprdat0,spcon1,spsta1,sppin1,sppre1,sptdat1,sprdat1; //fla add for init interrupt!//#define DEBUG#ifdef DEBUG#define DbgPrintk(S) printk(S)#else#define DbgPrintk(S)#endifstruct MCP_device {       volatile unsigned long RecvBuf;       volatile unsigned long RecvHead;       volatile unsigned long RecvTail;       volatile unsigned long RecvNum;                                                                                                                                                      wait_queue_head_t inq;   //or use as a global variable                                                                                                                                                      struct semaphore sem;    //semaphore used for mutex                                                                                                                                                      unsigned int      IrqNum;       unsigned int      MinorNum;/*device minor number*/       unsigned int      BaudRate;                                                                                                                                                      unsigned char     *SendBuf;       unsigned int      SendNum;       volatile unsigned long SendHead;       volatile unsigned long SendTail;};//__attribute__((aligned(L1_CACHE_BYTES),packed));                                                                                                                                               /*****************************Variable define*******************************/unsigned int MCP_major = MCP_MAJOR;struct MCP_device *Device[MCP_NUM];unsigned int MCP_irq[MCP_NUM] = {IRQ_EINT8t23,IRQ_EINT8t23};static char *MCP_name[MCP_NUM] = {"mcpcan0","mcpcan1"};/*****************************SJA device initialize*************************///这个函数用来对struct MCP_device进行初始化static int MCP_device_init(void){        int res,i;//        printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);        for(i=0;i<MCP_NUM;i++) {                Device[i] = kmalloc(sizeof(struct MCP_device),GFP_KERNEL);  //malloc the device struct                if(Device[i] == NULL) {                        printk(KERN_ALERT"allocate device memory failed.\n");                        return(-ENOMEM);                }                memset((char *)Device[i],0,sizeof(struct MCP_device));                //Device[i]->RecvBuf = (unsigned char *)get_free_page(GFP_KERNEL);  //malloc the recv buffer                Device[i]->RecvBuf = (unsigned long)kmalloc(sizeof(struct MCP_device) * 100,GFP_KERNEL);  //malloc the recv buffer                if(Device[i]->RecvBuf == 0) {                        printk(KERN_ALERT"allocate Recv memory failed.\n");                        return(-ENOMEM);                }                memset((char *)Device[i]->RecvBuf,0,sizeof(struct MCP_device) * 100);                Device[i]->RecvHead = Device[i]->RecvBuf;                Device[i]->RecvTail = Device[i]->RecvBuf;                Device[i]->RecvNum = 0;                //Device[i]->RecvQueue = NULL;                                //Device[i]->SendBuf = (unsigned char *)get_free_page(GFP_KERNEL);   //malloc the send buffer                Device[i]->SendBuf = kmalloc(sizeof(struct MCP_device) * 100,GFP_KERNEL);  //malloc the send buffer                if(Device[i]->SendBuf == NULL) {                        printk(KERN_ALERT"allocate Send memory failed.\n");                        return(-ENOMEM);                }                memset((char *)Device[i]->SendBuf,0,sizeof(struct MCP_device) * 100);                Device[i]->MinorNum = i;                //Device[i]->FrameMode = 1;                Device[i]->IrqNum = MCP_irq[i];                //Device[i]->BaudRate = MCP_baudrate[i];		init_waitqueue_head(&(Device[i]->inq));		//init_waitqueue_head(&(Device[i]->outq));		init_MUTEX(&(Device[i]->sem));		}        return 0;}/*****************************MCP device initialize*************************//* Initialize the mcp2510 */void MCP2510_Init(int MinorNum ){	// Configure the SPI Interface in MX1	//int canstat = 0;//  printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	SPI_Init( ); 	// Configure the mcp2510 through spi interface//  printk("look if in configure mode:%s\n",CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED )>>5!=0x04?"faile":"okay");	// Reset controller	CAN_SPI_CMD( SPI_CMD_RESET, ARG_UNUSED, ARG_UNUSED, ARG_UNUSED );		CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x80 );		// CONFIG MODE	// make sure we are in configuration mode	while( (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED )>>5)!=0x04 );//  printk("look if in configure mode:%s\n",CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED )>>5!=0x04?"faile":"okay");//  printk("hmmmmmmmmmmm!MCAP2510 NOW IN CONFIGURE MODE!\n");	// start configuration	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->BFPCTRL)), 	BFPCTRL_INIT_VAL, 	ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXRTSCTRL)), 	TXRTSCTRL_INIT_VAL, ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF3)), 		CNF3_INIT_VAL, 		ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF2)), 		CNF2_INIT_VAL, 		ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CNF1)),		CNF1_INIT_VAL, 		ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CANINTE)),	CANINTE_INIT_VAL, 	ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->CANINTF)), 	CANINTF_INIT_VAL, 	ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->EFLG)), 		EFLG_INIT_VAL, 		ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0CTRL)), 	TXBnCTRL_INIT_VAL, 	ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB1CTRL)), 	TXBnCTRL_INIT_VAL, 	ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB2CTRL)), 	TXBnCTRL_INIT_VAL, 	ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB0CTRL)), 	RXB1CTRL_INIT_VAL, 	ARG_UNUSED);	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->RXB1CTRL)), 	RXB1CTRL_INIT_VAL, 	ARG_UNUSED);		// switch to normal mode or loopback mode ( for testing)	//CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x40 );		// LOOP BACK MODE	CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x00 );		// normal mode		//printk("look if in configure mode:%s\n\//failed is right,because now in loop back mode!\n",CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED )>>5!=0x04?"faile":"okay");	//fla mask for a while!CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANCTRL)), 0xe0, 0x00 );	// NORMAL OPERATION MODE		// Flush the MX1 SPI receive buffer		CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANSTAT)), ARG_UNUSED, ARG_UNUSED );}/* Transmit data *//* TxBuf	: select the transmit buffer( 0=buffer0 or 1=buffer1 2=buffer2 ) IdType	: 0=standard id or 1=extended id id	: frame identifier DataLen	: the number of byte data	: the pointer to data byte*/void MCP2510_TX( int TxBuf, int IdType, unsigned int id, int DataLen, char * data ){	int i, offset;  printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	switch( TxBuf ){		case TXBUF0:			offset = 0;			break;		case TXBUF1:			offset = 0x10;			break;		case TXBUF2:			offset = 0x20;			break;	}	//printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	// Set the frame identifier	if( IdType==STANDID ){		//printk(KERN_ERR "STANDID,line %d passed!\n",__LINE__);		CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0SIDL))+offset, (id&0x7)<<5, ARG_UNUSED );		CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0SIDH))+offset, (id>>3)&0xff, ARG_UNUSED );	}else if( IdType==EXTID ){		//printk(KERN_ERR "EXTID,line %d passed!\n",__LINE__);		CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0EID0))+offset, id&0xff, ARG_UNUSED );		CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0EID8))+offset, (id>>8)&0xff, ARG_UNUSED );					CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0SIDL)), ((id>>16)&0x3)|0x08, ARG_UNUSED );	}	// Set the data length	CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0DLC))+offset, DataLen, ARG_UNUSED );	// fill the data	if( DataLen>8 )		DataLen = 8;	for( i=0; i<DataLen; i++ ){		CAN_SPI_CMD( SPI_CMD_WRITE, TOLONG(&(MCP2510_MAP->TXB0D0))+offset+i, data[i], ARG_UNUSED );	}	// initiate transmit	i = 0;	while( CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->TXB0CTRL))+offset, ARG_UNUSED, ARG_UNUSED )&0x08 ){		i++;		if(i == 1000)printk("Please connect the CAN PORT with wire.");	}	printk("HELLO,jupm over error!!\n");	CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->TXB0CTRL))+offset, 0x08, 0x08 );}/* Receive data *//* * RxBuf		: The receive buffer from which the data is get * IdType		: Identifier type of the data frame ( STANDID, EXTID ) * id		: The identifier of the received frame * DataLen	: The number of bytes received * data		: The received data */void MCP2510_RX( int RxBuf, int *IdType, unsigned int *id, int *DataLen, char *data ){	unsigned int flag;	int offset, i;	//printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	switch( RxBuf ){		case RXBUF0:			flag = 0x1;			offset = 0x00;			break;		case RXBUF1:			flag = 0x2;			offset = 0x10;			break;	}	// wait for a frame to com	while( !(CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->CANINTF)), ARG_UNUSED, ARG_UNUSED )&flag) );	// Get the identifier	if( CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0SIDL))+offset, ARG_UNUSED, ARG_UNUSED )&0x08 ){		// Extended identifier		if( IdType )			*IdType = EXTID;		if( id ){			*id = (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0SIDL))+offset, ARG_UNUSED, ARG_UNUSED )&0x3)<<16;			*id |= (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0EID8))+offset, ARG_UNUSED, ARG_UNUSED ))<<8;			*id |= (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0EID0))+offset, ARG_UNUSED, ARG_UNUSED ));		}	}else{		// Standard identifier		if( IdType )			*IdType = STANDID;		if( id ){			*id = (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0SIDH))+offset, ARG_UNUSED, ARG_UNUSED ))<<3;			*id |= (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0SIDL))+offset, ARG_UNUSED, ARG_UNUSED ))>>5;		}	}	// Get the data frame lenth	if( DataLen )		*DataLen = (CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0DLC))+offset, ARG_UNUSED, ARG_UNUSED )&0xf);	// Get the data	for( i=0; DataLen&&(i<*DataLen)&&data; i++ ){		data[i] = CAN_SPI_CMD( SPI_CMD_READ, TOLONG(&(MCP2510_MAP->RXB0D0))+offset+i, ARG_UNUSED, ARG_UNUSED );	}	// clear the receive int flag	CAN_SPI_CMD( SPI_CMD_BITMOD, TOLONG(&(MCP2510_MAP->CANINTF)), flag, 0x00 );	}/* * Atomicly increment an index into shortp_in_buffer */static inline void incr_buffer_pointer(volatile unsigned long*index, int delta, int i){	unsigned long newvalue = *index + delta;	//printk(KERN_ERR "hello,enter %s\n",__FUNCTION__);	barrier ();  /* Don't optimize these two together */	*index = (newvalue >= (Device[i]->RecvBuf + BUF_SIZE)) ? Device[i]->RecvBuf : newvalue;}//add irqreturn_t fla

⌨️ 快捷键说明

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