📄 arm_can_a.c
字号:
//中断设备程序的编写//1.编译开关://gcc -O2 -D__KERNEL__ -DMODULE -I/usr/src/linux/include -c example.c -o example.o//2.加载模快:// insmod example.o//3.卸载模快:// rmmod /************************* cana中断处理程序 *************************///设备名:cana,地址:D0000-D01FF//#define _debug //编译调试代码开关#include <asm/io.h>#define cana_ADDR 0xfa000000#define cana_MEM_LEN 0X200 #define INTERRUPT 0 //使用5号中断#define MODULE_VERSION "1.0"#define MODULE_NAME "can_a_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/io.h> static void Sx(int a){ unsigned long volatile *pp = (unsigned long volatile *)0xfe000064; if(a)*pp|=1; else *pp&=0xfffffffe; }//#define EnCanW Sx(0)//#define DisCanW Sx(1)#define EnCanW#define DisCanW/*************************** 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 *pcana;#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 cana_in_buffer[IN_BUFFER_LEN]; //接受缓冲区:指通过CAN接受的数据临时存放处,用户通过read函数读取该缓冲区static int cana_in_buf_head=0; //接受缓冲区头指针static int cana_in_buf_tail=0; //接受缓冲区尾指针static char cana_write_busy=0;//初始时置0,write后置1,发送中断产生时置0static struct proc_dir_entry *interrupt_cana_file;int cana_interruptcount = 0;char cana_flag=0;#include "filter.h"//中断处理函数static unsigned long irqt_tx=0,irqt_rx=0;static unsigned char rgbuf[20][12];static int prgb=0,btrig=0,btrigcount;void interrupt_interrupt_cana(int irq, void *dev_id, struct pt_regs *regs){ unsigned char ir; static char into_flag=0; static int first=1,errcount=0; static unsigned char rcount = 0; static int gua = 0; int i,ccc; if(into_flag) return; into_flag=1; ir=pcana->IR; printk("IR=%x,CR=%x\n",ir,pcana->CR); if((ir&FlagRI)) {//接受中断 //pcana->RxData[1] = 0x44; cana_in_buffer[cana_in_buf_tail]=pcana->RxDSCR[0]; cana_in_buffer[cana_in_buf_tail+1]=pcana->RxDSCR[1]; // if(IsOk(cana_in_buffer[cana_in_buf_tail])&&// ((cana_in_buffer[cana_in_buf_tail+1]&0x1f)<=8)) {// cana_in_buffer[cana_in_buf_tail+1]=pcana->RxDSCR[1]; cana_in_buffer[cana_in_buf_tail+2]=pcana->RxData[0]; cana_in_buffer[cana_in_buf_tail+3]=pcana->RxData[1]; cana_in_buffer[cana_in_buf_tail+4]=pcana->RxData[2]; cana_in_buffer[cana_in_buf_tail+5]=pcana->RxData[3]; cana_in_buffer[cana_in_buf_tail+6]=pcana->RxData[4]; cana_in_buffer[cana_in_buf_tail+7]=pcana->RxData[5]; cana_in_buffer[cana_in_buf_tail+8]=pcana->RxData[6]; cana_in_buffer[cana_in_buf_tail+9]=pcana->RxData[7]; if(cana_in_buf_tail+FRAME_DATA_SIZE<IN_BUFFER_LEN) cana_in_buf_tail=cana_in_buf_tail+FRAME_DATA_SIZE; else cana_in_buf_tail=0; }{static int flagin = 0;EnCanW;//if(flagin==1)// for(flagin=0;flagin<1000;flagin++); pcana->CMR=FlagRRB;//清除接受缓冲区//i = pcana->CMR;DisCanW;flagin=1;irqt_rx++;} } else if(ir&FlagTI||ir==0xe0)//发送中断 { cana_write_busy=0;// printk("send a"); irqt_tx++; } else { reset_interrupt_cana(); printk("reset a , SR=%x\n",pcana->SR); } into_flag=0; return;}static unsigned char scount=0;//read响应函数//page和count分别对应调用函数read传递的参数buf和count//而且一次只返回一帧数据,故count和其他参数忽略//返回值为0表示无数据,否则page返回一帧数据static int proc_read_interrupt_cana(char *page, char **start, off_t off, int count, int *eof, void *data){ printk("IRQ Times tx:%d,rx:%d , lastvalue tx:%x\n",irqt_tx,irqt_rx,scount); return 0;}int __init reset_interrupt_cana(void){//复为can控制器 unsigned char b; int i; EnCanW; pcana->CR=0x0f;//开放中断 pcana->CMR=0; pcana->BTR0=BTR0_Data; pcana->BTR1=BTR1_Data;//置波特率 if((pcana->BTR0!=BTR0_Data)|(pcana->BTR1!=BTR1_Data))//写入回读不同 return RESET_CAN_ERROR; pcana->ACR=0x07; pcana->AMR=0xff; pcana->OCR=0xfa; b=pcana->CR; pcana->CR=b&0xfe; cana_write_busy=0; DisCanW; return RESET_CAN_OK;}static char can_a_counts=0;//for debugstatic int proc_write_interrupt_cana(struct file *file, const char *buffer,unsigned long count,void *data){ static int loop=0,wif=1; int i,c=0,k; if(cana_write_busy) return 0; pcana->TxDSCR[0]=scount; pcana->TxDSCR[1]=(wif&1)?0xe8:0xe2; for(i=0;i<8;i++) { pcana->TxData[i] = scount+i; } for(i=0;i<8;i++) { while( pcana->TxData[i]!=scount+i ) { printk("error on write TxData[%d] now %x, should be %x\n",i,pcana->TxData[i],scount); pcana->TxData[i]=scount+i; } } scount++; scount&=0xf; pcana->CMR=FlagTR; cana_write_busy=1; return CAN_OK;}//初始化函数static int __init init_interrupt_cana(void){ int rv = 0; unsigned char b;// we use bank5 for can access unsigned long volatile *pp = (unsigned long volatile *)0xfc000000; *pp&=0xff0fffff; *pp|=0x00c00000; pp =0xfc000018; *pp =0x7ff0;EnCanW; pcana = cana_ADDR;// pcana = (struct CanControl *)ioremap_nocache(0x28000000,cana_MEM_LEN); pcana->CR=0x0f; // BUG---BUG //return EVerify; pcana->CMR=0x0; //printk("IR=%x,SR=%x\n",pcana->IR,pcana->SR); pcana->BTR1=BTR1_Data;//置波特率 pcana->BTR0=BTR0_Data; //printk(" 8bit read on 8bit device:%x,%x\n",&pcana->BTR0,&pcana->BTR1); printk(" 8bit read on 8bit device:%x,%x\n",pcana->BTR0,pcana->BTR1); printk("16bit read on 8bit device:%x\n",*((unsigned short *)&pcana->BTR0)); if((pcana->BTR0!=BTR0_Data)|(pcana->BTR1!=BTR1_Data)) {//写入回读不同 printk("What read is not what written when cana initialize\n"); iounmap((void *)pcana); return EVerify; } pcana->ACR=0x07; pcana->AMR=0xff; pcana->OCR=0xfa; b=pcana->IR; interrupt_cana_file = create_proc_entry("cana", 0444, NULL); if(interrupt_cana_file == NULL) { printk("create_proc_entry error....\n"); iounmap((void *)pcana); return -ENOMEM; } interrupt_cana_file->data = NULL; interrupt_cana_file->read_proc = &proc_read_interrupt_cana; interrupt_cana_file->write_proc = &proc_write_interrupt_cana; interrupt_cana_file->owner = THIS_MODULE; set_external_irq(INTERRUPT, EINT_FALLING_EDGE , 0 ); rv=request_irq(INTERRUPT, interrupt_interrupt_cana,SA_INTERRUPT, "cana",NULL); if(rv) { printk("Can't get interrupt %d\n", INTERRUPT); iounmap((void *)pcana); remove_proc_entry("cana", NULL); return -1; } b=pcana->CR; pcana->CR=b&0xfe; printk("%s %s initialized \n",MODULE_NAME, MODULE_VERSION); DisCanW; Sx(1); return 0;}static void __exit cleanup_interrupt_cana(void){ free_irq(INTERRUPT,NULL);//释放所占用中断号 iounmap((void *)pcana); remove_proc_entry("cana", NULL); printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION);}module_init(init_interrupt_cana);module_exit(cleanup_interrupt_cana);MODULE_AUTHOR("yh");MODULE_DESCRIPTION("interrupt_cana proc module");EXPORT_NO_SYMBOLS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -