2016-02-08 03:37 AM
Problem with the CAN Tx dropping packets.
I am testing by sending 8192 packets to a CAN Bus analyzer. each test packet is less than 8 data bytes. After about 60 packets have been sent at 250kBaud about half of the remaining are dropped. No indication of errors.Anything obvious I am doing wrong here?void setupCAN( void ){ float baudrate = (float)Calibrate.CAN_Baudrate, quanta, prescalar; uint8_t initStatus = CAN_InitStatus_Failed; CAN_DeInit( CAN1 ); //CAN cell init CANInit.CAN_TTCM = DISABLE; CANInit.CAN_ABOM = DISABLE; CANInit.CAN_AWUM = DISABLE; CANInit.CAN_NART = DISABLE;// CANInit.CAN_NART = ENABLE; CANInit.CAN_RFLM = ENABLE; //Discard incoming messages on FIFO overrun CANInit.CAN_TXFP = ENABLE; //Use as a FIFO where the priority order is given by the transmit request order CANInit.CAN_Mode = CAN_Mode_Normal; CANInit.CAN_SJW = CAN_SJW_1tq; CANInit.CAN_BS1 = CAN_BS1_9tq; CANInit.CAN_BS2 = CAN_BS2_1tq; quanta = 11; prescalar = 32768000 / (baudrate * quanta); CANInit.CAN_Prescaler = (uint16_t)( prescalar + 0.5 ); //Make sure we round to nearest whole number initStatus = CAN_Init(CAN1, &CANInit); if (initStatus == CAN_InitStatus_Failed) {Error.canRxError = true; Error.canTxError = true;} //CAN filter init ''FIFO0'' - we are only going to use this one in practice CANFilter.CAN_FilterNumber = 0; CANFilter.CAN_FilterMode = CAN_FilterMode_IdMask; CANFilter.CAN_FilterScale = CAN_FilterScale_32bit; CANFilter.CAN_FilterIdHigh = Calibrate.CAN_FilterIdHigh; CANFilter.CAN_FilterIdLow = Calibrate.CAN_FilterIdLow; CANFilter.CAN_FilterMaskIdHigh = Calibrate.CAN_FilterMaskIdHigh; CANFilter.CAN_FilterMaskIdLow = Calibrate.CAN_FilterMaskIdLow; CANFilter.CAN_FilterFIFOAssignment = 0; CANFilter.CAN_FilterActivation = ENABLE; CAN_FilterInit(&CANFilter); //Filling out the defaults in the Tx struct for CAN bus CANTxMessage.DLC = 8; //Default number of data bytes to send CANTxMessage.ExtId = 0; //No extended ID CANTxMessage.IDE = CAN_ID_STD; //Base Frame identifier CANTxMessage.RTR = CAN_RTR_DATA; //Remote transmission request for data frame CANTxMessage.StdId = Calibrate.CAN_stdID; //Our frame ID for data transmitted from the SoS board } ///////////////////////////////////////////////////////////////////////////// /// @brief The CAN bus transmit string function /// @note We just break the string into 8 byte chunks and transmit them /// If we cannot exactly divide by 8 then we pad the last few bytes with 0 /// Remember we are sending ASCII and 0 is a clear ''non data'' byte /// @param[in] pStr Pointer to the string /// @param[in] numBytes Number of bytes to send /// @return Boolean pass or fail - false==fail, true==pass /////////////////////////////////////////////////////////////////////////////bool stringToCAN( char* pStr, int numBytes ){ int i; char data; uint8_t mailBoxNumber=CAN_TxStatus_NoMailBox, dlc=8, canTxStatus=CAN_TxStatus_Failed; bool status=PASS; while (numBytes > 0) { watchdog(); // Kick the dog on long data dumps if (numBytes < 8) { dlc = numBytes; //Number of bytes, less than 8, that remain to be sent CANTxMessage.DLC = dlc; } else { CANTxMessage.DLC = 8; } for (i=0; i<dlc; i++) { data = *(pStr++); CANTxMessage.Data[i] = data; numBytes--; } while( mailBoxNumber == CAN_TxStatus_NoMailBox ) //Only transmit when mailbox is available { mailBoxNumber = CAN_Transmit( CAN1, &CANTxMessage ); } canTxStatus = CAN_TxStatus_Pending; while( canTxStatus == CAN_TxStatus_Pending ) { canTxStatus = CAN_TransmitStatus(CAN1, mailBoxNumber); } if (canTxStatus == CAN_TxStatus_Failed) { Error.canTxError = true; } } return( status );} #bxcan #!stm322016-02-09 02:33 AM
Update - If I put a 1mS delay between packet transmissions I do not lose packets. Looks like I am overwriting the Tx buffer somehow
2016-02-10 08:06 AM
Hi bigden.gary,
Thanks for your feedback and contribution by putting the solution you found.It seems you are using standard library, so Take a look to the
CAN_Networking
example which include similar use case at this path :stm32f30x_dsp_stdperiph_lib\STM32F30x_DSP_StdPeriph_Lib\Projects\STM32F30x_StdPeriph_Examples\CAN\CAN_Networking
-Hannibal-
Problem with the CAN Tx dropping packets.
I am testing by sending 8192 packets to a CAN Bus analyzer. each test packet is less than 8 data bytes. After about 60 packets have been sent at 250kBaud about half of the remaining are dropped. No indication of errors. Anything obvious I am doing wrong here? void setupCAN( void ) { float baudrate = (float)Calibrate.CAN_Baudrate, quanta, prescalar; uint8_t initStatus = CAN_InitStatus_Failed; CAN_DeInit( CAN1 ); //CAN cell init CANInit.CAN_TTCM = DISABLE; CANInit.CAN_ABOM = DISABLE; CANInit.CAN_AWUM = DISABLE; CANInit.CAN_NART = DISABLE; // CANInit.CAN_NART = ENABLE; CANInit.CAN_RFLM = ENABLE; //Discard incoming messages on FIFO overrun CANInit.CAN_TXFP = ENABLE; //Use as a FIFO where the priority order is given by the transmit request order CANInit.CAN_Mode = CAN_Mode_Normal; CANInit.CAN_SJW = CAN_SJW_1tq; CANInit.CAN_BS1 = CAN_BS1_9tq; CANInit.CAN_BS2 = CAN_BS2_1tq; quanta = 11; prescalar = 32768000 / (baudrate * quanta); CANInit.CAN_Prescaler = (uint16_t)( prescalar + 0.5 ); //Make sure we round to nearest whole number initStatus = CAN_Init(CAN1, &CANInit); if (initStatus == CAN_InitStatus_Failed) {Error.canRxError = true; Error.canTxError = true;} //CAN filter init ''FIFO0'' - we are only going to use this one in practice CANFilter.CAN_FilterNumber = 0; CANFilter.CAN_FilterMode = CAN_FilterMode_IdMask; CANFilter.CAN_FilterScale = CAN_FilterScale_32bit; CANFilter.CAN_FilterIdHigh = Calibrate.CAN_FilterIdHigh; CANFilter.CAN_FilterIdLow = Calibrate.CAN_FilterIdLow; CANFilter.CAN_FilterMaskIdHigh = Calibrate.CAN_FilterMaskIdHigh; CANFilter.CAN_FilterMaskIdLow = Calibrate.CAN_FilterMaskIdLow; CANFilter.CAN_FilterFIFOAssignment = 0; CANFilter.CAN_FilterActivation = ENABLE; CAN_FilterInit(&CANFilter); //Filling out the defaults in the Tx struct for CAN bus CANTxMessage.DLC = 8; //Default number of data bytes to send CANTxMessage.ExtId = 0; //No extended ID CANTxMessage.IDE = CAN_ID_STD; //Base Frame identifier CANTxMessage.RTR = CAN_RTR_DATA; //Remote transmission request for data frame CANTxMessage.StdId = Calibrate.CAN_stdID; //Our frame ID for data transmitted from the SoS board } ///////////////////////////////////////////////////////////////////////////// /// @brief The CAN bus transmit string function /// @note We just break the string into 8 byte chunks and transmit them /// If we cannot exactly divide by 8 then we pad the last few bytes with 0 /// Remember we are sending ASCII and 0 is a clear ''non data'' byte /// @param[in] pStr Pointer to the string /// @param[in] numBytes Number of bytes to send /// @return Boolean pass or fail - false==fail, true==pass ///////////////////////////////////////////////////////////////////////////// bool stringToCAN( char* pStr, int numBytes ) { int i; char data; uint8_t mailBoxNumber=CAN_TxStatus_NoMailBox, dlc=8, canTxStatus=CAN_TxStatus_Failed; bool status=PASS; while (numBytes > 0) { watchdog(); // Kick the dog on long data dumps if (numBytes < 8) { dlc = numBytes; //Number of bytes, less than 8, that remain to be sent CANTxMessage.DLC = dlc; } else { CANTxMessage.DLC = 8; } for (i=0; i<dlc; i++) { data = *(pStr++); CANTxMessage.Data[i] = data; numBytes--; } while( mailBoxNumber == CAN_TxStatus_NoMailBox ) //Only transmit when mailbox is available { mailBoxNumber = CAN_Transmit( CAN1, &CANTxMessage ); } canTxStatus = CAN_TxStatus_Pending; while( canTxStatus == CAN_TxStatus_Pending ) { canTxStatus = CAN_TransmitStatus(CAN1, mailBoxNumber); } if (canTxStatus == CAN_TxStatus_Failed) { Error.canTxError = true; } } return( status ); }2016-02-10 08:23 AM
Thanks, but they apparently make it work using this bit of code:
CAN_Transmit(CANx, &TxMessage); Delay();With the delay just being a loop decrementing from 0xFFF.Which is just a totally crap. In no way does it help maximize bus throughput or stability, and anyone putting that into a production bit of code ought to be fired.2016-04-05 06:13 AM
Hi bigden.gary,
Your feedback has been reported internally. -Hannibal-