LINUX-S3C2440-SJA1000驱动程序-笔记
/**************************************************************************************/ /*文件 program_22_1.c */ /*SJA1000驱动程序 */ /*************************************************************************************/ #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 <asm/hardware.h> /*这里包含了所有寄存器地址映射方式,有了这个头文件,CPU所有的寄存器都可以通过宏来实现 */ #include <asm/arch/cpu_s3c2440.h> #include <linux/interrupt.h> #include "candriver.h" /*这个头文件这里没有给出,包含驱动的私有变量和方法。*/ #define FAIL 0 #define SUCCESS 1 #define DEVICE_NAME "SJACAN" #define MAX_NR_FRAMES 100 /*允许接受的最大帧数目,据此定义缓冲的大小*/ unsigned char Receive(unsigned char *RCdata); void Transmit(unsigned char *TXdata); int log_flag = 1; // 0 -- stop buffer CAN frames. 1 -- start buffer CAN frames. struct rec { unsigned char databuf[13 * MAX_NR_FRAMES]; /*每一帧的数据是13个*/ 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*13],13); /*从rd_buf.databuf[rd_buf.start*13]开始读取数据,一次读取一帧=13个字节 */ rd_buf.start = ++rd_buf.start % MAX_NR_FRAMES; /*改变rd_buf.start的位置,指向下一帧*/ } void in_rd_buf(unsigned char *buf) { if(is_full_rd_buf()) return; /*如果满,返回*/ memcpy(&rd_buf.databuf[rd_buf.end*13],buf,13); /*从rd_buf.databuf[rd_buf.end*13]开始写数据,一次写一帧=13字节*/ rd_buf.end = ++rd_buf.end % MAX_NR_FRAMES; /*改变 rd_buf.end的位置,指向下一帧*/ } int intialize_can1(void) { CAN_STRUCT can1; UI i; //初始化can1 canReset(); /*因为SJA1000的地址数据复用,所以用一个CPLD对其时序做一个逻辑转换*/ //对SJA1000进行硬件重置 for(i=0;i<4;i++) { can1.acc_code[i]=0x00; /*设置acc掩码*/ can1.acc_mask[i]=0xff; } can1.bt0=0x03; /*波特率*/ can1.bt1=0x1c; if(canConfig(can1)==FAIL) /*如果设置错误,返回-1*/ { return -1; } //can1开始运行 canNormalRun(); //向寄存器CMR写入0x04就能清除接收缓冲中的数据 pokeb(SEG1,CMR,0x04); /*release receive buffer*/ peekb(SEG1,ALC); peekb(SEG1,ECC); return 0; } static irqreturn_t sja1000_can_irq(int irq, void *dev_id, struct pt_regs *regs) { unsigned char buf[13]; int intrkind,s; /*读中断寄存器状态*/ intrkind=peekb(SEG1,IR);//read the interrupt status printk("can1 get data!\n"); if((intrkind & 0x01) == 0)/*not receive interrupt*/ /*没有接收中断产生*/ { goto out; } Receive(buf); if(log_flag) in_rd_buf(buf); //buffer this frame /*将这一帧数据复制到接收缓冲中*/ peekb(SEG1,IR); pokeb(SEG1,CMR,0x04); /*release receive buffer*/ /*释放接收缓冲*/ s=peekb(SEG1,ALC); s=peekb(SEG1,ECC); return IRQ_HANDLED; out: pokeb(SEG1,CMR,0x04); //clear sja receive buffer in order to clear it's INT signal /*清除接收缓冲以便清除接手中断*/ return IRQ_NONE; } /*------------------------------------------------------------*/ unsigned char Receive(unsigned char *RCdata) { int i=16; /*接收缓冲地址是从16开始的*/ int j=0; unsigned char sr =peekb(SEG1,SR); /*读状态寄存器*/ for(;j<13;i++,j++){ RCdata[j] = peekb(SEG1,i); /*复制13个数据到内存*/ } return sr; } void Transmit(unsigned char *TXdata) { int i=16; /*发送缓冲的地址从16开始*/ int j=0; int MAXWAIT=1000; /*最大等待时间,总线可能忙*/ do{ // printk("xxxxxxxxxxxx\n"); MAXWAIT--; if (MAXWAIT==0) { printk("send fail!\n"); return;} }while( !(peekb(SEG1,SR)&0x04) ); /*读出状态寄存器的值,是否可以发送*/ for(;j<13;i++,j++){ pokeb(SEG1,i,TXdata[j]); /*如果可以发,就把数据从内存复制到SJA1000的发送缓冲中去*/ } pokeb(SEG1,CMR,0x01); /*写0x01给CMR,发送*/ } static ssize_t can_read(struct file *filep,char *buffer,size_t length,loff_t *ppos) { int total = 0; while(1){ if(total >= length) /*如果给定长度小于0,或者已将给定长度的数据读出去,就跳出*/ break; if(is_empty_rd_buf()) /*如果接收缓冲是空,跳出*/ break; out_rd_buf(buffer+total); /*读出接收缓冲里的数据*/ total+=13; /*每完成一次+13*/ } 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[13]; /*临时数组,用来存放发送数据*/ printk("the data to be sended by can1 is :\n"); for(i=0;i<13;i++){ printk("[%d]=%x ",i,buffer[i]); } printk("\n"); while(total+13 <= length){ memcpy(TXdata,buffer+total,13); /*将待发送数据复制到临时数组中*/ Transmit(TXdata); /*发送*/ total += 13; } return total; } /*------------------------------------------------------------------*/ 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 SJA_IOCTL_WRITE: copy_from_user(&sja_reg_data,(void *)arg,sizeof(struct sja_reg)); 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); pokeb(SEG1,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)); printk("sja_reg_addr=%x\n",sja_reg_data.sja_reg_addr); sja_reg_data.sja_reg_value = peekb(SEG1,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) { return 0; } static int can_release(struct inode *inode, struct file *file) { return 0; } struct file_operations fops = { owner: THIS_MODULE, open: can_open, read: can_read, write: can_write, ioctl: can_ioctl, release: can_release, /* a.k.a. close */ }; static void s3c2440_GPIO_init(void) { /*初始化CPU的GPIO口*/ Set_external_irq(IRQ_CAN,EXT_RISING_EDGE,GPIO_PULLUP_DIS); /*分配外部中断6,上升沿有效,下拉有效*/ delay(1000); } /*----------------init for module driver-----------------*/ int __init sja1000_init(void) { int a,ret; /*映射CAN的SJA1000物理地址*/ SEG1=ioremap((0x14000000+(0xDA000<<2)),128); /*硬件RESET的地址*/ SEG3=SEG1+(0x101<<2); /*初始化CAN寄存器*/ a=intialize_can1(); /*是否初始化成功,从打印的消息可以看出来*/ if(a==0){ s3c2440_GPIO_init(); /*申请中断号*/ ret=request_irq(IRQ_GPIO(92),&sja1000_can_irq,SA_INTERRUPT,"can1_irq",NULL); if(ret < 0) { printk ("%s device failed with %d\n","Sorry, registering the IRQ", ret); return ret; /*失败就退出*/ } delay(1000); /*申请设备号*/ ret = register_chrdev(126, DEVICE_NAME, &fops); if (ret < 0) { printk ("%s device failed with %d\n","Sorry, registering the character", ret); return ret; } delay(1000); printk("can1_sja1000 driver init ok!\n"); return 0; } else { printk("can1_sja1000 driver init fail!\n"); return -1; } } /* Cleanup - undid whatever init_module did */ void __exit sja1000_exit(void) { int ret; /*再次重置CAN*/ canReset(); /*注销中断号*/ free_irq(IRQ_GPIO(92), NULL); /*注销映射地址*/ iounmap(SEG1); /*注销设备号*/ ret = unregister_chrdev(126, DEVICE_NAME); if (ret < 0) printk("Error in unregister_chrdev: %d\n", ret); } module_init(sja1000_init); module_exit(sja1000_exit);
作者:子鱼
出处:https://www.yiboard.com
本文版权归作者和一板网电子技术论坛共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。