AnsweredAssumed Answered

Potential issue in std_periph CAN library, STM32F4xx specifically

Question asked by ScottW on Apr 21, 2015
Latest reply on Apr 21, 2015 by peacock.jack.003
Et Al,

Forgive me if this has been addressed already...

I believe I may have found an issue in the stm32f4xx_can.c file.

It can recreated this way:

Consume all the CAN transmit mailboxes by successive calls to CAN_Transmit().  After all of the mailboxes are consumed, CAN_Transmit() returns 'CAN_TxStatus_NoMailBox' (0x04) by way of the following code:
 
/* Select one empty transmit mailbox */
if ((CANx->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
{
  transmit_mailbox = 0;
}
else if ((CANx->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
{
  transmit_mailbox = 1;
}
else if ((CANx->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)
{
  transmit_mailbox = 2;
}
else
{
  transmit_mailbox = CAN_TxStatus_NoMailBox;
}

Then attempt to check the status of the 'errored' mailbox (CAN_TxStatus_NoMailBox) with CAN_TransmitStatus(), which contains the following code:

switch (TransmitMailbox)
{
  case (CAN_TXMAILBOX_0):
    state =   CANx->TSR &  (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0);
    break;
  case (CAN_TXMAILBOX_1):
    state =   CANx->TSR &  (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1);
    break;
  case (CAN_TXMAILBOX_2):
    state =   CANx->TSR &  (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2);
    break;
  default:
    state = CAN_TxStatus_Failed;
    break;
}

With TransmitMailbox argument set to the value of CAN_TxStatus_NoMailBox (0x04), the default case is executed, assigning the value of CAN_TxStatus_Failed (0x00) to 'state'.

In the very next switch statement, 'state' equaling the value of CAN_TxStatus_Failed (0x00) makes the first case true, thus assigning a CAN_TransmitStatus() return value of CAN_TxStatus_Pending (0x02) rather than the expected/desired value of CAN_TxStatus_Failed (0x00).

switch (state)
{
    /* transmit pending  */
  case (0x0): state = CAN_TxStatus_Pending;
    break;

Certainly the programmer can/should check the return value from CAN_Transmit() to determine if it's returning CAN_TxStatus_NoMailBox and not using that value as an argument to CAN_TransmitStatus().  But some defensive programming within CAN_TransmitStatus() could prevent the 'illusion' that a CAN packet sent on an invalid mailbox is pending.

Thoughts?

Scott

Outcomes