AnsweredAssumed Answered

Problem with generated CAN_LDD driver code for FlexCAN

Question asked by Laartoor on Apr 8, 2014
Latest reply on Nov 7, 2014 by Alessandro Vagniluca

When I look at the generated code for sending a frame, I wonder whether there is a race condition in it.

The code looks like this:

  uint32_t StatusReg = CAN_PDD_GetStatusInterruptFlags1(CAN0_BASE_PTR); /* Read content of the status register */
  .... // other error checks
  if ((StatusReg & (CAN_PDD_RECEIVING_MESSAGE | CAN_PDD_TRANSMITTING_MESSAGE)) != 0x00U) {
    return ERR_BUSY;                   /* If yes then error */
  }
  /* {MQXLite RTOS Adapter} Critical section begin (RTOS function call is defined by MQXLite RTOS Adapter property) */
  _int_disable();
  CAN_PDD_SetMessageBufferCode(CAN0_BASE_PTR, BufferIdx, CAN_PDD_MB_TX_NOT_ACTIVE); /* Set TX Buffer Inactive */
  .... /// Filling the buffer
  CAN_PDD_SetMessageBufferCode(CAN0_BASE_PTR, BufferIdx, TxMBCode); /* Set code for Tx buffer of the message */
  /* {MQXLite RTOS Adapter} Critical section ends (RTOS function call is defined by MQXLite RTOS Adapter property) */
  _int_enable();
  return ERR_OK;

 

I see the following problems with it:

a) the code can be interrupted in any place between lines 1 and 7, meaning that with a sufficiently long delay the message buffer will be updated while the module is active.

b) the code checks the global activity flag, instead of checking the buffer to be updated. With a high load on the CAN bus, this will lead to extra delays.

c) the code disables interrupts while it updates the buffer content. Is this really necessary given that FlexCAN will not touch buffers marked as inactive?

 

Would this at least be correct?

  uint32_t StatusReg;
  .... // other error checks
  _int_disable();
  StatusReg = CAN_PDD_GetStatusInterruptFlags1( CAN0_BASE_PTR);
  if ((StatusReg & (CAN_PDD_RECEIVING_MESSAGE | CAN_PDD_TRANSMITTING_MESSAGE)) != 0x00U) {
    _int_enable();
    return ERR_BUSY;
  }
  CAN_PDD_SetMessageBufferCode( CAN0_BASE_PTR, BufferIdx, CAN_PDD_MB_TX_NOT_ACTIVE); 
  _int_enable();
  .... // Fill the buffer
  CAN_PDD_SetMessageBufferCode( CAN0_BASE_PTR, BufferIdx, TxMBCode);
  return ERR_OK;

 

I still wonder whether the delay between checking the CAN activity and updating the buffer code is guaranteed to be short enough to not cause any interference.

Outcomes