On the PocketBeagle2 can the PRU processors or the M4F access a connection through to and LED? If so what device tree overlay do I need? Really I’m thinking of first programs for these internal CPUs, would be good to do the equivalent of “Hello World” which I take as a flashing LED on embedded devices …
I know that M4 can access the LED. Not sure about PRU.
Well, you would need to write an overlay that disables the LED on Linux. We do not want A53 and M4 to fight for the same LED.
Yes, and what I need to look into is do you have to configure the whole am chip, so that the pin (to the led) is configured as an output for the pru/m4f. I’m used to that on other ti devices, when an output pin has multiple functions - but that’s when they have only one cpu. I’ve never tried programming these ti devices with several cpu …
Checking the device tree - these seem unused:
led-3 {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_GREEN>;
gpios = <&main_gpio0 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
bootph-all;
};
led-4 {
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_GREEN>;
gpios = <&main_gpio0 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
bootph-all;
};
Ah yes - but simpler use leds-off overlay. Now to see which pins, the PRU R30 goes to and how to remap …
Not quite, for M4, you need to disable the leds, not just turn them off. So the following should work:
&led {
status = "disabled";
};
M4 running Zephyr can do it’s own pinmuxing.
Now for PRU, things are a bit more complicated. You can do pinmuxing from PRU code, or you can pinmux on linux side and just use the pin from PRU. As for example, I did do it when I was testing some things, but well, don’t have anything solid I can point you to.
Ta - easily done, but alas new device tree blob, still easy to do.
Harder is how to get the GPIO off the PRU, looks like both PRU are together, so first have to configure it to just be one. Then how to configure the whole CPU to redirect the PRU GPIO to the LED. Then work out what if any of this can be done via the device tree …
Ok, so found one of my overlays when I was testing PRU:
/dts-v1/;
/plugin/;
#include "ti/k3-pinctrl.h"
&main_pmx0 {
mypruicssm0pru1_pins_default: mypruicssm0pru1-default-pins {
pinctrl-single,pins = <
AM62X_IOPAD(0x00e4, PIN_INPUT, 5) /* (AA23) VOUT0_DATA11.PR0_PRU0_GPO1 */
>;
};
};
&main_gpio0 {
pinctrl-names = "default";
pinctrl-0 = <&mypruicssm0pru1_pins_default>;
status = "okay";
};
While the pin is not actually in main_gpio0, that is the easiest way to mux a pin without defining a device node.
Nice idea - I can use as guidance. Changing to an LED is easy.
Just need to understand now, how the remapping of pins is done in device tree (so the above, but trying to keep what I can of the original set up) . The TRT for this at 16613 pages give quite a bit of reading …
Looks like the gpio binding needs to go in bus@f0000/pruss@30040000, need to get my mind round how pinmux is done in the device tree - then hopefully can do that - I guess the loading of the device tree by the kernel, then programs the relevant part of the world from the arm64 part of the world (linux); then doing something similar on the pru to get into the pruss, and then drill out …
Yes quite a can of worms …
Thanks Ayusha for you help - if I get the device tree bit to work, I’ll post it here so you can add the beagle board tree …
Oh yes - as I’ll need the whole device tree for this chip, and then everything it builds from in the greater device tree, I guess I need a clone of the git repository. Is this best from you or the linux kernel? I guess from you - then if I get a working set up - I submit the change to beagleboard git?
Hey. I was under the impression that only the PRU had access to the R30 and R31 registers. Not the M4f. Can the M4F running zephyr access the GPIO pins? Aka the R30 and R31 registers?
My suspicion is it depends on the CPU, PRU seem set up to do GPIO actions, and so in the ISP R30 and R31 are set up for very fast GPIO. The M4F is a far more general arm cortex device - so you almost certainly need to write to memory in a certain area … Read the TRM for an authoritative answer, but thats a lot of work - hopefully someone here know where on the M4F.
pinmux will also be different between PRU and M4F - need to look into that bit …
Out if interest I checked what I did on an M0 device to flash the led:
#define GPIOA_BASE (0x400A0000U) /*!< Base address of module GPIOA */
typedef struct {
...
} GPIO_Regs;
static GPIO_Regs *GPIOA=(GPIO_Regs *)GPIOA_BASE;
GPIOA->DOUT31_0 ^= 1; // toggle PA0
The last line toggles the LED via inversion to the memory mapped GPIO register. The lines above are from the TI header - as to how it sets up the structure, and then sets the GPIO as a point to a memory locations, referenced by the structure.
So it ends up quite simple - but as its a memory write it will be slower (in CPU cycles) on the M4F than on the PRU. My guess is the M4F is clocked far higher - and so the M4F is quicker in actual time.
After several hours in the TRM, looks like the only easy way to get everything needed for the pin mux is the Texas Instruments SysConfig tool …
Oh yes - which pins are the LED on - seem to need that for the SysConfig tool …
There are technically 3 types of GPIOs:
- PRU
- MAIN
- MCU
Only PRU can access the PRU domain GPIOs (using the R30 and R31 regs). A53 or M4 cannot. Now of course multiple balls can be connected to the same header pin, so you will have pins that can support GPIO across multiple domain, but they are technically different balls. Or well sometimes same ball but muxed to different functionality.
Yes, sysconfig is the best way to get the correct dt generated.
Hmm, yes I was slowly coming to that conclusion. So it may well only be technically possible to flash an led on the headers. If so guess I need to order some leds. Should have the device tree done tomorrow, slightly different from yours, as R30 and R31 come out on the IEP EDIO, that seems to have slightly different pins, and I need to make it an output …
Ok think I’ve traced the IEP EDIO pins, only 4 are pinned out on PRUSS side its [28:31]. These come out on the four pins B19 A19 B16 A16, [A19 B19] come out on SPI2.MISO and SPI2.MOSI pins 10 and 12 on the P1 header, they are wired to A18 and AE18 - need to work out what that wiring does …
A16 and B16 are wired to the I2C0. Both of these sound wrong, so I’ll have to dig some more. Hassle is this is coming from SysConfig which so far has been only source of information …
I2C0 goes to the MSPM0+ chip - so its not a GPIO we can easily re-purpose. So looks like we can only get two signals out of the IEP EDEO, so only 2 bits from R30 and R31 (but can merge these I think if you want IO on the pins …)
Ah yes only 4 pins out over IEP - but the PRU also have direct connections - to the pinout with the same name. Some pin mutex can be done, but as @ayush1325 comment above, not to the LED (that I can find).
Think I’ve done a device tree blob. This is my dtso:
/dts-v1/;
/plugin/;#include <dt-bindings/gpio/gpio.h>
#include “ti/k3-pinctrl.h”/*
- Helper to show loaded overlays under: /proc/device-tree/chosen/overlays/
*/
&{/chosen} {
overlays {
k3-am62-pocketbeagle2-pru0-out.kernel = TIMESTAMP;
};
};&main_pmx0 {
pru0_pins_output: pru0_pins {
pinctrl-single,pins = <
AM62X_IOPAD(0x00e0, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) /* (V20) VOUT0_DATA10.PR0_PRU0_GPO0 /
AM62X_IOPAD(0x00e4, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AA23) VOUT0_DATA11.PR0_PRU0_GPO1 /
AM62X_IOPAD(0x00e8, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AB25) VOUT0_DATA12.PR0_PRU0_GPO2 /
AM62X_IOPAD(0x00ec, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AA24) VOUT0_DATA13.PR0_PRU0_GPO3 /
AM62X_IOPAD(0x00f0, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (Y22) VOUT0_DATA14.PR0_PRU0_GPO4 /
AM62X_IOPAD(0x00f4, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AA21) VOUT0_DATA15.PR0_PRU0_GPO5 /
AM62X_IOPAD(0x00f8, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AB24) VOUT0_HSYNC.PR0_PRU0_GPO6 /
AM62X_IOPAD(0x00fc, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (Y20) VOUT0_DE.PR0_PRU0_GPO7 /
AM62X_IOPAD(0x00b8, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (U22) VOUT0_DATA0.PR0_PRU0_GPO8 /
AM62X_IOPAD(0x00bc, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (V24) VOUT0_DATA1.PR0_PRU0_GPO9 /
AM62X_IOPAD(0x00c0, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (W25) VOUT0_DATA2.PR0_PRU0_GPO10 /
AM62X_IOPAD(0x00c4, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (W24) VOUT0_DATA3.PR0_PRU0_GPO11 /
AM62X_IOPAD(0x00c8, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (Y25) VOUT0_DATA4.PR0_PRU0_GPO12 /
AM62X_IOPAD(0x00cc, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (Y24) VOUT0_DATA5.PR0_PRU0_GPO13 /
AM62X_IOPAD(0x00d0, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (Y23) VOUT0_DATA6.PR0_PRU0_GPO14 /
AM62X_IOPAD(0x00d4, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AA25) VOUT0_DATA7.PR0_PRU0_GPO15 /
AM62X_IOPAD(0x00dc, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (W21) VOUT0_DATA9.PR0_PRU0_GPO16 /
AM62X_IOPAD(0x00d8, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (V21) VOUT0_DATA8.PR0_PRU0_GPO17 /
AM62X_IOPAD(0x0100, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AC25) VOUT0_VSYNC.PR0_PRU0_GPO18 /
AM62X_IOPAD(0x0104, PIN_OUTPUT|PIN_DRIVE_STRENGTH_NOMINAL, 5) / (AC24) VOUT0_PCLK.PR0_PRU0_GPO19 */;
};};
&pru0 {
pinctrl-names = “default”;
pinctrl-0 = <&pru0_pins_output>;
status = “okay”;
};
I’ve managed to get all 20 pins out on the header:
GPO0 V20 - HP1-36
GPO1 AA23 - HP1-33
GPO2 AB25 - HP2-32
GPO3 AA24 - HP2-30
GPO4 Y22 - HP1-31
GPO5 AA21 - HP2-34
GPO6 AB24 - HP2-28
GPO7 Y20 - HP1-29
GPO8 U22 - HP2-2
GPO9 V24 - HP2-4
GPO10 W25 - HP2-6
GPO11 W24 - HP2-8
GPO12 Y25 - HP2-20
GPO13 Y24 - HP1-20
GPO14 Y23 - HP2-24
GPO15 AA25 - HP2-33
GPO16 W21 - HP2-35
GPO17 V21 - HP2-18
GPO18 AC25 - HP2-22
GPO19 AC24 - HP2-17
I’ve LEDs on order - so will test with them when they arrive …
@RobertCNelson if it works when the LEDs arrive, do you want me to push it to you on github?
cylon.mkv (948.9 KB)
main0.c (1.2 KB)
k3-am62-pocketbeagle2-pru0-out.dtso (2.5 KB)
Managed to create a cylon with PRU0 using the attached device tree and pru code. Basically in R30 bits 8-11 are rotated left and right. I’ll push the dtso to @RobertCNelson