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

📄 can.c

📁 2410linux下的CAN驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************Copyright (c)**************************************************
**                                   
**                                    山西华控伟业
**                              http://www.hkwy.net.cn
**--------------文件信息--------------------------------------------------------------------------------
**文   件   名:  cannew.c
**创   建   人:  田涛
**最后修改日期:  2007年2月8日
**-------------- 历史版本信息----------------------------------------------------------------------------
** 创建人: 田涛
** 版  本: v1.0
** 日 期: 2007年2月8日
** 描 述: 原始版本
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
//注意:CAN0对应IRQ17, CAN1对应IRQ16
#ifndef		__KERNEL__
#define		__KERNEL__
#endif
#ifndef		MODULE
#define		MODULE
#endif
#include	"linux/capability.h"
#include	"linux/smp_lock.h"
#include	"linux/devfs_fs_kernel.h"
#include	"linux/module.h"
#include	"asm/hardware.h"
#include	"asm/io.h"
#include	"linux/init.h"
#include	"asm/semaphore.h"
#include	"asm/uaccess.h"
#include	"linux/wait.h"
#include 	"linux/config.h"
#include  "linux/irq.h"

#include	"sja1000.h"
#if		LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
#include	"linux/smp_lock.h"
#endif
//注意:CAN0对应IRQ17, CAN1对应IRQ16
#define 	CAN_RCV_BUF_SIZE	5
#define	CAN_NUM		2		
#define	CAN_MAJOR		200
#define 	CAN_SEND_MAX	25
//char   kernel_version[]=UTS_RELEASE;
static devfs_handle_t  dev_handle[CAN_NUM]; 
static unsigned int*  canaddr[CAN_NUM];			//can控制器的映射起始地址
static wait_queue_head_t canread_wq[2], canwrite_wq[2];
static struct semaphore canread_sem[CAN_NUM];
static struct semaphore canwrite_sem[CAN_NUM];

typedef	struct	_CAN_RCV_CYCLEBUF_
 {
	U32		WritePoint;		//CAN的写指针
	U32		ReadPoint;		//CAN的读指针
	U8		FullFlag;		//CAN缓冲区满标志
	MCNET_CAN_OBJ	RcvBuf[CAN_RCV_BUF_SIZE];
} CAN_RCV_CYCLEBUF, *PCAN_RCV_CYCLEBUF;

static CAN_RCV_CYCLEBUF CANRcvBuf[CAN_NUM];
static MCNET_INIT_CONFIG InitConfig;


/*********************************************************************************************************
** 函数名称: setcanport
** 功能描述: 设置can控制器相应寄存器的值
** 输 入: chanal:can通道号,reg:寄存器地址,data1:寄存器要设置的值
** 输 出: 无
** 全局变量: can0addr,can1addr
** 调用模块: 无
********************************************************************************************************/
static void setcanport(int chanal, unsigned char reg, unsigned char data1)
{
	if(chanal>=CAN_NUM) {
		printk("the biggest value of  can number is %d", CAN_NUM-1);
		return;
	}
	
	writeb(reg,canaddr[chanal]+100);   	//先发送地址信号,再发送数据  
    	writeb(data1,canaddr[chanal]);   
 }
/*********************************************************************************************************
** 函数名称: getcanport
** 功能描述: 读取can控制器相应寄存器的值
** 输 入: chanal:can通道号,reg:寄存器地址
** 输 出: 读取的值
********************************************************************************************************/
static unsigned char getcanport(int chanal, unsigned char reg)
{
    unsigned char temp;
    
    if(chanal>=CAN_NUM) {
		printk("the biggest value of  can number is %d", CAN_NUM-1);
		return 0;
	}
	
    writeb(reg,canaddr[chanal]+100);     	//先发送地址信号,再发送数据  
    return readb(canaddr[chanal]);
 }

/*********************************************************************************************************
** 函数名称: getrcvbufnum
** 功能描述: 判断接受缓冲器中数据的数目
** 输 入: chanal:can通道号
** 输 出: 1:有数据  0:无数据
********************************************************************************************************/
static unsigned int getrcvbufnum(int chanal)
{
	unsigned int temp;
   
	if ( CANRcvBuf[chanal].FullFlag==1 ) 	//缓冲区已满
		return CAN_RCV_BUF_SIZE;

	if ( CANRcvBuf[chanal].WritePoint>=CANRcvBuf[chanal].ReadPoint ) 
		return (CANRcvBuf[chanal].WritePoint-CANRcvBuf[chanal].ReadPoint);
	else
		return (CAN_RCV_BUF_SIZE+CANRcvBuf[chanal].WritePoint-CANRcvBuf[chanal].ReadPoint);
}

/*********************************************************************************************************
** 函数名称: clearrcvbuf
** 功能描述: 清除接受缓冲器
** 输 入: chanal:can通道号
** 输 出: 
********************************************************************************************************/
static void clearrcvbuf(int chanal)
{
	CANRcvBuf[chanal].FullFlag = 0;
	CANRcvBuf[chanal].ReadPoint = 0;
	CANRcvBuf[chanal].WritePoint = 0;
}

/*********************************************************************************************************
** 函数名称: testreg
** 功能描述: 
** 输 入: 
** 输 出: 无
********************************************************************************************************/
void test_greg(int chanal)
{
   printk("This is CAN %d!\n",chanal);
   
   printk( "REG_CONTROL: %.2x  ", getcanport(chanal,REG_CONTROL) );
   printk( "REG_STATUS: %.2x  ", getcanport(chanal,REG_STATUS) );
   printk( "REG_INTERRUPT: %.2x  ", getcanport(chanal,REG_INTERRUPT) );
   printk( "REG_INT_CONTROL: %.2x  ", getcanport(chanal,REG_INT_CONTROL) );
   printk( "REG_BTR0 : %.2x  ", getcanport(chanal,REG_BTR0 ) );
   printk( "REG_BTR1: %.2x  ", getcanport(chanal,REG_BTR1) );
   printk( "REG_OCR: %.2x  ", getcanport(chanal,REG_OCR) );
   printk( "REG_CDR: %.2x  ", getcanport(chanal,REG_CDR) );
   printk( "REG_ARBIT_LOSE: %.2x  ", getcanport(chanal,REG_ARBIT_LOSE) );
   printk( "REG_ERR_CODE : %.2x  ", getcanport(chanal,REG_ERR_CODE ) );
   printk( "REG_ERR_MAX: %.2x  ", getcanport(chanal,REG_ERR_MAX) );
   printk( "REG_RX_ERR: %.2x  ", getcanport(chanal,REG_RX_ERR) );
   printk( "REG_TX_ERR: %.2x\n", getcanport(chanal,REG_TX_ERR) );
 }
 
 void test_wreg(int chanal){
 	printk("This is CAN %d!\n",chanal);
 	
 	printk( "REG_FRAME_INFO: %.2x  ", getcanport(chanal,REG_FRAME_INFO) );
   	printk( "REG_FRAME_PID1: %.2x  ", getcanport(chanal,REG_FRAME_PID1) );
   	printk( "REG_FRAME_PID2: %.2x  ", getcanport(chanal,REG_FRAME_PID2) );
   	printk( "REG_FRAME_PID3: %.2x  ", getcanport(chanal,REG_FRAME_PID3) );
   	printk( "REG_FRAME_PID4: %.2x  ", getcanport(chanal,REG_FRAME_PID4) );
   	printk( "REG_FRAME_PDATA1: %.2x  ", getcanport(chanal,REG_FRAME_PDATA1) );
   	printk( "REG_FRAME_PDATA2: %.2x  ", getcanport(chanal,REG_FRAME_PDATA2) );
   	printk( "REG_FRAME_PDATA3: %.2x  ", getcanport(chanal,REG_FRAME_PDATA3) );
   	printk( "REG_FRAME_PDATA4: %.2x  ", getcanport(chanal,REG_FRAME_PDATA4) );
   	printk( "REG_FRAME_PDATA5: %.2x  ", getcanport(chanal,REG_FRAME_PDATA5) );
   	printk( "REG_FRAME_PDATA6: %.2x  ", getcanport(chanal,REG_FRAME_PDATA6) );
   	printk( "REG_FRAME_PDATA7: %.2x  ", getcanport(chanal,REG_FRAME_PDATA7) );
   	printk( "REG_FRAME_PDATA8: %.2x\n", getcanport(chanal,REG_FRAME_PDATA8) );
 }
 
 void test_freg(int chanal){
 	printk("This is CAN %d!\n",chanal);
 	
 	printk( "REG_ACR0: %.2x  ", getcanport(chanal,REG_ACR0) );
 	printk( "REG_ACR1: %.2x  ", getcanport(chanal,REG_ACR1) );
 	printk( "REG_ACR2: %.2x  ", getcanport(chanal,REG_ACR2) );
 	printk( "REG_ACR3: %.2x  ", getcanport(chanal,REG_ACR3) );
   	printk( "REG_AMR0: %.2x  ", getcanport(chanal,REG_AMR0) );
 	printk( "REG_AMR1: %.2x  ", getcanport(chanal,REG_AMR1) );
 	printk( "REG_AMR2: %.2x  ", getcanport(chanal,REG_AMR2) );
 	printk( "REG_AMR3: %.2x\n", getcanport(chanal,REG_AMR3) );
 }
/*********************************************************************************************************
** 函数名称: read_can
** 功能描述: 从CAN中读数据
** 输 入: filp文件指针,buf用户缓冲区,count要读的CAN帧的数目
** 输 出: 实际读到的CAN帧的数目
********************************************************************************************************/

static  int  read_can(struct file *filp, char *buf, size_t count, loff_t *f_pos)

{	
    	int i,canid;
	unsigned int num, read_num;
	PMCNET_CAN_OBJ	p_buf;
	
	////////////////////////////////////////////
	//printk( "write point:%d,  read point:%d", CANRcvBuf[canid].WritePoint, CANRcvBuf[canid].ReadPoint );
	///////////////////////////////////////

	canid = (int)filp->private_data;
	p_buf = (PMCNET_CAN_OBJ)buf;
	        
	down_interruptible(&canread_sem[canid]);	//占用读信号量
	
	for( read_num=0;  read_num<count; ++read_num ) {
		if( (CANRcvBuf[canid].FullFlag==0)&&(CANRcvBuf[canid].ReadPoint==CANRcvBuf[canid].WritePoint) ) {	//缓冲区中无数据
			if( read_num!=0 ) 			//已经读到数据
				break;
			else {				//还没读到数据
				while (1) {
					interruptible_sleep_on(&canread_wq[canid]);	//等待数据到来
					if ( (CANRcvBuf[canid].WritePoint!=CANRcvBuf[canid].ReadPoint)||(CANRcvBuf[canid].FullFlag==1)  ) {		//有数据到来
						copy_to_user( &p_buf[0], &CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].ReadPoint], sizeof(MCNET_CAN_OBJ) );
						if( (++CANRcvBuf[canid].ReadPoint)>=CAN_RCV_BUF_SIZE ) 
							CANRcvBuf[canid].ReadPoint =0;
						CANRcvBuf[canid].FullFlag = 0;
						break;
					}
				}
				read_num=1;
				break;		
			}
		} else {	//缓冲区中有数据
			copy_to_user( &p_buf[read_num], &CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].ReadPoint], sizeof(MCNET_CAN_OBJ) );
			if( (++CANRcvBuf[canid].ReadPoint)>=CAN_RCV_BUF_SIZE ) 
				CANRcvBuf[canid].ReadPoint =0;
			CANRcvBuf[canid].FullFlag = 0;
		}
	}
	
	
/*	num = getrcvbufnum(canid);	//缓冲区中数据的数目

	if ( num>=count ) {		//缓冲区中的数据足够多
		for ( i=0;i<count;++i) {
			copy_to_user( p_buf, &CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].ReadPoint], sizeof(MCNET_CAN_OBJ) );
			p_buf++;
			if( (++CANRcvBuf[canid].ReadPoint)>=CAN_RCV_BUF_SIZE ) 
				CANRcvBuf[canid].ReadPoint =0;
			CANRcvBuf[canid].FullFlag = 0;
		}
		read_num = count;
	} else if ( (num<count)&&(num!=0) ) {	//缓冲区中有数据但少于请求数据
		for ( i=0;i<num;++i) {
			copy_to_user( p_buf, &CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].ReadPoint], sizeof(MCNET_CAN_OBJ) );
			p_buf++;
			if( (++CANRcvBuf[canid].ReadPoint)>=CAN_RCV_BUF_SIZE ) 
					CANRcvBuf[canid].ReadPoint =0;
			CANRcvBuf[canid].FullFlag = 0;
		}
		read_num = num;
	} else if ( num==0 ) {		//缓冲区中无数据
		while (1) {
			interruptible_sleep_on(&canread_wq[canid]);	//等待数据到来
			if ( getrcvbufnum(canid)!=0 ) {
				copy_to_user( buf, &CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].ReadPoint], sizeof(MCNET_CAN_OBJ) );
				if( (++CANRcvBuf[canid].ReadPoint)>=CAN_RCV_BUF_SIZE ) 
					CANRcvBuf[canid].ReadPoint =0;
				CANRcvBuf[canid].FullFlag = 0;
				break;
			}
		}
		read_num = 1;
	}*/
	//printk( "write point:%d,  read point:%d", CANRcvBuf[canid].WritePoint, CANRcvBuf[canid].ReadPoint );
	up(&canread_sem[canid]);
	return read_num;
}

/*********************************************************************************************************
** 函数名称: write_can
** 功能描述: 往CAN中写数据
** 输 入: filp文件指针,buf用户缓冲区,count要写的CAN帧的数目
** 输 出: 实际读到的CAN帧的数目
********************************************************************************************************/

static int  write_can(struct file *filp,const char *buf,size_t count,loff_t *f_pos)
{    
	int i,j,canid;
	unsigned int num, write_num;
	MCNET_CAN_OBJ send_buf[CAN_SEND_MAX];

	canid = (int)filp->private_data;
	copy_from_user( send_buf,buf,count*sizeof(MCNET_CAN_OBJ) );
	
	/*
	printk("canid:%d  ID:%.4x  RTR:%d  FF:%d  DataLen:%.2x   Data:", canid, send_buf[0].ID,
				send_buf[0].RemoteFlag,send_buf[0].ExternFlag,send_buf[0].DataLen);
   	 for(i = 0; i<8;i++)
   	 	printk("%.2x ",send_buf[0].Data[i]);
   	 printk("\n");
	*/
        
	down_interruptible(&canwrite_sem[canid]);	//占用写信号量
	
	write_num = 0;
	for ( i=0;i<count;++i) {
		if (send_buf[i].ExternFlag==1) {	//发送扩展帧
			setcanport( canid,REG_FRAME_PID1,(send_buf[i].ID&0x1fe00000)>>21 );
			setcanport( canid,REG_FRAME_PID2,(send_buf[i].ID&0x001fe000)>>13 );
			setcanport( canid,REG_FRAME_PID3,(send_buf[i].ID&0x00001fe0)>>5 );
			setcanport( canid,REG_FRAME_PID4,(send_buf[i].ID&0x0000001f)<<3 );
			
			if (send_buf[i].RemoteFlag==1) {	//远程帧
				setcanport(canid, REG_FRAME_INFO, send_buf[i].DataLen+0x80+0x40);
			} else {	//数据帧
				//printk("send extern data frame\n");//////////////
				setcanport(canid, REG_FRAME_INFO, send_buf[i].DataLen+0x80);
				for (j=0;j<8;++j) 
					setcanport(canid, REG_FRAME_PDATA1+j, send_buf[i].Data[j]);
				//test_wreg(canid);///////////////////////////////
			}

⌨️ 快捷键说明

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