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.

FDT header not found during U-boot for custom AM3351 board

Good afternoon,

I have a custom AM3351-based board and am able to successfully load and run SPL, and then U-boot using CCSv6 and SDK 3.00.00.04 following the guide here

http://processors.wiki.ti.com/index.php/Sitara_Linux_Training:_uboot_linux_debug_with_ccsv5

I've stepped through u-boot code and found that it is failing inside fdt_check_header, in particular, the function fdt_magic is not returning the expected value FDT_MAGIC. It seems this should be compiled into the ELF file during the build process. Do you have any suggestions as to why this would fail? I've tried specifying the standard EVM dts and also my own custom dts in the am335x_evm_defconfig configuration file, i.e.

CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"

Here's a copy of fdt_check_header for reference:

int fdt_check_header(const void *fdt) {

  if (fdt_magic(fdt) == FDT_MAGIC) {
    /* Complete tree */
    if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
      return -FDT_ERR_BADVERSION;
    if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
      return -FDT_ERR_BADVERSION;
  } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
    /* Unfinished sequential-write blob */
    if (fdt_size_dt_struct(fdt) == 0)
        return -FDT_ERR_BADSTATE;
  } else {
    return -FDT_ERR_BADMAGIC; // <-- RETURNING HERE
  }

  return 0;

}

int fdtdec_prepare_fdt(void) {

  if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
  fdt_check_header(gd->fdt_blob)) {
  ...

    puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n");

    if (gd->fdt_blob) {
      printf("fdt_blob=%p\n", gd->fdt_blob);
      print_buffer((ulong)gd->fdt_blob, gd->fdt_blob, 4, 32, 0);
    }
    return -1;
  }
  return 0;
}

On a separate note, please help me enable the printf and puts functions to display to my console. It would be much faster debugging if I could see the console output. How can I enable logging to my UART0 console earlier in the u-boot program? I'm able to see the output from SPL so I know that my UART is configured properly during the SPL bootloader.

Thank you again for your support.

Best regards,

Chris

  • This will be forwarded to the software team. They will respond here.
  • Chris Lightcap said:
    It seems this should be compiled into the ELF file during the build process.

    What U-Boot config options are you using, and what is the boot device?

    https://git.ti.com/ti-u-boot/ti-u-boot/blobs/master/board/ti/am335x/README has some instructions about how to program the device tree into the boot device, and therefore maybe you need to program the device tree into the boot device.

    [While investigating, realized that the https://github.com/OLIMEX/u-boot-2013.10-ti2013.12.01-am3352_som I was using doesn't appear to be configured to read the device tree in U-Boot, and so the instructions on how to make the device tree available to U-Boot are board specific]

  • Hi Chester,

    At this stage, I'm using all the default options for am335x_evm_defconfig and am335x_evm.h found in TI Sitara SDK 3.00.00.04. I've copied the configuration file am335x_evm_defconfig below for reference. Is there any up-to-date guide to porting u-boot to custom am3351-based board? Should I be making custom changes to either am335x_evm_defconfig or am335x_evm.h, or both files? And which of these settings may be causing it to fail the fdt_check_header() function?

    CONFIG_ARM=y
    CONFIG_TARGET_AM335X_EVM=y
    CONFIG_SPL_STACK_R_ADDR=0x82000000
    CONFIG_DEFAULT_DEVICE_TREE="am335x-evm"
    CONFIG_SPL=y
    CONFIG_SPL_STACK_R=y
    CONFIG_SYS_EXTRA_OPTIONS="NAND"
    CONFIG_HUSH_PARSER=y
    CONFIG_AUTOBOOT_KEYED=y
    CONFIG_AUTOBOOT_PROMPT="Press SPACE to abort autoboot in %d seconds\n"
    CONFIG_AUTOBOOT_DELAY_STR="d"
    CONFIG_AUTOBOOT_STOP_STR=" "
    CONFIG_CMD_BOOTZ=y
    # CONFIG_CMD_IMLS is not set
    CONFIG_CMD_ASKENV=y
    # CONFIG_CMD_FLASH is not set
    CONFIG_CMD_MMC=y
    CONFIG_CMD_SF=y
    CONFIG_CMD_SPI=y
    CONFIG_CMD_I2C=y
    CONFIG_CMD_USB=y
    CONFIG_CMD_DFU=y
    CONFIG_CMD_GPIO=y
    # CONFIG_CMD_SETEXPR is not set
    CONFIG_OF_CONTROL=y
    CONFIG_DM_MMC=y
    CONFIG_CMD_DHCP=y
    CONFIG_CMD_MII=y
    CONFIG_CMD_PING=y
    CONFIG_CMD_EXT2=y
    CONFIG_CMD_EXT4=y
    CONFIG_CMD_EXT4_WRITE=y
    CONFIG_CMD_FAT=y
    CONFIG_CMD_FS_GENERIC=y
    CONFIG_SPI_FLASH=y
    CONFIG_SPI_FLASH_WINBOND=y
    CONFIG_DM_ETH=y
    CONFIG_SYS_NS16550=y
    CONFIG_TIMER=y
    CONFIG_OMAP_TIMER=y
    CONFIG_USB=y
    CONFIG_USB_MUSB_HOST=y
    CONFIG_USB_MUSB_GADGET=y
    CONFIG_USB_GADGET=y
    CONFIG_RSA=y
    CONFIG_FIT=y
    CONFIG_SPL_OF_LIBFDT=y
    CONFIG_SPL_LOAD_FIT=y
    CONFIG_OF_LIST="am335x-evm am335x-bone am335x-boneblack am335x-evmsk am335x-bonegreen am335x-icev2"
    CONFIG_DM_NAND=y
    CONFIG_USB_GADGET_DOWNLOAD=y
    CONFIG_G_DNL_MANUFACTURER="Texas Instruments"
    CONFIG_G_DNL_VENDOR_NUM=0x0451
    CONFIG_G_DNL_PRODUCT_NUM=0xd022
    CONFIG_MISC=y
    CONFIG_DM_USB=y
    CONFIG_USB_MUSB_TI=y
    CONFIG_OF_BOARD_SETUP=y
    CONFIG_CMD_TIME=y

    After more research, I'm confident that I am building the dtb file during my u-boot build process and that it is concatenating the u-boot-dtb.bin with original u-boot build, e.g. from my console window

    LD u-boot
    OBJCOPY u-boot-nodtb.bin
    CAT u-boot-dtb.bin
    COPY u-boot.bin

    I've tested this by created a new dts file and referencing it in my am335x_evm_defconfig configuration, and I see that it is built and added to u-boot-nodtb.bin.

    Thanks again for your help!

    Best regards,

    Chris

  • Chris Lightcap said:
    I've tested this by created a new dts file and referencing it in my am335x_evm_defconfig configuration, and I see that it is built and added to u-boot-nodtb.bin.

    The Perform U-Boot Debug section of the WIki page you referenced says to load the ELF image of U-Boot into memory.

    The binary device tree isn't part of the U-Boot ELF image, and therefore if the U-Boot ELF image is downloaded by CCS then the binary device tree won't be loaded in memory.

    In CCS are you downloading the U-Boot ELF image, or the raw binary u-boot.bin?

    I think you need to download the binary u-boot.bin, to which the build process has appended the binary device tree.

  • Chris Lightcap said:
    I've stepped through u-boot code and found that it is failing inside fdt_check_header, in particular, the function fdt_magic is not returning the expected value FDT_MAGIC. It seems this should be compiled into the ELF file during the build process.

    I tested U-Boot 2016.09-rc2 built using the default options for am335x_evm_defconfig, and running in a AM335x Starter Kit:

    1) If the ELF u-boot image was downloaded, then the fdt_check_header() failed with -FDT_ERR_BADMAGIC. As explained in my previous post the ELF u-boot image doesn't contain the binary device tree.

    2) If instead the binary u-boot.bin was loaded, to which the build process has appended the binary device tree, then the fdt_check_header() function succeeded and U-Boot proceeded to the point of trying to load the Linux Kernel. To load the binary u-boot.bin file I followed the steps on Perform SPL Debug, but changing to:

    - Before loading the binary file disable the watchdog by writing 0xAAAA then 0x5555 to the WDT_WSPR register (this is because the u-boot-spl had enabled the watchdog, and if didn't disable the watchdog the load of the binary u-boot.bin failed) 

    - Load the u-boot.bin file, rather than the u-boot-spl.bin

    - Use the start address of 0x80800000.

  • Hi Chester,

    Great catch! The user guide describes loading the ELF u-boot image, but the dtb is only added to the binary u-boot.bin. I'm not able to successfully load the binary and get around the error from fdt_check_header().

    I'm now able to get all the way to main_loop() and load symbols with the relocation address 0x83f4a000, but I'm failing inside the command bootcount = bootcount_load() located inside bootdelay_process(). Here's a copy of bootcount_load() for reference, where calling raw_bootcountload() causing the program to jump to do_data_abort():

    ulong bootcount_load(void)
    {
    unsigned long val;
    struct davinci_rtc *reg =
    (struct davinci_rtc *)CONFIG_SYS_BOOTCOUNT_ADDR;

    val = raw_bootcount_load(&reg->scratch2);
    if ((val & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000))
    return 0;
    else
    return val & 0x0000ffff;
    }

    void do_data_abort (struct pt_regs *pt_regs)

    {
    efi_restore_gd();
    printf ("data abort\n");
    show_regs (pt_regs);
    bad_mode ();
    }

    Here's the output from my console before the CPU reset,

    initcall: 8080e5f9 (relocated to 83f585f9)
    Net: No ethernet found.
    initcall: 8080e5f1 (relocated to 83f585f1)
    Initial value for argc=3
    Final value for argc=3
    data abort
    pc : [<83f65694>] lr : [<83f57f93>]
    reloc pc : [<8081b694>] lr : [<8080df93>]
    sp : 82f22788 ip : 00000000 fp : 00000017
    r10: 8086af68 r9 : 82f29ed8 r8 : 83faf130
    r7 : 83f9d4ac r6 : 83fab525 r5 : 83faf0bc r4 : fc8b6000
    r3 : 44e3e000 r2 : b0010000 r1 : 00000000 r0 : 00000000
    Flags: nZcv IRQs off FIQs on Mode SVC_32
    Resetting CPU ...

    resetting ...
    CCCCCCCC

    (Note that the initcall function pointer 8080e5f1 (relocated to 83f585f1) points to run_main_loop())

    I noticed that the function bootcount_load() is only called when CONFIG_BOOTCOUNT_LIMIT is defined. Should this be defined in my case? Any suggestions as to why I'm failing at this stage in the code? On a side note, I'm using a simplifed dts file based on the am33xx.dtsi file at this stage, and plan to add in dts source from pinmux tool once I get u-boot loaded. Here's a copy of my simplified dts file

    /dts-v1/;

    #include "am33xx.dtsi"

    / {
    model = "TI AM335x ZC";
    compatible = "ti,am335x-zc", "ti,am33xx";

    chosen {
    stdout-path = &uart0;
    };

    memory {
    device_type = "memory";
    reg = <0x80000000 0x04000000>; /* 64 MB */
    };

    };

    &am33xx_pinmux {
    uart0_pins: pinmux_uart0_pins {
    pinctrl-single,pins = <
    0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */
    0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */
    >;
    };


    };

    &uart0 {
    pinctrl-names = "default";
    pinctrl-0 = <&uart0_pins>;

    status = "okay";
    };

    Thank you so much for your quick responses. Looking forward to hearing your feedback.

    Best regards,

    Chris

  • Hi Chester,

    I just realized that this may be caused because my board does not support the RTC 32K oscillator, which is described in the following post:

    https://e2e.ti.com/support/arm/sitara_arm/f/791/p/506211/1835530#1835530

    I'll give this a try and let you know the results. Please let me know if you think of anything else to try in the meantime.

    Best regards,

    Chris

  • Hi Chester,

    That was the solution! From the earlier post by Yordan,

    ----------------------------------

    Try commenting/removing all RTC relevant parts from UBOOT//arch/arm/cpu/armv7/am33xx/board.c.  Then you need to get rid of the RTC related defines in your u-boot config files:

     Consider commenting RTC defines in include/configs/am335x_evm.h:

          /* Bootcount using the RTC block */
         #define CONFIG_BOOTCOUNT_LIMIT
         #define CONFIG_BOOTCOUNT_AM33XX
         #define CONFIG_SYS_BOOTCOUNT_BE

      include/configs/ti_am335x_common.h:      

          #define CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC   => remove this if you don't use the RTC 32K oscilator

    Consider commenting the following define: 

          /*
           * RTC related defines. To use bootcount you must set bootlimit in the
           * environment to a non-zero value and enable CONFIG_BOOTCOUNT_LIMIT
           * in the board config.
           */
          #define CONFIG_SYS_BOOTCOUNT_ADDR 0x44E3E000

    ----------------------------------

    Thanks for all of your support! I'm now working on loading u-boot through the UART0 console and loading the linux image.

    Best regards,

    Chris