I have a circuit that is happy when both CAN devices are the same baud rate. I have now setup the end device to have a different baud rate at startup to purposefully cause a timeout of the CAN tx message. I feel there is something missing in my 'resetting' of the timeout as the code only works every other time.
What I mean is when F2808 is 20Kbps and end device is 1Mbps, the first time, the F2808 CAN Tx timesout and then moves to a function to update the baudrate to 1Mbps and then the rest of the CAN messages are processed as expected. I then stop the execution and then restart the same code, the F2808 start at 20Kbps, CAN message timesout, switches to 1Mbps but the next message fails but I can't trace why. I then restart the code and the same baud process executes but this time it works as expected. Every other CPU reset it works as expected but every other reset fails.
Seems as if some flag during the failed state is reset when the next CPU reset is issued but I can't seem to find it.
What are some of the key flags to ensure is cleared during a CAN tx timeout, and how do I reset them?
Or should I abort the Tx message before trying to change baud rate (or send another message any time a TO occurs)?
PMDresult CAN_SendCmdMsg(struct CAN_CONFIG* cancfg, Uint16 bytecount, Uint16* bytes) { PMDresult result = PMD_NOERROR; cancfg->TX_MBOX->MSGCTRL.bit.DLC = bytecount; // add bytes to mailbox StuffMailbox(cancfg, bytecount, &bytes[0]); /* Clear the "Time Stamp Counter" */ EALLOW; ECanaRegs.CANTSC = 0; EDIS; ECanRegsShadow.CANTRS.all = 0; ECanRegsShadow.CANTRS.all = cancfg->TX_BIT; // Set TRS for mailbox under test ECanaRegs.CANTRS.all = ECanRegsShadow.CANTRS.all; // // Wait for TAn bits to be set // TODO Set timeouts on all do..while // ECanRegsShadow.CANTA.all = ECanaRegs.CANTA.all; do { ECanRegsShadow.CANTOS.all = ECanaRegs.CANTOS.all; ECanRegsShadow.CANTA.all = ECanaRegs.CANTA.all; } while((ECanRegsShadow.CANTA.all & cancfg->TX_BIT) == 0 && // Wait for TAx = 1 (Successful CAN transmit) (ECanRegsShadow.CANTOS.all & cancfg->TX_BIT) == 0); // TOS = 1 when timeout occurred /* Service a timeout? */ if((ECanRegsShadow.CANTOS.all & cancfg->TX_BIT) == cancfg->TX_BIT) { // timeout occurred so clear the bit and move on ECanRegsShadow.CANTOC.all = ECanaRegs.CANTOC.all; ECanRegsShadow.CANTOC.all = cancfg->TX_BIT; ECanaRegs.CANTOC.all = ECanRegsShadow.CANTOC.all; // CANTOC should be clear now result = PMD_ERR_Timeout; } ECanRegsShadow.CANTA.all = 0; ECanRegsShadow.CANTA.all = cancfg->TX_BIT; // Clear tx bit ECanaRegs.CANTA.all = ECanRegsShadow.CANTA.all; return result; }
/* * This bit globally enables all interrupts for the ECAN0INT line if the corresponding masks are set. */ ECanRegsShadow.CANGIM.all = ECanRegsShadow.CANGIM.all; ECanRegsShadow.CANGIM.bit.I0EN = 1; // Enable eCAN0INT ECanRegsShadow.CANGIM.bit.I1EN = 0; // Disable eCAN1INT ECanRegsShadow.CANGIM.bit.MTOM = 1; // Enable mailbox timeouts ecanregs->CANGIM.all = ECanRegsShadow.CANGIM.all; /* * Setup transmit and receive timeouts * Limit-value of the time-stamp counter (TSC) 100 clocks / uSec * TSC is incremented by bit clock so it is independent of bit per second */ ECanaMOTORegs.MOTO[INIT_TX_CANMBOX] = 0x400; ECanaMOTORegs.MOTO[INIT_RX_CANMBOX] = 0x400; ECanaMOTORegs.MOTO[AZ_TX_CANMBOX] = 0x400; ECanaMOTORegs.MOTO[AZ_RX_CANMBOX] = 0x400; /* Enable time-out function for the mailboxes */ ECanaRegs.CANTOC.all = MAILBOX0BIT | MAILBOX5BIT | MAILBOX16BIT | MAILBOX21BIT; /* Clear the "Time Stamp Counter" */ ECanaRegs.CANTSC = 0;