Xilinx / qemu

Xilinx's fork of Quick EMUlator (QEMU) with improved support and modelling for the Xilinx platforms.
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/821395464/QEMU+User+Documentation
Other
231 stars 150 forks source link

MPSoC CAN QEMU acceptance filter register layout not compatible with hardware #74

Open k7g03z opened 1 year ago

k7g03z commented 1 year ago

We have CAN running on both the ZCU104 development board on the R5 cores and also on QEMU as delivered in Vitis/2022.1 (Xilinx_Unified_2022.1_0420_0327.tar.gz)

When we introduced the CAN Acceptance filter API to the hardware code, it worked fine on the hardware, but the same code on QEMU stopped working.

Digging deeper, I believe I found this root cause:

From the definition here: https://github.com/Xilinx/qemu/blob/74d70f8008bfbd1566c2eed3496a077a974de0d0/include/net/can_emu.h#L44

/*
 * Controller Area Network Identifier structure
 *
 * bit 0-28    : CAN identifier (11/29 bit)
 * bit 29      : error frame flag (0 = data frame, 1 = error frame)
 * bit 30      : remote transmission request flag (1 = rtr frame)
 * bit 31      : frame format flag (0 = standard 11 bit, 1 = extended 29 bit)
 */

The CAN_ID has a different bit layout than the MPSoC hardware.

From: https://www.xilinx.com/htmldocs/registers/ug1087/can___afir1.html

Here is the hardware Layout if the Filter ID (same for mask)

Field Name Bits Type Reset Value Description
AIIDH 31:21 rw 0 Standard Message ID / Standard Identifier
AISRR 20 rw 0 Substitute Remote Transmission Request / Indicates the Remote Transmission Request bit for Standard frames
AIIDE 19 rw 0 Identifier Extension / Differentiates between Standard and Extended frames
AIIDL 18:1 rw 0 Extended Message ID Mask Extended Identifier
AIRTR 0 rw 0 Remote Transmission Request Mask RTR bit for Extended frames.

So when we use the settings for the hardware on QEMU, this line will always fail:

https://github.com/Xilinx/qemu/blob/74d70f8008bfbd1566c2eed3496a077a974de0d0/hw/net/can/xlnx-zynqmp-can.c#L641

And no message will land in the QEMU receive FIFO.

gvikram31 commented 1 year ago

Hi, Thanks for filing this issue. Can you please also share your test application? I am interested in knowing the Filters setting and TX data. I think it's failing mostly due to RTR bits or Extended ID bit. We cannot support Remote Transmission requests on emulation bus.

Why order of can_id will not matter: can_id is sent as uint32_t on emulated bus and received as same, so with right AFMR and TX_FIFO_ID, it should pass through filter. QEMU CAN just reads the appropriate data from TX_FIFO_ID and copies whole TX_FIFO_ID to can_id without manipulating the bits. So, even the bits are different, it shouldn't cause failures.

Regards, Vikram

k7g03z commented 1 year ago

Hi @gvikram31 ,

Hi, Thanks for filing this issue. Can you please also share your test application? I am interested in knowing the Filters setting and TX data. I think it's failing mostly due to RTR bits or Extended ID bit. We cannot support Remote Transmission requests on emulation bus.

We are simply sending Standard ID messages, no RTR bit, no extended Frame.

can0  001   [8]  14 B4 00 02 03 00 33 03
can0  001   [8]  13 B4 00 02 03 00 33 03
can0  001   [8]  12 B4 00 02 03 00 33 03
can0  001   [8]  11 B4 00 02 03 00 33 03
can0  001   [8]  0F B4 00 02 03 00 33 03
can0  001   [8]  0E B4 00 02 03 00 33 03
can0  001   [8]  0D B4 00 02 03 00 33 03
can0  001   [8]  0C B4 00 02 03 00 33 03

Why order of can_id will not matter: can_id is sent as uint32_t on emulated bus and received as same, so with right AFMR and TX_FIFO_ID, it should pass through filter. QEMU CAN just reads the appropriate data from TX_FIFO_ID and copies whole TX_FIFO_ID to can_id without manipulating the bits. So, even the bits are different, it shouldn't cause failures.

As I wrote in the original post, the problem occurs when the code we wrote for the MPSoC Hardware (XCZU7EV) is run in the QEMU.

Upon CAN Reception in the hardware, a message with ID 0x001 (as in the above trace) has a received ID as 0x00200000. This fits the hardware definition of shifting the ID 0x001 to the left 21 times...

The Acceptance filter API expects the ID filter and mask to have the same bit layout, therefore for the hardware, we also have to shift the ID bits to the left 21 times so 0x00200000 with pass the filter.

XCanPs_AcceptFilterSet(&CanConfig, XCANPS_AFR_UAF1_MASK,
                         0x7ff << XCANPS_IDR_ID1_SHIFT,
                         0x001 << XCANPS_IDR_ID1_SHIFT);

And now the problem:

Since QEMU has a different bit order in the ID message, the Acceptance filter code breaks above.

Since in QEMU, the same CAN message sent over SocketCAN shows up as 0x00000001 instead of 0x00200000, the QEMU filter drops all the messages.

My expectation is that the Xilinx QEMU implementation of the CanPs code would keep the bit order the same as the hardware implementation.