/* is not very useful! use it if you are sure the tx queu is empty */ int can_Send(struct inode *inode, canmsg_t *Tx) { unsigned int minor = MINOR(inode->i_rdev); canmsg_t tx; if( verify_area(VERIFY_READ,Tx,sizeof(canmsg_t)) ) { return -EINVAL; } __lddk_copy_from_user((canmsg_t *) &tx, (canmsg_t *) Tx,sizeof(canmsg_t)); return CAN_SendMessage(minor, &tx); }
/* is not very useful! use it if you are sure the tx queue is empty */ int can_Send(struct inode *inode, canmsg_t *Tx) { unsigned int minor = iminor(inode); canmsg_t tx; unsigned long _cnt; if( !access_ok(VERIFY_READ, Tx, sizeof(canmsg_t)) ) { return -EINVAL; } __lddk_copy_from_user((canmsg_t *)&tx, (canmsg_t *)Tx, sizeof(canmsg_t)); return CAN_SendMessage(minor, &tx); }
void CAN_Com_LoopBack_IRQ(void) { /* initialize the interrupt controller */ VIC_Config(CAN_ITLine, VIC_IRQ, Priority_1); /* initialize the CAN at a standard bitrate, interrupts enabled */ CAN_InitStructure.CAN_ConfigParameters=CAN_CR_IE; CAN_InitStructure.CAN_Bitrate=CAN_BITRATE_100K; CAN_Init(&CAN_InitStructure); /* switch into Loopback+Silent mode (self-test) */ CAN_EnterTestMode(CAN_TESTR_LBACK | CAN_TESTR_SILENT); /* configure the message objects */ CAN_InvalidateAllMsgObj(); CAN_SetTxMsgObj(CAN_TX_MSGOBJ, CAN_EXT_ID); CAN_SetRxMsgObj(CAN_RX_MSGOBJ, CAN_EXT_ID, 0, CAN_LAST_EXT_ID, TRUE); /* enable global interrupt */ VIC_ITCmd(CAN_ITLine, ENABLE); /* Send the pre-defined frame */ CAN_SendMessage(CAN_TX_MSGOBJ, &TxCanMsg[2]); /* wait until end of transmission */ CAN_WaitEndOfTx(); /* reception and release are done in the interrupt handler */ /* delay to add when the reception occurs */ delay(0x7FF); /* Test Received Msg */ if((RxCanMsg.IdType == CAN_EXT_ID)&&(RxCanMsg.Id == 0x12345678)&&(RxCanMsg.Dlc == 8) &&(RxCanMsg.Data[0]==0x10)&&(RxCanMsg.Data[1]==0x11)&&(RxCanMsg.Data[2]==0x12)&&(RxCanMsg.Data[3]==0x13) &&(RxCanMsg.Data[4]==0x14)&&(RxCanMsg.Data[5]==0x15)&&(RxCanMsg.Data[6]==0x16)&&(RxCanMsg.Data[7]==0x17)){ /*Received Msg OK*/ LED_ON(LD3); } else { /*Received Msg KO*/ LED_ON(LD4); } /* switch back into Normal mode */ CAN_LeaveTestMode(); /* disable interrupts globally */ VIC_ITCmd(CAN_ITLine, DISABLE); }
void CAN_Com_LoopBack(void) { /* initialize the CAN at a standard bitrate, interrupts disabled */ CAN_InitStructure.CAN_ConfigParameters=0x0; CAN_InitStructure.CAN_Bitrate=CAN_BITRATE_1M; CAN_Init(&CAN_InitStructure); /* switch into Loopback+Silent mode (self-test) */ CAN_EnterTestMode(CAN_TESTR_LBACK | CAN_TESTR_SILENT); /* configure the message objects */ CAN_InvalidateAllMsgObj(); CAN_SetTxMsgObj(CAN_TX_MSGOBJ, CAN_STD_ID); CAN_SetRxMsgObj(CAN_RX_MSGOBJ, CAN_STD_ID, 0, CAN_LAST_STD_ID, TRUE); /* Send the pre-defined answer */ CAN_SendMessage(CAN_TX_MSGOBJ, &TxCanMsg[1]); /* wait until end of transmission */ CAN_WaitEndOfTx(); /* wait for reception of a data frame */ while (!CAN_ReceiveMessage(CAN_RX_MSGOBJ, FALSE, &RxCanMsg)) { /*Add Timer*/ } /* Test Received Msg */ if((RxCanMsg.IdType == CAN_STD_ID)&&(RxCanMsg.Id == 0x321)&&(RxCanMsg.Dlc == 4) &&(RxCanMsg.Data[0]==0xAA)&&(RxCanMsg.Data[1]==0x55)&&(RxCanMsg.Data[2]==0xAA)&&(RxCanMsg.Data[3]==0x55)){ /*Received Msg OK*/ LED_ON(LD2); } else { /*Received Msg KO*/ LED_ON(LD4); } /* release the message objects */ CAN_ReleaseTxMessage(CAN_TX_MSGOBJ); CAN_ReleaseRxMessage(CAN_RX_MSGOBJ); /* switch back into Normal mode */ CAN_LeaveTestMode(); }
__LDDK_WRITE_TYPE can_write( __LDDK_WRITE_PARAM ) { unsigned int minor = __LDDK_MINOR; msg_fifo_t *TxFifo = &Tx_Buf[minor]; canmsg_t *addr; canmsg_t tx; unsigned long flags; int written = 0; DBGin("can_write"); #ifdef DEBUG_COUNTER Cnt1[minor] = Cnt1[minor] + 1; #endif /* DEBUG_COUNTER */ /* DEBUG_TTY(1, "write: %d", count); */ DBGprint(DBG_DATA,(" -- write %d msg\n", count)); /* printk("w[%d/%d]", minor, TxFifo->active); */ addr = (canmsg_t *)buffer; if(verify_area(VERIFY_READ, (canmsg_t *)addr, count * sizeof(canmsg_t))) { DBGout();return -EINVAL; } while( written < count ) { /* enter critical section */ save_flags(flags);cli(); /* there are data to write to the network */ if(TxFifo->free[TxFifo->head] == BUF_FULL) { /* DEBUG_TTY(1, "ret buffer full"); */ /* there is already one message at this place */; DBGout(); /* return -ENOSPC; */ return written; } if( TxFifo->active ) { /* more than one data and actual data in queue */ __lddk_copy_from_user( /* copy one message to FIFO */ (canmsg_t *) &(TxFifo->data[TxFifo->head]), (canmsg_t *) &addr[written], sizeof(canmsg_t) ); /* DEBUG_TTY(1, " fifo active: id %d/%x; head %d/tail %d", */ /* TxFifo->data[TxFifo->head].id, */ /* TxFifo->data[TxFifo->head].id, */ /* TxFifo->head, */ /* TxFifo->tail); */ TxFifo->free[TxFifo->head] = BUF_FULL; /* now this entry is FULL */ TxFifo->head = ++(TxFifo->head) % MAX_BUFSIZE; } else { __lddk_copy_from_user( (canmsg_t *) &tx, (canmsg_t *) &addr[written], sizeof(canmsg_t) ); /* DEBUG_TTY(1, " fifo in-active: id %d/%x; head %d/tail %d", */ /* tx.id, tx.id, */ /* TxFifo->head, */ /* TxFifo->tail ); */ /* f - fast -- use interrupts */ // Hack hobe TxFifo->active = 0; wird normalerweise auf 1 gesetzt --> und wenn der Inaterrupt // kommt dann wird in Can_Interrupt TxFifo->active wieder zurückgesetzt!!! if( count >= 1 ) { /* !!! CHIP abh. !!! */ TxFifo->active = 1; } CAN_SendMessage( minor, &tx); /* Send, no wait */ } written++; /* leave critical section */ restore_flags(flags); } /* printk("W[%d/%d]", minor, TxFifo->active); */ DBGout(); return written; }
__LDDK_WRITE_TYPE can_write( __LDDK_WRITE_PARAM ) { unsigned int minor = __LDDK_MINOR; msg_fifo_t *TxFifo = &Tx_Buf[minor]; canmsg_t *addr; canmsg_t tx; unsigned long flags = 0; /* still needed for local_irq_save() ? */ int written = 0; int blocking; unsigned long _cnt; DBGin(); /* spin_lock_irqsave(&write_splock[minor], flags ); */ #ifdef DEBUG_COUNTER Cnt1[minor] = Cnt1[minor] + 1; #endif /* DEBUG_COUNTER */ /* detect write mode */ blocking = !(file->f_flags & O_NONBLOCK); DBGprint(DBG_DATA,(" -- write %d msg, blocking=%d", (int)count, blocking)); /* printk("w[%d/%d]", minor, TxFifo->active); */ addr = (canmsg_t *)buffer; if(!access_ok(VERIFY_READ, (canmsg_t *)addr, count * sizeof(canmsg_t))) { written = -EINVAL; goto can_write_exit; } /* enter critical section */ local_irq_save(flags); while( written < count ) { if(virtual != 0) { /* virtual CAN write, put the frame in all RX queues only */ int rx_fifo; msg_fifo_t *RxFifo; int16_t myindex = (int16_t)((struct _instance_data *)(file->private_data))->rx_index; struct timeval timestamp; DBGprint(DBG_DATA,(" -- write msg %d, virtual, blocking=%d, size=%d", (int)written, blocking, (int)sizeof(canmsg_t))); /* depending on the number of open processes * the TX data has to be copied in different * RX FIFOs */ /* get one message from the userspace buffer */ /* FIXME: with CANFD, does it make sense to copy only the number * of data bytes specified in the length field of canmsg_t ? * Instead of sizeof(canmsg_t) it is something like * sizeof(canmsg_t) - CAN_MSG_LENGTH + length */ __lddk_copy_from_user( (canmsg_t *) &tx, (canmsg_t *) &addr[written], sizeof(canmsg_t) ); /* we are taking this as receive time stamp */ if (use_timestamp[minor]) { do_gettimeofday(×tamp); } else { timestamp.tv_sec = 0; timestamp.tv_usec = 0; } 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 */ /* printk(KERN_INFO "self copy to [%d][%d]\n", minor, rx_fifo); */ /* * Don't copy the message in the receive queue * of the process that sent the message unless * this process requested selfreception. */ if ((myindex == rx_fifo) && (selfreception[minor][rx_fifo] == 0)) { /* printk("CAN[%d][%d] Don't copy message in my queue\n", * minor, rx_fifo); */ continue; } // printk( // "CAN[%d][%d] Copy message to queue %d\n", // minor, myindex, rx_fifo); /* prepare buffer to be used */ RxFifo = &Rx_Buf[minor][rx_fifo]; RxFifo->data[RxFifo->head].flags = 0; memcpy( (void *)&RxFifo->data[RxFifo->head], (void *)&tx, sizeof(canmsg_t)); /* Now copy the time stamp to the RX FIFO */ RxFifo->data[RxFifo->head].timestamp.tv_sec = timestamp.tv_sec; RxFifo->data[RxFifo->head].timestamp.tv_usec = timestamp.tv_usec; /* Set software overflow flag */ if((RxFifo->status & BUF_OVERRUN) != 0) { RxFifo->data[RxFifo->head].flags |= MSG_BOVR; } /* Mark message as 'self sent/received' */ if ((myindex == rx_fifo) && (selfreception[minor][rx_fifo] != 0)) { 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 */ } } else { /* we have a real hardware to handle */ /* Do we really need to protect something here ???? * e.g. in this case the TxFifo->free[TxFifo->head] value * * If YES, we have to use spinlocks for synchronization */ /* - new Blocking code -- */ if(blocking) { if(wait_event_interruptible(CanOutWait[minor], \ TxFifo->free[TxFifo->head] != BUF_FULL)) { written = -ERESTARTSYS; goto can_write_exit; } } else { /* there are data to write to the network */ if(TxFifo->free[TxFifo->head] == BUF_FULL) { /* but there is already one message at this place */; /* write buffer full in non-blocking mode, leave write() */ goto can_write_exit; } } /* ---- */ /* * To know which process sent the message we need an index. * This is used in the TX IRQ to decide in which receive queue * this message has to be copied (selfreception) */ addr[written].cob = (int16_t)((struct _instance_data *)(file->private_data))->rx_index; if( TxFifo->active ) { /* more than one data and actual data in queue, * add this message to the Tx queue */ __lddk_copy_from_user( /* copy one message to FIFO */ (canmsg_t *) &(TxFifo->data[TxFifo->head]), (canmsg_t *) &addr[written], sizeof(canmsg_t) ); TxFifo->free[TxFifo->head] = BUF_FULL; /* now this entry is FULL */ /* TxFifo->head = ++(TxFifo->head) % MAX_BUFSIZE; */ ++TxFifo->head; (TxFifo->head) %= MAX_BUFSIZE; } else { /* copy message into local canmsg_t structure */ __lddk_copy_from_user( (canmsg_t *) &tx, (canmsg_t *) &addr[written], sizeof(canmsg_t) ); /* f - fast -- use interrupts */ if( count >= 1 ) { /* !!! CHIP abh. !!! */ TxFifo->active = 1; } /* write CAN msg data to the chip and enable the tx interrupt */ CAN_SendMessage( minor, &tx); /* Send, no wait */ } /* TxFifo->active */ } written++; }