ST意法半导体
直播中

温暖镜头

10年用户 1056经验值
擅长:电源/新能源 制造/封装
私信 关注
[问答]

H750 + TouchGFX分散加载KEIL5报错Error: L6216E的原因?怎么解决?

分散加载选中这些文件夹就会报错

报错信息:.STM32H750XBH6_GFX_RSTM32H750XBH6_GFX_R.axf: Error: L6216E: Cannot use base/limit symbols for non-contiguous section .init_array

回帖(2)

李裕伦

2025-3-14 14:55:53
通常该错误是由于 .ARM.exidx 段在内存中被分割成了多个不连续的部分。同样,.init_array 段也必须在内存中


是连续的,并且在同一个执行区域中。


下面是一个 Keil 分散加载文件的部分内容供你参考。
LR_IROM1 0x08000000 0x00080000xa0xa0{xa0 xa0 ; load region size_region
xa0xa0ER_IROM1 0x08000000 0x00080000xa0xa0{xa0xa0; load address = execution address
xa0 xa0 filex.o (+RO)xa0 xa0; 来自 源文件
xa0 xa0 * (.ARM.exidx)xa0xa0; 放置 .ARM.exidx 段
xa0 xa0 * (.init_array) ; 放置 .init_array 段
xa0 xa0 * (+RO)
xa0xa0}
。。。。。。
举报

无人岛

2025-3-21 17:53:31

在Keil5中使用STM32H750配合TouchGFX时遇到L6216E: Cannot use base/limit symbols for non-contiguous section .init_array错误,通常是由于分散加载文件(Scatter File)配置不当导致.init_array段被分配到非连续的内存区域。以下是原因分析和解决方案:




问题原因




  1. .init_array段的作用

    该段存放C++全局对象的构造函数指针,需保证连续性。链接器发现该段被拆分到不连续的内存区域时,会触发此错误。




  2. 分散加载配置冲突  



    • 分散加载文件中可能存在多个执行域(Execution Region)包含.init_array段。

    • 内存区域(Memory Region)定义不连续(如同时使用DTCM和AXI SRAM)。




  3. TouchGFX资源分配影响

    TouchGFX可能将部分资源(如图形缓冲区)分配到外部RAM(如SDRAM),导致默认内存布局被修改。






解决方案


1. 确保.init_array段连续


在分散加载文件中,强制将.init_array分配到单一连续区域,例如内部RAM(如DTCM或AXI SRAM)。示例配置:


LR_IROM1 0x08000000 0x00200000 {   ; Flash地址
  ER_IROM1 0x08000000 0x00200000 { ; 加载域
    *.o (RESET, +First)
    *(InRoot$$Sections)
    .ANY (+RO)
  }

  RW_IRAM1 0x20000000 0x00020000 { ; 使用DTCM(连续RAM)
    .ANY (+RW +ZI)
    *(.init_array)     ; 显式指定.init_array到连续区域
  }

  RW_IRAM2 0x24000000 0x00080000 { ; AXI SRAM(其他资源)
    *touchgfx*.o (+RW +ZI)         ; TouchGFX资源
  }
}

2. 合并分散的.init_array输入段


如果.init_array被多个模块分散,使用+RO+RW合并:


RW_IRAM1 0x20000000 0x00020000 {
  .ANY (+RW +ZI)
  *(.init_array)        ; 合并所有.init_array输入段
}

3. 避免跨域分配


确保同一段(如.init_array)不跨越多个执行域。检查分散加载文件中是否存在重复定义。


4. 使用UNIONFIXED属性


如果必须使用多个RAM区域,尝试用UNION共享内存或FIXED固定地址:


RW_IRAM1 0x20000000 0x00020000 (FIXED) { ; 固定地址
  *(.init_array)
}

5. 检查启动文件


确认启动文件(如startup_stm32h750xx.s)是否正确复制.init_array段到RAM。需包含以下代码:


; 复制.init_array到RAM
ldr r0, =_sinit_array
ldr r1, =_einit_array
ldr r2, =_init_array_start
copy_init_array_loop:
  cmp r0, r1
  beq copy_init_array_done
  ldr r3, [r0], #4
  str r3, [r2], #4
  b copy_init_array_loop
copy_init_array_done:

6. 参考TouchGFX官方配置


查看TouchGFX示例工程的分散加载文件,确保关键段(如.text.data.bss)和TouchGFX资源(如BitmapCache)分配合理。




验证步骤



  1. 编译后查看.map文件,搜索.init_array确认其位置。

  2. 确认.init_array的起始(Load Address)和结束地址是否连续。

  3. 逐步简化分散加载文件,定位冲突区域。


通过以上调整,应能解决L6216E错误。如问题依旧,建议提供分散加载文件完整内容进一步分析。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分