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

📄 s3c2410can.c

📁 mcp2510的spi驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/miscdevice.h>#include <linux/sched.h>#include <linux/delay.h>#include <linux/poll.h>#include <linux/spinlock.h>#include <linux/delay.h>#include <asm/hardware.h>#include "spi.h"#include "mcp2510.h"#include "can.h"#include <asm/arch/S3C2410.h>spinlock_t lock;/* debug macros */#undef DEBUG//#define DEBUG#ifdef DEBUG#define DPRINTK( x... )	printk("s3c2410can: " ##x)#else#define DPRINTK( x... )#endif/********************** MCP2510 Pin *********************************/#define MCP2510_IRQ		IRQ_EINT19	//IRQ_EINT6#define MCP2510_PIN_CS		(0x00000004)  //GPIO_G2#define GPIO_MCP2510_CS		(GPIO_MODE_OUT | GPIO_PULLUP_DIS | GPIO_G2)#define MCP2510_Enable()	do {GPGDAT &= ~MCP2510_PIN_CS;udelay(1000);}while(0);#define MCP2510_Disable()	do {GPGDAT |= MCP2510_PIN_CS;}while(0);#define MCP2510_OPEN_INT()		enable_irq(MCP2510_IRQ)		//added by wb#define MCP2510_CLOSE_INT()		disable_irq(MCP2510_IRQ)////////////////////////////////////////////////////////////////////////////// Start the transmission from one of the tx buffers.#define MCP2510_transmit(address)		do{MCP2510_WriteBits(address, TXB_TXREQ_M, TXB_TXREQ_M);}while(0)#define MCP2510_CanRevBuffer	128	//CAN接收缓冲区大小/********************** MCP2510 Candata *********************************/typedef struct {	CanData MCP2510_Candata[MCP2510_CanRevBuffer];	//recieve data buffer	int nCanRevpos;	//recieve buffer pos for queued events	int nCanReadpos;	//read buffer pos for queued events	int loopbackmode;	wait_queue_head_t wq;	spinlock_t lock;}Mcp2510_DEV;static Mcp2510_DEV mcp2510dev;#define NextCanDataPos(pos)		do{(pos)=((pos)+1>=MCP2510_CanRevBuffer? 0: (pos)+1);}while(0)#define DEVICE_NAME		"s3c2410can"#define SPIRAW_MINOR	1static int Major = 203;static int opencount=0;#define TRUE 1#define FALSE 0///////////////////////////////////////////////////////////////////static void printRegisters(void){  printk ("GPFCON:%x\tGPFUP:%x\tGPFDAT:%x\n",	  GPFCON, GPFUP, GPFDAT );  printk ("GPGCON:%x\tGPGUP:%x\tGPGDAT:%x\n",	  GPGCON, GPGUP, GPGDAT );  printk ("INTMOD:%x\tINTMSK:%x\tINTPND:%x\tSRCPND:%x\n",	  INTMOD, INTMSK, INTPND, SRCPND);  printk ("EXTINT0:%x\tEINTMASK:%x\tEINTPEND:%x\n",	  EXTINT0, EINTMASK, EINTPEND );}static void printGPE (void){  printk ("GPECON:%x\tGPEUP:%x\tGPEDAT:%x\n",	  GPECON, GPEUP, GPEDAT );}static void printSPI (void){ printk ("SPPRE0:%d\tSPCON0:%x\tSPSTA0:%x\n", SPPRE0, SPCON0, SPSTA0 );  printk ("SPTDAT0:%x\tSPRDAT0:%x\n", SPTDAT0, SPRDAT0 );  printk ("SPPIN0:%x\n", SPPIN0);}///////////////////////////////////////////////////////////////////////static void  SendSIOData(unsigned int data){	SPISend(data,0);}	static unsigned int ReadSIOData(){	return SPIRecv(0);	}static inline void MCP2510_Reset(void){	MCP2510_Enable();	SendSIOData(MCP2510INSTR_RESET);	MCP2510_Disable();}static void MCP2510_Write(int address, int value){	int flags;	local_irq_save(flags);	MCP2510_Enable();	SendSIOData(MCP2510INSTR_WRITE);	SendSIOData((unsigned char)address);	SendSIOData((unsigned char)value);	MCP2510_Disable();	local_irq_restore(flags);}static unsigned char MCP2510_Read(int address){	unsigned char result;	int flags;	local_irq_save(flags);	MCP2510_Enable();	SendSIOData(MCP2510INSTR_READ);	SendSIOData((unsigned char)address);	SendSIOData(0);	result=ReadSIOData();	MCP2510_Disable();	local_irq_restore(flags);	return result;}/*static unsigned char MCP2510_ReadStatus(void){	unsigned char result;	int flags;	local_irq_save(flags);	MCP2510_Enable();	SendSIOData(MCP2510INSTR_RDSTAT);	SendSIOData(0);	result=ReadSIOData();	MCP2510_Disable();	local_irq_restore(flags);	return result;}*/static void MCP2510_WriteBits( int address, int data, int mask ){	int flags;	local_irq_save(flags);	MCP2510_Enable();	SendSIOData(MCP2510INSTR_BITMDFY);	SendSIOData((unsigned char)address);	SendSIOData((unsigned char)mask);	SendSIOData((unsigned char)data);	MCP2510_Disable();	local_irq_restore(flags);}/*******************************************\*	序列读取MCP2510数据				*\*******************************************/static void MCP2510_SRead( int address, unsigned char* pdata, int nlength ){	int i;	int flags;	local_irq_save(flags);	MCP2510_Enable();	SendSIOData(MCP2510INSTR_READ);	SendSIOData((unsigned char)address);	for (i=0; i<nlength; i++) {		SendSIOData(0);		*pdata=ReadSIOData();		pdata++;	}	MCP2510_Disable();	local_irq_restore(flags);}/*******************************************\*	序列写入MCP2510数据				*\*******************************************/static void MCP2510_Swrite(int address, unsigned char* pdata, int nlength){	int i;	int flags;	local_irq_save(flags);	MCP2510_Enable();	SendSIOData(MCP2510INSTR_WRITE);	SendSIOData((unsigned char)address);	for (i=0; i < nlength; i++) {		SendSIOData((unsigned char)*pdata);		pdata++;	}	MCP2510_Disable();	local_irq_restore(flags);}/************************************************************\*	设置MCP2510 CAN总线波特率						**	参数: bandrate为所设置的波特率				**			IsBackNormal为是否要返回Normal模式		*\************************************************************/static void MCP2510_SetBandRate(CanBandRate bandrate, int IsBackNormal){		MCP2510_Write(MCP2510REG_CANCTRL, MODE_CONFIG);	switch(bandrate){	case BandRate_125kbps:		MCP2510_Write(CNF1, SJW1|BRP4);	//Synchronization Jump Width Length =1 TQ		MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7		MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4		break;	case BandRate_250kbps:		MCP2510_Write(CNF1, SJW1|BRP2);	//Synchronization Jump Width Length =1 TQ		MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7		MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4		break;	case BandRate_500kbps:		MCP2510_Write(CNF1, SJW1|BRP1);	//Synchronization Jump Width Length =1 TQ		MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG4<<3)|SEG7); // Phase Seg 1 = 4, Prop Seg = 7		MCP2510_Write(CNF3, SEG4);// Phase Seg 2 = 4		break;	case BandRate_1Mbps:		MCP2510_Write(CNF1, SJW1|BRP1);	//Synchronization Jump Width Length =1 TQ		MCP2510_Write(CNF2, BTLMODE_CNF3|(SEG3<<3)|SEG2); // Phase Seg 1 = 2, Prop Seg = 3		MCP2510_Write(CNF3, SEG2);// Phase Seg 2 = 1		break;	}	if(IsBackNormal){		//Enable clock output		MCP2510_Write(CLKCTRL, MODE_NORMAL | CLKEN | CLK1);	}}/*******************************************\*	读取MCP2510 CAN总线ID				**	参数: address为MCP2510寄存器地址**			can_id为返回的ID值			**	返回值								**	TRUE,表示是扩展ID(29位)			**	FALSE,表示非扩展ID(11位)		*\*******************************************/static int MCP2510_Read_Can_ID( int address, __u32* can_id){	__u32 tbufdata;	unsigned char* p=(unsigned char*)&tbufdata;	MCP2510_SRead(address, p, 4);	*can_id = (tbufdata<<3)|((tbufdata>>13)&0x7);	*can_id &= 0x7ff;	if ( (p[MCP2510LREG_SIDL] & TXB_EXIDE_M) ==  TXB_EXIDE_M ) {		*can_id = (*can_id<<2) | (p[MCP2510LREG_SIDL] & 0x03);		*can_id <<= 16;		*can_id |= tbufdata>>16;		return TRUE;	}	return FALSE;}/***********************************************************\*	读取MCP2510 接收的数据							**	参数: 													**		nbuffer为第几个缓冲区可以为3或者4		**		CanData为CAN数据结构							*\***********************************************************/static void MCP2510_Read_Can(unsigned char nbuffer, PCanData candata){	unsigned char mcp_addr = (nbuffer<<4) + 0x31, ctrl;	int IsExt;	char dlc;	IsExt=MCP2510_Read_Can_ID( mcp_addr, &(candata->id));	ctrl=MCP2510_Read(mcp_addr-1);	dlc=MCP2510_Read( mcp_addr+4);	if ((ctrl & 0x08)) {		candata->rxRTR = TRUE;	}	else{		candata->rxRTR = FALSE;	}	dlc &= DLC_MASK;	MCP2510_SRead(mcp_addr+5, candata->data, dlc);	candata->dlc=dlc;}/*******************************************\*	设置MCP2510 CAN总线ID				**	参数: address为MCP2510寄存器地址**			can_id为设置的ID值			**			IsExt表示是否为扩展ID	*\*******************************************/static void MCP2510_Write_Can_ID(int address, __u32 can_id, int IsExt){	__u32 tbufdata;	if (IsExt) {		can_id &= 0x1fffffff;	//29位		tbufdata=can_id &0xffff;		tbufdata<<=16;		tbufdata|=((can_id>>(18-5))&(~0x1f));		tbufdata |= TXB_EXIDE_M;	}	else{		can_id&=0x7ff;	//11位		tbufdata= (can_id>>3)|((can_id&0x7)<<13);	}	MCP2510_Swrite(address, (unsigned char*)&tbufdata, 4);	MCP2510_Read_Can_ID(address, &tbufdata);	printk("write can id=%x, result id=%x\n",can_id, tbufdata);}static void MCP2510_Write_Can( unsigned char nbuffer, PCanData candata){	unsigned char dlc;	unsigned char mcp_addr = (nbuffer<<4) + 0x31;	dlc=candata->dlc;	MCP2510_Swrite(mcp_addr+5, candata->data, dlc);  // write data bytes	MCP2510_Write_Can_ID( mcp_addr, candata->id,candata->IsExt);  // write CAN id	if (candata->rxRTR)		dlc |= RTR_MASK;  // if RTR set bit in byte	MCP2510_Write((mcp_addr+4), dlc);            // write the RTR and DLC}static void MCP2510_Write_CanData( unsigned char nbuffer, char *pbuffer, int nsize){	unsigned char dlc;	unsigned char mcp_addr = (nbuffer<<4) + 0x31;	dlc=nsize&DLC_MASK;	//nbuffer must <= 8	MCP2510_Swrite(mcp_addr+5, pbuffer, dlc);  // write data bytes	MCP2510_Write((mcp_addr+4), dlc);            // write the RTR and DLC}static void MCP2510_Write_CanRTR( unsigned char nbuffer){	unsigned char dlc=0;	unsigned char mcp_addr = (nbuffer<<4) + 0x31;	dlc |= RTR_MASK;  // if RTR set bit in byte	MCP2510_Write((mcp_addr+4), dlc);            // write the RTR and DLC}static void MCP2510_Setup(PCanFilter pfilter){    	if(pfilter){	//有过滤器		MCP2510_WriteBits(RXB0CTRL, (RXB_BUKT|RXB_RX_STDEXT|RXB_RXRTR|RXB_RXF0), 0xFF);		MCP2510_WriteBits(RXB1CTRL, RXB_RX_STDEXT, 0xFF);	}	else{

⌨️ 快捷键说明

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