?? can.c
字號:
/****************************************Copyright (c)**************************************************
**-----------------------------------------文件信息-----------------------------------------------------
**文 件 名: 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 + -