BIN file size ecxeeds flash size with no error

Sysprogs forums Forums VisualGDB BIN file size ecxeeds flash size with no error

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
    Posts
  • #24190
    wtywtykk
    Participant

    Hello,

    I found that the compiler/linker stores the initial value of the variables just after code area in the flash. But the size of this area is not taken into account when linking. So the actual BIN file size can exceed the size of the flash, without triggering any warnings or errors. However, under this condition, the initial values are actually placed outside the flash and will be missing at runtime.

    Procedures to reproduce the problem:

    1. Create a project with a low density mcu (i.e. stm32f030)

    2. Write lots of code, trying to use every bytes in the flash. You can also declare a large constant array to occupy the area.

    3. Declare a large non-constant array with initial values.

    4. Compile.

    5. The code should compile. The memory report will look like this:

    1>——————- Memory utilization report ——————-
    1>Used FLASH: 17KB out of 16KB (100%)
    1>Used SRAM: 2036 bytes out of 4096 bytes (49%)

    Clearly that’s not right. The actual BIN file is larger than 16K.

    The demonstration project is attached. (Edit: I failed to upload it, so I put the file to https://pan.baidu.com/s/1SuToeenDg9T6_gxF1PkyDg  . The extration code(password) is “ch6p” (without the quotation marks) .)

    I suspect that’s a linker bug or a problem with the linker script. But I’m not familar with the linker script so that’s all I can investigate.

     

    • This topic was modified 5 years, 1 month ago by wtywtykk.
    • This topic was modified 5 years, 1 month ago by wtywtykk.
    #24199
    support
    Keymaster

    Hi,

    Most likely the new variable gets optimized away or placed into a different section. Please try following our linker script tutorial to familiarize yourself with customizing the linker-related settings and techniques used to troubleshoot them.

    #24217
    wtywtykk
    Participant

    Hi,

    The variables aren’t optimized away or placed into a different section. Normally they are placed after the code and copied to sram by a for loop in the Reset_Handler. But in this case, they are simply placed outside the flash because there are no room left.

    It turns out that the original linker script makes the linker unware of the size needed for the initial value area. From the report by objdump, no section is assigned for them, and the linker simply put all the data after the address that symbol “_sidata” points to.

    The solution I found is changing the data section description in the linker script to

    .data :
    {
    . = ALIGN(4);
    _sdata = .;

    PROVIDE(__data_start__ = _sdata);
    *(.data)
    *(.data*)
    . = ALIGN(4);
    _edata = .;

    PROVIDE(__data_end__ = _edata);
    } > SRAM AT > FLASH

    Note that the “AT” at the first line is removed and the “AT > FLASH” at the last line is added.

    PS: I doesn’t have a board to test this fix for now. But I checked the symbols and sections with objdump, and it seems to work. The linker also shows an error message if the flash isn’t large enough.

    PPS: May be the there are still some problems with the ALIGN statements. It’s not fully tested.

    #24226
    support
    Keymaster

    Thanks for sharing this. We will investigate it and get back to you in the next 24 hours.

    #24233
    support
    Keymaster

    OK, we have tried reproducing this issue with the default linker script file for STM32F030F4  (unfortunately, the project link you shared does not work without a login and generally we are not able to review the code/projects that does not come from us unless it triggers bugs in VisualGDB itself), using several variations of the attributes. Generally, unless you declare the variable as volatile, gcc optimizes it away (you can verify it with the offline disassembly). If you do declare it as volatile, you do get a linker error as expected.

    We have used the following definition (tried data/rodata and also with/without const):

    volatile __attribute__((section(".rodata"))) const char g_LargeVar[32 * 1024] = {1, 2, 3};
    
    int main()
    {
        volatile int test = g_LargeVar[0];
    }

    Please double-check if you can reproduce the problem with the default linker script coming from our STM32 BSP and with minimal modifications to the default LEDBlink source (i.e. just adding one global variable and the line accessing it). If not, the problem is likely caused by some other setting specific to your project.

    #24244
    wtywtykk
    Participant

    Hi,

    I’m sorry. I just forgot the fact that I can just put the code here…. The code is based on the LEDBlink project for stm32f030f4.

    #include <stm32f0xx_hal.h>
    #include <stm32_hal_legacy.h>
    
    const uint8_t Large_Const_Array[1024 * 13 + 256] = { 0 };
    uint8_t Large_Nonconst_Array[2000] = { 0x00,0x01,0x03,0x04,0x05 };
    
    #ifdef __cplusplus
    extern "C"
    #endif
    void SysTick_Handler(void)
    {
    HAL_IncTick();
    HAL_SYSTICK_IRQHandler();
    }
    
    int main(void)
    {
    HAL_Init();
    
    __GPIOC_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStructure;
    
    GPIO_InitStructure.Pin = GPIO_PIN_12;
    
    GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStructure.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    uint32_t i = 0;
    for (;;)
    {
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET);
    HAL_Delay(500);
    HAL_Delay(Large_Const_Array[(i++) % sizeof(Large_Const_Array)]);//Just prevent the array from being optimized out
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET);
    HAL_Delay(500);
    HAL_Delay(Large_Nonconst_Array[i % sizeof(Large_Nonconst_Array)]);//Just prevent the array from being optimized out
    }
    }

     

    • This reply was modified 5 years, 1 month ago by support. Reason: formatting
    #24267
    support
    Keymaster

    No problem. We have investigated this and confirm that the syntax used in the VisualGDB-supplied linker scripts indeed does not check for FLASH overflow when placing the initialization data for RAM sections.

    We have done several tests with the “> SRAM AT > FLASH” syntax and confirm that it solves the problem and is otherwise equivalent to the old one, so we have updated our linker script generation tool to use the new syntax and also changed the logic used by the “Additional Memories” page in VisualGDB.

    The next STM32 BSP update will include the linker scripts using the new syntax. As a workaround until then, please consider editing them manually, although the only difference in behavior would be the error message for FLASH overflows caused by the RAM initialization data (regular FLASH and RAM overflows are still reported correctly with both linker script versions).

    Thanks for providing detailed repro steps and sorry for the confusion – we have previously encountered many cases when the unexpected image layout was caused by optimization and have never received any reports on issues caused by the VisualGDB’s linker script format.

    #24312
    wtywtykk
    Participant

    Hi,

    Bad news. The new syntax has some new problem. The “_sidata” symbol points to a wrong address when the “Ignore standard libraries (-nostdlib)” option is turned on in the project properties. I do find an solution to this (using LOADADDR() ), but I’m not confident about it. I’ll test my modification with my previous projects and some special cases.

    However I suspect whether it’s worth taking the risk to change a stable code. May be the linker script should remain untouched.

    #24319
    support
    Keymaster

    We did actually use LOADADDR in our tests and the new generator – this is the proper documented way to get the load address of a section (i.e. the location of the section values stored in FLASH) and it worked reliably in several different configurations.

Viewing 9 posts - 1 through 9 (of 9 total)
  • You must be logged in to reply to this topic.