📄 at9263funcs.c
字号:
rp->id = oid; /* printk(" X = %d\n", ext); */ ext = CAN_OBJ[RECEIVE_STD_OBJ].msr; rp->length = (ext & 0x000f0000) >> 16; ext = (ext & CANBIT_MSR_MRTR) ? 1 : 0; /* printk(" DLC = %d %s\n", rp->length, ext ? "- RTR" : ""); */ if(ext) { rp->flags |= MSG_RTR; } rp->length = (CAN_OBJ[RECEIVE_STD_OBJ].msr & 0x000f0000) >> 16; /* Get data bytes FIXME: Don't take care of message length for now */ data = CAN_OBJ[RECEIVE_STD_OBJ].mdl; rp->data[0] = (u8)data; rp->data[1] = (u8)(data >> 8); rp->data[2] = (u8)(data >> 16); rp->data[3] = (u8)(data >> 24); data = CAN_OBJ[RECEIVE_STD_OBJ].mdh; rp->data[4] = (u8)data; rp->data[5] = (u8)(data >> 8); rp->data[6] = (u8)(data >> 16); rp->data[7] = (u8)(data >> 24); RxFifo->status = BUF_OK; RxFifo->head = ++(RxFifo->head) % MAX_BUFSIZE; if(RxFifo->head == RxFifo->tail) { printk(KERN_WARNING "CAN[%d] RX: FIFO overrun\n", minor); 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]); /* check for CAN controller overrun */ } } /* reset interrupt condition of this object */ CAN_OBJ[RECEIVE_STD_OBJ].mcr = CANBIT_MCR_MTCR; } /*========== transmit interrupt */ /*=============================*/ if(sr & (1 << TRANSMIT_OBJ)) { /* CAN frame successfully sent */ canmsg_t *tp = &TxFifo->data[TxFifo->tail]; /* use time stamp sampled with last INT */ last_Tx_object[minor].timestamp = timestamp; /* depending on the number of open processes * the TX data has to be copied in different * 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 */ /* * Don't copy the message in the receive queue * of the process that sent the message unless * this process requested selfreception. */ if ((last_Tx_object[minor].cob == rx_fifo) && (selfreception[minor][rx_fifo] == 0)) { continue; } /* prepare buffer to be used */ RxFifo = &Rx_Buf[minor][rx_fifo]; memcpy( (void *)&RxFifo->data[RxFifo->head], (void *)&last_Tx_object[minor], sizeof(canmsg_t)); /* Mark message as 'self sent/received' */ RxFifo->data[RxFifo->head].flags |= MSG_SELF; /* increment write index */ RxFifo->status = BUF_OK; 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]); } /* this FIFO is in use */ } /* end for loop filling all rx-fifos */ /* Reset Interrupt Flag of transmit object * mailbox mode register */ CAN_OBJ[TRANSMIT_OBJ].mmr = 0; if( TxFifo->free[TxFifo->tail] == BUF_EMPTY ) { /* TX FIFO empty, nothing more to sent */ /* printk("TXE\n"); */ TxFifo->status = BUF_EMPTY; TxFifo->active = 0; /* This function will wake up all processes that are waiting on this event queue, that are in interruptible sleep */ wake_up_interruptible(&CanOutWait[minor]); goto Tx_done; } /* enter critical section */ local_irq_save(iflags); /* The TX message FIFO contains other CAN frames to be sent * The next frame in the FIFO is copied into the last_Tx_object * and directly into the hardware of the CAN controller */ /* The TX message FIFO contains other CAN frames to be sent * The next frame in the FIFO is copied into the last_Tx_object * and directly into the hardware of the CAN controller */ memcpy( (void *)&last_Tx_object[minor], (void *)&TxFifo->data[TxFifo->tail], sizeof(canmsg_t)); /* 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(tp->flags & MSG_EXT) { /* use ID in extended message format */ CAN_WRITE_XOID(TRANSMIT_OBJ, tp->id); } else { CAN_WRITE_OID(TRANSMIT_OBJ, tp->id); } /* - fill data -------------------------------------------------- */ /* FIXME: Don't take care of message length for now */ CAN_OBJ[TRANSMIT_OBJ].mdl = tp->data[0] + (tp->data[1] << 8) + (tp->data[2] << 16) + (tp->data[3] << 24); CAN_OBJ[TRANSMIT_OBJ].mdh = tp->data[4] + (tp->data[5] << 8) + (tp->data[6] << 16) + (tp->data[7] << 24); /* - /end -------------------------------------------------------- */ if( tp->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 = (tp->length << CANBIT_MCR_MDLC_POS) + ((tp->flags & MSG_RTR) ? CANBIT_MCR_MRTR : 0ul) + CANBIT_MCR_MTCR; /* now this entry is EMPTY */ TxFifo->free[TxFifo->tail] = BUF_EMPTY; TxFifo->tail = ++(TxFifo->tail) % MAX_BUFSIZE; local_irq_restore(iflags); Tx_done: ; } /* Tx ISR */ /*=========== status interrupt */ /*=============================*/ /* take care of: * in Error Passive State, also ERRA bit is set */ if(sr & ( CANBIT_SR_BOFF + CANBIT_SR_ERRA + CANBIT_SR_ERRP )) { int status_changed = 0; char *m = NULL; /* printk(">> state = %d, status_changed %d\n", state, status_changed ); */ if(sr & CANBIT_SR_BOFF) { m = "BusOFF"; sr &= ~CANBIT_SR_BOFF; /* reset error passive bit */ /* Bus-Off: disable the Controller - the user has to call Start_CAN() */ CANoutl(minor, mode, CANBIT_MR_CANDIS); /* disable the IRQ. * If no Busoff, we enable the IRQ again. */ CANoutl(minor, idr, CANBIT_IR_BOFF); errorints++; if(state != busoff); { /* printk(" CAN_Status %s Interrupt(%d)\n", m, errorints); */ state = busoff; fflags = MSG_BUSOFF; status_changed = 1; } goto signal_error; } if(sr & CANBIT_SR_ERRP) { m = "ErrorPassive"; sr &= ~CANBIT_SR_ERRP; /* reset error passive bit */ if(state != passive) { state = passive; fflags = MSG_PASSIVE; status_changed = 1; } errorints++; CANoutl(minor, idr, CANBIT_IR_ERRP); /* printk("Imask = 0x%08x stat = 0x%08x\n", CANinl(minor, imr), CANinl(minor, sr)); */ } else if(sr & CANBIT_SR_ERRA) { m = "ErrorActive"; sr &= ~CANBIT_SR_ERRA; /* reset error passive bit */ if(state != active) { state = active; fflags = 0; status_changed = 1; CANoutl(minor, ier, CANBIT_IR_BOFF + CANBIT_IR_ERRP /* + CANBIT_IR_ERRA */ ); } errorints = 0; } if (m != NULL && status_changed) { /* printk(" CAN Status %s Interrupt(%d)\n", m, errorints); */ ; } if(errorints > 40) { /* disable all error interrupts */ CANoutl(minor, idr, CANBIT_IR_BOFF + CANBIT_IR_ERRP + CANBIT_IR_ERRA); } signal_error: /* Insert CAN error in rx queues */ if(status_changed) { /* generate a pseude message with id 0xffffffff */ /* and put it in every rx queu where someone is waiting */ 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 = fflags; (RxFifo->data[RxFifo->head]).id = CANDRIVERERROR; (RxFifo->data[RxFifo->head]).length = 0; RxFifo->status = BUF_OK; /* handle fifo 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; } /* tell someone that there is a new error message */ wake_up_interruptible(&CanWait[minor][rx_fifo]); status_changed = 0; } /* this FIFO is in use */ } /* end for loop filling all rx-fifos */ } /* Status changed */ } /* end status interrupt */ break; /* TODO: looping through all interruts */ } /* while interrupt available */#if CONFIG_TIME_MEASURE reset_led();#endif return IRQ_RETVAL(IRQ_HANDLED);}/* dump all global CAN registers to printk */void CAN_register_dump(int minor){/* pointer to the global registers of the CAN memory map */volatile at9263can_t *at_can = (at9263can_t *)(can_base[minor]);unsigned long s; printk("ATMEL AT91SAM9263 CAN register layout\n");#define printregister(name) printk(" " #name " \t%p %0x\n", &name , name) printregister(CAN_Mode); printregister(CAN_InterruptEnableRegister); printregister(CAN_InterruptDisableRegister); printregister(CAN_InterruptMaskRegister); printregister(CAN_StatusRegister); s = CAN_StatusRegister; printk(" %s ", (s & CANBIT_SR_ERRA) ? "ERROR-Actve" : ""); printk("%s ", (s & CANBIT_SR_ERRP) ? "ERROR-Passive" : ""); printk("%s ", (s & CANBIT_SR_BOFF) ? "Bus-Off" : ""); printk("%s\n", (s & CANBIT_SR_WARN) ? "Warning-Limit" : ""); printregister(CAN_BaudrateRegister); printregister(CAN_TimerRegister); printregister(CAN_TimeStampRegister); printregister(CAN_ErrorCounterRegister); printregister(CAN_TransferCommandRegister); printregister(CAN_AbortCommandRegister); printk("\n");}/* dump the content of the selected message object (MB) to printk * * only 2byte word or short int access is allowed, * each register starts on a 4 byte boundary * Mailbox 0 starts at 0xFFC02C00 * Each Mailbox is built from 8 word registers * * Additional information is unfortunately located on other memory * locations like the acceptance masks*/void CAN_object_dump(int minor, int object){unsigned long v; /* content value of an register */char *m;/* pointer to an CAN object, "Mailbox" according to the ATMEL doc */volatile unsigned long *cp = (unsigned long *)(can_base[minor] + 0x200 + (0x20 * object)); printk(KERN_INFO "CAN object %d (at %p)\n", object, cp); for(v = 0; v < 8; v++) { printk("%8lx ", *(cp + (v * 4))); if (v == 3) printk("| "); } printk("\n"); v = CAN_OBJ[object].mmr; v &= CANBIT_MMR_MOT_MSK; switch(v) { case CANBIT_MMR_MOT_DISABLE: m = "mailbox disabled"; break; case CANBIT_MMR_MOT_RX: m = "reception mailbox"; break; case CANBIT_MMR_MOT_RX_OVL: m = "reception mailbox with overwrite"; break; case CANBIT_MMR_MOT_TX: m = "transmit mailbox"; break; case CANBIT_MMR_MOT_RX_RTR: m = "consumer mailbox"; break; case CANBIT_MMR_MOT_TX_RTR: m = "producer mailbox"; break; default: m = "reserveed bit combination in MOT"; } printk(KERN_INFO "mailbox type: %s,", m); v = CAN_OBJ[object].msr; printk(" DLC=0x%lx", (v & CANBIT_MSR_MDLC_MSK) >> 16); v = CAN_OBJ[object].msr; printk(" RTR=0x%lx", (v & CANBIT_MSR_MRTR) >> 20); printk(" RDY=0x%lx\n", (v & CANBIT_MSR_MRDY) >> 23); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -