📄 s3c2410can.c
字号:
#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 + -