/**************************************************************************************/
/*文件 program_22_1.c */
/*SJA1000驱动程序 */
/*************************************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/ioport.h>
#include <linux/poll.h>
#include <linux/delay.h>
#include <asm/hardware.h>
/*这里包含了所有寄存器地址映射方式,有了这个头文件,CPU所有的寄存器都可以通过宏来实现 */
#include <asm/arch/cpu_s3c2440.h>
#include <linux/interrupt.h>
#include "candriver.h" /*这个头文件这里没有给出,包含驱动的私有变量和方法。*/
#define FAIL 0
#define SUCCESS 1
#define DEVICE_NAME "SJACAN"
#define MAX_NR_FRAMES 100 /*允许接受的最大帧数目,据此定义缓冲的大小*/
unsigned char Receive(unsigned char *RCdata);
void Transmit(unsigned char *TXdata);
int log_flag = 1; // 0 -- stop buffer CAN frames. 1 -- start buffer CAN frames.
struct rec
{
unsigned char databuf[13 * MAX_NR_FRAMES]; /*每一帧的数据是13个*/
int start,end; /*0,1,2,...9*/
} rd_buf;
void init_rd_buf()
{
rd_buf.start = 0;
rd_buf.end = 0;
}
int is_empty_rd_buf()
{
return (rd_buf.start == rd_buf.end); /*判断第一帧个最后一帧的位置是否相同,是则为空*/
}
int is_full_rd_buf()
{
return (rd_buf.start == (rd_buf.end+1) % MAX_NR_FRAMES); /*判断接收缓冲是否满*/
}
void out_rd_buf(unsigned char *buf)
{
if(is_empty_rd_buf())
return; /*如果是空的,返回*/
memcpy(buf, &rd_buf.databuf[rd_buf.start*13],13);
/*从rd_buf.databuf[rd_buf.start*13]开始读取数据,一次读取一帧=13个字节 */
rd_buf.start = ++rd_buf.start % MAX_NR_FRAMES; /*改变rd_buf.start的位置,指向下一帧*/
}
void in_rd_buf(unsigned char *buf)
{
if(is_full_rd_buf())
return; /*如果满,返回*/
memcpy(&rd_buf.databuf[rd_buf.end*13],buf,13);
/*从rd_buf.databuf[rd_buf.end*13]开始写数据,一次写一帧=13字节*/
rd_buf.end = ++rd_buf.end % MAX_NR_FRAMES; /*改变 rd_buf.end的位置,指向下一帧*/
}
int intialize_can1(void)
{
CAN_STRUCT can1;
UI i;
//初始化can1
canReset(); /*因为SJA1000的地址数据复用,所以用一个CPLD对其时序做一个逻辑转换*/
//对SJA1000进行硬件重置
for(i=0;i<4;i++)
{
can1.acc_code[i]=0x00; /*设置acc掩码*/
can1.acc_mask[i]=0xff;
}
can1.bt0=0x03; /*波特率*/
can1.bt1=0x1c;
if(canConfig(can1)==FAIL) /*如果设置错误,返回-1*/
{
return -1;
}
//can1开始运行
canNormalRun();
//向寄存器CMR写入0x04就能清除接收缓冲中的数据
pokeb(SEG1,CMR,0x04); /*release receive buffer*/
peekb(SEG1,ALC);
peekb(SEG1,ECC);
return 0;
}
static irqreturn_t sja1000_can_irq(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char buf[13];
int intrkind,s;
/*读中断寄存器状态*/
intrkind=peekb(SEG1,IR);//read the interrupt status
printk("can1 get data!\n");
if((intrkind & 0x01) == 0)/*not receive interrupt*/ /*没有接收中断产生*/
{
goto out;
}
Receive(buf);
if(log_flag)
in_rd_buf(buf); //buffer this frame /*将这一帧数据复制到接收缓冲中*/
peekb(SEG1,IR);
pokeb(SEG1,CMR,0x04); /*release receive buffer*/ /*释放接收缓冲*/
s=peekb(SEG1,ALC);
s=peekb(SEG1,ECC);
return IRQ_HANDLED;
out:
pokeb(SEG1,CMR,0x04); //clear sja receive buffer in order to clear it's INT signal
/*清除接收缓冲以便清除接手中断*/
return IRQ_NONE;
}
/*------------------------------------------------------------*/
unsigned char Receive(unsigned char *RCdata)
{
int i=16; /*接收缓冲地址是从16开始的*/
int j=0;
unsigned char sr =peekb(SEG1,SR); /*读状态寄存器*/
for(;j<13;i++,j++){
RCdata[j] = peekb(SEG1,i); /*复制13个数据到内存*/
}
return sr;
}
void Transmit(unsigned char *TXdata)
{
int i=16; /*发送缓冲的地址从16开始*/
int j=0;
int MAXWAIT=1000; /*最大等待时间,总线可能忙*/
do{
// printk("xxxxxxxxxxxx\n");
MAXWAIT--;
if (MAXWAIT==0)
{
printk("send fail!\n");
return;}
}while( !(peekb(SEG1,SR)&0x04) ); /*读出状态寄存器的值,是否可以发送*/
for(;j<13;i++,j++){
pokeb(SEG1,i,TXdata[j]); /*如果可以发,就把数据从内存复制到SJA1000的发送缓冲中去*/
}
pokeb(SEG1,CMR,0x01); /*写0x01给CMR,发送*/
}
static ssize_t can_read(struct file *filep,char *buffer,size_t length,loff_t *ppos)
{
int total = 0;
while(1){
if(total >= length) /*如果给定长度小于0,或者已将给定长度的数据读出去,就跳出*/
break;
if(is_empty_rd_buf()) /*如果接收缓冲是空,跳出*/
break;
out_rd_buf(buffer+total); /*读出接收缓冲里的数据*/
total+=13; /*每完成一次+13*/
}
return total; /*返回总的读出数据长度*/
}
static ssize_t can_write(struct file *filep,const char *buffer,size_t length, loff_t *ppos)
{
int total = 0,i;
unsigned char TXdata[13]; /*临时数组,用来存放发送数据*/
printk("the data to be sended by can1 is :\n");
for(i=0;i<13;i++){
printk("[%d]=%x ",i,buffer[i]);
}
printk("\n");
while(total+13 <= length){
memcpy(TXdata,buffer+total,13); /*将待发送数据复制到临时数组中*/
Transmit(TXdata); /*发送*/
total += 13;
}
return total;
}
/*------------------------------------------------------------------*/
static int can_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int error, n, rc = 0;
struct sja_reg sja_reg_data;// = 0;
switch (cmd) {
case SJA_IOCTL_WRITE:
copy_from_user(&sja_reg_data,(void *)arg,sizeof(struct sja_reg));
printk("write_sja_reg_addr=%x\n",sja_reg_data.sja_reg_addr);
printk("write_sja_reg_value=%x\n",sja_reg_data.sja_reg_value);
pokeb(SEG1,sja_reg_data.sja_reg_addr, sja_reg_data.sja_reg_value);
break;
case SJA_IOCTL_READ:
printk("enter read\n");
copy_from_user(&sja_reg_data,(void *)arg,sizeof(struct sja_reg));
printk("sja_reg_addr=%x\n",sja_reg_data.sja_reg_addr);
sja_reg_data.sja_reg_value = peekb(SEG1,sja_reg_data.sja_reg_addr);
printk("sja_reg_value=%x\n",sja_reg_data.sja_reg_value);
copy_to_user((void *)arg,&sja_reg_data,sizeof(struct sja_reg));
break;
default:
rc = -EINVAL;
break;
}
return rc;
}
static int can_open(struct inode *inode, struct file *file)
{
return 0;
}
static int can_release(struct inode *inode, struct file *file)
{
return 0;
}
struct file_operations fops = {
owner: THIS_MODULE,
open: can_open,
read: can_read,
write: can_write,
ioctl: can_ioctl,
release: can_release, /* a.k.a. close */
};
static void s3c2440_GPIO_init(void)
{
/*初始化CPU的GPIO口*/
Set_external_irq(IRQ_CAN,EXT_RISING_EDGE,GPIO_PULLUP_DIS);
/*分配外部中断6,上升沿有效,下拉有效*/
delay(1000);
}
/*----------------init for module driver-----------------*/
int __init sja1000_init(void)
{
int a,ret;
/*映射CAN的SJA1000物理地址*/
SEG1=ioremap((0x14000000+(0xDA000<<2)),128);
/*硬件RESET的地址*/
SEG3=SEG1+(0x101<<2);
/*初始化CAN寄存器*/
a=intialize_can1();
/*是否初始化成功,从打印的消息可以看出来*/
if(a==0){
s3c2440_GPIO_init();
/*申请中断号*/
ret=request_irq(IRQ_GPIO(92),&sja1000_can_irq,SA_INTERRUPT,"can1_irq",NULL);
if(ret < 0)
{
printk ("%s device failed with %d\n","Sorry, registering the IRQ", ret);
return ret; /*失败就退出*/
}
delay(1000);
/*申请设备号*/
ret = register_chrdev(126, DEVICE_NAME, &fops);
if (ret < 0)
{
printk ("%s device failed with %d\n","Sorry, registering the character", ret);
return ret;
}
delay(1000);
printk("can1_sja1000 driver init ok!\n");
return 0;
}
else
{
printk("can1_sja1000 driver init fail!\n");
return -1;
}
}
/* Cleanup - undid whatever init_module did */
void __exit sja1000_exit(void)
{
int ret;
/*再次重置CAN*/
canReset();
/*注销中断号*/
free_irq(IRQ_GPIO(92), NULL);
/*注销映射地址*/
iounmap(SEG1);
/*注销设备号*/
ret = unregister_chrdev(126, DEVICE_NAME);
if (ret < 0)
printk("Error in unregister_chrdev: %d\n", ret);
}
module_init(sja1000_init);
module_exit(sja1000_exit);