Xilinx ZynqMP CAN controller logical error - mixed RX and TX channels Description of problem: In the code of CAN controller of Xilinx ZynqMP board (`hw/net/can/xlnx-zynqmp-can.c`) in function `update_rx_fifo()` there seems to be a typo or logical error mixing RX and TX buffers: ```c /* Store the message in fifo if it passed through any of the filters. */ if (filter_pass && frame->can_dlc <= MAX_DLC) { if (fifo32_is_full(&s->rx_fifo)) { ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1); } else { timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer); fifo32_push(&s->rx_fifo, frame->can_id); fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT, R_RXFIFO_DLC_DLC_LENGTH, frame->can_dlc) | deposit32(0, R_RXFIFO_DLC_RXT_SHIFT, R_RXFIFO_DLC_RXT_LENGTH, timestamp)); /* First 32 bit of the data. */ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT, R_TXFIFO_DATA1_DB3_LENGTH, frame->data[0]) | deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT, R_TXFIFO_DATA1_DB2_LENGTH, frame->data[1]) | deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT, R_TXFIFO_DATA1_DB1_LENGTH, frame->data[2]) | deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT, R_TXFIFO_DATA1_DB0_LENGTH, frame->data[3])); ``` Additional information: Possible fix: ```diff git diff 12:29:23 diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c index 82ac48cee2..e93e6c5e19 100644 --- a/hw/net/can/xlnx-zynqmp-can.c +++ b/hw/net/can/xlnx-zynqmp-can.c @@ -696,30 +696,30 @@ static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame) timestamp)); /* First 32 bit of the data. */ - fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT, - R_TXFIFO_DATA1_DB3_LENGTH, + fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DATA1_DB3_SHIFT, + R_RXFIFO_DATA1_DB3_LENGTH, frame->data[0]) | - deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT, - R_TXFIFO_DATA1_DB2_LENGTH, + deposit32(0, R_RXFIFO_DATA1_DB2_SHIFT, + R_RXFIFO_DATA1_DB2_LENGTH, frame->data[1]) | - deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT, - R_TXFIFO_DATA1_DB1_LENGTH, + deposit32(0, R_RXFIFO_DATA1_DB1_SHIFT, + R_RXFIFO_DATA1_DB1_LENGTH, frame->data[2]) | - deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT, - R_TXFIFO_DATA1_DB0_LENGTH, + deposit32(0, R_RXFIFO_DATA1_DB0_SHIFT, + R_RXFIFO_DATA1_DB0_LENGTH, frame->data[3])); /* Last 32 bit of the data. */ - fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT, - R_TXFIFO_DATA2_DB7_LENGTH, + fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DATA2_DB7_SHIFT, + R_RXFIFO_DATA2_DB7_LENGTH, frame->data[4]) | - deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT, - R_TXFIFO_DATA2_DB6_LENGTH, + deposit32(0, R_RXFIFO_DATA2_DB6_SHIFT, + R_RXFIFO_DATA2_DB6_LENGTH, frame->data[5]) | - deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT, - R_TXFIFO_DATA2_DB5_LENGTH, + deposit32(0, R_RXFIFO_DATA2_DB5_SHIFT, + R_RXFIFO_DATA2_DB5_LENGTH, frame->data[6]) | - deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT, - R_TXFIFO_DATA2_DB4_LENGTH, + deposit32(0, R_RXFIFO_DATA2_DB4_SHIFT, + R_RXFIFO_DATA2_DB4_LENGTH, frame->data[7])); ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1); ```