📄 sja1000.c
字号:
#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/fs.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/ioport.h>#include <linux/poll.h>#include <linux/delay.h>#include "sja1000.h"#define DEVICE_NAME "SJACAN"unsigned char Receive(unsigned char *RCdata);void Transmit(unsigned char *TXdata);unsigned SJA1000_READ(unsigned sja_reg_addr);void SJA1000_WRITE(unsigned sja_reg_addr, unsigned value);unsigned long SJA1000_DATA_VBASE=0;unsigned long SJA1000_ADDR_VBASE=0;int log_flag = 1; // 0 -- stop buffer CAN frames. 1 -- start buffer CAN frames.#define MAX_NR_FRAMES 100struct rec{ unsigned char databuf[11 * MAX_NR_FRAMES]; int start,end; /*0,1,2,...9*/} rd_buf;void init_rd_buf(){ rd_buf.start = 0; rd_buf.end = 0;}int is_empty_rd_buf(){ return (rd_buf.start == rd_buf.end);}int is_full_rd_buf(){ return (rd_buf.start == (rd_buf.end+1) % MAX_NR_FRAMES);}void out_rd_buf(unsigned char *buf){ if(is_empty_rd_buf()) return; memcpy(buf, &rd_buf.databuf[rd_buf.start*11],11); rd_buf.start = ++rd_buf.start % MAX_NR_FRAMES;}void in_rd_buf(unsigned char *buf){ if(is_full_rd_buf()) return; memcpy(&rd_buf.databuf[rd_buf.end*11],buf,11); rd_buf.end = ++rd_buf.end % MAX_NR_FRAMES;}void sja1000_can_irq(int irq, void *dev_id, struct pt_regs *regs){ unsigned char buf[11]; int intrkind; intrkind=SJA1000_READ(SJA1000_IR);//read the interrupt status if(intrkind & 0x01 == 0)/*not receive interrupt*/ { goto out; } Receive(buf); //printk("int1 : %d %d %d %d %d %d %d %d %d %d %d\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10]); if(log_flag) in_rd_buf(buf); //buffer this frameout: SJA1000_WRITE(SJA1000_CMR,4); //clear sja receive buffer in order to clear it's INT signal //*(volatile unsigned long*)(MCF_MBAR + 0x20) |= 0x80000000;//clear pending bit //clear EPP interrupt}/*-------------------------------------------------------------------*/unsigned SJA1000_READ(unsigned sja_reg_addr){ unsigned value; SJA1000_SET_AEN; writeb(sja_reg_addr,SJA1000_ADDR_VBASE); SJA1000_CLR_AEN; value=readb(SJA1000_DATA_VBASE); return value;}void SJA1000_WRITE(unsigned sja_reg_addr, unsigned value){ SJA1000_SET_AEN; writeb(sja_reg_addr,SJA1000_ADDR_VBASE); SJA1000_CLR_AEN; writeb(value,SJA1000_DATA_VBASE); }/*------------------------------------------------------------*/unsigned char Receive(unsigned char *RCdata){ int i=16; int j=0; unsigned char sr = SJA1000_READ(SJA1000_SR); for(;j<11;i++,j++){ RCdata[j] = SJA1000_READ(i); } SJA1000_WRITE(SJA1000_CMR,0x04); return sr; }void Transmit(unsigned char *TXdata){ int i=16; int j=0; do{ printk("xxxxxxxxxxxx\n"); }while( !(SJA1000_READ(SJA1000_SR)&0x04) ); for(;j<11;i++,j++){ SJA1000_WRITE(i,TXdata[j]); printk("TXdata[%d]=%d ",j,TXdata[j]); } SJA1000_WRITE(SJA1000_CMR,0x01);//0x01); }/*------------------------------------------------------------------*/static int can_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ int error, n, rc = 0; struct sja_reg sja_reg_data;// = 0; switch (cmd) {// case QSPIIOCS_LOGCANFRAMES:// log_flag = arg;// break; case SJA_IOCTL_WRITE: copy_from_user(&sja_reg_data,(void *)arg,sizeof(struct sja_reg)); //sja_reg_data = (struct sja_reg*)arg; //error = verify_area(VERIFY_READ, sja_reg_data, // sizeof(struct sja_reg)); //if (error) // return error; printk("write_sja_reg_addr=%x\n",sja_reg_data.sja_reg_addr); printk("write_sja_reg_value=%x\n",sja_reg_data.sja_reg_value); SJA1000_WRITE(sja_reg_data.sja_reg_addr, sja_reg_data.sja_reg_value); break; case SJA_IOCTL_READ: printk("enter read\n"); copy_from_user(&sja_reg_data,(void *)arg,sizeof(struct sja_reg)); //sja_reg_data = (struct sja_reg*)arg; printk("sja_reg_addr=%x\n",sja_reg_data.sja_reg_addr); //error = verify_area(VERIFY_READ, sja_reg_data, // sizeof(struct sja_reg)); //if (error) //return error; sja_reg_data.sja_reg_value = SJA1000_READ(sja_reg_data.sja_reg_addr); printk("sja_reg_value=%x\n",sja_reg_data.sja_reg_value); copy_to_user((void *)arg,&sja_reg_data,sizeof(struct sja_reg)); break; default: rc = -EINVAL; break; } return rc;}static int can_open(struct inode *inode, struct file *file){ MOD_INC_USE_COUNT; return 0;}static int can_release(struct inode *inode, struct file *file){ MOD_DEC_USE_COUNT; return 0;}static loff_t can_llseek(struct file *filep, loff_t off, int mod){ return off;}/*---------------------------------------------------*/static ssize_t can_read(struct file *filep,char *buffer,size_t length,loff_t *ppos){ int total = 0;// down(&sem); be careful! while(1){ if(total >= length) break; if(is_empty_rd_buf()) break; out_rd_buf(buffer+total); total+=11; }// up(&sem); return total;}static ssize_t can_write(struct file *filep,const char *buffer,size_t length, loff_t *ppos){ int total = 0,i; unsigned char TXdata[11];// down(&sem);/* memcpy(dbuf, buffer, length);*/ for(i=0;i<11;i++){ printk("[%d]=%d ",i,buffer[i]); } printk("\n"); while(total+11 <= length){ memcpy(TXdata,buffer+total,11); Transmit(TXdata); total += 11; } // up(&sem); return total;}unsigned int can_poll(struct file *filep, struct poll_table_struct *table){ unsigned int mask = 0; if(! is_empty_rd_buf() ) mask = POLLIN; return mask; }struct file_operations fops = { owner: THIS_MODULE, read: can_read, poll: can_poll, llseek: can_llseek, write: can_write, ioctl: can_ioctl, open: can_open, release: can_release, /* a.k.a. close */};void Egpio_Init(void){ unsigned int uiPADDR, uiPADR,config; uiPADDR = inl(GPIO_PADDR) | 0x10;//egpio4 outl( uiPADDR, GPIO_PADDR ); uiPADR = inl(GPIO_PADR) | 0x10;//outdata is 1: 4 outl( uiPADR, GPIO_PADR ); uiPADDR = inl(GPIO_PADDR) & 0xdf;//egpio5 is input outl( uiPADDR, GPIO_PADDR ); config=inl(GPIO_AINTEN) & 0xdf; outl(config,GPIO_AINTEN); config=inl(GPIO_AINTTYPE1) & 0xdf; outl(config,GPIO_AINTTYPE1); config=inl(GPIO_AINTTYPE2) & 0xdf; outl(config,GPIO_AINTTYPE2); config=inl(GPIO_AEOI) | 0x20; outl(config,GPIO_AEOI); config=inl(GPIO_AINTEN) | 0x20; outl(config,GPIO_AINTEN); config = inl(SMCBCR2); printk ("SMCBCR2=0X%X\n",config); config &=0xcfffffff; outl(config,SMCBCR2); config = inl(SMCBCR2); printk ("SMCBCR2=0X%X\n",config);}#define MAXWAIT 2000int InitializeSJA(void){ int i,j,status=0; unsigned char txbuffer[11]={0,0,0,0,8,255,255,4,255,4},rxbuffer[11]={0}; txbuffer[0]=0x08; txbuffer[1]=30; txbuffer[2]=70; txbuffer[3]=5; for(i=0;i<MAXWAIT;i++) { j=SJA1000_READ(SJA1000_MOD); printk ("SJA1000_MOD_00 0X%X\n",j); SJA1000_WRITE(SJA1000_MOD,0x01); //reset mode j=SJA1000_READ(SJA1000_MOD); printk ("SJA1000_MOD_01 0X%X\n",j); if(j&0x01)//(SJA1000_READ(SJA1000_MOD)&0x01) break; } if(i==MAXWAIT) { printk ("time out\n"); return -1; } SJA1000_WRITE(SJA1000_BTR0,0X0d); SJA1000_WRITE(SJA1000_BTR1,0X22); //125KHz SJA1000_WRITE(SJA1000_OCR,0xdA); //output control 1a SJA1000_WRITE(SJA1000_CDR,0XCf); //PeliCAN mode,bypass the input comparator //disable clkout out SJA1000_WRITE(SJA1000_ACR0,0xff); SJA1000_WRITE(SJA1000_ACR1,0xff); SJA1000_WRITE(SJA1000_ACR2,0xff); SJA1000_WRITE(SJA1000_ACR3,0xff); SJA1000_WRITE(SJA1000_AMR0,0xff); SJA1000_WRITE(SJA1000_AMR1,0xff); SJA1000_WRITE(SJA1000_AMR2,0xff); SJA1000_WRITE(SJA1000_AMR3,0xff); SJA1000_WRITE(SJA1000_INT_IER,0XFF); //0X00 disable interrupt 0x01 enable receive interrupt SJA1000_READ(SJA1000_IR); //clear the interrupt register(except receive interrupt bit) SJA1000_WRITE(SJA1000_CMR,0x04);//clear receive buffer. if no other message then //clear receive interrupt bit printk ("--------------------------------------\n"); for(i=0;i<MAXWAIT;i++) { SJA1000_WRITE(SJA1000_MOD,0x00); if( ! (SJA1000_READ(SJA1000_MOD)&0x01) ) break; } if(i==MAXWAIT) return -1; /* status=SJA1000_READ(SJA1000_SR); printk("pre_status=0X%X\n",status); printk("pre_rxbuffer:"); for(i=0;i<11;i++){ printk(" %d",rxbuffer[i]);} printk("\n"); while(1) { status=SJA1000_READ(SJA1000_SR); if(status & 0x01) { status=SJA1000_READ(SJA1000_IR); printk("SJA1000_IR=0X%X\n",status); status=Receive(rxbuffer); printk("status=0X%X\n",status); for(i=0;i<11;i++) { printk(" %d",rxbuffer[i]); } printk("\n"); Transmit(txbuffer); } } */ return 0;}/*----------------init for module driver-----------------*/int __init sja1000_init(void){ int ret; Egpio_Init(); ret=request_irq(IRQ_GPIO,sja1000_can_irq,SA_INTERRUPT,"can_irq",NULL); if(ret < 0) { printk ("%s device failed with %d\n","Sorry, registering the IRQ", ret); return ret; } ret = register_chrdev(CAN_MAJOR, DEVICE_NAME, &fops); if (ret < 0) { printk ("%s device failed with %d\n","Sorry, registering the character", ret); return ret; } SJA1000_DATA_VBASE =ioremap(nCS2_PHYBASE,4); SJA1000_ADDR_VBASE =ioremap(nCS7_PHYBASE,4); InitializeSJA(); init_rd_buf(); //init read buffer printk("sja1000 driver init ok.\n"); return 0;} /* Cleanup - undid whatever init_module did */void __exit sja1000_exit(void){ int ret; free_irq(IRQ_GPIO, NULL); iounmap(SJA1000_DATA_VBASE); iounmap(SJA1000_ADDR_VBASE); ret = unregister_chrdev(CAN_MAJOR, DEVICE_NAME); if (ret < 0) printk("Error in unregister_chrdev: %d\n", ret);}module_init(sja1000_init);module_exit(sja1000_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -