LINUX-S3C2440-SJA1000驱动程序-笔记

/**************************************************************************************/
/*文件 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);

 

posted @ 2012-08-21 19:40  子鱼_  阅读(1036)  评论(0编辑  收藏  举报