📄 s3c2410can.c
字号:
MCP2510_WriteBits(RXB0CTRL, (RXB_BUKT|RXB_RX_ANY|RXB_RXRTR), 0xFF); MCP2510_WriteBits(RXB1CTRL, RXB_RX_ANY, 0xFF); }}static int ntxbuffer=0;static inline void MCP2510_canTxBuffer(void){ switch(ntxbuffer){ case 0: MCP2510_transmit(TXB0CTRL); ntxbuffer=1; break; case 1: MCP2510_transmit(TXB1CTRL); ntxbuffer=2; break; case 2: MCP2510_transmit(TXB2CTRL); ntxbuffer=0; break; }}static inline void MCP2510_canWrite(PCanData data){ MCP2510_Write_Can(ntxbuffer, data); MCP2510_canTxBuffer();}static inline void MCP2510_canWriteData(char *pbuffer, int nbuffer){ MCP2510_Write_CanData(ntxbuffer, pbuffer, nbuffer); MCP2510_canTxBuffer();}static inline void MCP2510_canWriteRTR(void){ MCP2510_Write_CanRTR(ntxbuffer); MCP2510_canTxBuffer();}static void s3c2410_isr_mcp2510(int irq, void *dev_id, struct pt_regs *reg){ unsigned char byte; spin_lock_irq(&lock); printk("enter interrupt!\n"); byte=MCP2510_Read(CANINTF); if(byte & RX0INT){ MCP2510_Read_Can(3,&(mcp2510dev.MCP2510_Candata[mcp2510dev.nCanRevpos])); NextCanDataPos(mcp2510dev.nCanRevpos); printk("mcp2510dev0.nCanRevpos= %d\n", mcp2510dev.nCanRevpos); printk("mcp2510dev0.nCanReadpos= %d\n", mcp2510dev.nCanReadpos); MCP2510_WriteBits(CANINTF, ~RX0INT, RX0INT); // Clear interrupt } if(byte & RX1INT){ MCP2510_Read_Can(4,&(mcp2510dev.MCP2510_Candata[mcp2510dev.nCanRevpos])); MCP2510_WriteBits(CANINTF, ~RX1INT, RX1INT); // Clear interrupt NextCanDataPos(mcp2510dev.nCanRevpos); printk("mcp2510dev1.nCanRevpos= %d\n", mcp2510dev.nCanRevpos); printk("mcp2510dev1.nCanReadpos= %d\n", mcp2510dev.nCanReadpos); } if(byte & (RX0INT|RX1INT)){ wake_up_interruptible(&(mcp2510dev.wq)); } spin_unlock_irq(&lock);}static int init_MCP2510(CanBandRate bandrate){ unsigned char i,j,a; MCP2510_Reset(); MCP2510_SetBandRate(bandrate,FALSE); MCP2510_Write(CANINTE, NO_IE); MCP2510_Write_Can_ID(RXM0SIDH, 0, TRUE); MCP2510_Write_Can_ID(RXM1SIDH, 0, TRUE); MCP2510_Write_Can_ID(RXF0SIDH, 0, 0); MCP2510_Write_Can_ID(RXF1SIDH, 0, 0); MCP2510_Write_Can_ID(RXF2SIDH, 0, 0); MCP2510_Write_Can_ID(RXF3SIDH, 0, 0); MCP2510_Write_Can_ID(RXF4SIDH, 0, 0); MCP2510_Write_Can_ID(RXF5SIDH, 0, 0); MCP2510_Write_Can_ID(TXB0SIDH, 123, 0); MCP2510_Write_Can_ID(TXB1SIDH, 100, 0); MCP2510_Write_Can_ID(TXB2SIDH, 111, 0); MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLKEN | CLK1); a = TXB0CTRL; for (i = 0; i < 3; i++) { for (j = 0; j < 14; j++) { MCP2510_Write(a, 0); a++; } a += 2; } MCP2510_Write(RXB0CTRL, 0); MCP2510_Write(RXB1CTRL, 0); MCP2510_Write(BFPCTRL, 0x3C); return 0;}static void MCP2510_SetFilter(PCanFilter pfilter){ MCP2510_Write(MCP2510REG_CANCTRL, MODE_CONFIG); MCP2510_Write(CANINTE, NO_IE); if(!pfilter){ MCP2510_Write_Can_ID(RXM0SIDH, 0, TRUE); MCP2510_Write_Can_ID(RXM1SIDH, 0, TRUE); MCP2510_Write_Can_ID(RXF0SIDH, 0, 0); MCP2510_Write_Can_ID(RXF1SIDH, 0, 0); MCP2510_Write_Can_ID(RXF2SIDH, 0, 0); MCP2510_Write_Can_ID(RXF3SIDH, 0, 0); MCP2510_Write_Can_ID(RXF4SIDH, 0, 0); MCP2510_Write_Can_ID(RXF5SIDH, 0, 0); } else{ MCP2510_Write_Can_ID(RXM0SIDH, pfilter->Mask, TRUE); MCP2510_Write_Can_ID(RXM1SIDH, pfilter->Mask, TRUE); MCP2510_Write_Can_ID(RXF0SIDH, pfilter->Filter, pfilter->IsExt); MCP2510_Write_Can_ID(RXF1SIDH, pfilter->Filter, pfilter->IsExt); MCP2510_Write_Can_ID(RXF2SIDH, pfilter->Filter, pfilter->IsExt); MCP2510_Write_Can_ID(RXF3SIDH, pfilter->Filter, pfilter->IsExt); MCP2510_Write_Can_ID(RXF4SIDH, pfilter->Filter, pfilter->IsExt); MCP2510_Write_Can_ID(RXF5SIDH, pfilter->Filter, pfilter->IsExt); } if(mcp2510dev.loopbackmode) MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLKEN | CLK1); else MCP2510_Write(CLKCTRL, MODE_NORMAL| CLKEN | CLK1); MCP2510_Write(RXB0CTRL, 0); MCP2510_Write(RXB1CTRL, 0); MCP2510_Setup(pfilter);}static int s3c2410_mcp2510_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int flags;local_irq_save(flags); switch (cmd){ case UPCAN_IOCTRL_SETBAND: //set can bus band rate MCP2510_SetBandRate((CanBandRate)arg ,TRUE); mdelay(10); break; case UPCAN_IOCTRL_SETID: //set can frame id data MCP2510_Write_Can_ID(TXB0SIDH, arg, arg&UPCAN_EXCAN); MCP2510_Write_Can_ID(TXB1SIDH, arg, arg&UPCAN_EXCAN); MCP2510_Write_Can_ID(TXB2SIDH, arg, arg&UPCAN_EXCAN); break; case UPCAN_IOCTRL_SETLPBK: //set can device in loop back mode or normal mode if(arg){ MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLKEN | CLK1); mcp2510dev.loopbackmode=1; } else{ MCP2510_Write(CLKCTRL, MODE_NORMAL| CLKEN | CLK1); mcp2510dev.loopbackmode=0; } break; case UPCAN_IOCTRL_SETFILTER://set a filter for can device MCP2510_SetFilter((PCanFilter)arg); break; case UPCAN_IOCTRL_PRINTRIGISTER://set a filter for can device printGPE(); printSPI(); printRegisters(); break; } local_irq_restore(flags); printk("IO control command=0x%x\n", cmd); return 0;}/***************************************************************\* write and send Can data interface for can device file ** there are 2 mode for send data: ** 1, if write data size = sizeof(CanData) then send a full can frame ** 2, if write data size <=8 then send can data, ** we must set frame id first *\****************************************************************/static ssize_t s3c2410_mcp2510_write(struct file *file, const char *buffer, size_t count, loff_t * ppos){ char sendbuffer[sizeof(CanData)]; if(count==sizeof(CanData)){ //send full Can frame---frame id and frame data copy_from_user(sendbuffer, buffer, sizeof(CanData)); MCP2510_canWrite((PCanData)sendbuffer); printk("Send a Full Frame\n"); return count; } if(count>8) {printk("count>8"); return 0;} copy_from_user(sendbuffer, buffer, count); MCP2510_canWriteData(sendbuffer, count); printk("Send data size=%d\n", count); printk("data=%x,%x,%x,%x,%x,%x,%x,%x\n", sendbuffer[0],sendbuffer[1],sendbuffer[2],sendbuffer[3], sendbuffer[4],sendbuffer[5],sendbuffer[6],sendbuffer[7]); return count;}static int RevRead(CanData *candata_ret){ spin_lock_irq(&(mcp2510dev.lock)); memcpy(candata_ret, &(mcp2510dev.MCP2510_Candata[mcp2510dev.nCanReadpos]), sizeof(CanData)); NextCanDataPos(mcp2510dev.nCanReadpos); spin_unlock_irq(&(mcp2510dev.lock)); return sizeof(CanData);}static ssize_t s3c2410_mcp2510_read(struct file *filp, char *buffer, size_t count, loff_t *ppos){ CanData candata_ret; printk("run in s3c2410_mcp2510_read\n");retry: if (mcp2510dev.nCanReadpos != mcp2510dev.nCanRevpos) { int count; count = RevRead(&candata_ret); if (count) copy_to_user(buffer, (char *)&candata_ret, count); printk("read data size=%d\n", count); printk("id=%x, data=%x,%x,%x,%x,%x,%x,%x,%x\n", candata_ret.id, candata_ret.data[0], candata_ret.data[1], candata_ret.data[2], candata_ret.data[3], candata_ret.data[4], candata_ret.data[5], candata_ret.data[6], candata_ret.data[7]); return count; } else { if (filp->f_flags & O_NONBLOCK) { return -EAGAIN; } interruptible_sleep_on(&(mcp2510dev.wq)); if (signal_pending(current)){ return -ERESTARTSYS; } goto retry; } printk("read data size=%d\n", sizeof(candata_ret)); return sizeof(candata_ret);}static int s3c2410_mcp2510_open(struct inode *inode, struct file *file){ int i,j,a;//init_MCP2510(BandRate_250kbps); if(opencount==1) return -EBUSY; opencount++; memset(&mcp2510dev, 0 ,sizeof(mcp2510dev)); init_waitqueue_head(&(mcp2510dev.wq)); //Enable clock output MCP2510_Write(CLKCTRL, MODE_NORMAL| CLKEN | CLK1); // Clear, deactivate the three transmit buffers a = TXB0CTRL; for (i = 0; i < 3; i++) { for (j = 0; j < 14; j++) { MCP2510_Write(a, 0); a++; } a += 2; // We did not clear CANSTAT or CANCTRL } // and the two receive buffers. MCP2510_Write(RXB0CTRL, 0); MCP2510_Write(RXB1CTRL, 0); //Open Interrupt //MCP2510_Write(CANINTE, RX0IE|RX1IE); MCP2510_Write(CANINTE, RX0IE); MCP2510_Setup(NULL); MCP2510_OPEN_INT(); set_gpio_ctrl(GPIO_MCP2510_CS); MOD_INC_USE_COUNT; printk("device open\n"); return 0;}static int s3c2410_mcp2510_release(struct inode *inode, struct file *filp){ opencount--; MCP2510_Write(CANINTE, NO_IE); MCP2510_Write(CLKCTRL, MODE_LOOPBACK| CLKEN | CLK1); MCP2510_CLOSE_INT(); MOD_DEC_USE_COUNT; printk("device release\n"); return 0;}static struct file_operations s3c2410_fops = { owner: THIS_MODULE, write: s3c2410_mcp2510_write, read: s3c2410_mcp2510_read, ioctl: s3c2410_mcp2510_ioctl, open: s3c2410_mcp2510_open, release: s3c2410_mcp2510_release,};#ifdef CONFIG_DEVFS_FSstatic devfs_handle_t devfs_spi_dir, devfs_spiraw;#endifvoid SPI_Init(Void){ int index; GPGDAT |= 0xFFFFFFFB; CLKCON |= (1<<18); SPCON0 |= 0x00000018; SPPRE0=255; SPCON0 = 0x00000018; for( index = 0; index < 20; index++) SPTDAT0 = 0xFF;}static int __init s3c2410_mcp2510_init(void){ int ret; int flags; ret = register_chrdev(Major, DEVICE_NAME, &s3c2410_fops); if (ret < 0) { printk(DEVICE_NAME " can't get major number\n"); return ret; } printk("4"); Major = ret; GPEUP&=~(0x3800); GPEUP|=0x2000; GPECON=((GPECON&0xf03fffff)|0xa800000); SPI_Init(); set_gpio_ctrl(GPIO_MCP2510_CS); printk("1"); local_irq_save(flags); printk("2"); init_MCP2510(BandRate_250kbps); /* Register IRQ handlers */ printk("3"); //ret = set_external_irq(MCP2510_IRQ, EXT_LOWLEVEL, GPIO_PULLUP_DIS); ret = set_external_irq(MCP2510_IRQ, EXT_FALLING_EDGE, GPIO_PULLUP_EN); if (ret) return ret; local_irq_restore(flags); /* Enable touch interrupt */ ret = request_irq(MCP2510_IRQ, s3c2410_isr_mcp2510, SA_INTERRUPT, DEVICE_NAME, s3c2410_isr_mcp2510); if (ret) return ret; MCP2510_CLOSE_INT(); printk("5");#ifdef CONFIG_DEVFS_FS devfs_spi_dir = devfs_mk_dir(NULL, "can", NULL); devfs_spiraw = devfs_register(devfs_spi_dir, "0", DEVFS_FL_DEFAULT, Major, SPIRAW_MINOR, S_IFCHR | S_IRUSR | S_IWUSR, &s3c2410_fops, NULL);#endif printk(DEVICE_NAME " initialized\n"); return 0;}static void __exit s3c2410_mcp2510_exit(void){ printk(DEVICE_NAME " unloaded\n");}module_init(s3c2410_mcp2510_init);module_exit(s3c2410_mcp2510_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -