📄 can.c
字号:
/****************************************Copyright (c)**************************************************
** 西安傅立叶电子有限公司
** 研 发 部
** http://www.FFTChina.com
**-----------------------------------------文件信息-----------------------------------------------------
**文 件 名: cantest.c
**创 建 人:
**最后修改日期: 2005年6月30日
**描 述: CAN模块测试驱动程序(查询模式)
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include "linux/types.h"
#include "linux/fs.h"
#include "linux/mm.h"
#include "linux/errno.h"
#include "linux/major.h"
#include "linux/blkdev.h"
#include "linux/capability.h"
#include "linux/smp_lock.h"
#include "linux/module.h"
#include "linux/version.h"
#include "linux/kernel.h"
#include "linux/config.h"
#include "asm/uaccess.h"
#include "asm/io.h"
#include "sja1000.h"
void *can1addr;
void *can0addr;
char kernel_version[]=UTS_RELEASE;
unsigned int fftcan_major=0;
/*******************************************************
** 函数原形:setcanport(unsigned char chanal, unsigned char reg, unsigned char data1)
** 参数: chanal : can通道号
** reg : 寄存器地址
** data : 要写入的数据
** 函数说明:向CAN写数据
/*******************************************************/
void setcanport(unsigned char chanal, unsigned char reg, unsigned char data1)
{
if(!chanal) //是通道0
{ /*与IOREMAP配套的使用函数*/
writeb(reg,can0addr+8); //模拟ALE锁存地址,发地址信号;
writeb(data1,can0addr); //发送数据到地址
}
else
{
writeb(reg,can1addr+8);
writeb(data1,can1addr);
}
}
/*******************************************************
*函数原形:getcanport(unsigned char chanal, unsigned char reg)
*参数: chanal : can的通道号
* reg :寄存器地址
*返回值 : 读出寄存器的值
*函数说明:读出寄存器的值
/*******************************************************/
unsigned char getcanport(unsigned char chanal, unsigned char reg)
{
unsigned char temp;
if(!chanal)
{
writeb(reg,can0addr+8); //先将地址发送出去,然后再读出此处的值;
temp=readb(can0addr);
}
else
{
writeb(reg,can1addr+8);
temp=readb(can1addr);
}
return (temp);
}
/*******************************************************
** 函数原形:ifgetdata(unsigned char chanal)
** 参数: chanal : can通道号
** 返回值 :1:有可用数据
** 0:无可用数据
** 函数说明:判断can是否收到数据
/*******************************************************/
unsigned char ifgetdata(unsigned char chanal)
{
unsigned char temp;
if(((getcanport(chanal,REG_STATUS) & 0x01) != 1))
temp = 1;
else
temp = 0;
return (temp);
}
/*******************************************************
*函数原形:read_fftcan(struct file *file, char *buf, size_t count,loff_t *f_pos)
*参数: buf : 传入该函数的数据缓冲区指针
* count:CAN的通道号
*返回值 : 0
*函数说明:读出接收到的CAN数据
/*******************************************************/
int read_fftcan(struct file *file, char *buf, size_t count,loff_t *f_pos)
{
int num,i;
unsigned char chanal;
unsigned char data[11] = {0};
unsigned char dlc;
buf = data;
chanal = count;
if((getcanport(chanal,REG_RxBuffer2) & 0x10) == 0)
{
dlc = (getcanport(chanal,REG_RxBuffer2) & 0x0f) + 2;
} else {
dlc = 2;
}
for(i = 0; i < dlc ;i ++ )
{
*(buf + i) = getcanport(chanal,REG_RxBuffer1+i);
}
*(buf+i) = '\0';
setcanport(chanal,REG_COMMAND,0x04); //free receive memory
setcanport(chanal,REG_COMMAND,0x08); //free overflow memory
return (0);
}
/*******************************************************
*函数原形:write_fftcan(struct file *file,const char *buf,size_t count,loff_t *f_pos)
*参数: buf : 传入该函数的数据缓冲区指针
* count:CAN的通道号
*返回值 : 0 说明成功写入
*函数说明:向CAN总线发送数据
/*******************************************************/
int write_fftcan(struct file *file,const char *buf,size_t count,loff_t *f_pos)
{
unsigned char chanal;
unsigned char temp ;
int i;
unsigned char dlc;
chanal = count; //在这里我们将count当成通道号来进行传递;
temp = getcanport(chanal,REG_STATUS);
while((getcanport(chanal,REG_STATUS) & 0x08) == 0)printk("send dat not finish!\n"); //检查发送缓冲区是否释放
while((getcanport(chanal,REG_STATUS) & 0x04) == 0)printk("senddatreg locked\n");
if((*(buf+1)&0x10) == 0)
{
dlc = (*(buf+1) & 0x0f) + 2;
}
else
{
dlc = 2;
}
for(i = 0 ;i < dlc;i ++)
{
setcanport(chanal,REG_TxBuffer1+i,*(buf+i));
}
setcanport(chanal,REG_COMMAND,0x01); //将当前的信息发送出去
do
{
temp = getcanport(chanal,REG_STATUS); //如果发送完毕就退出循环
if((temp & 0x08) == 0x08)
break;
} while(1); //If it is transmitted succeded?
return (0);
}
/*******************************************************
*函数原形:FFT_init_can(unsigned char chanal,unsigned char ac,unsigned char am,unsigned char btr0,unsigned char btr1)
*参数: chanel: CAN的通道号
ac : 验收代码寄存器的值
* am :验收屏蔽寄存器的值
btr0 : 波特率设置
btr1 :
*返回值 : 0 :说明初始化成功
*函数说明:配置CAN总线
/*******************************************************/
void FFT_init_can(unsigned char chanal,unsigned char ac,unsigned char am,unsigned char btr0,unsigned char btr1)
{
unsigned char temp ;
int i;
/*Config MOD&CR register进入复位模式,同时使能发送和接收中断*/
do
{
temp = 0x07;
setcanport(chanal,REG_CONTROL,temp);
} while((temp&0x01) != 0x01);
//测试波特率的值
setcanport(chanal, REG_BTR0, btr0);
setcanport(chanal, REG_BTR1, btr1);
//设置验收代码寄存器的值
setcanport(chanal,REG_ACR, ac);
//设置验收滤波寄存器的值
setcanport(chanal,REG_AMR, am);
//设置输出控制寄存器的值
setcanport(chanal,REG_OCR, 0xda);
//设置始时钟分频寄存器的值
setcanport(chanal, REG_CDR, 0x48);
//退出复位模式
do
{
setcanport(chanal, REG_CONTROL,0x06 );
temp = getcanport(chanal,REG_CONTROL);
} while((temp & 0x01) != 0 );
return 0;
}
/*******************************************************
*函数原形:open_fftcan(struct inode *inode,struct file *file)
*参数:
*返回值 :
*函数说明:
/*******************************************************/
int open_fftcan(struct inode *inode,struct file *file)
{
return 0;
}
/*******************************************************
*函数原形:open_fftcan(struct inode *inode,struct file *file)
*参数:
*返回值 :
*函数说明:
/*******************************************************/
int release_fftcan(struct inode *inode,struct file *file)
{
return 0;
}
/***************************************************************************************************
*函数原形:ioctl_fftcan(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
*参数: cmd : 传入该函数的命令参数
* 0 :判断是否CAN0收到可用数据
1 :判断是否CAN1收到可用数据
3 :初始化CAN0总线
4 :初始化CAN1总线
arg :传入的参数
*返回值 : 0 :接收到有效数据
1 :没有接收到有效数据
3 :成功初始化CAN0
4 :成功初始化CAN1
5 :无效的命令
*函数说明:向CAN总线发送数据
/**************************************************************************************************/
static int ioctl_fftcan(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
unsigned char temp1,temp2;
unsigned char ac,am,btr0,btr1,chanal;
switch (cmd)
{
case 0:
temp1=ifgetdata(0);
break;
case 1:
temp1=ifgetdata(1);
break;
case 3:
chanal = 0;
ac = (arg & 0xff000000) >> 24 ;
am = (arg & 0x00ff0000) >> 16;
btr0 = (arg & 0x0000ff00) >> 8;
btr1 = (arg & 0x000000ff) ;
FFT_init_can(chanal,ac,am,btr0,btr1);
temp1 = 3;
break;
case 4:
chanal = 1;
ac = (arg & 0xff000000) >> 24 ;
am = (arg & 0x00ff0000) >> 16;
btr0 = (arg & 0x0000ff00) >> 8;
btr1 = (arg & 0x000000ff) ;
FFT_init_can(chanal,ac,am,btr0,btr1);
temp1 = 4;
break;
default:
temp1 = 5;
break;
}
return (temp1);
}
/**************************************
** 函数指针结构: file_operations
** 说明 :
***************************************/
struct file_operations fftcan_fops={
read : read_fftcan,
write: write_fftcan,
ioctl: ioctl_fftcan,
open : open_fftcan,
release: release_fftcan,
};
/******************************************************
** 初始化模块:在加载模块时候调用
** 函数原形 : init_module(void)
** 说 明 :不用修改
******************************************************/
int init_module(void)
{
int result;
result=register_chrdev(0,"fftcan",&fftcan_fops); //注册一个设备,得到驱动的主设备号
if(result<0)
{
printk("cannot get fftcan major number\n"); //没有成功
return result;
}
printk("congraulation,fftcan are successful registed\n");
if(fftcan_major==0)
{
fftcan_major=result; //记录下主设备号
}
//映射物理地址到IO内存,可以让软件直接访问IO内存
can0addr= ioremap(0x50800000,0x20);
/*将物理地址直接映射到IO内存*/
can1addr=ioremap(0x50c00000,0x20); /*第一个参数是物理地址,第2个是映射的大小,因为CAN只有32字节的地址空间,所以就0X10*/
return 0;
}
/*******************************************************
** 函数原形 : cleanup_module(void)
** 说明 : 在卸载模块时调用
******************************************************/
void cleanup_module(void)
{
iounmap(can0addr);
iounmap(can1addr);
unregister_chrdev(fftcan_major,"fftcan");
printk("exit fftcan\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -