📄 at9263funcs.c
字号:
CANresetl(minor, mode, CANBIT_MR_CANEN); /* Disable Interrupts */ CANoutl(minor, idr, 0xFFFFFFFFul); /* CAN_StartChip will enable again */ DBGout(); return 0;}/* set value of the output control register * The register is not available, nothing happens here * besides printing some debug information * * The AT91SAM9263 has no such register */int CAN_SetOMode (int minor, int arg){ DBGin(); DBGprint(DBG_DATA,("[%d] outc=0x%x", minor, arg)); 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)*/int CAN_SetListenOnlyMode (int minor, int arg){ DBGin(); if (arg) { CANsetl(minor, mode, CANBIT_MR_ABM); } else { CANresetl(minor, mode, CANBIT_MR_ABM); } DBGout(); return 0;}/* * Not implemented yet, * the driver has no filter and receives all messages on the bus */int CAN_SetMask (int minor, unsigned int code, unsigned int mask){ DBGin(); DBGprint(DBG_DATA,("CAN_SetMask ! Not yet implemented !")); DBGprint(DBG_DATA,("[%d] acc=0x%x mask=0x%x", minor, code, mask)); DBGout(); return 0;}/* Single CAN frames or the very first Message are copied into the CAN controllerusing this function. After that an transmission request is set in theCAN controllers command register.After a succesful transmission, an interrupt will be generated,which will be handled in the CAN ISR CAN_Interrupt()*/int CAN_SendMessage (int minor, canmsg_t *tx){int i = 0;u32 stat; DBGin(); /* Wait for the transmitter to be idle At the Moment I don't know how to achive that. It might not be necessarry anyway. The CAN Status Register CAN_SR signals in bit TBSY: 0 - CAN transmitter is not transmitting a frame 1 - CAN transmitter is transmitting a frame */ while ( ! (stat = CANinl(minor, sr)) & CANBIT_SR_TBSY) { #if LINUX_VERSION_CODE >= 131587 # if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) cond_resched(); # else if( current->need_resched ) schedule(); # endif #else if( need_resched ) schedule(); #endif } DBGprint(DBG_DATA,( "CAN[%d]: tx.flags=%d tx.id=0x%lx tx.length=%d stat=0x%x", minor, tx->flags, tx->id, tx->length, stat)); tx->length %= 9; /* limit CAN message length to 8 */ /* To prevent concurrent access with the internal CAN core, the application must disable the mailbox before writing to CAN_MIDx registers. */ CAN_OBJ[TRANSMIT_OBJ].mmr = 0; /* fill the frame info and identifier fields , ID-Low and ID-High */ if(tx->flags & MSG_EXT) { /* use ID in extended message format */ DBGprint(DBG_DATA, ("---> send ext message \n")); CAN_WRITE_XOID(TRANSMIT_OBJ, tx->id); } else { DBGprint(DBG_DATA, ("---> send std message \n")); CAN_WRITE_OID(TRANSMIT_OBJ, tx->id); } /* - fill data ---------------------------------------------------- */ /* FIXME: Don't take care of message length for now */ CAN_OBJ[TRANSMIT_OBJ].mdl = tx->data[0] + (tx->data[1] << 8) + (tx->data[2] << 16) + (tx->data[3] << 24); CAN_OBJ[TRANSMIT_OBJ].mdh = tx->data[4] + (tx->data[5] << 8) + (tx->data[6] << 16) + (tx->data[7] << 24); /* - /end --------------------------------------------------------- */ if( tx->flags & MSG_RTR) { } else { } /* Enable transmit mail box */ CAN_OBJ[TRANSMIT_OBJ].mmr = CANBIT_MMR_MOT_TX; /* Writing data length code, set transmit request */ CAN_OBJ[TRANSMIT_OBJ].mcr = (tx->length << CANBIT_MCR_MDLC_POS) + ((tx->flags & MSG_RTR) ? CANBIT_MCR_MRTR : 0ul) + CANBIT_MCR_MTCR; if(selfreception[minor]) { /* prepare for next TX Interrupt and selfreception */ memcpy( (void *)&last_Tx_object[minor], (void *)tx, sizeof(canmsg_t)); } /* CAN_object_dump(minor, TRANSMIT_OBJ); */ DBGout();return i;}/* CAN_GetMessage is used in Polling Mode with ioctl() * !!!! curently not working for the PELICAN mode * and BASIC CAN mode code already removed !!!! * * Not implemented for the AT91SAM9263 */int CAN_GetMessage (int minor, canmsg_t *rx ){ DBGin(); DBGprint(DBG_DATA, ("CAN_GetMessage ! Polling for frames not implemented !")); 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 TERGET specific file target.c */int CAN_VendorInit (int minor){ DBGin(); /* It's Memory I/O , CAN is located somewhere, see Base[minor] */ can_range[minor] = 0x4000; /* 16 Kbyte */ if(NULL == request_mem_region(Base[minor], can_range[minor], "CAN-IO")) { DBGprint(DBG_DATA,("Request_mem_region CAN-IO failed at %lx\n", Base[minor])); return -EBUSY; } can_base[minor] = ioremap(Base[minor], can_range[minor]); /* now the virtual address can be used for the register address macros */ if( IRQ[minor] > 0 ) { if( Can_RequestIrq( minor, IRQ[minor] , CAN_Interrupt) ) { printk(KERN_ERR "Can[%d]: Can't request IRQ %d \n", minor, IRQ[minor]); DBGout(); return -EBUSY; } } 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(). */ err = request_irq(irq, handler, IRQF_SHARED, "Can", &Can_minors[minor]); if( !err ){/* printk("Requested IRQ[%d]: %d @ 0x%x", minor, irq, handler); */ 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;}#if CONFIG_TIME_MEASURE/* You can use all unassigned PIO which are available on expansion slots J24 and J25. Check the PIO_USAGE (Schemactics 1/1), unused PIO are without function suffixes, for example PB11_SPI0_NPCS3 is used and PB12 unused. You can use, for example, PB21 available on J24 pin 21.*//* switch LED on */inline void set_led(void){}/* switch LED off */inline void reset_led(void){}#endif/* * The plain AT91SAM9263 interrupt * * After completing the driver, do some measures and write results * down here. */ irqreturn_t CAN_Interrupt(int irq, void *dev_id){int minor;int rx_fifo; /* loopindex for different rx queues */#if 0 /* debug the error registers */int ecr; /* error counter register */#endifstruct timeval timestamp;unsigned fflags = 0; /* CAN frame flags */unsigned long iflags; /* processor interrupt flags */msg_fifo_t *RxFifo; msg_fifo_t *TxFifo;u32 sr; /* status register */static int errorints = 0;#if CONFIG_TIME_MEASURE /* do we have some LEDS on the EVA board ? */ set_led();#endif minor = *(int *)dev_id; /* printk("CAN - ISR ; minor = %d\n", *(int *)dev_id); */ RxFifo = &Rx_Buf[minor][0]; /* predefined to use the first */ TxFifo = &Tx_Buf[minor]; /* beginn interrupt handling */#define CAN_ISR_MASK (3 + 0x000C0000) /* MB 0+1, BOFF, ERRP */ while( (sr = CANinl(minor, sr)) & CAN_ISR_MASK) { /* loop through all interrupts until done */ canmsg_t *rp = &RxFifo->data[RxFifo->head];#if 0 /* for testing only */ ecr = CANinl(minor, ecr); printk("==>\nstatus = 0x%04x + 0x%04x\n", (unsigned int)(sr & 0xffff0000ul) >> 16, (unsigned int)(sr & 0xFFFF)); printk(" rxe %3d; txe %3d\n", (int)(ecr & 0xff), (int)(ecr & 0x00ff0000ul) >> 16);#endif /* fill timestamp as first action. * Getting a precises time takes a lot of time * (additional 7 祍 of ISR time ) * if a time stamp is not needed, it can be switched of * by ioctl() */ if (use_timestamp[minor]) { do_gettimeofday(×tamp); } else { timestamp.tv_sec = 0; timestamp.tv_usec = 0; } /* here must be the for-loop for multiple rx queues */ for(rx_fifo = 0; rx_fifo < CAN_MAX_OPEN; rx_fifo++) { RxFifo = &Rx_Buf[minor][rx_fifo]; rp = &RxFifo->data[RxFifo->head]; RxFifo->data[RxFifo->head].timestamp = timestamp; /* preset flags */ rp->flags = (RxFifo->status & BUF_OVERRUN ? MSG_BOVR : 0); if(state == passive) { rp->flags |= MSG_PASSIVE; } } rx_fifo = 0; /* The CAN Status register indicates for each Mailbox an * Mailbox Event */ /*========== receive interrupt */ /*=============================*/ if(sr & (1 << RECEIVE_STD_OBJ)) { int ext; int data; u32 mid; unsigned int oid = 0xffffffff; /* pre set with 'error' */ /* printk("RX ISR, sr=0x%08x\n", sr); */ /* CAN_OBJ[RECEIVE_STD_OBJ].mmr = 0; */ mid = CAN_OBJ[RECEIVE_STD_OBJ].mid; ext = (mid & 0x20000000) ? 1 : 0; /* printk(" ID = 0x%x\n", mid); */ if(ext) { /* printk(" xID = 0x%x\n", CAN_READ_XOID(RECEIVE_STD_OBJ)); */ /* printk(" xID = 0x%x\n", mid & 0x1fffffff); */ /* oid = CAN_READ_XOID(RECEIVE_STD_OBJ); */ oid = mid & 0x1fffffff; rp->flags |= MSG_EXT; } else { /* printk(" sID = 0x%x\n", CAN_READ_OID(RECEIVE_STD_OBJ)); */ /* printk(" sID = 0x%x\n", (mid & 0x03fc0000) >> 18); */ /* oid = CAN_READ_OID(RECEIVE_STD_OBJ); */ oid = (mid & 0x01ffc0000) >> 18; } /* ---------- fill frame data -------------------------------- */ /* 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]; /* use it */ rp = &RxFifo->data[RxFifo->head];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -