2025-10-14 2:26 AM - edited 2025-10-14 2:27 AM
I am simulating messages to be received via CAN on the STM32F0xx series uC. The hardware FIFO does not overflow as I have activated the overflow interrupt and checked the FIFO level, which never exceeds 1. The current implementation consists of a 128-byte software buffer. Now, the system is able to handle messages sent at 100 ms intervals. When I start sending messages at 10 ms intervals, it begins to overwrite the previous entry in the buffer. It does so once after a long time of sending messages, and does not happen frequently.
The potential issue is that the interrupt fires every 10 milliseconds, while the main message processing happens every 50 milliseconds, so the buffer is cleared/read after 5 messages have already been sent. What I am noticing is that the current index for the ring buffer "resets" to the previous interrupt's counter value, the occurrence of which is low. Hence, when the message counter in the CAN frame is received, due to the current index being "reset", it overwrites the previous entry in the ring buffer.
My question is, since my function is being called inside HAL_CAN_RxFifo0MsgPendingCallback, is it possible that while servicing the interrupt, the same interrupt fires, the indices for looping through the software buffer did not increment, hence I end up with missing counter values?
Code inside the callback is:
bool msg_to_queue(const CAN_MSG* const rx)
{
bool ret = false;
if ((rx->dlc >= 1u) && (rx->dlc <= CAN_PAYLOAD_SIZE))
{
const uint32_t curr_rx_buf_inp = rx_buf_inp & (MAX_CAN_RECEIVE_MSG - 1u);
const uint32_t next_rx_buf_inp = (curr_rx_buf_inp + 1u) & (MAX_CAN_RECEIVE_MSG - 1u); // is next entry in buffer free
if (next_rx_buf_inp != rx_buf_outp) // if next entry not empty (inp+1 == outp), then discard message
{
rx_buffer[curr_rx_buf_inp] = *rx;
/* Move to next entry */
rx_buf_inp = next_rx_buf_inp;
retval = true; // Success
}
else
{
++can_receive_error_overrun;
}
}
return ret;
}