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..

I missed the existence of the EEPROM Write Protection. In any case, I don’t think that this is a huge issue, since I can just specify the exact FDT I want to use in the extlinux.conf.

uboot reads the eeprom, so it knows which device tree to load. It’s a different device tree for bbb and the pb. So you need the right characters in the eeprom for uboot to identify the machine and hence device tree. I’ve both so should be able to find out, but @RobertCNelson will know of the top of his head …

1 Like

Hate Android changes words everywhere. Meant das uboot …

1 Like

GND TP4 (between 5v and eth jack..) that gnd’s write protect…

PB1 has the WP pin on the bottom..

lots of random eeprom’s: boot-scripts/device/bone at master · RobertCNelson/boot-scripts · GitHub

Regards,

3 Likes

Oh yes this is where uboot has the identification of am355x boards.

Okay, fun times, I changed the EEPROM to match our custom board name, but now it won’t boot at all… welp. All I get from serial now is a bunch of junk.

Terminal ready
����������������

Hard to tell if what’s going on is due to the EEPROM, but that’s the only thing that changed. Checking with my team.

I read from an Octavo App Note that I could “patch” u-boot to hardcode the EEPROM boot string.

static inline int board_is_pb(void) {
  // return board_ti_is("A335PBGL");
  return 1;
}

This did not work either, though I’m not entirely sure why. What I imagined would happen is that u-boot would skip to setting up the board regardless of what the bootstring actually is. Maybe there’s some error with how u-boot is configuring hardware ahead of the u-boot console. Or maybe I’m not compiling in my patch…

that was based on our tree…

On blank we assume “green”… am335x: boot blank eeprom as green · beagleboard/u-boot@cb86a91 · GitHub

On mainline we have to reconfigure that…

Let me check on this. I inherited this code base, so I’m not well versed in it yet. At a glance, our fork of u-boot is older than that commit.

For a long time, that patch referenced was not in by default, so octavo had recommended it in their guide…

Side note, using this binaries might be enough for you to get into u-boot: beagle-pkgs / u-boot-am335x-beagle · GitLab

No, luck… starting to look more and more like I killed my chip somehow :sob:

Just to check my understanding, I downloaded the MLO and u-boot-dtb.img to the build directory (fs-boot, fs-root, MLO, u-boot-dtb.img) and generated an image using genimage. Skipping ahead to boot time, what I should see is that the EEPROM is either “damaged” or “unrecognized” and it should try to run u-boot regardless. If I’m following, even if the bbg device tree isn’t present it should drop into u-boot console.

P.S. I have the EEPROM_WP line bodged to ground. Is there some chance that’s the issue? Also attaching photos of the board if anyone is curious…


If anyone was curious the solution was straightforward, a legacy version of u-boot was being loading from the eMMC unexpectedly; the bootloader would fail when it found an unrecognizable boot string.