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

📄 mcp2515funcs.c

📁 can4linux-3.5.3.gz can4 linux
💻 C
📖 第 1 页 / 共 3 页
字号:
	DBGprint(DBG_DATA, ("refused baud[%d]=%d already set to %d",			minor, baud, Baud[minor]));	return -1;    }    DBGprint(DBG_DATA, ("baud[%d]=%d", minor, baud));    switch(baud)    {	case   10: i = 0; break;	case   20: i = 1; break;	case   50: i = 2; break;	case  100: i = 3; break;	case  125: i = 4; break;	case  250: i = 5; break;	case  500: i = 6; break;	case  800: i = 7; break;	case 1000: i = 8; break;	default  : 		custom = 1;    }    if(custom) {	dev_info(&priv->dev, "%s, no custom bit register setting yet\n",			    __FUNCTION__);    } else {	mcp251x_write_reg(CNF1, (u8)CanTiming[i][0]);	mcp251x_write_reg(CNF2, (u8)CanTiming[i][1]);	mcp251x_write_reg(CNF3, (u8)(CanTiming[i][1] >> 8));    }    DBGout();    return 0;}int CAN_StartChip(int minor){    DBGin();    RxErr[minor] = TxErr[minor] = 0L;   /* empty error counters */    /* clear interrupts */    /* nothing to do ? */    /* Interrupts on Rx, TX, any Status change and data overrun */    /* The CANINTE register contains the individual interrupt enable bits     * for each interrupt source.     */    mcp251x_write_reg(CANINTE,		CANINTE_ERRIE | CANINTE_TX2IE | CANINTE_TX1IE |		CANINTE_TX0IE | CANINTE_RX1IE | CANINTE_RX0IE );    if(listenmode == 1 ) {	mcp251x_write_reg(CANCTRL, CANCTRL_REQOP_LISTEN_ONLY);	udelay(10);    } else {	mcp251x_write_reg(CANCTRL, CANCTRL_REQOP_NORMAL);	while (mcp251x_read_reg(CANSTAT) & 0xE0)	    udelay(10);    }    /* Reset error conditions */    mcp251x_write_reg(EFLG, 0);    DBGout();    return 0;}int CAN_StopChip(int minor){    DBGin();    /* FIXME: Issue  CAN controller reset */    /* Disable and clear pending interrupts */    mcp251x_write_reg(CANINTE, 0x00);    mcp251x_write_reg(CANINTF, 0x00);    mcp251x_write_reg(CANCTRL, CANCTRL_REQOP_CONF);    /* Wait for the device to enter config mode */    while ((mcp251x_read_reg(CANSTAT) & 0x80) == 0)	    udelay(10);    DBGout();    return 0;}/* set value of the output control register */int CAN_SetOMode (int minor, int arg){    DBGin();	DBGprint(DBG_DATA,("[%d] outc=0x%x", minor, arg));	printk(KERN_INFO "no \"output mode\" to set\n");    DBGout();    return 0;}/*Listen-Only ModeIn listen-only mode, the CAN module is able to receive messageswithout giving an acknowledgment.Since the module does not influence the CAN bus in this modethe host device is capable of functioning like a monitoror for automatic bit-rate detection. must be done after CMD_START (CAN_StopChip) and before CMD_START (CAN_StartChip) MCP2515:Listen-only mode provides a means for the MCP2515 to receiveall messages (including messages with errors) by configuring theRXBnCTRL.RXM<1:0> bits.The Listen-only mode is activated by setting the mode request bitsin the CANCTRL register.    bit 7-5 REQOP: Request Operation Mode bits <2:0>        000 = Set Normal Operation mode		CANCTRL_REQOP_NORMAL        001 = Set Sleep mode        010 = Set Loopback mode        011 = Set Listen-only mode		CANCTRL_REQOP_LISTEN_ONLY        100 = Set Configuration mode		CANCTRL_REQOP_CONF         All other values for REQOP bits are invalid and should not be used*/int CAN_SetListenOnlyMode(int minor, int arg){    DBGin();    if (arg) {	/* switch to listen only mode */	mcp251x_write_reg(CANCTRL, CANCTRL_REQOP_LISTEN_ONLY);	listenmode = 1;    } else {	/* switch to normal mode */	mcp251x_write_reg(CANCTRL, CANCTRL_REQOP_NORMAL);	listenmode = 0;    }    /* while (mcp251x_read_reg(CANSTAT) & 0xE0) */	    udelay(10);    DBGout();    return 0;}/*The mask and filter registers can only be modifiedwhen the MCP2515 is in Configuration mode (seeSection 10.0 "Modes of Operation").Used is only Mask1 and Filter1                      Extended Frame+---------------+-------------------------------------------------+|ID10       ID0 | EID17                                       EID0|+---------------+-------------------------------------------------+     Masks and Filters apply to the entire 29-bit ID field*/int CAN_SetMask(int minor, unsigned int code, unsigned int mask){struct mcp251x_priv *priv = &realone;//struct spi_device *spi = spidevice[minor];    DBGin();    dev_dbg(&priv->dev, "%s: not implemented\n", __FUNCTION__);    DBGprint(DBG_DATA,("[%d] acc=0x%x mask=0x%x",  minor, code, mask));    mcp251x_write_reg(RXM0SIDH, (u8)(mask >> 24));    mcp251x_write_reg(RXM0SIDL, (u8)(mask >> 16));    mcp251x_write_reg(RXM0EID8, (u8)(mask >>  8));    mcp251x_write_reg(RXM0EID0, (u8)(mask >>  0));    mcp251x_write_reg(RXF0SIDH, (u8)(code >> 24));     mcp251x_write_reg(RXF0SIDL, (u8)(code >> 16));     mcp251x_write_reg(RXF0EID8, (u8)(code >>  8));     mcp251x_write_reg(RXF0EID0, (u8)(code >>  0));     DBGout();    return 0;}/* CAN_SendMessage send a single CAN frame using SPI Blocktransfer */int CAN_SendMessage(int minor, canmsg_t *tx){    struct mcp251x_priv *priv = &realone;    u8 *tx_buf = priv->spi_tx_buf;    /* u8 *rx_buf = priv->spi_rx_buf; */    u32 sid, eid, ext, rtr;    /* DBGin(); */    sid  = tx->id & CAN_SFF_MASK; /* Standard ID */    eid  = tx->id & CAN_EFF_MASK; /* Extended ID */    ext  = (tx->flags & MSG_EXT) ? 1 : 0; /* Extended ID Enable */    rtr  = (tx->flags & MSG_RTR) ? 1 : 0; /* Remote transmission */    down(&priv->spi_lock);    tx_buf[0] = INSTRUCTION_LOAD_TXB(TRANSMIT_OBJ);    if(ext) {	tx_buf[1] = (eid >> 21) & 0xff;	tx_buf[2] = ((eid >> 13) & 0xe0) + 0x08 + ((eid & 0x30000) >> 16);	tx_buf[3] = (eid & 0xff00) >> 8;	tx_buf[4] = (eid & 0xff);    } else {	tx_buf[1] = sid >> 3;	tx_buf[2] = (sid << 5);    }    tx_buf[5] = (rtr << 6) | tx->length;    /* copy data to spi buffer */    memcpy(tx_buf + 6, tx->data, tx->length);    at91_spihw_rwn(priv->spi_tx_buf, priv->spi_rx_buf,    					6 + CAN_FRAME_MAX_DATA_LEN);    up(&priv->spi_lock);#if 1    down(&priv->spi_lock);    at91_spihw_wr8(MCP_RTS_TX0);#ifdef CANSPI_USEKTHREAD    udelay(500);    /* test with busyloop    do {        tx_buf[0] = 0xA0;        at91_spihw_rwn(priv->spi_tx_buf, priv->spi_rx_buf, 1);    } while (rx_buf[0] & 0x04); */#endif    up(&priv->spi_lock);#else    mcp251x_write_reg(TXBCTRL(TRANSMIT_OBJ), TXBCTRL_TXREQ);#endif   /*      * Save last message that was sent.     * Since can4linux 3.5 multiple processes can access     * one CAN interface. On a CAN interrupt this message is copied into      * the receive queue of each process that opened this same CAN interface.     */    memcpy(	(void *)&last_Tx_object[minor],	(void *)tx,	sizeof(canmsg_t));    /* DBGout(); */    return 0;}/* * Perform Vendor, that means sometimes CAN controller * or only board manufacturer specific initialization. * * Mainly it gets needed IO and IRQ ressources and initilaizes  * special hardware functions. * * This code should normally be in the CAN_VendorInit() function * in a TARGET specific file  target.c */int CAN_VendorInit (int minor){    DBGin();    /* SPI specific Tasks:     * register the ISR     * enable the PIO pins wher the CAN is connected to     *     * CAN interrupts are later enabled in     * CAN_StartChip(minor)     * according to can4linux rules     */    if( IRQ[minor] > 0 || IRQ[minor] > MAX_IRQNUMBER ){        if( Can_RequestIrq(minor, IRQ[minor] , CAN_Interrupt) ) {	     printk("Can[%d]: Can't request IRQ %d \n", minor, IRQ[minor]);	     DBGout(); return -EBUSY;        }    } else {	/* Invalid IRQ number in /proc/.../IRQ */	DBGout(); return -EBUSY;    }    listenmode = 0; /* sot NORMAL mode when opening the driver */    /* arrange the PIO interrupt on PB24 */    /*	board-sbc9263.c     */    DBGout(); return 0;}int Can_RequestIrq(int minor, int irq,    irqreturn_t (*handler)(int, void *)){int err = 0;    DBGin();    /*    int request_irq(unsigned int irq,			// interrupt number                void (*handler)(int, void *, struct pt_regs *), // pointer to ISR		              irq, dev_id, registers on stack              unsigned long irqflags, const char *devname,              void *dev_id);       dev_id - The device ID of this handler (see below).              This parameter is usually set to NULL,       but should be non-null if you wish to do  IRQ  sharing.       This  doesn't  matter when hooking the       interrupt, but is required so  that,  when  free_irq()  is       called,  the  correct driver is unhooked.  Since this is a       void *, it can point to anything (such  as  a  device-spe-       cific  structure,  or even empty space), but make sure you       pass the same pointer to free_irq().    */    /* From include/linux/irq.h       IRQ line status.	IRQ types	IRQ_TYPE_NONE		Default, unspecified type	IRQ_TYPE_EDGE_RISING	Edge rising type	IRQ_TYPE_EDGE_FALLING	Edge falling type	IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)	IRQ_TYPE_LEVEL_HIGH	Level high type	IRQ_TYPE_LEVEL_LOW	Level low type	IRQ_TYPE_SENSE_MASK	Mask of the above	IRQ_TYPE_PROBE		Probing in progress       From include/linux/irq.h       IRQF_DISABLED - keep irqs disabled when calling the action handler    */   /* We don't need the interrupt to be shared for now */   /* On AT91    	IRQF_DISABLED		- recognized   	IRQF_NOBALANCING	- not   	IRQF_TRIGGER_FALLING,	- not    */    disable_irq(gpio_to_irq(AT91_PIN_PB24));#if 0    /* TODO: IRQF_DISABLED must work - fix handler */    err = request_irq(irq, handler,    	IRQF_NOBALANCING | IRQF_TRIGGER_FALLING,    	"Can", &Can_minors[minor]);#else    err = request_irq(irq, handler,    	IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TRIGGER_FALLING,    	"Can", &Can_minors[minor]);#endif    if( !err ){      DBGprint(DBG_BRANCH,("Requested IRQ: %d @ 0x%lx",      				irq, (unsigned long)handler));      IRQ_requested[minor] = 1;    }    DBGout(); return err;}int Can_FreeIrq(int minor, int irq ){    DBGin();    IRQ_requested[minor] = 0;    /* printk(" Free IRQ %d  minor %d\n", irq, minor);  */    free_irq(irq, &Can_minors[minor]);    DBGout();    return 0;}/* insert_rxfifo * insert a CAN frame, pointed to by 'frame'  * into the active rx_fifos * The driver can handle an rx_fifo for each * process which open() the driver */static void insert_rxfifo(int minor, canmsg_t *frame){msg_fifo_t   *RxFifo; 	/* pointer to the active FIFO */int rx_fifo;		/* looping through these fifo indicies */    DBGin();    /* handle all subscribed rx fifos */    for(rx_fifo = 0; rx_fifo < CAN_MAX_OPEN; rx_fifo++) {	/* for every rx fifo */	if (CanWaitFlag[minor][rx_fifo] == 1) {	    /* this FIFO is in use */	    RxFifo = &Rx_Buf[minor][rx_fifo]; /* prepare buffer to be used */	    (RxFifo->data[RxFifo->head]).flags  = frame->flags;	    (RxFifo->data[RxFifo->head]).id     = frame->id;	    (RxFifo->data[RxFifo->head]).length = frame->length;	    (RxFifo->data[RxFifo->head]).timestamp = frame->timestamp;	    memcpy( &(RxFifo->data[RxFifo->head]).data[0],		    &frame->data[0], frame->length);	    /* mark just written entry as OK and full */	    RxFifo->status = BUF_OK;	    /* Handle buffer wrap-around */	    RxFifo->head = ++(RxFifo->head) % MAX_BUFSIZE;	    if(RxFifo->head == RxFifo->tail) {		    printk("CAN[%d][%d] RX: FIFO overrun\n", minor, rx_fifo);		    RxFifo->status = BUF_OVERRUN;	    } 	    /*---------- kick the select() call  -*/	    /* This function will wake up all processes	       that are waiting on this event queue,	       that are in interruptible sleep	    */	    wake_up_interruptible(&CanWait[minor][rx_fifo]); 	}    } /* end loop fill rx buffers */    DBGout();}/* Read an CAN Frame from the MCP2515 hardware from the numbered RX hardware bufferand store it in the drivers rx queues*/static void mcp251x_hw_rx(	struct spi_device *spi,	int buf_idx,	struct timeval *tv	){/* struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); */struct mcp251x_priv *priv = &realone;u8 *tx_buf = priv->spi_tx_buf;u8 *rx_buf = priv->spi_rx_buf;msg_fifo_t   *RxFifo; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -