Hello!
I am working on updating the PRU/DMA example posted in the example here to use kernel 5.10. That version was last seen functioning in kernel 4.19 but I was having stability issues and now I think I understand why.
A lot changed with remoteproc between 4.19 and 5.10. One of the best clues I found was from the TI SDK, with a note about how to track the changes in 5.10.
Roughly, in 4.19 the remoteproc resource table contained an interrupt-controller resource entry, which was to list all the incoming and outgoing interrupts that the PRUSS would send/receive. In 5.10, only the incoming interrupts would be configured through a static table, and it would be through a separate table of type pru_irq_rsc, and the PRU firmware would be responsible for configuring its own outgoing interrupts.
To configure the outgoing interrupt, I followed the instructions here, binding system event 19 to channel 9 (a.k.a. host7, the 7th outgoing interrupt):
CT_INTC.EISR_bit.EN_SET_IDX = SYSEVT_PRU_TO_EDMA; // sysevt 18 / channel 9
CT_INTC.CMR4_bit.CH_MAP_18 = HOST_INTERRUPT_CHANNEL_PRU_TO_EDMA;
CT_INTC.HMR2_bit.HINT_MAP_9 = HOST_INTERRUPT_CHANNEL_PRU_TO_EDMA;
CT_INTC.HIEISR_bit.HINT_EN_SET_IDX = HOST_INTERRUPT_CHANNEL_PRU_TO_EDMA;
Also, the PRU has to use Shadow Region 1. This is the only shadow region wired to the PRU. The ARM core uses Shadow Region 0 (and the TRM makes ominous notes about not mixing the use of global and shadow regions–the prior example used the global region).
Things that have to change in the device-tree for this configuration to work.
- The ARM core needs to avoid using DMA channels number 0 and 1 as these are hard-wired to the PRU interrupt channels 0 and 1 (i.e., these are the only channels for which the PRU can receive completion interrupts).
- The DMA controller needs several PaRAM slots reserved for the PRU too.
- To use the EDMA controller from the PRU, interrupt channel 9 has to be assigned to the PRU by telling the ARM core to ignore it (this is where my instability came from).
I was able to fiddle my way through this by checking out ti-linux-kernel-dev branch ti-linux-5.10.y, then editing the device tree as follows:
From 6f20fa5818ea7f51eba874fba4da3ce473e83e8e Mon Sep 17 00:00:00 2001
From: Josh MacDonald <jmacd@lightstep.com>
Date: Wed, 16 Aug 2023 21:35:41 -0700
Subject: [PATCH 2/2] Device tree changes for using EDMA from PRUSS
---
arch/arm/boot/dts/am33xx-l4.dtsi | 8 ++++++--
arch/arm/boot/dts/am33xx.dtsi | 1 +
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/am33xx-l4.dtsi b/arch/arm/boot/dts/am33xx-l4.dtsi
index 2d16b2d9c86b..f0ad10735ec1 100644
--- a/arch/arm/boot/dts/am33xx-l4.dtsi
+++ b/arch/arm/boot/dts/am33xx-l4.dtsi
@@ -846,6 +846,9 @@ pruss: pruss@0 {
#address-cells = <1>;
#size-cells = <1>;
ranges;
+ /* 0 and 1 are fixed for PRU-initiated DMAs, see TRM ... */
+ dmas = <&edma 0 2>, <&edma 1 2>;
+ dma-names = "prucpy0", "prucpy1";
pruss_mem: memories@0 {
reg = <0x0 0x2000>,
@@ -902,13 +905,14 @@ pruss_mii_rt: mii-rt@32000 {
pruss_intc: interrupt-controller@20000 {
compatible = "ti,pruss-intc";
reg = <0x20000 0x2000>;
- interrupts = <20 21 22 23 24 25 26 27>;
+ interrupts = <20 21 22 23 24 25 26>;
interrupt-names = "host_intr0", "host_intr1",
"host_intr2", "host_intr3",
"host_intr4", "host_intr5",
- "host_intr6", "host_intr7";
+ "host_intr6";
interrupt-controller;
#interrupt-cells = <3>;
+ ti,irqs-reserved = /bits/ 8 <0x80>; /* BIT(7) */
};
pru0: pru@34000 {
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 7f3ff48eb277..3acc11651faa 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -232,6 +232,7 @@ edma: dma@0 {
<&edma_tptc2 0>;
ti,edma-memcpy-channels = <20 21>;
+ ti,edma-reserved-slot-ranges = <0 4>;
};
};
--
2.30.2
It worked! The most confusing aspect of this is to disable the interrupt, which requires three lines:
- remove system event 17
- remove host7
- mask bit 7
I’ve tried to translate this into an overlay. Here’s the actual file I tried with: https://github.com/jmacd/nerve/blob/jmacd/lumberjack2023/pru/BB-PRU-DMA.dts
// SPDX-License-Identifier: Apache-2.0
/*
* Copyright (C) Josh MacDonald
*/
/dts-v1/;
/plugin/;
&{/chosen} {
overlays {
PRUDMA.kernel = __TIMESTAMP__;
};
};
/* in am33xx-l4.dtsi */
&pruss_tm {
pruss {
/* 0 and 1 are fixed for PRU-initiated DMAs, see TRM ... */
dmas = <&edma 0 2>, <&edma 1 2>;
dma-names = "prucpy0", "prucpy1";
pruss_intc {
/* This is host_intr7 i.e., 8th bit to say that this
* outgoing irq is not meant for the ARM core. */
ti,irqs-reserved = /bits/ 8 <0x80>; /* BIT(7) */
interrupt-names = "host_intr0", "host_intr1",
"host_intr2", "host_intr3",
"host_intr4", "host_intr5",
"host_intr6";
interrupts = <20 21 22 23 24 25 26>;
};
};
};
/* in am33xx.dtsi */
&edma {
ti,edma-reserved-slot-ranges = <0 4>;
};
This looks like the same set of device-tree changes, but something’s not right.
I built the kernel w/ overlays (edited the Makefile, which lists each dtbo
in the arch/arm/boot/dts/overlays directory) installed it, and added the overlay to uEnv.txt, booted, and I see the overlay was loaded. But the application doesn’t work, and now I’m looking for tips and tricks for debugging overlays.
Since the overlay is applied before the kernel starts, I wonder if there are any ways to get debugging messages from that moment in time, maybe? Are there other ways I can confirm that the device-tree overlay is doing what I think and/or whether it’s simply filling in nodes in the wrong location?
Thanks,
Josh