Top level api function CAN::write calls can_write inside can_api.c. It is supposed to return 1 if the write was a success but 0 if the write failed. As it stands now it will only ever return a 1. I updated it so if the mailboxes are full it returns a 0 as expected. It appears likely this was the intended behavior. My solution was to introduce a success variable that is only set to 1 if a free mailbox is found.
\mbed-os\hal\targets\hal\TARGET_STM\TARGET_STM32F0\can_api.c
int can_write(can_t *obj, CAN_Message msg, int cc)
{
int success = 0;
uint32_t transmitmailbox = 5;
CAN_TypeDef *can = (CAN_TypeDef *)(obj->can);
/* Select one empty transmit mailbox */
if ((can->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) {
transmitmailbox = 0;
} else if ((can->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) {
transmitmailbox = 1;
} else if ((can->TSR&CAN_TSR_TME2) == CAN_TSR_TME2) {
transmitmailbox = 2;
} else {
transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
}
if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX) {
can->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
if (!(msg.format)) {
can->sTxMailBox[transmitmailbox].TIR |= ((msg.id << 21) | msg.type);
}
else {
can->sTxMailBox[transmitmailbox].TIR |= ((msg.id << 3) | CAN_ID_EXT | msg.type);
}
/* Set up the DLC */
can->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0;
can->sTxMailBox[transmitmailbox].TDTR |= (msg.len & (uint8_t)0x0000000F);
/* Set up the data field */
can->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)msg.data[3] << 24) |
((uint32_t)msg.data[2] << 16) |
((uint32_t)msg.data[1] << 8) |
((uint32_t)msg.data[0]));
can->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)msg.data[7] << 24) |
((uint32_t)msg.data[6] << 16) |
((uint32_t)msg.data[5] << 8) |
((uint32_t)msg.data[4]));
/* Request transmission */
can->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
success = 1;
}
return success;
}
At a glance, the problem seems to appear for all STM32 targets. A similar change would probably work, but I am not able to check the change for all of these.
A similar problem exists for CAN::read and can_read, where it Always returns 1 when you call the function whether or not there is new data. This behavior does not match the documentation which says it returns 0 if no message has arrived.
Top level api function CAN::write calls can_write inside can_api.c. It is supposed to return 1 if the write was a success but 0 if the write failed. As it stands now it will only ever return a 1. I updated it so if the mailboxes are full it returns a 0 as expected. It appears likely this was the intended behavior. My solution was to introduce a success variable that is only set to 1 if a free mailbox is found.
\mbed-os\hal\targets\hal\TARGET_STM\TARGET_STM32F0\can_api.c
At a glance, the problem seems to appear for all STM32 targets. A similar change would probably work, but I am not able to check the change for all of these.
A similar problem exists for CAN::read and can_read, where it Always returns 1 when you call the function whether or not there is new data. This behavior does not match the documentation which says it returns 0 if no message has arrived.