⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sja1000.c

📁 9315-can
💻 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 + -