在Keil5中使用STM32H750配合TouchGFX时遇到L6216E: Cannot use base/limit symbols for non-contiguous section .init_array错误,通常是由于分散加载文件(Scatter File)配置不当导致.init_array段被分配到非连续的内存区域。以下是原因分析和解决方案:
问题原因
.init_array段的作用
该段存放C++全局对象的构造函数指针,需保证连续性。链接器发现该段被拆分到不连续的内存区域时,会触发此错误。
分散加载配置冲突
- 分散加载文件中可能存在多个执行域(Execution Region)包含
.init_array段。
- 内存区域(Memory Region)定义不连续(如同时使用DTCM和AXI SRAM)。
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. 使用UNION或FIXED属性
如果必须使用多个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)分配合理。
验证步骤
- 编译后查看
.map文件,搜索.init_array确认其位置。
- 确认
.init_array的起始(Load Address)和结束地址是否连续。
- 逐步简化分散加载文件,定位冲突区域。
通过以上调整,应能解决L6216E错误。如问题依旧,建议提供分散加载文件完整内容进一步分析。
在Keil5中使用STM32H750配合TouchGFX时遇到L6216E: Cannot use base/limit symbols for non-contiguous section .init_array错误,通常是由于分散加载文件(Scatter File)配置不当导致.init_array段被分配到非连续的内存区域。以下是原因分析和解决方案:
问题原因
.init_array段的作用
该段存放C++全局对象的构造函数指针,需保证连续性。链接器发现该段被拆分到不连续的内存区域时,会触发此错误。
分散加载配置冲突
- 分散加载文件中可能存在多个执行域(Execution Region)包含
.init_array段。
- 内存区域(Memory Region)定义不连续(如同时使用DTCM和AXI SRAM)。
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. 使用UNION或FIXED属性
如果必须使用多个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)分配合理。
验证步骤
- 编译后查看
.map文件,搜索.init_array确认其位置。
- 确认
.init_array的起始(Load Address)和结束地址是否连续。
- 逐步简化分散加载文件,定位冲突区域。
通过以上调整,应能解决L6216E错误。如问题依旧,建议提供分散加载文件完整内容进一步分析。
举报