📄 sja1000.c
字号:
#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 "sja1000.h"
#define DEVICE_NAME "SJACAN"
unsigned char Receive(unsigned char *RCdata);
void Transmit(unsigned char *TXdata);
unsigned SJA1000_READ(unsigned sja_reg_addr);
void SJA1000_WRITE(unsigned sja_reg_addr, unsigned value);
unsigned long SJA1000_DATA_VBASE=0;
unsigned long SJA1000_ADDR_VBASE=0;
int log_flag = 1; // 0 -- stop buffer CAN frames. 1 -- start buffer CAN frames.
#define MAX_NR_FRAMES 100
struct rec
{
unsigned char databuf[11 * MAX_NR_FRAMES];
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*11],11);
rd_buf.start = ++rd_buf.start % MAX_NR_FRAMES;
}
void in_rd_buf(unsigned char *buf)
{
if(is_full_rd_buf())
return;
memcpy(&rd_buf.databuf[rd_buf.end*11],buf,11);
rd_buf.end = ++rd_buf.end % MAX_NR_FRAMES;
}
void sja1000_can_irq(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char buf[11];
int intrkind;
intrkind=SJA1000_READ(SJA1000_IR);//read the interrupt status
if(intrkind & 0x01 == 0)/*not receive interrupt*/
{
goto out;
}
Receive(buf);
//printk("int1 : %d %d %d %d %d %d %d %d %d %d %d\n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10]);
if(log_flag)
in_rd_buf(buf); //buffer this frame
out:
SJA1000_WRITE(SJA1000_CMR,4); //clear sja receive buffer in order to clear it's INT signal
//*(volatile unsigned long*)(MCF_MBAR + 0x20) |= 0x80000000;//clear pending bit
//clear EPP interrupt
}
/*-------------------------------------------------------------------*/
unsigned SJA1000_READ(unsigned sja_reg_addr)
{
unsigned value;
SJA1000_SET_AEN;
writeb(sja_reg_addr,SJA1000_ADDR_VBASE);
SJA1000_CLR_AEN;
value=readb(SJA1000_DATA_VBASE);
return value;
}
void SJA1000_WRITE(unsigned sja_reg_addr, unsigned value)
{
SJA1000_SET_AEN;
writeb(sja_reg_addr,SJA1000_ADDR_VBASE);
SJA1000_CLR_AEN;
writeb(value,SJA1000_DATA_VBASE);
}
/*------------------------------------------------------------*/
unsigned char Receive(unsigned char *RCdata)
{
int i=16;
int j=0;
unsigned char sr = SJA1000_READ(SJA1000_SR);
for(;j<11;i++,j++){
RCdata[j] = SJA1000_READ(i);
}
SJA1000_WRITE(SJA1000_CMR,0x04);
return sr;
}
void Transmit(unsigned char *TXdata)
{
int i=16;
int j=0;
do{
printk("xxxxxxxxxxxx\n");
}while( !(SJA1000_READ(SJA1000_SR)&0x04) );
for(;j<11;i++,j++){
SJA1000_WRITE(i,TXdata[j]);
printk("TXdata[%d]=%d ",j,TXdata[j]);
}
SJA1000_WRITE(SJA1000_CMR,0x01);//0x01);
}
/*------------------------------------------------------------------*/
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 QSPIIOCS_LOGCANFRAMES:
// log_flag = arg;
// break;
case SJA_IOCTL_WRITE:
copy_from_user(&sja_reg_data,(void *)arg,sizeof(struct sja_reg));
//sja_reg_data = (struct sja_reg*)arg;
//error = verify_area(VERIFY_READ, sja_reg_data,
// sizeof(struct sja_reg));
//if (error)
// return error;
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);
SJA1000_WRITE(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));
//sja_reg_data = (struct sja_reg*)arg;
printk("sja_reg_addr=%x\n",sja_reg_data.sja_reg_addr);
//error = verify_area(VERIFY_READ, sja_reg_data,
// sizeof(struct sja_reg));
//if (error)
//return error;
sja_reg_data.sja_reg_value = SJA1000_READ(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)
{
MOD_INC_USE_COUNT;
return 0;
}
static int can_release(struct inode *inode, struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
static loff_t can_llseek(struct file *filep, loff_t off, int mod)
{
return off;
}
/*
---------------------------------------------------
*/
static ssize_t can_read(struct file *filep,char *buffer,size_t length,loff_t *ppos)
{
int total = 0;
// down(&sem); be careful!
while(1){
if(total >= length)
break;
if(is_empty_rd_buf())
break;
out_rd_buf(buffer+total);
total+=11;
}
// up(&sem);
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[11];
// down(&sem);
/* memcpy(dbuf, buffer, length);*/
for(i=0;i<11;i++){
printk("[%d]=%d ",i,buffer[i]);
}
printk("\n");
while(total+11 <= length){
memcpy(TXdata,buffer+total,11);
Transmit(TXdata);
total += 11;
}
// up(&sem);
return total;
}
unsigned int can_poll(struct file *filep, struct poll_table_struct *table)
{
unsigned int mask = 0;
if(! is_empty_rd_buf() )
mask = POLLIN;
return mask;
}
struct file_operations fops = {
owner: THIS_MODULE,
read: can_read,
poll: can_poll,
llseek: can_llseek,
write: can_write,
ioctl: can_ioctl,
open: can_open,
release: can_release, /* a.k.a. close */
};
void Egpio_Init(void)
{
unsigned int uiPADDR, uiPADR,config;
uiPADDR = inl(GPIO_PADDR) | 0x10;//egpio4
outl( uiPADDR, GPIO_PADDR );
uiPADR = inl(GPIO_PADR) | 0x10;//outdata is 1: 4
outl( uiPADR, GPIO_PADR );
uiPADDR = inl(GPIO_PADDR) & 0xdf;//egpio5 is input
outl( uiPADDR, GPIO_PADDR );
config=inl(GPIO_AINTEN) & 0xdf;
outl(config,GPIO_AINTEN);
config=inl(GPIO_AINTTYPE1) & 0xdf;
outl(config,GPIO_AINTTYPE1);
config=inl(GPIO_AINTTYPE2) & 0xdf;
outl(config,GPIO_AINTTYPE2);
config=inl(GPIO_AEOI) | 0x20;
outl(config,GPIO_AEOI);
config=inl(GPIO_AINTEN) | 0x20;
outl(config,GPIO_AINTEN);
config = inl(SMCBCR2);
printk ("SMCBCR2=0X%X\n",config);
config &=0xcfffffff;
outl(config,SMCBCR2);
config = inl(SMCBCR2);
printk ("SMCBCR2=0X%X\n",config);
}
#define MAXWAIT 2000
int InitializeSJA(void)
{
int i,j,status=0;
unsigned char txbuffer[11]={0,0,0,0,8,255,255,4,255,4},rxbuffer[11]={0};
txbuffer[0]=0x08;
txbuffer[1]=30;
txbuffer[2]=70;
txbuffer[3]=5;
for(i=0;i<MAXWAIT;i++)
{
j=SJA1000_READ(SJA1000_MOD);
printk ("SJA1000_MOD_00 0X%X\n",j);
SJA1000_WRITE(SJA1000_MOD,0x01); //reset mode
j=SJA1000_READ(SJA1000_MOD);
printk ("SJA1000_MOD_01 0X%X\n",j);
if(j&0x01)//(SJA1000_READ(SJA1000_MOD)&0x01)
break;
}
if(i==MAXWAIT)
{
printk ("time out\n");
return -1;
}
SJA1000_WRITE(SJA1000_BTR0,0X0d);
SJA1000_WRITE(SJA1000_BTR1,0X22); //125KHz
SJA1000_WRITE(SJA1000_OCR,0xdA); //output control 1a
SJA1000_WRITE(SJA1000_CDR,0XCf); //PeliCAN mode,bypass the input comparator
//disable clkout out
SJA1000_WRITE(SJA1000_ACR0,0xff);
SJA1000_WRITE(SJA1000_ACR1,0xff);
SJA1000_WRITE(SJA1000_ACR2,0xff);
SJA1000_WRITE(SJA1000_ACR3,0xff);
SJA1000_WRITE(SJA1000_AMR0,0xff);
SJA1000_WRITE(SJA1000_AMR1,0xff);
SJA1000_WRITE(SJA1000_AMR2,0xff);
SJA1000_WRITE(SJA1000_AMR3,0xff);
SJA1000_WRITE(SJA1000_INT_IER,0XFF); //0X00 disable interrupt 0x01 enable receive interrupt
SJA1000_READ(SJA1000_IR); //clear the interrupt register(except receive interrupt bit)
SJA1000_WRITE(SJA1000_CMR,0x04);//clear receive buffer. if no other message then
//clear receive interrupt bit
printk ("--------------------------------------\n");
for(i=0;i<MAXWAIT;i++)
{
SJA1000_WRITE(SJA1000_MOD,0x00);
if( ! (SJA1000_READ(SJA1000_MOD)&0x01) )
break;
}
if(i==MAXWAIT) return -1;
/*
status=SJA1000_READ(SJA1000_SR);
printk("pre_status=0X%X\n",status);
printk("pre_rxbuffer:");
for(i=0;i<11;i++){
printk(" %d",rxbuffer[i]);}
printk("\n");
while(1)
{
status=SJA1000_READ(SJA1000_SR);
if(status & 0x01)
{
status=SJA1000_READ(SJA1000_IR);
printk("SJA1000_IR=0X%X\n",status);
status=Receive(rxbuffer);
printk("status=0X%X\n",status);
for(i=0;i<11;i++)
{
printk(" %d",rxbuffer[i]);
}
printk("\n");
Transmit(txbuffer);
}
}
*/
return 0;
}
/*----------------init for module driver-----------------*/
int __init sja1000_init(void)
{
int ret;
Egpio_Init();
ret=request_irq(IRQ_GPIO,sja1000_can_irq,SA_INTERRUPT,"can_irq",NULL);
if(ret < 0)
{
printk ("%s device failed with %d\n","Sorry, registering the IRQ", ret);
return ret;
}
ret = register_chrdev(CAN_MAJOR, DEVICE_NAME, &fops);
if (ret < 0)
{
printk ("%s device failed with %d\n","Sorry, registering the character", ret);
return ret;
}
SJA1000_DATA_VBASE =ioremap(nCS2_PHYBASE,4);
SJA1000_ADDR_VBASE =ioremap(nCS7_PHYBASE,4);
InitializeSJA();
init_rd_buf(); //init read buffer
printk("sja1000 driver init ok.\n");
return 0;
}
/* Cleanup - undid whatever init_module did */
void __exit sja1000_exit(void)
{
int ret;
free_irq(IRQ_GPIO, NULL);
iounmap(SJA1000_DATA_VBASE);
iounmap(SJA1000_ADDR_VBASE);
ret = unregister_chrdev(CAN_MAJOR, DEVICE_NAME);
if (ret < 0)
printk("Error in unregister_chrdev: %d\n", ret);
}
module_init(sja1000_init);
module_exit(sja1000_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -