cancel
Showing results for 
Search instead for 
Did you mean: 

Potential issue in std_periph CAN library, STM32F4xx specifically

scottwright
Associate
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
1 REPLY 1
jpeacock
Associate III
Posted on April 21, 2015 at 23:05

In my application the situation you describe never occurs because I only use CAN_Transmit after an interrupt signals a mailbox is free.  The CAN stack writes to a message queue which is emptied by the interrupt, so I never stall waiting for a mailbox.

Straight polling, well, the error returned isn't all that important.  There's no mailbox so all you can do is sit and wait.  If you use the TX interrupt the logic in CAN_Transmit makes sense.  With polling the error is incidental, so better it stays as is so it works right with interrupts.

  Jack Peacock