cancel
Showing results for 
Search instead for 
Did you mean: 

CAN Bus Tx packets missing [STM32F303x]

gbigden
Associate III
Posted on February 08, 2016 at 12:37

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 #!stm32
4 REPLIES 4
gbigden
Associate III
Posted on February 09, 2016 at 11:33

Update - If I put a 1mS delay between packet transmissions I do not lose packets. Looks like I am overwriting the Tx buffer somehow

Walid FTITI_O
Senior II
Posted on February 10, 2016 at 17:06

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 );

}
gbigden
Associate III
Posted on February 10, 2016 at 17:23

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.

Walid FTITI_O
Senior II
Posted on April 05, 2016 at 15:13

Hi bigden.gary,

Your feedback has been reported internally.

-Hannibal-