Hi,
I'm putting together a very basic MCAN class on a SAME70Q21B, the relevant code of which aligns with the ASF Quick Start 'qs_mcan_basic.c' NEW_MESSAGE interrupt approach as follows:
if (status & MCAN_RX_FIFO_0_NEW_MESSAGE) { mcan_clear_interrupt_status(&mcan_instance, MCAN_RX_FIFO_0_NEW_MESSAGE); mcan_get_rx_fifo_0_element(&mcan_instance, &rx_element_fifo_0, standard_receive_index); mcan_rx_fifo_acknowledge(&mcan_instance, 0, standard_receive_index); standard_receive_index++; if (standard_receive_index == CONF_MCAN0_RX_FIFO_0_NUM) { standard_receive_index = 0; } printf("\n\r Standard message received in FIFO 0. The received data is: \r\n"); for (i = 0; i < rx_element_fifo_0.R1.bit.DLC; i++) { printf(" %d",rx_element_fifo_0.data[i]); } printf("\r\n\r\n"); }
I won't focus too much on the above, as my MCAN configuration (I'm using MCAN0) works as expected, and the NEW_MESSAGE interrupt is fired when I send a CAN packet from the remote CAN device as expected. The very first CAN packet received is processed correctly (i.e. the DLC count is correct, as are the Data bytes), however, for any packets sent after the first one, the packet might be correctly processed, or the packet might be completely empty. I have my oscilloscope connected to the bus, and can confirm that the packets are being sent correctly.
In the above code, the ASF function where the received data is read from the FIFO is:
mcan_get_rx_fifo_0_element(&mcan_instance, &rx_element_fifo_0, standard_receive_index);
The mcan_get_rx_fifo_0_element function reads the received CAN data out of the pre-configured FIFO array at the provided index into the provided 'mcan_rx_element_fifo_0' struct (rx_element_fifo_0 in the above code):
Nothing unexpected here, it simply checks whether the MCAN instance is MCAN0 or MCAN1, then uses memcpy() to copy the FIFO data from the current mcan0_rx_fifo_0 index into the mcan_rx_element_fifo_0 struct pointer.
I've stepped through the code with my debugger, and have identified this function as the cause of the issue I'm seeing. I've included screenshots of my Atmel Studio interface below to highlight the issue.
I've stopped the debugger on the memcpy() function and added watches on the index value, as well as on the mcan0_rx_fifo_0 array at the index value. Note that this is the second packet received (i.e. index value 1), where the first packet received (i.e. index value 0) is always processed correctly. As you can see, there are 8 bytes of data in mcan0_rx_fifo_0 at index 1 (each packet sent has the same Arbitration ID and the same 8 incrementing bytes of data).
In the next screenshot, I've advanced the debugger by a single step, such that the memcpy() operation has been executed. I've added watches on each of the struct components of the rx_element struct; R0, R1 and data. As you can see, all struct variables are 0x00.
How is this possible? From the first screenshot we can clearly see that the source for the memcpy() function is valid, yet the destination buffer is completely empty after the memcpy() function has executed?
As mentioned earlier, whether this memcpy() execution results in a correct rx_element struct or an empty one seems to be random. I've sent several hundred packets (all with the same Arbitration ID, DLC and data bytes), and the resultant rx_element struct is sporadically full or empty.
Any thoughts on this would be greatly appreciated as always!