📄 obcanb.c
字号:
//中断设备程序的编写//1.编译开关://gcc -O2 -D__KERNEL__ -DMODULE -I/usr/src/linux/include -c example.c -o example.o//2.加载模快:// insmod example.o//3.卸载模快:// rmmod /************************* canb中断处理程序 *************************///设备名:canb,地址:D0000-D01FF//#define _debug //编译调试代码开关#include <asm/io.h>#define canb_ADDR 0xfb000000#define canb_MEM_LEN 0x200 //#define INTERRUPT 0x04 //使用5号中断#define MODULE_VERSION "1.0"#define MODULE_NAME "can_b_for_arm"#include <linux/module.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/proc_fs.h>#include <linux/string.h>#include <asm/arch/irqs.h>#define INTERRUPT IRQ_EINT3 //使用5号中断/*************************** can控制器 ***************************///1.错误代码定义#define EVerify 12 // 写入回读不同#define RESET_CAN_OK 13 // 复位成功#define RESET_CAN_ERROR 14 // 复位错误#define CAN_RESET 15 //#define CAN_DEBUG 16 //0XFF#define CAN_DEBUG_ERROR 17#define CAN_OK 11#define CAN_READ_NO_DATA 9 //无数据#define CAN_WRITE_BUSY 10 //写数据忙 //2.控制寄存器#define FlagRR 0x01 // 复位请求// 命令寄存器#define FlagCOS 0x08 // 清除超载#define FlagRRB 0x04 // 清除接收缓冲,允许接收#define FlagAT 0x02 // 中止发送#define FlagTR 0x01 // 发送请求//3.状态寄存器#define FlagBS 0x80 // 总线脱离#define FlagES 0x40 // 错误#define FlagTS 0x20 // 正在发送#define FlagRS 0x10 // 正在接收#define FlagTCS 0x08 // 发送完成#define FlagTBS 0x04 // 发送缓冲可用#define FlagDO 0x02 // 数据超载#define FlagRBS 0x01 // 接收缓冲有效//4.中断寄存器#define FlagWUI 0x10 // 唤醒中断#define FlagOI 0x08 // 超载中断#define FlagEI 0x04 // 错误中断#define FlagTI 0x02 // 发送中断#define FlagRI 0x01 // 接收中断//5.速度#define BTR0_125K 0x03 // 波特率=125Kbps(16MHZ),(3+1)*2=8#define BTR1_125K 0x1C // TSEG1=0x0C=>13,TSEG2=0x01=>2,1+13+2=16#define BTR0_500K 0x01 // 波特率=500Kbps(16MHZ),(1+1)*2=4#define BTR1_500K 0x14 // TSEG1=0x04=>5,TSEG2=0x01=>2,1+5+2=8#define BTR0_1M 0x00 // 波特率=1Mbps(16MHZ),(1)*2=2#define BTR1_1M 0x14 // TSEG1=0x04=>5,TSEG2=0x01=>2,1+5+2=8#define BTR0_Data BTR0_500K#define BTR1_Data BTR1_500K//6.其他#define DLCMask 0x0F // DLC屏蔽#define IDLMask 0xE0 // D低字节高3位屏蔽#define IDLShift 5 // ID低字节高3位右对齐移位计数#define TimeReset 100 // 复位时间,毫秒char volatile *OUTP;#define outb(X,Y) OUTP=(char *)(0xfb000000+Y);*OUTP=X;struct CanControl { unsigned char CR; //控制寄存器 unsigned char CMR;//命令寄存器 unsigned char SR; //状态寄存器 unsigned char IR;//中断寄存器 unsigned char ACR;//验收寄存器 unsigned char AMR;//屏蔽寄存器 unsigned char BTR0; unsigned char BTR1; unsigned char OCR; unsigned char TR; // 寄存器00..09 unsigned char TxDSCR[2],TxData[8];//发送ID,数据 10..19 unsigned char RxDSCR[2],RxData[8];//接收ID,数据 20..29 unsigned char XX30,CDR;//31 时钟驱动 30..31 // unsigned char XX32[0x0100-32],RST; //复位控制 0x0100} volatile *pcanb;#define FRAME_DATA_SIZE 10 //每帧大小(包括TxDSCR[2]、TxData[8]或RxDSCR[2]、RxData[8])#define IN_BUFFER_LEN FRAME_DATA_SIZE*200 //接受缓冲区大小:100帧static unsigned char canb_in_buffer[IN_BUFFER_LEN]; //接受缓冲区:指通过CAN接受的数据临时存放处,用户通过read函数读取该缓冲区static int canb_in_buf_head=0; //接受缓冲区头指针static int canb_in_buf_tail=0; //接受缓冲区尾指针static char canb_write_busy=0;//初始时置0,write后置1,发送中断产生时置0static unsigned long irqt_tx=0,irqt_rx=0;static unsigned char rcount; static struct proc_dir_entry *interrupt_canb_file;int canb_interruptcount = 0;char canb_flag=0;#include "filter.h"//中断处理函数void interrupt_interrupt_canb(int irq, void *dev_id, struct pt_regs *regs){ unsigned char ir; static char into_flag=0; int i; if(into_flag) return; into_flag=1; ir=pcanb->IR; if((ir&FlagRI)) {//接受中断 canb_in_buffer[canb_in_buf_tail]=pcanb->RxDSCR[0]; canb_in_buffer[canb_in_buf_tail+1]=pcanb->RxDSCR[1]; //if(IsOk(canb_in_buffer[canb_in_buf_tail])&& //((canb_in_buffer[canb_in_buf_tail+1]&0x1f)<=8)) if(1) {// canb_in_buffer[canb_in_buf_tail+1]=pcanb->RxDSCR[1]; canb_in_buffer[canb_in_buf_tail+2]=pcanb->RxData[0]; canb_in_buffer[canb_in_buf_tail+3]=pcanb->RxData[1]; canb_in_buffer[canb_in_buf_tail+4]=pcanb->RxData[2]; canb_in_buffer[canb_in_buf_tail+5]=pcanb->RxData[3]; canb_in_buffer[canb_in_buf_tail+6]=pcanb->RxData[4]; canb_in_buffer[canb_in_buf_tail+7]=pcanb->RxData[5]; canb_in_buffer[canb_in_buf_tail+8]=pcanb->RxData[6]; canb_in_buffer[canb_in_buf_tail+9]=pcanb->RxData[7]; // a little test , depends on the sender send the same 8 bytesa if(1) { static unsigned char lst; static int first=1; if(first)lst=pcanb->RxData[7]; first=0; for(i=0;i<8;i++)if(lst+i!=pcanb->RxData[i]) { printk("error last:%x,now:%x,%x,%x,%x,%x,%x,%x,%x\n",lst, pcanb->RxData[0],pcanb->RxData[1],pcanb->RxData[2],pcanb->RxData[3], pcanb->RxData[4],pcanb->RxData[5],pcanb->RxData[6],pcanb->RxData[7]); lst=pcanb->RxData[0]; break; } lst++; lst&=0xf; rcount=lst; irqt_rx++; }/* if(canb_in_buf_tail+FRAME_DATA_SIZE<IN_BUFFER_LEN) canb_in_buf_tail=canb_in_buf_tail+FRAME_DATA_SIZE; else canb_in_buf_tail=0; */ } pcanb->CMR=FlagRRB;//清除接受缓冲区// i = pcanb->CMR; } else if(ir&FlagTI)//发送中断 { canb_write_busy=0; printk("send b"); irqt_tx++; } else reset_interrupt_canb(); into_flag=0; return;}//read响应函数//page和count分别对应调用函数read传递的参数buf和count//而且一次只返回一帧数据,故count和其他参数忽略//返回值为0表示无数据,否则page返回一帧数据static int proc_read_interrupt_canb(char *page, char **start, off_t off, int count, int *eof, void *data){ printk("IRQ Times tx:%d,rx:%d , lastvalue rx:%x\n",irqt_tx,irqt_rx,rcount); return 0; if(canb_flag==0) { if(canb_in_buf_head==canb_in_buf_tail)//无数据 return CAN_READ_NO_DATA; page[0]=canb_in_buffer[canb_in_buf_head]; page[1]=canb_in_buffer[canb_in_buf_head+1]; page[2]=canb_in_buffer[canb_in_buf_head+2]; page[3]=canb_in_buffer[canb_in_buf_head+3]; page[4]=canb_in_buffer[canb_in_buf_head+4]; page[5]=canb_in_buffer[canb_in_buf_head+5]; page[6]=canb_in_buffer[canb_in_buf_head+6]; page[7]=canb_in_buffer[canb_in_buf_head+7]; page[8]=canb_in_buffer[canb_in_buf_head+8]; page[9]=canb_in_buffer[canb_in_buf_head+9]; if(canb_in_buf_head+FRAME_DATA_SIZE>=IN_BUFFER_LEN) canb_in_buf_head=0; else canb_in_buf_head=canb_in_buf_head+FRAME_DATA_SIZE; canb_flag=1; } else canb_flag=0; return CAN_OK;}int __init reset_interrupt_canb(void){//复为can控制器 unsigned char b; pcanb->CR=0x0f;//开放中断 pcanb->BTR0=BTR0_Data; pcanb->BTR1=BTR1_Data;//置波特率 if((pcanb->BTR0!=BTR0_Data)|(pcanb->BTR1!=BTR1_Data))//写入回读不同 return RESET_CAN_ERROR; pcanb->ACR=0x07; pcanb->AMR=0xff; pcanb->OCR=0xfa; b=pcanb->CR; pcanb->CR=b&0xfe; canb_write_busy=0; return RESET_CAN_OK;}//write响应函数//buffer和count分别对应调用函数write传递的参数buf和count//其他参数在can中断设备程序中忽略//如果输入参数buffer[0]==CAN_DEBUG进入调试//buffer[1]和buffer[2]分别为对应寄存器编号和将赋的值,并返回该寄存器旧值static char can_b_counts=0;static int proc_write_interrupt_canb(struct file *file, const char *buffer,unsigned long count,void *data){ if(buffer[0]==CAN_RESET) return reset_interrupt_canb(); if(canb_write_busy) { if(can_b_counts>3) { reset_interrupt_canb();can_b_counts=0;} else can_b_counts++; return CAN_WRITE_BUSY; } /* pcanb->TxDSCR[0]=buffer[0]; pcanb->TxDSCR[1]=buffer[1]; pcanb->TxData[0]=buffer[2]; pcanb->TxData[1]=buffer[3]; pcanb->TxData[2]=buffer[4]; pcanb->TxData[3]=buffer[5]; pcanb->TxData[4]=buffer[6]; pcanb->TxData[5]=buffer[7]; pcanb->TxData[6]=buffer[8]; pcanb->TxData[7]=buffer[9]; */ pcanb->TxDSCR[0]=0x50; pcanb->TxDSCR[1]=0xe8; pcanb->TxData[0]=1; pcanb->TxData[1]=2; pcanb->TxData[2]=3; pcanb->TxData[3]=4; pcanb->TxData[4]=5; pcanb->TxData[5]=6; pcanb->TxData[6]=7; pcanb->TxData[7]=8; pcanb->CMR=FlagTR; canb_write_busy=1; return CAN_OK;}//初始化函数static int __init init_interrupt_canb(void){ int rv = 0; unsigned char b;pcanb = canb_ADDR; pcanb=(struct CanControl *)ioremap_nocache(0x29000000,canb_MEM_LEN); pcanb->CR=0x0f; pcanb->CMR=0x0; pcanb->BTR0=BTR0_Data; pcanb->BTR1=BTR1_Data;//置波特率 if((pcanb->BTR0!=BTR0_Data)|(pcanb->BTR1!=BTR1_Data)) {//写入回读不同 printk("What read is not what written when canb initialize\n"); iounmap((void *)pcanb); return EVerify; } pcanb->ACR=0x07; pcanb->AMR=0xff; pcanb->OCR=0xfa; b=pcanb->IR; interrupt_canb_file = create_proc_entry("canb", 0444, NULL); if(interrupt_canb_file == NULL) { printk("create_proc_entry error....\n"); iounmap((void *)pcanb); return -ENOMEM; } interrupt_canb_file->data = NULL; interrupt_canb_file->read_proc = &proc_read_interrupt_canb; interrupt_canb_file->write_proc = &proc_write_interrupt_canb; interrupt_canb_file->owner = THIS_MODULE; set_external_irq(INTERRUPT,EXT_FALLING_EDGE,0); rv=request_irq(INTERRUPT, interrupt_interrupt_canb,SA_INTERRUPT, "canb",NULL); if(rv) { printk("Can't get interrupt %d\n", INTERRUPT); iounmap((void *)pcanb); remove_proc_entry("canb", NULL); return -1; } b=pcanb->CR; pcanb->CR=b&0xfe; printk(KERN_INFO "%s %s initialized\n",MODULE_NAME, MODULE_VERSION);printk("init CR=%x\n",pcanb->CR); return 0;}static void __exit cleanup_interrupt_canb(void){ free_irq(INTERRUPT,NULL);//释放所占用中断号 iounmap((void *)pcanb); remove_proc_entry("canb", NULL); printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION);}module_init(init_interrupt_canb);module_exit(cleanup_interrupt_canb);MODULE_AUTHOR("yh");MODULE_DESCRIPTION("interrupt_canb proc module");EXPORT_NO_SYMBOLS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -