⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 obcana_pxa.c

📁 这是在linux下的key驱动,很不错的.
💻 C
字号:
/* *	General Char Device for linux * */ #include <linux/module.h>#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/miscdevice.h>#include <linux/reboot.h>#include <linux/smp_lock.h>#include <linux/init.h>#include <asm/uaccess.h>#include <asm/io.h> #include <asm-arm/arch-pxa/irqs.h>#include "can_pxa.h"#define	mdprintk	printk#define	DEVICE_MINOR	100#define	DEVICE_NAME		"cana"#define cana_addr 0xeb200000MODULE_LICENSE("GPL");/***************************  can控制器   ***************************///#include "can.h"//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//6.其他#define    DLCMask         0x0F   // DLC屏蔽#define    IDLMask         0xE0   // D低字节高3位屏蔽#define    IDLShift        5      // ID低字节高3位右对齐移位计数#define    TimeReset       100    // 复位时间,毫秒struct CanControl {   char CR; //控制寄存器   char CMR;//命令寄存器   char SR; //状态寄存器    char IR;//中断寄存器   char ACR;//验收寄存器   char AMR;//屏蔽寄存器   char BTR0;   char BTR1;   char OCR;   char TR; // 寄存器00..09   char TxDSCR[2],TxData[8];//发送ID,数据 10..19   char RxDSCR[2],RxData[8];//接收ID,数据 20..29   char XX30,CDR;//31 时钟驱动 30..31} volatile *pcan=0;static int can_irq=13;static int canid=0;static int canspeed=0;static int speed=0;static int get_sp0(){	switch( canspeed )	{		case	1:	return BTR0_1M;		case	0:	return BTR0_500K;//		case	B125:	return BTR0_125K;	}	return 0;}static int get_sp1(){	switch( canspeed )	{		case	1:	return BTR1_1M;		case	0:	return BTR1_500K;//		case	B125:	return BTR1_125K;	}	return 0;}#define    BTR0_Data       get_sp0()#define    BTR1_Data       get_sp1()#define	CAN_IN_BUF_SIZE	100static struct canmsg_t	can_in_buffer[CAN_IN_BUF_SIZE];static int can_in_buf_head=0; //接受缓冲区头指针static int can_in_buf_tail=0; //接受缓冲区尾指针static char can_write_busy=0;//初始时置0,write后置1,发送中断产生时置0static DECLARE_WAIT_QUEUE_HEAD(r_queue);static DECLARE_WAIT_QUEUE_HEAD(w_queue);static int irqt_tx=0 , irqt_rx=0 ;void interrupt_interrupt_can(int irq, void *dev_id, struct pt_regs *regs){	char ir;	int i;	char t1,t2;	struct canmsg_t *pct = &can_in_buffer[can_in_buf_tail];  ir=(pcan->IR);	  if((ir&FlagRI))  {//接受中断        		t1  = (pcan->RxDSCR[0]);		t2	= (pcan->RxDSCR[1]);		pct->id = (t1<<3) | (t2>>5);    	pct->length = t2&0xf;	for(i=0;i<8;i++) pct->data[i] = pcan->RxData[i];		pcan->CMR=FlagRRB;//清除接受缓冲区		can_in_buf_tail++;		can_in_buf_tail%=CAN_IN_BUF_SIZE;					irqt_rx++;	}  else{    if(ir&FlagTI)//发送中断    {		irqt_tx++;    }    else    {      if(ir&FlagEI)      {		reset_interrupt_can();		printk("some error in cana\n");		printk("can reset , SR=%x, IR=%x\n",pcan->SR,ir);      }      else printk("unknown interrupt\n");    }  }	return;}int reset_interrupt_can(void){//复为can控制器   short b;   int i;   pcan->CR=0x0f;   pcan->CMR=0;   pcan->BTR0=BTR0_Data;   pcan->BTR1=BTR1_Data;   printk(" 8bit read on 8bit device:%x,%x\n",pcan->BTR0,pcan->BTR1);   printk("8bit read on 8bit device:%x,%x\n",BTR0_Data,BTR1_Data);   if((pcan->BTR0!=BTR0_Data)|(pcan->BTR1!=BTR1_Data))   {   		printk("error\n");      		return RESET_CAN_ERROR;   }   pcan->ACR=0x07;   pcan->AMR=0xff;   pcan->OCR=0xfa;      pcan->CR &= 0xfe;      can_in_buf_head = 0;   can_in_buf_tail = 0;   can_write_busy=0;      return RESET_CAN_OK;}/* *	Allow only one person to hold it open */static int g_chdrv_open(struct inode *inode, struct file *file){	mdprintk("g_chdrv device %s opened\n",DEVICE_NAME);	reset_interrupt_can();	return 0;}static int g_chdrv_release(struct inode *inode, struct file *file){	mdprintk("g_chdrv device %s released\n",DEVICE_NAME);	return 0;}static ssize_t g_chdrv_read(struct file *file, char *data, size_t len, loff_t *ppose){	struct canmsg_t	t;		//printk("g_chdrv device %s read %d bytes\n",DEVICE_NAME,len);	while(can_in_buf_head==can_in_buf_tail);	copy_to_user( data , &can_in_buffer[can_in_buf_head] , sizeof(t) );		can_in_buf_head++;	can_in_buf_head%=CAN_IN_BUF_SIZE;	return 1;}static ssize_t g_chdrv_write(struct file *file, const char *data, size_t len, loff_t *ppos){	struct canmsg_t	t;	int i,j;	//mdprintk("g_chdrv device %s write %d bytes\n",DEVICE_NAME,len);		if(pcan->SR&FlagTS)	{	  printk("busy");	  return 0;	}		copy_from_user( &t , data , sizeof(t) );	if( t.length>8 )t.length=8;		pcan->TxDSCR[0] = t.id>>3 ;	pcan->TxDSCR[1] = ((t.id&7)<<5) | (t.length&0xf);	for(i=0;i<t.length;i++){		pcan->TxData[i] = t.data[i];		for(j=0;j<10;j++);	}		pcan->CMR=FlagTR;	return 1;}static int g_chdrv_ioctl(struct inode *inode, struct file *file,	unsigned int cmd, unsigned long arg){	return 0;}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static struct file_operations g_chdrv_fops = {	owner:		THIS_MODULE,	read:		g_chdrv_read,	write:		g_chdrv_write,	ioctl:		g_chdrv_ioctl,	open:		g_chdrv_open,	release:	g_chdrv_release,};static struct miscdevice g_chdrv_miscdev = {	minor:		DEVICE_MINOR,	name:		DEVICE_NAME,	fops:		&g_chdrv_fops,};MODULE_PARM(canid,"i");MODULE_PARM(canspeed,"i");MODULE_PARM(speed,"i");static int __init g_chdrv_init(void){	int ret;	int volatile *p=0xfa00000c;	*p=0x0470000+speed;			can_irq = 14;		pcan = cana_addr;		g_chdrv_miscdev.minor = DEVICE_MINOR;		g_chdrv_miscdev.name = DEVICE_NAME;	set_GPIO_IRQ_edge(can_irq,GPIO_FALLING_EDGE);	if( request_irq(IRQ_GPIO(can_irq), interrupt_interrupt_can,SA_INTERRUPT, g_chdrv_miscdev.name,NULL) )	{		printk("Get Interrupt %d Error\n" , can_irq );		return -1;	}	ret = misc_register(&g_chdrv_miscdev);	mdprintk("g_chdrv device %s init\n",DEVICE_NAME);	if (ret)	{		free_irq(IRQ_GPIO(can_irq),NULL);		printk("error\n");		return ret;	}	reset_interrupt_can();	return 0;}static void __exit g_chdrv_exit(void){	free_irq(IRQ_GPIO(can_irq),NULL);	misc_deregister(&g_chdrv_miscdev);	mdprintk("g_chdrv device %s exit\n",DEVICE_NAME);}module_init(g_chdrv_init);module_exit(g_chdrv_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -