Custom device tree prevents boot

Hey all, I’m in the process of writing a custom device tree for my board. Here’s what I have so far. The problem is that u-boot hangs at “starting kernel”, and I believe that this dts file is at fault somehow–maybe the interrupt parent. GPIO helper is apparently outdated too. It would be really nice if someone would suggest an overview of how to write device trees specifically with the PRU. I haven’t found a super beginner friendly resource.

/* OreSat Star Tracker v1.2 device tree */

/dts-v1/;

#include "oresat-base.dtsi"

/ {
  prucam {
    compatible = "psas,prucam-ar013x";

    ti,prus = <&pru0>, <&pru1>;
    interrupt-parent = <&pruss_intc>;

    interrupts = <18 2 2>, <16 0 0>, <17 1 1>;
    interrupt-names = "pru1_to_arm", "arm_to_prus", "pru0_to_pru1";
  };
};

&am33xx_pinmux {
  st_i2c2_pins: pinmux-st-i2c2-pins {
    pinctrl-single,pins = <
      AM33XX_IOPAD(AM335X_PIN_UART1_CTSN, PIN_INPUT | MUX_MODE3) /* i2c2_sda */
      AM33XX_IOPAD(AM335X_PIN_UART1_RTSN, PIN_INPUT | MUX_MODE3) /* i2c2_scl */
    >;
  };

  st_gpio_pins: pinmux-st-gpio-pins {
    pinctrl-single,pins = <
      /* Pins for CAM_control. */
      AM33XX_IOPAD(AM335X_PIN_MII1_TXD3, PIN_INPUT | MUX_MODE7) /* gpio0_16 / FLASH */
      AM33XX_IOPAD(AM335X_PIN_MII1_CRS, PIN_OUTPUT | MUX_MODE7) /* gpio3_1 / BUS_OE */
      AM33XX_IOPAD(AM335X_PIN_MII1_COL, PIN_OUTPUT | MUX_MODE7) /* gpio3_0 / CAM_OE */
      AM33XX_IOPAD(AM335X_PIN_MII1_RX_CLK, PIN_OUTPUT | MUX_MODE7) /* gpio3_10 / CLK_EN */
      AM33XX_IOPAD(AM335X_PIN_MII1_RXD0, PIN_OUTPUT | MUX_MODE7) /* gpio2_21 / INPUT_EN */
      AM33XX_IOPAD(AM335X_PIN_MII1_RXD1, PIN_OUTPUT | MUX_MODE7) /* gpio2_20 / RESET */
      AM33XX_IOPAD(AM335X_PIN_MII1_RXD2, PIN_OUTPUT | MUX_MODE7) /* gpio2_19 / SADDR */
      AM33XX_IOPAD(AM335X_PIN_MII1_RXD3, PIN_OUTPUT | MUX_MODE7) /* gpio2_18 / STANDBY */
      AM33XX_IOPAD(AM335X_PIN_MII1_RX_ER, PIN_OUTPUT | MUX_MODE7) /* gpio3_2 / TRIGGER */
      AM33XX_IOPAD(AM335X_PIN_MII1_RX_DV, PIN_OUTPUT | MUX_MODE7) /* gpio3_4 / VREG_EN */
      /* Pins for CAM_parallel bus. Currently only getting top 8 bits of pixel data. */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_ACLKX, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_0 / CAM_D4 */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_FSX, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_1 / CAM_D5 */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_AXR0, PIN_INPUT | MUX_MODE6) /*pr1_pru0_pru_r31_2 / CAM_D6 */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_AHCLKR, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_3 / CAM_D7 */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_ACLKR, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_4 / CAM_D8 */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_FSR, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_5 / CAM_D9 */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_AXR1, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_6 / CAM_D10 */
      AM33XX_IOPAD(AM335X_PIN_MCASP0_AHCLKX, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_7 / CAM_D11 */
      AM33XX_IOPAD(AM335X_PIN_GPMC_AD14, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_14 / CAM_VSYNC */
      AM33XX_IOPAD(AM335X_PIN_GPMC_AD15, PIN_INPUT | MUX_MODE6) /* pr1_pru0_pru_r31_15 / CAM_HSYNC */
      AM33XX_IOPAD(AM335X_PIN_XDMA_EVENT_INTR1, PIN_INPUT | MUX_MODE5) /* pr1_pru0_pru_r31_16 / CAM_PXL_CLK */
    >;
  };
};

&i2c2 {
  #address-cells = <1>;
  #size-cells = <0>;
  status = "okay";
  pinctrl-names = "default";
  pinctrl-0 = <&st_i2c2_pins>;
  clock-frequency = <100000>;
};

&ocp {
  cape-universal {
    compatible = "gpio-of-helper";
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&st_gpio_pins>;

    FLASH {
      gpio-name = "FLASH";
      gpio = <&gpio0 16 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_TXD3 */
      input;
    };

    BUS_OE {
      gpio-name = "BUS_OE";
      gpio = <&gpio3 1 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_CRS */
      output;
    };

    CAM_OE {
      gpio-name = "CAM_OE";
      gpio = <&gpio3 0 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_COL */
      output;
    };

    CLK_EN {
      gpio-name = "CLK_EN";
      gpio = <&gpio3 10 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_RX_CLK */
      output;
    };

    CAM_INPUT_EN {  /* name cannot be INPUT_EN */
      gpio-name = "INPUT_EN";
      gpio = <&gpio2 21 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_RXD0 */
      output;
    };

    RESET {
      gpio-name = "RESET";
      gpio = <&gpio2 20 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_RXD1 */
      output;
    };

    SADDR {
      gpio-name = "SADDR";
      gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_RXD2 */
      output;
    };

    STANDBY {
      gpio-name = "STANDBY";
      gpio = <&gpio2 18 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_RXD3 */
      output;
    };

    TRIGGER {
      gpio-name = "TRIGGER";
      gpio = <&gpio3 2 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_RX_ER */
      output;
    };

    VREG_EN {
      gpio-name = "VREG_EN";
      gpio = <&gpio3 4 GPIO_ACTIVE_HIGH>; /* AM335X_PIN_MII1_RX_DV */
      output;
    };
  };
};

&pruss {
  status = "okay";
};

&pruss_tm {
  status = "okay";
};

This is my extlinux.conf, Where fdt is the dtb for the preceding device tree.

TIMEOUT 1
DEFAULT linux

LABEL linux
KERNEL /vmlinuz-${kernel_version}
INITRD /initrd.img-${kernel_version}
FDT /dtbs/${kernel_version}/${fdt}
APPEND console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait

Seeing your serial boot log thru u-boot would help

add earlycon to see if we can get more infoo..

It’s not much to see

edit: I think I added earlycon right… Changed APPEND console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait to APPEND console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait earlycon.

U-Boot SPL 2024.10-g369ff7cf8cc9 (Feb 01 2026 - 09:03:17 -0800)
Trying to boot from MMC1


U-Boot 2024.10-g369ff7cf8cc9 (Feb 01 2026 - 09:03:17 -0800)

CPU  : AM335X-GP rev 2.1
Model: TI AM335x BeagleBone Black
DRAM:  512 MiB
Core:  161 devices, 18 uclasses, devicetree: separate
WDT:   Started wdt@44e35000 with servicing every 1000ms (60s timeout)
NAND:  0 MiB
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from FAT... Unable to read "uboot.env" from mmc0:1... 
<ethaddr> not set. Validating first E-fuse MAC
Net:   eth2: ethernet@4a100000using musb-hdrc, OUT ep1out IN ep1in STATUS ep2in
MAC de:ad:be:ef:00:01
HOST MAC de:ad:be:ef:00:00
RNDIS ready
, eth3: usb_ether
Hit any key to stop autoboot:  0 
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found /extlinux/extlinux.conf
Retrieving file: /extlinux/extlinux.conf
1:	linux
Retrieving file: /vmlinuz-5.10.168-ti-r66
Retrieving file: /initrd.img-5.10.168-ti-r66
append: console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait earlycon
Retrieving file: /dtbs/5.10.168-ti-r66/oresat-star-tracker-0102.dtb
Kernel image @ 0x82000000 [ 0x000000 - 0xab7200 ]
## Flattened Device Tree blob at 88000000
   Booting using the fdt blob at 0x88000000
Working FDT set to 88000000
   Loading Ramdisk to 8f92a000, end 8ffff768 ... OK
   Loading Device Tree to 8f910000, end 8f9297dc ... OK
Working FDT set to 8f910000

Starting kernel ...

It seems like there might also be an issue with my board’s EEPROM. Not 100% sure since I don’t really understand what the EEPROM does; but I don’t know why else u-boot would read that my board was a pocketbeagle.

edit: My current understanding is that by specifying the path to the FDT in extlinux.conf, that extlinux would override any environment information provided by the EEPROM.

edit: So reading the boards EEPROM shows

=> i2c md 0x50 0x08.2
0008: 50 42 47 4c 30 31 30 32 30 30 30 30 50 53 41 53    PBGL01020000PSAS

I tried over writing the EEPROM, but it didn’t work

=> i2c mw 0x50 0x08.2 4f
=> i2c mw 0x50 0x09.2 53
=> i2c md 0x50 0x08.2
0008: 50 42 47 4c 30 31 30 32 30 30 30 30 50 53 41 53    PBGL01020000PSAS

I tried write an ‘O’ and an ‘S’ over the ‘PB’, but it had no effect for some reason.

Okay, this is almost certainly a device tree problem, though I’m not sure where the issue emerges. My Bookworm that’s built with the same script used the am335x-boneblack.dtb and boots successfully..