You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32H757xI项目移植IAR:仅将Flash读写段复制到RAM的配置

STM32H757xI + QUADSPI项目IAR移植的ICF配置问题

项目背景

基于STM32H757xI带QUADSPI扩展内存的自定义板项目,由TouchGFX Designer生成,原适配STM32CubeIDE,现移植到IAR。项目主体结构可正常编译,但ICF文件配置存在问题,无法实现CubeIDE中LD文件的逻辑:仅将Flash中的特定读写段(.data/.RamFunc系列)加载到RAM,而非全部内容。

CubeIDE中的LD配置(参考)

原LD文件中.data段的加载逻辑如下:

.data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM_D1 AT> FLASH

当前编写的ICF代码

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__      = 0x08040000;
define symbol __ICFEDIT_region_ROM_end__        = 0x080FFFFF;  /* 1 Mbyte */

/*-Internal RAM Memory Regions-*/
define symbol __ICFEDIT_region_ITCMRAM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ITCMRAM_end__   = 0x0000FFFF;  /*  64 Kbytes */
define symbol __ICFEDIT_region_DTCMRAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_DTCMRAM_end__   = 0x2001FFFF;  /* 128 Kbytes */
define symbol __ICFEDIT_region_RAM_start__     = 0x24000000;  /* 512 Kbytes */
define symbol __ICFEDIT_region_RAM_end__       = 0x2407FFFF;
define symbol __ICFEDIT_region_RAM_D2_start__  = 0x30000000;  /* 288 Kbytes */
define symbol __ICFEDIT_region_RAM_D2_end__    = 0x30047FFF;
define symbol __ICFEDIT_region_RAM_D3_start__  = 0x38000000;  /* 64 Kbytes */
define symbol __ICFEDIT_region_RAM_D3_end__    = 0x3800FFFF;
define symbol __ICFEDIT_region_SDRAM_start__   = 0xD0000000;  /*  3600 Kbytes */
define symbol __ICFEDIT_region_SDRAM_end__     = 0xD0383FFF;
define symbol __ICFEDIT_region_SDRAM2_start__  = 0xD0384000;  /*  4592 Kbytes */
define symbol __ICFEDIT_region_SDRAM2_end__    = 0xD07FFFFF;

/*-Quad-SPI Memory Regions-*/
define symbol __ICFEDIT_region_QSPI_start__   = 0x90000000;
define symbol __ICFEDIT_region_QSPI_end__     = 0x93FFFFFF;  /* 64 Mbytes */

/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x1000;  /* 2 Kb */
define symbol __ICFEDIT_size_heap__   = 0xC000;   /* 2 Kb */
/**** End of ICF editor section. ###ICF###*/

define memory mem with size = 4G;
define region ROM_region        = mem:[from __ICFEDIT_region_ROM_start__        to __ICFEDIT_region_ROM_end__    ];

define region ITCMRAM_region    = mem:[from __ICFEDIT_region_ITCMRAM_start__    to __ICFEDIT_region_ITCMRAM_end__];
define region DTCMRAM_region    = mem:[from __ICFEDIT_region_DTCMRAM_start__    to __ICFEDIT_region_DTCMRAM_end__];
define region RAM_region        = mem:[from __ICFEDIT_region_RAM_start__        to __ICFEDIT_region_RAM_end__    ];
define region RAM_D2_region     = mem:[from __ICFEDIT_region_RAM_D2_start__     to __ICFEDIT_region_RAM_D2_end__ ];
define region RAM_D3_region     = mem:[from __ICFEDIT_region_RAM_D3_start__     to __ICFEDIT_region_RAM_D3_end__ ];
define region SDRAM_region      = mem:[from __ICFEDIT_region_SDRAM_start__      to __ICFEDIT_region_SDRAM_end__  ];
define region SDRAM2_region     = mem:[from __ICFEDIT_region_SDRAM2_start__     to __ICFEDIT_region_SDRAM2_end__ ];

define region QSPI_region    = mem:[from __ICFEDIT_region_QSPI_start__    to __ICFEDIT_region_QSPI_end__];
//define block CSTACK       with alignment = 8, size = __ICFEDIT_size_cstack__    { };
//define block HEAP         with alignment = 8, size = __ICFEDIT_size_heap__      { };

define block FRAME_BUF    with alignment = 4    { first section TouchGFX_Framebuffer };

initialize by copy { readwrite }
except { section .isr_vector, section .text_init, section .text, section .rodata_init, section .preinit_array, section .init_array, section .data_init,
         section ExtFlashSection_init, section ExtFlashSection, section FontFlashSection_init, section FontFlashSection, section FontSearchFlashSection };
 
do not initialize  { section .noinit, section .bss, section TouchGFX_Framebuffer, section BufferSection };

place in ITCMRAM_region     { };
place in DTCMRAM_region     { };
place in RAM_region         { readwrite , section .bss, last section ._user_heap_stack };
place in RAM_D2_region      { };
place in RAM_D3_region      { };
place in SDRAM_region       { block FRAME_BUF };
place in SDRAM2_region      { section BufferSection };
place at start of ROM_region { readonly section .isr_vector };
place in ROM_region         { readonly, first section .text_init, section .text,section .rodata_init, section .rodata, section .ARM, section .preinit_array, section .init_array, section .fini_array, section TextFlashSection, last ro code section .data }; //section .rodata,
place in QSPI_region        { first section ExtFlashSection, section FontFlashSection_init, section FontFlashSection, last section FontSearchFlashSection };

遇到的错误

错误1:RAM空间不足

Error[Lp011]: section placement failed unable to allocate space for sections/blocks with a total estimated minimum size of 0x27'02f0 bytes (max align 0x4) in <[0x2400'0000-0x2407'ffff]> (total uncommitted space 0x8'0000).

问题根源:initialize by copy { readwrite } 会尝试将所有读写段(包括QUADSPI中的段)复制到RAM,但RAM空间远不足以容纳。

错误2:ROM区域混合放置读写段

Error[Lp005]: placement includes a mix of sections with content (example "ro data init_array section .init_array in TouchGFXConfiguration.o") [suitable for placement in ROM] and sections without content (example "rw data section .data in HardwareMJPEGDecoder.o symbols: [JPEG_OUT_Read_BufferIndex, Jpeg_OUT_BufferTab, MCU_BlockIndex, semDecodingDone, DMA2D_CopyBufferEnd]") [suitable for placement in RAM] C:\MT\MT394\SW\Riverdi_7\MT394.251014.Riverdi7_Steam_gui_v1.4.2E_BK03_test_IAR_9.70_err_comp\EWARM\stm32h747xx_flash_CM7_example.icf 83

问题根源:在ROM区域的放置规则中加入了section .data,而.data是读写段,只能放在RAM,其初始化数据应放在ROM而非段本身。

解决方案

针对上述问题,对ICF文件做以下关键修改:

  1. 缩小initialize by copy的范围
    替换原有的initialize by copy { readwrite } except ...,改为仅指定需要从Flash复制到RAM的段:

    initialize by copy { section .data, section .data*, section .RamFunc, section .RamFunc* };
    

    这样就不会将QUADSPI中的读写段(如果有的话)纳入复制范围,避免RAM被过度占用。

  2. 修正RAM区域的放置规则
    明确指定RAM区域需要放置的段,包括.data系列、.bss和堆栈:

    place in RAM_region         
    { 
        section .data, 
        section .data*, 
        section .RamFunc, 
        section .RamFunc*, 
        section .bss, 
        last section ._user_heap_stack 
    };
    
  3. 移除ROM区域中的.data段
    删除ROM区域放置规则中的last ro code section .data,确保ROM只放置只读段:

    place in ROM_region         
    { 
        readonly, 
        first section .text_init, 
        section .text,
        section .rodata_init, 
        section .rodata, 
        section .ARM, 
        section .preinit_array, 
        section .init_array, 
        section .fini_array, 
        section TextFlashSection 
    };
    
  4. 调整do not initialize规则
    移除.bss(IAR默认会自动清零.bss,无需手动标记不初始化):

    do not initialize  { section .noinit, section TouchGFX_Framebuffer, section BufferSection };
    

完整修改后的ICF核心片段

// ... 保留原有的memory region定义部分 ...

define block FRAME_BUF    with alignment = 4    { first section TouchGFX_Framebuffer };

// 仅复制需要加载到RAM的读写段
initialize by copy { section .data, section .data*, section .RamFunc, section .RamFunc* };
 
do not initialize  { section .noinit, section TouchGFX_Framebuffer, section BufferSection };

place in ITCMRAM_region     { };
place in DTCMRAM_region     { };
place in RAM_region         
{ 
    section .data, 
    section .data*, 
    section .RamFunc, 
    section .RamFunc*, 
    section .bss, 
    last section ._user_heap_stack 
};
place in RAM_D2_region      { };
place in RAM_D3_region      { };
place in SDRAM_region       { block FRAME_BUF };
place in SDRAM2_region      { section BufferSection };
place at start of ROM_region { readonly section .isr_vector };
place in ROM_region         
{ 
    readonly, 
    first section .text_init, 
    section .text,
    section .rodata_init, 
    section .rodata, 
    section .ARM, 
    section .preinit_array, 
    section .init_array, 
    section .fini_array, 
    section TextFlashSection 
};
place in QSPI_region        
{ 
    first section ExtFlashSection, 
    section FontFlashSection_init, 
    section FontFlashSection, 
    last section FontSearchFlashSection 
};

原理说明

  • .data和.RamFunc系列段是读写段,需要在RAM中运行,其初始化数据存储在Flash,通过initialize by copy实现启动时从Flash复制到RAM。
  • QUADSPI中的段是只读资源(如字体、图片),直接在QSPI Flash中访问即可,无需复制到RAM,节省RAM空间。
  • ROM区域仅放置只读代码和数据,避免混合读写段导致的Lp005错误。

内容的提问来源于stack exchange,提问作者Yozora

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 05:37:00