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.

PROCESSOR-SDK-AM335X: SPI boot fails

Part Number: PROCESSOR-SDK-AM335X

Hi,

I have a system which is running fine under debug -- both a secondary bootloader running in L3 OCMC RAM, and an app running in external DRAM.  But I can't get the secondary bootloader to run out of SPI flash at power up.

SYSBOOT[4:0] is set to 11001b, so the ROM bootloader boot sequence should be SPI0->MMC0->EMAC1->UART0.

When the flash is blank, I see the ROM bootloader execute 4 short SPI bursts (presumably each is a 512 byte page) then stop.  When the flash is programmed with my SBL code, then there is a longer SPI burst (approx. 44ms), which would be a reasonable amount of time to read in the SBL, given its size of 38860 bytes.

But then it apparently does not execute.  The only way I can tell this is that in the current version of the SBL it will sit flashing an LED after it has finished initializing the system -- and there is no LED activity.

The first several bytes in the flash are as follows, starting at address zero and laid out as 32-bit big-endian words . .
00 00 97 D4   40 30 00 00   E5 9F F0 18   E5 1F F0 08   E5 9F F0 18  etc.

Expanding this out a bit, you can see the header followed by a fairly normal looking ARM irq_vector/instruction sequence:
0x000097D4
0x40300000
0xE59FF018
0xE51FF008
0xE59FF018
0xE51FF008
0xE51FF008
0xE51FF008
0xE51FF008
0xE51FF008
0x40300050
0x00000000
0x40300049
0x00000000
0x00000000
0x00000000
0x00000000
0x00000000
0x4030004F
0xE7FEE7FE
0xE7FEE7FE
0xE7FEE7FE
0xE59F002C
0xEE0C0F10
0xEE113F50
0xE383360F
0xEE013F50
0xE3A03000
0xE3A00101
0xEEE80A10
0xEE073F95
0xE59FA00C
0xE1A0E00F
0xE12FFF1A
0xE24FF008
etc.     

The SBL is being loaded at the bottom L3 OCMC RAM at address 0x40300000.  It does not exceed the available limit of 0x4030B800 as it is shown in the Initialization chapter of the TRM.

The TRM also claims that you can use the SRAM area between 0x402F0400 and 0x40300000, but I have not been able to successfully link and debug in that area.  However that is not a major issue at this time.

Can anyone see what the problem is here?  I must be doing something wrong but I just can't see it.  I did try going back to little-endian for the body of the code, but that didn't work either!

My setup is as follows:
Custom PCB
AM3352BZCZ30
CCS Version: 6.1.2.00015
bios_6_45_01_29
pdk_am335x_1_0_3
GNU v4.9.3 (Linaro)
Win 7 64-bit

Thanks,
GerryL

  • The RTOS team have been notified. They will respond here.
  • Gerry,

    Have you run any diagnostics on the SPI flash. Is the general Read write working as expected. How are you flashing the binary, Is the MLO at base of SPI flash and the APP at the correct offset(default 0x20000). Can you also confirm the steps that you used to create _ti.bin file.

    Did you try the same on any of the TI supported evaluation platforms.

    Regards,
    Rahul
  • Hi Rahul,

    Flash read/write is working normally. I have a library of flash and SPI code that has been working reliably for many years, and it was "simply" a matter of plugging in the starterware McSPI functions into my code and it all came up ok. I am testing manually via a serial port, which is how I got the partial flash dump for the original post.

    I am unfamiliar with the term MLO, but the image header -- size and address -- is at flash location 0. The ROM code should be running from 0x20000, but I am trying to run my code from address 0x40300000.

    The image was assembled and programmed in several steps . .
    1. Convert .out to binary using an elf2bin from SiZiOUS. (I have not checked every byte of the output, but the early part of the file looks correct, and the overall length corresponds exactly to the start of the bss section.)
    2. Convert binary to .h using a reliable Bin2c.
    3. Build a small flash programming app incorporating the .h to be run on the Sitara through the debugger. The big-endian adaptation is done here.

    This is not an ideal way of going from .out to programmed flash, but other than some code examples I couldn't find any TI tools to do the work.

    I'm not using an eval board. We had to go straight to hardware.

    Returning to the original post,
    - Does the byte sequence in the flash look ok to you?
    - And is the 0x40300000 bas address meant to be ok for the ROM bootloader to jump to?

    (Btw, the flash is a Micron N25Q128A11ESE40 -- forgot to mention that.)

    Thanks,
    Gerry
  • Can anyone offer any advice on this?

    I'm somewhat dead in the water, and having a hard time figuring out how to debug the problem. Any insights would be valuable.

    Thanks,
    Gerry
  • Gerry,

    Sorry for the delay in getting back to you on this issue. If you have a emulator connection can you provide the value of the program counter when the ARM fails to boot. I can compare this with the ROM symbol table and let you know where it failed.

    The other option is you can use the SPI flash ing utility that we described here to make sure that the format of the image on the flash is correct.
    processors.wiki.ti.com/.../AM437x

    Regards,
    Rahul
  • Hi Rahul,

    I have an XDS100v2 debug probe -- I'm not sure how to use that to intercept ROM operations.

    In the meantime, I did try spi_flash_writer_AM335X.out some time ago, and it produced the following output . .

    [CortxA8] AM335X part detected.
    SF: Got idcode 20 bb 18
    Checking if Winbond flash writer can be used..
    SF: Unsupported Winbond ID bb18
    No known Serial Flash found

    I am using a Micron N25Q128A11ESE40, so no joy there.

    Returning to some previous questions:
    - Does the byte sequence in the flash look ok? (see original post)
    - Is 0x40300000 ok as a base address for loading and executing the code?

    Thanks,
    Gerry

  • This problem has been solved.

    Basically, for the SBL build:
    - Turned off standard system startup files (-nostartfiles) for the linker.
    - Modified the original startup_ARMCA8.S with some code borrowed from C:\ti\pdk_am335x_1_0_3\packages\ti\starterware\soc\armv7a\gcc\sbl_init.S.  It does some additional initialization then jumps directly to main() instead of _start().  (I did lose malloc in the process, so had to make a really simple one of my own.  If anyone knows how standard startup initializes malloc then I would be eager to hear about it.)

    You can place the SBL anywhere in the range 0x402F0400 thru 0x4030B800 (see Public RAM Memory Map in the TRM Initialization chapter).  It is convenient to use 0x40300000, as the debugger is happy with that.  But if you need more room then drop down to 0x402F0400, although the debugger won't run there (it tries to load data down around 0x402F0054, which is out of bounds).

    Btw, *BIG* warning for hardware designers -- to boot from SPI Flash, the McSPI connections for MOSI and MISO are both non-intuitive and different from the default setup . .

       Signal   McSPI Pin   Flash Pin
          ======       =========       =========
       MOSI     spi0_d1     DQ0
       MISO     spi0_d0     DQ1

    GerryL

    For what it's worth, here are the startup and .lds files I ended up with (the post wouldn't accept an .lds file, so it's loaded as a .txt) . .

    7127.startup_SBL.S

    SBL__lds.txt
    /****************************************************************************/
    /*  SBL.lds (originally AM335x.lds)                                         */
    /*  - could possibly be simplified further, as in am335x_boot_ccs.lds,      */
    /*    found in C:\ti\pdk_am335x_1_0_3\packages\ti\starterware\examples\gcc  */
    /*                                                                          */
    /*  Copyright (c) 2014  Texas Instruments Incorporated                      */
    /*  Author: Rafael de Souza                                                 */
    /*                                                                          */
    /*    Description: This file is a sample linker command file that can be    */
    /*                 used for linking programs built with the GCC compiler    */
    /*                 and running the resulting .out file on an AM335x device. */
    /*                 Use it as a guideline.  You will want to                 */
    /*                 change the memory layout to match your specific          */
    /*                 target system.  You may want to change the allocation    */
    /*                 scheme according to the size of your program.            */
    /*                                                                          */
    /****************************************************************************/
    
    /* Original: */
    /*    L3OCMC0 :  o = 0x40300000,  l = 0x00010000  /* 64kB L3 OCMC SRAM  */
    
    /* Alternates: */
    /*    IMAGERAM : o = 0x402F0400,  l = 0x0001B400  /+ combined 64kB internal SRAM & p/o 64kB L3 OCMC SRAM, but n.g. for debug */
    /*    IMAGERAM : o = 0x40300000,  l = 0x0000B800  /+ same as L3OCMC0 */
    
    MEMORY
    {
        SRAM :     o = 0x402F0400,  l = 0x0000FC00  /* 64kB internal SRAM */
        L3OCMC0 :  o = 0x40300000,  l = 0x0000B800  /* 64kB L3 OCMC SRAM <<< available after ROM bootloader <<< */
    
        IMAGERAM : o = 0x40300000,  l = 0x0000B800  /* same as L3OCMC0 */
    
        M3SHUMEM : o = 0x44D00000,  l = 0x00004000  /* 16kB M3 Shared Unified Code Space */
        M3SHDMEM : o = 0x44D80000,  l = 0x00002000  /* 8kB M3 Shared Data Memory */
        DDR0 :     o = 0x80000000,  l = 0x40000000  /* 1GB external DDR Bank 0 */
    }
    
    ENTRY(Entry)
    
    SECTIONS
    {
        .rsthand :
        {
            . = ALIGN(0x400);
            KEEP(*(.isr_vector))
            *startup_SBL.o (.text)
        } > IMAGERAM
    
        . = ALIGN(4);
        .text :
        {
            *(.text*)
    
            KEEP(*(.init))
            KEEP(*(.fini))
    
            /* .ctors */
            *crtbegin.o(.ctors)
            *crtbegin?.o(.ctors)
            *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
            *(SORT(.ctors.*))
            *(.ctors)
    
            /* .dtors */
             *crtbegin.o(.dtors)
             *crtbegin?.o(.dtors)
             *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
             *(SORT(.dtors.*))
             *(.dtors)
    
            *(.rodata*)
    
            KEEP(*(.eh_frame*))
        } > IMAGERAM
    
        .ARM.extab :
        {
            *(.ARM.extab* .gnu.linkonce.armextab.*)
        } > IMAGERAM
    
        __exidx_start = .;
        .ARM.exidx :
        {
            *(.ARM.exidx* .gnu.linkonce.armexidx.*)
        } > IMAGERAM
        __exidx_end = .;
    
    
        .data :
        {
            . = ALIGN(4);
            __data_start__ = .;
            *(vtable)
            *(.data*)
    
            . = ALIGN(4);
            /* preinit data */
            PROVIDE_HIDDEN (__preinit_array_start = .);
            KEEP(*(.preinit_array))
            PROVIDE_HIDDEN (__preinit_array_end = .);
    
            . = ALIGN(4);
            /* init data */
            PROVIDE_HIDDEN (__init_array_start = .);
            KEEP(*(SORT(.init_array.*)))
            KEEP(*(.init_array))
            PROVIDE_HIDDEN (__init_array_end = .);
    
    
            . = ALIGN(4);
            /* finit data */
            PROVIDE_HIDDEN (__fini_array_start = .);
            KEEP(*(SORT(.fini_array.*)))
            KEEP(*(.fini_array))
            PROVIDE_HIDDEN (__fini_array_end = .);
    
            . = ALIGN(4);
            /* All data end */
            __data_end__ = .;
    
        } > IMAGERAM
    
        .bss :
        {
            . = ALIGN(4);
            __bss_start__ = .;
            *(.bss*)
            *(COMMON)
            __bss_end__ = .;
        } > IMAGERAM
    
        .heap (NOLOAD):
        {
            /* The line below can be used to FILL the memory with a known value and
             * debug any stack overruns. For this to work, the specifier (NOLOAD) above
             * must be removed at the expense of an increase in the output binary size */
            FILL(0xDEADBEEF)
            . = ALIGN(4);
            __end__ = .;
            end = __end__;
            /* The line below created to be compatible with Linaro's semihosting support */
            __HeapBase = __end__;
            *(.heap*)
            . = . + HEAPSIZE;
            __HeapLimit = .;
        } > IMAGERAM
    
        /* .stack section doesn't contain any symbols. It is only
         * used for linker to calculate size of stack sections, and assign
         * values to stack symbols later */
        .stack (NOLOAD):
        {
            /* The line below can be used to FILL the memory with a known value and
             * debug any stack overruns. For this to work, the specifier (NOLOAD) above
             * must be removed at the expense of an increase in the output binary size */
            FILL(0xBAD0BAD0)
            . = ALIGN(4);
            __StackLimit = . ;
            *(.stack*)
            . = . + STACKSIZE;
            __StackTop = . ;
            /* The line below created to be compatible with Linaro's semihosting support */
            __StackBase = . ;
        } > IMAGERAM
        PROVIDE(__stack = __StackTop);
    
    }
    /**************************************************************************/