📄 can.c
字号:
} else { //发送标准帧
setcanport( canid,REG_FRAME_BID1,(send_buf[i].ID&0x000007f8)>>3 );
setcanport( canid,REG_FRAME_BID2,(send_buf[i].ID&0x00000007)<<5 );
if (send_buf[i].RemoteFlag==1) { //远程帧
setcanport(canid, REG_FRAME_INFO, send_buf[i].DataLen+0x40);
} else { //数据帧
setcanport(canid, REG_FRAME_INFO, send_buf[i].DataLen);
for (j=0;j<8;++j)
setcanport(canid, REG_FRAME_BDATA1+j, send_buf[i].Data[j]);
}
}
setcanport(canid,REG_COMMAND,TR_CMD); //发送数据
if( (getcanport(canid, REG_STATUS)&0x08)==0 ) { //发送未完成
interruptible_sleep_on_timeout(&canwrite_wq[canid],HZ); //等待发送完成
if( (getcanport(canid, REG_STATUS)&0x08)==0 ) //不成功
break;
}
//printk("send success\n"); ///////////////////
++write_num; //发送成功数加一
}
up(&canwrite_sem[canid]);
return write_num;
}
/*********************************************************************************************************
** 函数名称: config_can
** 功能描述: 设置CAN
** 输 入: chanal CAN设备号, pInitConfig 配置项
** 输 出: 无
********************************************************************************************************/
static void config_can(int chanal, PMCNET_INIT_CONFIG pInitConfig)
{
unsigned char val ;
val = ((pInitConfig->Filter)<<3)+0x01; //设置滤波模式并进入复位状态
do {
setcanport(chanal,REG_CONTROL,val);
} while( (getcanport(chanal,REG_CONTROL)&0x1f)!=val );
do {
setcanport(chanal,REG_INT_CONTROL, 0x0f);
} while( getcanport(chanal,REG_INT_CONTROL)!=0x0f );
//setcanport(chanal, REG_INT_CONTROL, 0x0f); //设置中断使能
setcanport(chanal, REG_BTR0, pInitConfig->Timing0); //设置波特率
setcanport(chanal, REG_BTR1, pInitConfig->Timing1);
//设置滤波相关寄存器
setcanport( chanal,REG_ACR0, pInitConfig->AccCode&0x000000ff );
setcanport( chanal,REG_ACR1, (pInitConfig->AccCode&0x0000ff00)>>8 );
setcanport( chanal,REG_ACR2, (pInitConfig->AccCode&0x00ff0000)>>16 );
setcanport( chanal,REG_ACR3, (pInitConfig->AccCode&0xff000000)>>24 );
setcanport( chanal,REG_AMR0, pInitConfig->AccMask&0x000000ff );
setcanport( chanal,REG_AMR1, (pInitConfig->AccMask&0x0000ff00)>>8 );
setcanport( chanal,REG_AMR2, (pInitConfig->AccMask&0x00ff0000)>>16 );
setcanport( chanal,REG_AMR3, (pInitConfig->AccMask&0xff000000)>>24 );
//设置错误计数相关寄存器
setcanport(chanal, REG_ERR_MAX, 0xff);
setcanport(chanal, REG_RX_ERR, 0x00);
setcanport(chanal, REG_TX_ERR, 0x00);
//设置输出和时钟寄存器
setcanport(chanal,REG_OCR,0xda);
setcanport(chanal,REG_CDR,0xc8);
//test_greg(chanal);
//test_freg(chanal);
val = getcanport(chanal,REG_CONTROL)&0xfe; //进入工作状态
do {
setcanport(chanal, REG_CONTROL,val );
} while( (getcanport(chanal,REG_CONTROL)&0x1f)!=val );
return ;
}
/*********************************************************************************************************
** 函数名称: ioctl_can
** 功能描述:
** 输 入: 无
** 输 出: 无
********************************************************************************************************/
static int ioctl_can(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
int i,j,canid;
canid = (int)filp->private_data;
copy_from_user( &InitConfig, (void *)arg, sizeof(MCNET_INIT_CONFIG) );
//printk("canid:%d time0:%.2x time1:%.2x acr:%.8x amr:%.8x filter:%d mode:%d", canid, InitConfig.Timing0, ///////////////////////
// InitConfig.Timing1, InitConfig.AccCode, InitConfig.AccMask, InitConfig.Filter, InitConfig.Mode); ///////////////////////
switch (cmd) {
case IOC_CAN_INIT:
clearrcvbuf(canid);
config_can(canid,&InitConfig);
break;
case IOC_CAN_RESET:
clearrcvbuf(canid);
config_can(canid,&InitConfig);
break;
case IOC_CAN_EXIT:
//进入复位状态
do {
setcanport(canid,REG_CONTROL,0x01);
} while( (getcanport(canid,REG_CONTROL)&0x1f)!=0x01 );
break;
case IOC_CAN_GETRCVNUM:
(*((int *)arg)) = getrcvbufnum(canid);
//printk("canid:%d rcvnum:%d\n", canid, (*((int *)arg)) );
break;
default:
break;
}
//test_greg(canid);
//test_wreg(canid);
return 0;
}
/*********************************************************************************************************
** 函数名称: open_can
** 功能描述:
** 输 入:
** 输 出:
********************************************************************************************************/
static int open_can(struct inode *inode,struct file *filp)
{
filp->private_data = (void *)MINOR(inode->i_rdev); //次设备号保存至file结构中
MOD_INC_USE_COUNT;
return 0;
}
/*********************************************************************************************************
** 函数名称: release_can
** 功能描述:
** 输 入:
** 输 出:
********************************************************************************************************/
static int release_can(struct inode *inode,struct file *filp)
{
MOD_DEC_USE_COUNT;
return 0;
}
/*********************************************************************************************************
** 函数名称: can_handler
** 功能描述: can控制器中断处理函数
** 输 入: 无
** 输 出: 无
** 全局变量: 无
** 调用模块: 无
********************************************************************************************************/
static void can_handler( int irq, void *dev_id, struct pt_regs *regs)
{
int canid, i;
unsigned char temp, val;
unsigned int id1, id2, id3, id4;
//注意:CAN0对应IRQ17, CAN1对应IRQ16
if( irq==IRQ_EINT17 )
canid=0;
else if( irq==IRQ_EINT16 )
canid=1;
temp = getcanport(canid, REG_INTERRUPT); //读中断寄存器的值
if ( (temp&0x01) != 0) { //接收中断
printk("can%d receive irq occured.\n", canid);
// printk( "before canid:%d write point:%d, read point:%d", canid, CANRcvBuf[canid].WritePoint, CANRcvBuf[canid].ReadPoint );
wake_up_interruptible(&canread_wq[canid]); //通知数据到来
if( 0==CANRcvBuf[canid].FullFlag ) { //缓冲区未满
val = getcanport(canid, REG_FRAME_INFO);
if ( (val&0x80)!=0 ) { //扩展帧
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].ExternFlag = 1;
id1 = getcanport(canid, REG_FRAME_PID1);
id2 = getcanport(canid, REG_FRAME_PID2);
id3 = getcanport(canid, REG_FRAME_PID3);
id4 = getcanport(canid, REG_FRAME_PID4);
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].ID =
(id1<<21)+(id2<<13)+(id3<<5)+(id4>>3);
if ( (val&0x40)!=0 ) { //远程帧
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].RemoteFlag = 1;
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].DataLen = 0;
} else { //数据帧
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].RemoteFlag = 0;
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].DataLen = (val&0x0f);
for(i=0;i<8;++i)
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].Data[i] =
getcanport(canid, REG_FRAME_PDATA1+i);
}
} else { //标准帧
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].ExternFlag = 0;
id1 = getcanport(canid, REG_FRAME_BID1);
id2 = getcanport(canid, REG_FRAME_BID2);
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].ID =
(id1<<3)+(id2>>5);
if ( (val&0x40)!=0 ) { //远程帧
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].RemoteFlag = 1;
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].DataLen = 0;
} else { //数据帧
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].RemoteFlag = 0;
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].DataLen = (val&0x0f);
for(i=0;i<8;++i)
CANRcvBuf[canid].RcvBuf[CANRcvBuf[canid].WritePoint].Data[i] =
getcanport(canid, REG_FRAME_BDATA1+i);
}
}
if( ++CANRcvBuf[canid].WritePoint>=CAN_RCV_BUF_SIZE )
CANRcvBuf[canid].WritePoint = 0;
if( CANRcvBuf[canid].WritePoint==CANRcvBuf[canid].ReadPoint ) //缓冲区是否已满
CANRcvBuf[canid].FullFlag =1;
}
// printk( "canid:%d write point:%d, read point:%d", canid, CANRcvBuf[canid].WritePoint, CANRcvBuf[canid].ReadPoint );
setcanport(canid,REG_COMMAND,RRB_CMD); //释放接收缓冲区
}
if ( (temp&0x02) != 0) { //发送中断
printk("can%d send irq occured.\n", canid);
wake_up_interruptible( &canwrite_wq[canid] );
}
if ( (temp&0x04) != 0) { //错误报警中断
printk("can%d err irq occured.\n", canid);
//config_can(canid,&InitConfig);
}
if ( (temp&0x08) != 0) { //数据溢出中断
printk("can%d overflow irq occured.\n", canid);
//setcanport(canid,REG_COMMAND,COS_CMD); //free overflow memory
}
}
/**************************************
** 文件函数指针结构: can_fops
**
***************************************/
static struct file_operations can_fops={
read : read_can,
write: write_can,
ioctl: ioctl_can,
open: open_can,
release: release_can,
owner: THIS_MODULE,
};
/******************************************************
** 函数名称:init_module
** 功能描述:模块初始化函数
** 输入:无
******************************************************/
static int __init can_init(void)
{
int ret;
sema_init( &canread_sem[0], 1 );
sema_init( &canwrite_sem[0], 1 );
init_waitqueue_head( &canread_wq[0] );
init_waitqueue_head( &canwrite_wq[0] );
sema_init( &canread_sem[1], 1 );
sema_init( &canwrite_sem[1], 1 );
init_waitqueue_head( &canread_wq[1] );
init_waitqueue_head( &canwrite_wq[1] );
//注意:CAN0对应IRQ17, CAN1对应IRQ16
set_external_irq( IRQ_EINT16, EXT_RISING_EDGE, GPIO_PULLUP_DIS);
set_external_irq( IRQ_EINT17, EXT_RISING_EDGE, GPIO_PULLUP_DIS);
ret = request_irq( IRQ_EINT16,can_handler,SA_INTERRUPT,"can1",NULL );
if (ret<0) {
printk("sorry, can1 irq registation failed.\n");
return ret;
}
ret = request_irq( IRQ_EINT17,can_handler,SA_INTERRUPT,"can0",NULL );
if (ret<0) {
printk("sorry, can0 irq registation failed.\n");
return ret;
}
dev_handle[0] = devfs_register( NULL, "can0", DEVFS_FL_DEFAULT, CAN_MAJOR, 0,
S_IFCHR, &can_fops, (void *)0 );//|S_IRUGO|S_IWUGO
dev_handle[1] = devfs_register( NULL, "can1", DEVFS_FL_DEFAULT, CAN_MAJOR, 1,
S_IFCHR, &can_fops, (void *)1 );
canaddr[0]= ioremap(0x28000000,0x20);
canaddr[1]= ioremap(0x28400000,0x20);
printk("congraulation, can are successful registed.\n");
return 0;
}
/*******************************************************
** 函数名称:can_clear
** 功能描述:模块卸载函数
** 输入:无
******************************************************/
static void __exit can_clear(void)
{
iounmap(canaddr[0]);
iounmap(canaddr[1]);
//注意:CAN0对应IRQ17, CAN1对应IRQ16
free_irq(IRQ_EINT16,NULL);
free_irq(IRQ_EINT17,NULL);
devfs_unregister (dev_handle[0]);
devfs_unregister (dev_handle[1]);
printk("exit can successfully.\n");
}
MODULE_LICENSE("GPL");
module_init(can_init);
module_exit(can_clear);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -