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.

Problem with multiple block read of MMCSD on AM572x

I am using evmAM572x board and SDK 03.00.00.04.

It seems to me that MMCSD driver invoked by MLO (no DMA, no interrupts) cannot perform multiple block reads. If it reads the SD card one block at a time - everything is fine, but attempt to read two blocks results in wrong data.

Seems like for MLO bootloader, the case of multiple block read is triggered by RPRC section aligned on sector border (512 bytes) and large enough (>= 2K). SBL_FileRead() reads file's content 1K per one f_read() call. And it results in two calls of disk_read() in FatFs, one sector each - unless the read is sector-aligned, in this case it is one disk_read() of two sectors. And disk_read() of two sectors yields wrong data; entire 1K buffer is populated with the last 32-bit word of two sectors read.

I looked into MMCSD_v1_read(), MMCSD_v1_transfer() and HSMMCSDCommandSend().

Reading multiple blocks is CMD18. According to processor's datasheet (spruhz6.pdf, page 6693), CMD_TYPE field in MMCHS_CMD register must be 0 for all commands, except CMD12 and CMD52. But MMCSD_v1_read() sets transaction flag MMCSD_CMDRSP_ABORT for CMD18 and MMCSD_v1_transfer() turns this flag into command type 3. I removed this flag, but it didn't help.

So, my MLO cannot perform multiple block reads. I tried two different SD cards. And it is likely that this MMCSD driver has the same problem with writes.

  • Can you please provide more details of your use case? The MLO's primary function is to configure the device and load U-boot.
  • My MLO is "sbl" project, which loads and runs file named "app". It is part of SDK.
    I compile my project, get ELF. Then I convert ELF to RPRC by out2rprc.exe utility. Then MulticoreImageGen.exe composes multiple RPRCs into one "app" file (multicore image).

    So, file "app" contains a high-level multicore header and multiple RPRC images, each of which has its own header. RPRC image has multiple sections, which are loaded into memory independently.

    If section happens to be aligned on sector border (inside "app" file, not per destination memory address) then multiple block read is invoked and it doesn't seem to work. If section is not sector-aligned, then multiple block read is never invoked, regardless of the size of the section.
    Multicore header is sector-aligned (it is located at offset 0 in "app" file), but it is less than 512 bytes (sector size), so reading it does not invoke multiple block read either.
  • Thanks. I have notified the software team. They will respond here.
  • "If section happens to be aligned on sector border (inside "app" file, not per destination memory address) then multiple block read is invoked and it doesn't seem to work. If section is not sector-aligned, then multiple block read is never invoked, regardless of the size of the section.
    Multicore header is sector-aligned (it is located at offset 0 in "app" file), but it is less than 512 bytes (sector size), so reading it does not invoke multiple block read either.

    Seems like for MLO bootloader, the case of multiple block read is triggered by RPRC section aligned on sector border (512 bytes) and large enough (>= 2K). "

    From your description, if the app is larger than 2K and 512 bytes border aligned then it should triggers a multiple block read and should fail.

    From my experience we used MLO successfully booted many different "apps", the app image is bigger than 2K, we didn't see any such issue.

    Can you elaborate?

    Regards, Eric
  • Size of app is irrelevant. Some RPRC section inside it must be sector-aligned and >=1K. (2K was a mistake/typo, sorry about that). It is pretty rare, I have built a lot of binaries before I encountered this corner case.

    I composed an example, which demonstrates this effect for you. It is based on GPIO toggle example from CSL. Please, try it.

    In this example, I introduced two sections, ".data_a" and ".data_b". ".data_b" is the section, which will be loaded incorrectly, if it is sector-aligned. In order to make it sector-aligned inside app, you need to adjust the size of preceding ".data_a" section. For me, array size 126 made section ".data_b" sector-aligned, but for you it might be a different number, depending on your compiler and its settings.
    You should use the special marker word, 0x12345678, to find the start of section ".data_b" is any hexviewer. Please, build, postlink and check offset of the marker in "app". Then adjust the size of ".data_a" to get the marker sector-aligned. For such app, section ".data_b" will be loaded incorrectly and UART output will say so. Then try +/- 1 sizes of ".data_a" section array and for both builds section ".data_b" will be loaded successfully.
  • /*
     *  Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
     /**
     *  \file   main.c
     *
     *  \brief This file demonstrates toggling gpio pins high and low
     *         using GPIO dal API's.
     *
     */
    
    /* ========================================================================== */
    /*                             Include Files                                  */
    /* ========================================================================== */
    #include "stdint.h"
    #include <ti/csl/csl_gpio.h>
    #if defined (SOC_AM572x) || defined (SOC_AM571x)
    #include <ti/board/board.h>
    #endif
    #include <ti/csl/example/utils/common/inc/uartConfig.h>
    #include <ti/csl/soc.h>
    #include <ti/csl/hw_types.h>
    
    /* ========================================================================== */
    /*                                 Macros                                     */
    /* ========================================================================== */
    /* None */
    
    /* ========================================================================== */
    /*                            Global Variables                                */
    /* ========================================================================== */
    uint32_t pinDirection = GPIO_DIR_OUTPUT;
    
    /*To use UARTConfigPuts(uartBaseAddr, function for prints*/
    /*To use UARTConfigPuts function for prints*/
    #if (defined (SOC_AM572x)) || (defined (SOC_AM571x))
    uint32_t uartBaseAddr = CSL_MPU_UART3_REGS;
    #endif
    #if defined (SOC_TDA2EX) || defined (SOC_TDA2XX) || defined (SOC_DRA7XX)
    uint32_t uartBaseAddr = SOC_UART1_BASE;
    #endif
    #if defined (SOC_TDA3XX)
    uint32_t uartBaseAddr = SOC_UART3_BASE;
    #endif
    
    #if (defined (SOC_AM572x)) || (defined (SOC_AM571x))
    uint32_t gpio_base_address = CSL_MPU_GPIO7_REGS;
    uint32_t gpio_pin          = 8;
    #elif defined (SOC_TDA2EX) || defined (SOC_TDA2XX) || defined (SOC_DRA7XX)
    uint32_t gpio_base_address = SOC_GPIO1_BASE;
    uint32_t gpio_pin          = 14;
    #elif defined (SOC_TDA3XX)
    uint32_t gpio_base_address = SOC_GPIO4_BASE;
    uint32_t gpio_pin          = 9;
    #endif
    
    /* ========================================================================== */
    /*                          Function Definitions                              */
    /* ========================================================================== */
    void padconfig_PrcmEnable()
    {
    #if defined (SOC_AM572x) || defined (SOC_AM571x)
        /*Pad configurations */
        Board_initCfg boardCfg;
        boardCfg = BOARD_INIT_UNLOCK_MMR | BOARD_INIT_UART_STDIO | 
                   BOARD_INIT_MODULE_CLOCK | BOARD_INIT_PINMUX_CONFIG;
        Board_init(boardCfg);  
    
        HW_WR_REG32(CSL_MPU_CORE_PAD_IO_REGISTERS_REGS+CSL_CONTROL_CORE_PAD_IO_PAD_DCAN1_TX,0x0006000E);
        /*Enable GPIO clock*/
        HW_WR_REG32(CSL_MPU_L4PER_CM_CORE_REGS+CSL_L4PER_CM_CORE_COMPONENT_CM_L4PER_GPIO2_CLKCTRL_REG,0x102);
         while ((HW_RD_REG32(CSL_MPU_L4PER_CM_CORE_REGS+CSL_L4PER_CM_CORE_COMPONENT_CM_L4PER_GPIO2_CLKCTRL_REG) & (0x00030000U)) != 0x0)
            {
                ;
            }
        HW_WR_REG32(CSL_MPU_L4PER_CM_CORE_REGS+CSL_L4PER_CM_CORE_COMPONENT_CM_L4PER_GPIO3_CLKCTRL_REG,0x102);
         while ((HW_RD_REG32(CSL_MPU_L4PER_CM_CORE_REGS+CSL_L4PER_CM_CORE_COMPONENT_CM_L4PER_GPIO3_CLKCTRL_REG) & (0x00030000U)) != 0x0)
            {
                ;
            }
        HW_WR_REG32(CSL_MPU_L4PER_CM_CORE_REGS+CSL_L4PER_CM_CORE_COMPONENT_CM_L4PER_GPIO4_CLKCTRL_REG,0x102);
        while ((HW_RD_REG32(CSL_MPU_L4PER_CM_CORE_REGS+CSL_L4PER_CM_CORE_COMPONENT_CM_L4PER_GPIO4_CLKCTRL_REG) & (0x00030000U)) != 0x0)
            {
                ;
            }
    #endif
    #if defined (SOC_TDA2XX) || defined (SOC_TDA2EX) || defined (SOC_DRA7XX)
        /*Pad configurations */
        HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_UART1_RXD,0x00040000);
        HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_UART1_TXD,0x00040000);
        HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_DCAN1_TX,0x0006000E);
        /*Enable GPIO clock*/
        HW_WR_REG32(SOC_L4PER_CM_CORE_BASE+CM_L4PER_GPIO2_CLKCTRL,0x102);
        while ((HW_RD_REG32(SOC_L4PER_CM_CORE_BASE+CM_L4PER_GPIO2_CLKCTRL) & (0x00030000U)) != 0x0)
            {
                ;
            }
        HW_WR_REG32(SOC_L4PER_CM_CORE_BASE+CM_L4PER_GPIO3_CLKCTRL,0x102);
         while ((HW_RD_REG32(SOC_L4PER_CM_CORE_BASE+CM_L4PER_GPIO3_CLKCTRL) & (0x00030000U)) != 0x0)
            {
                ;
            }
        HW_WR_REG32(SOC_L4PER_CM_CORE_BASE+CM_L4PER_GPIO4_CLKCTRL,0x102);
        while ((HW_RD_REG32(SOC_L4PER_CM_CORE_BASE+CM_L4PER_GPIO4_CLKCTRL) & (0x00030000U)) != 0x0)
            {
                ;
            }
        /* Set the UART Parameters */
        UARTConfigInit(uartBaseAddr, BAUD_RATE_115200, UART_WORD_LENGTH_8, UART_STOP_BIT_1, UART_NO_PARITY,
                       UART_16x_MODE);
    #endif
    #if defined (SOC_TDA3XX)
        HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_IO_SPI1_SCLK,0x00040001);
        HW_WR_REG32(SOC_CORE_PAD_IO_REGISTERS_BASE+CTRL_CORE_PAD_IO_SPI1_CS0,0x00000001);
        /* Set the access to the GPMC registers - Enable GPMC Clock */
        HW_WR_REG32(SOC_L4PER_CM_CORE_BASE + CM_L4PER_GPIO2_CLKCTRL, 0x102);
        while ((HW_RD_REG32(SOC_L4PER_CM_CORE_BASE +
                        CM_L4PER_GPIO2_CLKCTRL) & (0x00030000U)) != 0x0)
           {
                ;
           }
       HW_WR_REG32(SOC_L4PER_CM_CORE_BASE + CM_L4PER_GPIO3_CLKCTRL, 0x102);
       while ((HW_RD_REG32(SOC_L4PER_CM_CORE_BASE +
                        CM_L4PER_GPIO2_CLKCTRL) & (0x00030000U)) != 0x0)
           {
                ;
           }
       HW_WR_REG32(SOC_L4PER_CM_CORE_BASE + CM_L4PER_GPIO4_CLKCTRL, 0x102);
       while ((HW_RD_REG32(SOC_L4PER_CM_CORE_BASE +
                        CM_L4PER_GPIO2_CLKCTRL) & (0x00030000U)) != 0x0)
           {
                ;
           }
        /* Set the UART Parameters */
        UARTConfigInit(uartBaseAddr, BAUD_RATE_115200, UART_WORD_LENGTH_8, UART_STOP_BIT_1, UART_NO_PARITY,
                       UART_16x_MODE);
    #endif
    }
    void delay(void)
    {
        volatile uint32_t i;
        for (i = 0; i < 4000000; i++)
        {}
    }
    
    
    #define MARKER 0x12345678
    
    // Adjust the size of section ".data_a" so section "data_b" is 0x200 bytes aligned in "app" file
    // Just look for marker word in some hexwiew and check its offset
    
    // Array size needs to be adjusted depending on compiler version and settings
    // For me, it works if array size is 125, does not work for 126 and works again for 127
    uint32_t a[126] __attribute__((section(".data_a"))) = {1};
    
    uint32_t b[256] __attribute__((section(".data_b"))) = {MARKER}; // 1K is enough
    
    
    int main(void)
    {
        volatile uint32_t checkOutput = 1;
    
        padconfig_PrcmEnable();
    
        uint32_t dummy = a[0];  // Dummy access to data_a section, otherwise compiler eliminates it
    
        if (b[0] == MARKER)
        {
            UARTConfigPuts(uartBaseAddr,"\nSection \".data_b\" loaded correctly", -1);
        }
        else
        {
            UARTConfigPuts(uartBaseAddr,"\nSection \".data_b\" loaded incorrectly", -1);
        }
    
        
        UARTConfigPuts(uartBaseAddr,"\nGPIO Output App", -1);
        UARTConfigPuts(uartBaseAddr,"\nGenerating a square wave on GPIO pin", -1);
    #if defined (SOC_AM572x) || defined (SOC_TDA2XX) || defined (SOC_DRA7XX) || defined (SOC_AM571x) || defined (SOC_TDA2EX)
        UARTConfigPuts(uartBaseAddr,"\nProbe the GPIO1 pin 14 on JP2 connector - pin 1 on EVM", -1);
    #elif defined (SOC_TDA3XX)
        UARTConfigPuts(uartBaseAddr,"\nProbe the GPIO4 pin 9 on J6108 connector - pin 1 on EVM", -1);
    #endif
    
        GPIOModuleReset(gpio_base_address);
    
        GPIOModuleEnable(gpio_base_address);
    
        GPIODirModeSet(gpio_base_address, gpio_pin, pinDirection);
    
        while (checkOutput)
        {
            GPIOPinWrite(gpio_base_address, gpio_pin, GPIO_PIN_HIGH);
            delay();
    
            GPIOPinWrite(gpio_base_address, gpio_pin, GPIO_PIN_LOW);
            delay();
        }
    
        return (int)dummy;
    }
    /********************************* End of file ******************************/
    
    

  • John,

    Thanks for the details! Let me do some study and get back to you!

    Regards, Eric
  • John,

    I looked at your file and did the same thing in a file at my side. I used \pdk_am57xx_1_0_3\packages\ti\board\diag\uart\src\uart_diag.c, as I have a top level batch file to call the makefile to build the .out on A15, then rprc conversion, finally uses multicoregen to covert it. Note the output is called uart_TEST after this process, then I rename it to "app" to be loaded by MLO in a SD card.

    I also have data section a and b as you and adjust the section a size to make the section b aligned to 0x200 boundary. One thing I am not sure is 0x200 to what address?

    If you open the "app" by a binary viewer, starting at address 0x0 is the multicore image header, starting at 0x20 is the RPRC header, starting from 0x48 is the real image.

    So I used aa[187] or aa[195] or aa[205] to make it aligned to different offset. Below is a picture of the hex view of the app, and my last attempt to align 0x200 to the offset of 0x48 (real starting of the code). My data_b pattern is 55 55 55 55. In all of the 3 trials, I can't reproduce your issue, that is section b is loaded properly in my test.

    Can you explain in what kinds of 0x0200 align to see the issue? I also attached my source code for your info.

     

    /*
     * Copyright (c) 2015, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    #include <ti/drv/uart/UART_stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <tistdtypes.h>
    
    #include "board.h"
    #include "board_cfg.h"
    
    int uart_test()
    {
    	UART_printf("\n*********************************************\n"); 
    	UART_printf  ("*                 UART Test                 *\n");
    	UART_printf  ("*********************************************\n");
    
    	UART_printf("\nTesting UART print to console at 115.2k baud rate\n");
    
    	UART_printf("\nTest PASSED!\n");
    	return 0;
    }
    
    #define MARKER   0x55555555
    uint32_t aa[205] __attribute__((section(".data_a"))) = {1};
    uint32_t bb[256] __attribute__((section(".data_b"))) = {MARKER}; // 1K is enough
    
    int main(void)
    {
        uint32_t dummy = aa[0];  // Dummy access to data_a section, otherwise compiler eliminates it
    	aa[0] = 0x12345678;
    	
    	Board_initCfg boardCfg;
    #ifdef PDK_RAW_BOOT
        boardCfg = BOARD_INIT_PINMUX_CONFIG | 
            BOARD_INIT_UART_STDIO;
    #else
        boardCfg = BOARD_INIT_UART_STDIO;
    #endif
        Board_init(boardCfg);
    	
    	if (bb[0] == MARKER)
        {
            UART_printf("Section .data_b loaded correctly\n");
        }
        else
        {
            UART_printf("Section .data_b loaded incorrectly\n");
        }
    	
        return uart_test();
    }
    

    Regards, Eric

  • In your example marker has offset 0x8848. So, you need to shift the marker back to 0x8800 or forward to 0x8a00. Assuming that this binary was generated from source with aa[205], you want to change the length of array "aa" to either
    205 - 0x48/4 = 205 - 18 = 187
    or
    205 + (0x200-0x48) / 4 = 205 + 0x6e = 205 + 110 = 315.

    So, you should use 187 or 315, whichever you prefer.

    You said that for 187 you weren't able to reproduce the problem. If so, can you give me the binary ("app"), for which marker is sector-aligned and problem is not reproducible? I will try it here.

    By the way, better use debug build. For release build compiler does all kinds of optimizations and you have less control over the final binary. Anyway, if you manage to set the marker sector-aligned and section is still >= 1K, it should trigger the problem.

    I tried your example. I had to edit the source code, because it did not compile for me (different include paths, warnings as errors etc.). For me, aa[191] put the marker at 0xc200 (I use debug build).
    And, voila:

    Section .data_b loaded incorrectly
  • Sorry, I am blind. I have read your offset as 0x8848, while it is 0x8448. So, you want to shift it to either 0x8400 or 0x8600. But the numbers 187 and 315 still do apply.
  • John,

    offset 0x8400 was one of my test case. Attached is the .out file, .map file and app with number 187.  You can see the map:

    *(.data*)

    .data_a        0x8000652c      0x2ec /ti/PDK_AM~4/packages//ti/board/obj/idkAM571x/armv7/uart_diag.o

                   0x8000652c                aa

    .data_b        0x80006818      0x400 /ti/PDK_AM~4/packages//ti/board/obj/idkAM571x/armv7/uart_diag.o

                   0x80006818                bb

    Also, binary viewer showed marker at offset 0x8400. I didn't see any issue when app is loaded by MLO (the UART printed right info). I also connected JTAG to A15 core, and looked at memory address  0x80006818 to make sure it is the marker there.

    Regarding the compile issue you met when using my source code, I think you need to run the pdksetenv.bat first to setup you path and tool. Then run the gmake idkAM571x_sd under diag folder for this. Of course, this created many diagnostic images, but I just use setup for my convienece. I renamed uart_TEST into app to be loaded by MLO.

    I am not sure if you use AM571 or AM572, and what kinds of EVM. The app I sent you may not run properly on your card for UART print, but I think you can connect the JTAG to check the address of data_b to make sure it is loaded correctly into memory.

    Temp.zip

    Regards, Eric

  • In your "app" marker is sector-aligned now, but it does not start an RPRC section.

    My understanding is that each allocatable ELF section turns into RPRC section (I might be wrong).

    Here are the sections of your ELF file (uart_diagExample_idkAM571x_armv7.out):

    There are 23 section headers, starting at offset 0x5c67c:

    Section Headers:

     [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

     [ 0]                   NULL            00000000 000000 000000 00      0   0  0

     [ 1] .startcode        PROGBITS        80000000 016d4c 000000 00   W  0   0  1

     [ 2] .text             PROGBITS        80000000 010000 00652c 00  AX  0   0  8

     [ 3] .data             PROGBITS        8000652c 01652c 000820 00  WA  0   0  4

     [ 4] .bss              NOBITS          80006d4c 016d4c 000460 00  WA  0   0  4

     [ 5] .heap             NOBITS          800071ac 016d4c 001000 00  WA  0   0  1

     [ 6] .stack            NOBITS          800081ac 016d4c 010000 00  WA  0   0  1

     [ 7] BOARD_IO_DELAY_CO PROGBITS        40300000 008000 0003e8 00  AX  0   0  8

     [ 8] .ARM.exidx        ARM_EXIDX       403003e8 0083e8 000008 00  AL  2   0  4

     [ 9] BOARD_IO_DELAY_DA PROGBITS        403003f0 0083f0 00177c 00  WA  0   0  4

     [10] .debug_info       PROGBITS        00000000 016d4c 01f396 00      0   0  1

     [11] .debug_abbrev     PROGBITS        00000000 0360e2 002b04 00      0   0  1

     [12] .debug_loc        PROGBITS        00000000 038be6 009a4f 00      0   0  1

     [13] .debug_aranges    PROGBITS        00000000 042638 000a40 00      0   0  8

     [14] .debug_ranges     PROGBITS        00000000 043078 001218 00      0   0  1

     [15] .debug_line       PROGBITS        00000000 044290 007453 00      0   0  1

     [16] .debug_str        PROGBITS        00000000 04b6e3 00eda2 01  MS  0   0  1

     [17] .comment          PROGBITS        00000000 05a485 000070 01  MS  0   0  1

     [18] .ARM.attributes   ARM_ATTRIBUTES  00000000 05a4f5 000039 00      0   0  1

     [19] .debug_frame      PROGBITS        00000000 05a530 002054 00      0   0  4

     [20] .shstrtab         STRTAB          00000000 05c584 0000f6 00      0   0  1

     [21] .symtab           SYMTAB          00000000 05ca14 001d00 10     22 296  4

     [22] .strtab           STRTAB          00000000 05e714 000f87 00      0   0  1

    Key to Flags:

     W (write), A (alloc), X (execute), M (merge), S (strings)

     I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)

     O (extra OS processing required) o (OS specific), p (processor specific)

    There are no ".data_a" or ".data_b" sections. Only conventional sections ".text", ".data" and etc.

    The reason is your linker script, which merges all *(.data*) sections into one .data section of the output ELF. Your map file shows that:

    .data           0x8000652c      0x820

                   0x8000652c                . = ALIGN (0x4)

    *(.data*)

    .data_a        0x8000652c      0x2ec /ti/PDK_AM~4/packages//ti/board/obj/idkAM571x/armv7/uart_diag.o

                   0x8000652c                aa

    .data_b        0x80006818      0x400 /ti/PDK_AM~4/packages//ti/board/obj/idkAM571x/armv7/uart_diag.o

                   0x80006818                bb

    So, section ".data_b" in *.o file does not generate the section in ELF file and, therefore, RPRC section in "app".

    Proposed solutions:

    1. Rename ".data_a" and ".data_b" to something else, which does not match the pattern .data* from your linker script. But make sure it does not match any other pattern either. Your first goal would be to get two custom sections be present in ELF file, in this case they will turn into RPRC sections in app.

    2. Edit the linker script, for example, declare explicit output sections ".data_a" and ".data_b". Change the pattern for output ".data" from *(.data*) to *(.data.*).

    3. Try to make .data section sector-aligned. You will need to change the size ".text" section. You can do by writing dummy code or, (most probably) by adding const arrays (typically const data goes to .rodata section in object files and end up in .text section in ELF - but check your linker script). Also don't forget to place the marker in the very beginning of ".data" section - it starts with "aa" array per your map file.

  • John,

    I see. You need them into some seperate sections rather the .data to let the problem happening. As suggested, I created new sections in linker command file and padded code to make bb array 0x200 aligned. I reproduced the issue and will debug this with our development team. Thanks for the guide!

    Regards, Eric
  • The trigger condition is - RPRC section must be sector-aligned and >= 1K. It can be any section, including .data, .text or whatever. But it is easier to shift the start of custom section and place the marker in the beginning of it.

    Glad you reproduced the problem. I believe at some point of time you were thinking that I am complaining about non-existing issue and it does not work due to some sort of my own fault.