This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/AM3358: PRU interrupts question

Part Number: AM3358


Tool/software: Linux

I have a question about pruss_intc_trigger() in drivers/remoteproc/pruss_intc.c

The function comments indicate that this takes a Linux IRQ number. From the TRM (section 6.3) you can see that ARM interrupts 20-27 map to PRU host interrupts 2-9. Based on that and the pruss_intc node from am33xx.dtsi, I am interpreting the irq function parameter as the ARM interrupt number. Walking through the code it is obvious that the function is setting a system event via SISR. I am a little unclear of how the ARM interrupt number is bound to the PRU system event but I think this is done using struct pruss_intc_config and the firmware resource table?

The resource table lets you configure host interrupts 0-9 but the device tree only has entries for host interrupts 2-9. Because of that I assume you can't trigger host interrupts 0 and 1 with this function. Can anyone confirm?

  • Hello Andrew,

    For interpreting the pruss_intc node in am33xx.dtsi, in the linux portion of the SDK take a look at Documentation/devicetree/bindings/remoteproc/ti,pruss-remoteproc. The device tree node matches the mapping of PRU host interrupts 2-9 to ARM interrupts 20-27. The device tree only includes things that Linux cares about - since host interrupts 0 and 1 are mapped back to the PRUs rather than the ARM, the device tree will not include information about host interrupts 0 and 1.

    The code must then map system events to channels. Those channels are then mapped to host interrupts. For more information on system events, channels, and host interrupts, please check out the Interrupt Controller (INTC) portion of the PRU TRM chapter (section 4.4.2 for AM335x TRM).

    Both of those mappings are done in the resource table. Note that if you want to create additional event mapping, it should also be done in the resource table: the ARM applies the INTC settings in the resource table before it loads and runs the PRU firmware, so if you change INTC settings in your PRU firmware they may overwrite the resource table settings.

    Within the resource table, pru_intc_map maps system events to a channel: for example, in PRU_RPMsg_Echo_Interrupt0/resource_table_0.h pru_intc_map maps system event 16 to channel 2 and system event 17 to channel 0. The resourceTable structure performs Channel-to-host mapping: in PRU_RPMsg_Echo_Interrupt0/resource_table_0.h resourceTable maps channel 0 to host interrupt 0, and channel 2 to host interrupt 2. This matches the PRU_RPMsg_Echo_Interrupt0/main.c file, where we define system event 16 as going out from the PRU towards the ARM, and system event 17 as coming in to the PRU from the ARM. In main.c, those system event numbers are passed to the RPMsg driver through pru_rpmsg_init().

    Regards,
    Nick
  • Nick,

    Thanks for the information about the resource table mapping. To summarize, you cannot trigger host interrupts 0 and 1 with pruss_intc_trigger() due to the way the device tree is setup. The solution is to pick a different host interrupt or roll your own trigger function.

  • Hello Andrew,

    What is your use case? eg, trying to trigger an interrupt in the PRU from the ARM outside the scope of RPMsg? Understanding how the ARM sets system event 17 in the above RPMsg example to trigger a PRU interrupt? Something else?

    Regards,
    Nick
  • Basically I am removing RPMsg from some driver / firmware code due to overhead and unpredictable timing. My communication needs are simple enough that I can do this with two interrupts and some shared memory (located in PRU memory not DDR). I was looking to use the PRUSS remoteproc function pru_intc_trigger() to have the ARM interrupt the PRU.
  • Sorry for the confusion Nick. Apparently I fail at reading documentation and your responses. The "interrupts" listed in the device tree are really just the system event numbers. The PRUSS driver relies on the firmware resource table to supply the binding to an actual interrupt line. I think the fact that PRU system events were chosen to match the ARM interrupt numbers is what tripped me up. Thanks for helping me out.
  • Hello Andrew,

    1) Glad things are making sense. Let me know if there is anything I can dig into for you on this side.

    2) I'd like your feedback: Do you have a wishlist for functionality you would like for memory throughput and synchronization between userspace/kernel and PRU? How about a list of shortcomings in TI's current RemoteProc/RPMsg solution?

    Thanks,
    Nick
  • Honestly I think the RemoteProc/RPMsg is a pretty decent implementation. It was easy to modify the example code to get something working. Out of the box it probably does everything 90% of your potential users would ever need. I know a lot of people like prussdrv but I have never used it and can't offer a comparison.

    To be clear I am only attempting to drop RPMsg. I am still using remoteproc to boot and manage the PRU. I wasn't using the stock pru_rpmsg driver anyway as I didn't need to link to user space. My original code used a custom RPMsg driver (which was based off of pru_rpmsg) for communication between my kernel module and the PRU. My application has real-time constraints and interacts with multiple IP blocks asynchronously. My reason for dropping RPMsg was an attempt to reduce the number of times the PRU has to access global memory over the L3 interconnect. The idea being this would minimize the impact of bus stalls. Just use interrupts with multiple system events, keep the PRU busy, and let ARM or EDMA worry about bus access.

    I believe the virtqueues are located in DDR. Can you confirm this (if they aren't my reasons for dropping RPMsg go away)? After initialization the ARM core loads the addresses into the resource table for use by the PRU library? If that is the case how difficult would it be to place the virtqueues somewhere in PRU shared memory?

  • Hello Andrew,

    That makes sense - thank you. The virtqueues are located in DDR memory, and the ARM core loads the virtqueue addresses into the resource table during initialization for the PRU to use.

    I don't have time to look at changing where the virtqueues are placed today, but if you reply it will give me a reminder to look into that question soon.

    Regards,
    Nick
  • Hello Andrew,

    I have not yet looked into changing where the virtqueues are placed. If that is still a topic you would like me to look into, let me know and I will.

    Regards,
    Nick
  • Thank you for the offer to investigate. At this point I don't think we need to look into this further.