Question
Potential issue in std_periph CAN library, STM32F4xx specifically
Posted on April 21, 2015 at 22:34
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
#can