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.

TMS320C6678: Can the DDR3 memory controller on C6678 be re-initialized in the application code after the processor is boot up from RBL via PCIe

Part Number: TMS320C6678

Hi

Can the DDR3 memory controller on C6678 be re-initialized in the application code after the processor is boot up from RBL via PCIe?

Thanks!

Wai Kokw

  • Hi,

    Yes, you can use a two stage PCIE boot. In the first stage, the PCIE boot code only initialize the DDR. Then the second stage, the application is loaded into DDR and boot there. See the pdk_c667x_2_0_xx\packages\ti\boot\examples\pcie\pcieboot_ddrinit. 

    Regards, Eric

  • Hi,

    Also refer to sections 9.2 and 9.3 of the attached doc.

    Regards, Eric

    0310.README.pdf

  • Hi Eric

    Thanks for your answer. According to the section 2 (DDR3 Controller Configuration) in the user guide, KeyStone I DDR3 Initialization (SPRABL2E–January 2012–Revised October 2016), 

    The DDR3 controller initialization process as defined in this document has been proven to be robust. It is
    meant to be executed once from start to finish. Portions of this sequence cannot be implemented in a
    loop. If a system design requires multiple DDR3 Controller initialization sequences, each initialization
    should follow a device reset


    If the DDR3 memory controller has already been initialized by ROM bootloader (RBL), how can it be re-initialized in the intermediate bootloader (IBL) without a device reset which will execute RBL again.  

    Thanks!

    Wai Kwok

  • Hi Eric

    Just one addition information about my system. In my system, RBL boots up the processor via PCIe and then an IBL is loaded. In my IBL, PLL and DDR3 memory controller are initialized. But the DDR3 memory test run right after the DDR3 memory controller initialization fails about 3 time out of 30 reboots.

    Thanks!

    Wai Kwok

  • Hi,

    The RBL doesn't initialize the DDR3. That is in IBL we load a small application to initialize the DDR, then load another application in DDR to run.

    Regards, Eric

  • Hi,

    But the DDR3 memory test run right after the DDR3 memory controller initialization fails about 3 time out of 30 reboots.========> Need more info about your system:

    1) is this TI C6678 EVM

    2) what is the DDR speed and brand name/module number

    3) what kind of memory test

    4) do you have other ways to initialize the DDR in no-boot mode, like use GEL file or an application. And the DDR test always work?

    5) Is the same DDR3 initialization code from 4) you used in PCIE/IBL case?

    6) need more info about failure pattern

    7) In the RBL boot, are you able to confirm that RBL didn't initialize the DDR3. You can look at a few DDR3 PLL registers, dump them out. I thought RBL shouldn't do this.

    Regards, Eric  

  • 1) is this TI C6678 EVM

    It is an in-house customized C6678 board.

    2) what is the DDR speed and brand name/module number

    It is DDR3-1333.

    3) what kind of memory test

    Following is the memory test code. When it fails, the value read back a memory location is different from the value written to it.

    /*
     * ddrMemTest.c
     *
     *  Created on: Mar 2, 2020
     *      Author:
     */

    #include <stdint.h>
    #include "platform_internal.h"

    // boot-loader DDR memory test
    #define DDR_MEM_SIZE_TO_TEST       (10 * 1024)            // 10KB
    #define DDR_MEM_START_PATTERN      (10041518462085691392) // starting pattern was randomly chosen
    #define TOTAL_NUM_OF_WORDS         (DDR_MEM_SIZE_TO_TEST / sizeof(uint64_t)) // total words or patterns

    /* This pseudo-random generator uses Fibonacci linear-feedback shift
     *   register (LFSR) to create 64-bit pseudo-random patterns.
     *   The LFSR below is represented as: x^64 + x^63 + x^61 + x^60 + 1
     */
    #pragma CODE_SECTION (MemTestPatternGenerator, ".sl2scratch")
    static inline uint64_t MemTestPatternGenerator( uint64_t a_pattern )
    {
        uint64_t newBit;
        uint64_t lfsr;
        uint64_t r_pattern;
        uint64_t tempNewBits;

        lfsr = a_pattern;

        // 5th and 4th bit XOR with 2nd and 1st bit
        tempNewBits = lfsr ^ (lfsr << 3);

        // 5th bit XOR with 4th bit
        newBit = ( tempNewBits ^ ( tempNewBits << 1) ) & 16; // newBit created is on 5th bit

        // Make room for new bit, and move new bit to the most significant bit to create new pattern
        r_pattern = ( (lfsr >> 1) | (newBit << 59) );

        return r_pattern;
    }


    /* The test is 64-bits words
     *
     * Tests SpDsp_Interface region (as of 03/09/2017 = SpDsp_Interface size is ~7KB)
     * It was decided to test a conservative size of 10KB starting from the DDR base address
     * since the SpDsp_Interface region size can change.
     *
     * L1D and L2 Cache are disabled.
     *
     * return address fail value or empty if pass
     */

    #pragma CODE_SECTION (dspDdrMemoryTest, ".sl2scratch")
    uint32_t ddrMemTest(void)
    {
        uint32_t         i;
        uint64_t         pattern, actualData;
        uint64_t         *pMem;

        // starting address must be 8 byte aligned.
        const uint32_t   startAddr = PLL_REINIT_DDR3_TEST_START_ADDR & ~7;

        // test is 64-bit type
        pMem = (uint64_t *)startAddr;

        pattern = DDR_MEM_START_PATTERN;

        // write new pseudo pattern
        #pragma MUST_ITERATE( TOTAL_NUM_OF_WORDS, TOTAL_NUM_OF_WORDS )
        for( i = 0; i < ( TOTAL_NUM_OF_WORDS ); i++ )
        {
            pattern = MemTestPatternGenerator(pattern);

            _amem8(pMem++) = pattern;
        }

        // rebase for pseudo pattern verification
        pattern = DDR_MEM_START_PATTERN;

        // rebase
        pMem = (uint64_t *)startAddr;

        // verify pseudo-pattern, and write its complementary pattern
        for( i = 0; i < ( TOTAL_NUM_OF_WORDS ); i++ )
        {
            pattern = MemTestPatternGenerator(pattern);
            actualData = _amem8(pMem);

            if ( actualData != pattern )
            {
                return (uint32_t)(pMem);
            }

            // write complementary
             _amem8(pMem++) = ~pattern;
        }

        // rebase for complementary verification
        pattern = DDR_MEM_START_PATTERN;

        // rebase
        pMem = (uint64_t *)startAddr;

        // verify complementary
        for( i = 0; i < ( TOTAL_NUM_OF_WORDS ); i++ )
        {
            pattern = MemTestPatternGenerator(pattern);
            actualData = _amem8(pMem);

            if ( actualData != ~pattern )
            {
                return (uint32_t)(pMem);
            }

            pMem++;
        }

        return 0;  // return nothing since no errors
    }/*dspDdrMemoryTest*/

    4) do you have other ways to initialize the DDR in no-boot mode, like use GEL file or an application. And the DDR test always work?

    The PCIe boot mode is configured to initialize DDR3 memory controller before loading IBL from a host processor via PCIe. Can the DDR3 memory controller be re-initialized again after it has been initialized by RBL? In "C:\ti\ccsv6\ccs_base\emulation\boards\evmc6678l\gel\evmc6678l.gel", the PPL and DDR3 memory controller are initialized  in a loop in Global_Default_Setup_Silent() until the ddr3 memory test passes or the loop count is more than 10. Should I implement this re-initialization in a loop?

    5) Is the same DDR3 initialization code from 4) you used in PCIE/IBL case?

    It is not the same. My ex-colleague copied platform_init() from C:\ti\pdk_c667x_2_0_5\packages\ti\platform\evmc6678l\platform_lib\src\platform.c and modify it a little bit.

    6) need more info about failure pattern

    The memory test described in (3)  only fails 3-6 times out of 30 system reboots which triggers power on reset on C6678.

    7) In the RBL boot, are you able to confirm that RBL didn't initialize the DDR3. You can look at a few DDR3 PLL registers, dump them out. I thought RBL shouldn't do this.

    See my answer to (4)

  • Hi Eric

    In C:\ti\pdk_c667x_2_0_5\packages\ti\platform\evmc6678l\platform_lib\include\platform_internal.h, there are 3 defined symbols for a workaround to re-initialize PLL and DDR.

    /* This flag implements a workaround to re-initialize PLL and DDR
       if DDR test after DDR initialization */
    #define PLATFORM_PLL_REINIT
    #define PLL_REINIT_DDR3_TEST_START_ADDR (0x80000000)
    #define PLL_REINIT_DDR3_TEST_END_ADDR   (PLL_REINIT_DDR3_TEST_START_ADDR + (128 *1024))

    PLATFORM_PLL_REINIT is undefined or turned off in my modified version of platform_internal.h. Is this workaround for EVM6678l board or C6678 silicon Revision 2? Should I turned on PLATFORM_PLL_REINIT for my customized C6678 board?

    Thanks!

    Wai Kwok

  • Hi Eric

    The DDR3 memory test passes all the times in my code after the re-initialization workaround is enabled by defining PLATFORM_PLL_REINIT in my customized platform_local.c. Is this re-initialization workaround specific for EVM6678l board or C6678 processor?

    Thanks!

    Wai Kwok

  • Wai,

    PLATFORM_PLL_REINIT or loop_counter = 10 is for 6678L EVM, we have some DDR3 test failure occasionally (<<1%) and this was used. On your own board, you may check how many times you do REINIT to get DDR3 test past. If it is often more than once, then you have other issues that need to be resolved.  I would point you back to the AN: http://www.ti.com/lit/an/spracl8/spracl8.pdf and recommend that you carefully follow and validate each step.  They also need to make sure that their ‘wait’ periods of 600us and 3ms actually occur.  If not properly implemented, optimizing compilers will strip these out.  Repeated PHY initialization is often needed when the waits do not occur.

    Regards, Eric

     

  • Hi Eric

    The DDR3 partial automatic leveling registers (DATA1_WRLVL_INIT_RATIO,..,DATA8_WRLVL_INIT_RATIO, DATA0_GTLVL_INIT_RATIO,...,DATA8_GTLVL_INIT_RATIO) in my customized bootcode have the default values for EVM6678l board. After replacing them with the calculated values for my customized board, there is no memory test failure in 1000 tests. It seems like the initial automatic leveling values have to be closed to true values for the automatic leveling algorithm to work.  Thanks very much for your help.

    Wai kwok