Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
k7g03z opened this issue Sep 28, 2022 · 2 comments

Comments

@k7g03z
Copy link

k7g03z commented Sep 28, 2022

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:

typedef uint32_t qemu_canid_t;

/*
 * 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:

uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;

And no message will land in the QEMU receive FIFO.

@gvikram31
Copy link

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
Copy link
Author

k7g03z commented Oct 4, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants