Hello,
I discovered unexpected behaviour in the RPMsg framework: Sending a message from PRU to ARM triggers the host interrupt, that is supposed to be associated with receiving a message (system event 17 in the given example). That can easily be demonstrated running the example from 'pru-software-support-package/examples/am335x/PRU_RPMsg_Echo_Interrupt0'.
I inserted two lines of code to the original example code in order to toggle a debug pin. After checking if the ARM has kicked (assuming we got a new message), I set a pin high using R30 and set it low after processing the interrupt. See the snippet below:
/* Initialize the RPMsg transport structure */ pru_rpmsg_init(&transport, &resourceTable.rpmsg_vring0, &resourceTable.rpmsg_vring1, TO_ARM_HOST, FROM_ARM_HOST); /* Create the RPMsg channel between the PRU and ARM user space using the transport structure. */ while (pru_rpmsg_channel(RPMSG_NS_CREATE, &transport, CHAN_NAME, CHAN_DESC, CHAN_PORT) != PRU_RPMSG_SUCCESS); while (1) { /* Check bit 30 of register R31 to see if the ARM has kicked us */ if (__R31 & HOST_INT) { /* Set debug pin high */ __R30 |= (1 << 1); /* Clear the event status */ CT_INTC.SICR_bit.STS_CLR_IDX = FROM_ARM_HOST; /* Receive all available messages, multiple messages can be sent per kick */ while (pru_rpmsg_receive(&transport, &src, &dst, payload, &len) == PRU_RPMSG_SUCCESS) { /* Echo the message back to the same address from which we just received */ pru_rpmsg_send(&transport, dst, src, payload, len); } /* Set debug pin low */ __R30 &= ~(1 << 1); } }
Running this code on the PRU, I used the example Linux 'rpmsg_pru' driver on the ARM host and sent a single message like this: ```echo 1 > /dev/rpmsg_pru30``` watching the corresponding pin with a logic analyzer.
Expected behaviour: Message is received by the PRU, the pin goes high, PRU echoes the message, pin goes low.
Actual behavious: Message is received by the PRU, the pin goes high, PRU echoes the message, pin goes low (as expected). However, to my surprise the pin goes high for a second time around 100us later for a short period (<1us), indicating that Host interrupt 0 is triggered a second time. Apparently the virtio_rpmsg_bus signals the reception of the message to the PRU via the same interrupt line that is used for signalling a sent message.
Looking closer into the implementation of RPMsg on PRU and Linux side, I found that indeed the receive routines (Linux: rpmsg_recv_done(..) in virtio_rpmsg_bus.c, PRU: pru_rpmsg_receive in pru_rpmsg.c) both trigger an interrupt at the end of the function.
Questions:
1) What is the purpose of sending this "receive done" interrupt after finishing the receive routine on either side?
2) Why is the "receive done" interrupt mapped to the same system event as the interrupt that signals a new message?
3) Why is that "receive done" interrupt not handled on the PRU-side code?
Regards,
Kai