OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 65|回复: 1

STM32H743跑FreeRTOS系统SDRAM空间冲突

[复制链接]

348

主题

518

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1619
金钱
1619
注册时间
2014-7-11
在线时间
283 小时
发表于 4 天前 | 显示全部楼层 |阅读模式
3金钱
原子哥 STM32H743跑FreeRTOS系统SDRAM空间冲突
..\OBJ\Template.axf: Error: L6982E: AT section malloc.o(.ARM.__AT_0xC01F4000) with base 0xc01f4000 limit 0xc1e30000 overlaps address range with AT section usarthandler.o(.ARM.__AT_0xC01F8E20) with base 0xc01f8e20 limit 0xc02e3420.
请问这是怎么回事

例程有SDRAM,没有这个错误,请问是怎么回事

最佳答案

查看完整内容[请看2#楼]

好的,这个问题是典型的链接器错误,提示在STM32H743的SDRAM内存空间中,有两个不同的程序段(section)被分配到了重叠的地址范围。我们来分析一下:错误信息解读: [*]Error: L6982E: 这是ARM Compiler Linker(链接器)报告的一个错误代码。 [*]AT section malloc.o(.ARM.__AT_0xC01F4000) with base 0xc01f4000 limit 0xc1e30000: 这表示来自 malloc.o 文件(通常与堆内存分配相关)的一个段被显式指定(AT = Address Transla ...
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

911

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4483
金钱
4483
注册时间
2019-9-4
在线时间
910 小时
发表于 4 天前 | 显示全部楼层
好的,这个问题是典型的链接器错误,提示在STM32H743的SDRAM内存空间中,有两个不同的程序段(section)被分配到了重叠的地址范围。我们来分析一下:
错误信息解读:
  • Error: L6982E: 这是ARM Compiler Linker(链接器)报告的一个错误代码。
  • AT section malloc.o(.ARM.__AT_0xC01F4000) with base 0xc01f4000 limit 0xc1e30000: 这表示来自 malloc.o 文件(通常与堆内存分配相关)的一个段被显式指定(AT = Address Translation,指定地址)放在以 0xC01F4000 开始的地址。根据基址和限制,这个段试图占据 0xC01F4000 到 0xC1E30000 之间的空间(注意:limit通常指下一个可用地址,所以实际范围是到 0xC1E2FFFF)。0xCxxxxxxx 地址通常是STM32H7系列映射到SDRAM的地址空间。
  • overlaps address range with AT section usarthandler.o(.ARM.__AT_0xC01F8E20) with base 0xc01f8e20 limit 0xc02e3420: 这表示来自 usarthandler.o 文件(你编写的或引用的处理USART逻辑的代码)的一个段也被显式指定放在以 0xC01F8E20 开始的地址。这个段试图占据 0xC01F8E20 到 0xC02E3420 之间的空间。
  • 冲突点: 第二个段的起始地址 0xC01F8E20 明显位于第一个段的地址范围 0xC01F4000 - 0xC1E30000 之内。链接器不允许两个不同的段占用同一块内存,因此报错。

核心原因:
问题的根本原因在于,你的代码或工程配置中,至少有两个地方显式地(使用 __attribute__((section(".ARM.__AT_address"))) 或 #pragma location=address 等方式)指定了要将数据或代码放置在SDRAM的特定地址上,并且这两个指定的地址范围发生了重叠。
为什么例程没有这个错误,而你的工程有?
这通常说明你在官方例程的基础上做了修改,而这些修改导致了地址冲突。可能的原因包括:
  • 手动指定变量/函数到SDRAM地址: 你可能在 usarthandler.c 文件或其头文件中,定义了某个较大的数组(比如USART接收/发送缓冲区)或者某个函数,并使用了类似 __attribute__((section(".ARM.__AT_0xC01F8E20"))) 的语法,想把它直接定位到SDRAM的 0xC01F8E20 地址。
  • FreeRTOS堆(Heap)放置冲突: FreeRTOS通常需要一个较大的内存堆 (ucHeap) 来管理任务栈、队列、信号量等。在有SDRAM的系统中,非常普遍的做法是将FreeRTOS的堆放置在SDRAM中以获得更大的空间。
    • malloc.o 相关的段 ARM.__AT_0xC01F4000 很可能就是FreeRTOS的堆或者C库的堆被配置到了SDRAM的这个地址。这通常是在FreeRTOS的 heap_x.c 文件(如 heap_4.c 或 heap_5.c)中定义 ucHeap 数组时,通过 __attribute__ 或者在链接器脚本(scatter file, .sct 文件)中指定的。
    • 你的 usarthandler.o 中的段又被指定到了 0xC01F8E20,这个地址落在了前面堆所占用的范围内。

  • 链接器脚本(Scatter File, .sct)配置问题: 你可能修改了工程的链接器脚本文件(通常是 .sct 后缀),在里面定义了两个或多个加载域(Load Region)或执行域(Execution Region)指向了SDRAM的重叠地址范围,并且将 malloc.o 和 usarthandler.o 中的特定段分别放到了这两个冲突的区域。
  • 重复定义或分配: 可能存在某种形式的重复定义或配置,导致同一个或不同的数据结构被多次尝试放置在SDRAM的相似位置。

如何解决?
你需要找到是哪里指定了这两个冲突的地址,并修改其中一个或两个,使它们的地址范围不再重叠。
  • 检查 usarthandler.c 及相关文件:
    • 全局搜索你的工程代码(特别是 usarthandler.c 和相关的头文件),查找 __attribute__((section(".ARM.__AT_0xC01F8E20"))) 或包含 0xC01F8E20 的类似地址指定语法(如 #pragma location=, __at(address) 等)。
    • 如果你找到了,确认这个地址是否是你故意设置的。如果是,考虑修改这个地址,让它避开 0xC01F4000 开始的区域。或者,如果这个变量/函数并非绝对需要放在SDRAM的固定地址,可以考虑去掉这个显式地址指定,让链接器自动为其分配SDRAM中的空间(如果配置了自动分配的话)。

  • 检查FreeRTOS堆的配置:
    • 查找 ucHeap 数组的定义位置(通常在 heap_4.c 或 heap_5.c 中,或者如果 configAPPLICATION_ALLOCATED_HEAP 为1,则可能在你自己的某个文件中)。
    • 查看它是否有 __attribute__((section(".ARM.__AT_0xC01F4000"))) 或类似的指定。
    • 检查 FreeRTOSConfig.h 中关于堆的配置。
    • 检查链接器脚本(.sct 文件),看是否有专门的区域定义给FreeRTOS堆,地址是否是 0xC01F4000。

  • 检查链接器脚本(.sct 文件):
    • 打开你工程使用的 .sct 文件(可以在Keil MDK的工程选项 -> Linker -> Scatter File 中找到)。
    • 仔细检查里面定义的关于SDRAM(地址以 0xC0000000 或 0xD0000000 开头)的执行域(Execution Region)。
    • 看是否有多个域被赋予了 AT 属性并且地址重叠。
    • 查找 malloc.o 和 usarthandler.o 中的段是如何被分配到这些区域的。特别注意 InRoot$$Sections、HEAP、STACK 以及任何包含 AT 地址的定义。
    • 对比你的 .sct 文件和官方例程的 .sct 文件,看看在SDRAM区域的定义和分配上有何不同。

  • 调整分配策略:
    • 如果你确实需要在SDRAM中放置 usarthandler.o 的某个大数据块和FreeRTOS的堆,你需要规划好SDRAM的空间。例如,将堆放在 0xC0000000 开始的一段空间,然后将你的USART缓冲区放在堆结束之后的地址。
    • 修改 __attribute__ 或 .sct 文件中的地址,确保它们不再冲突。例如,如果堆大小是N字节,你可以把 usarthandler 的数据放在 0xC01F4000 + N 之后(注意对齐)。
    • 更好的做法通常是:在 .sct 文件中定义一个SDRAM区域用于放置堆(比如叫 SDRAM_HEAP_AREA),再定义另一个区域用于放置其他用户数据(比如叫 SDRAM_USER_DATA_AREA),确保这两个区域地址不重叠。然后在代码中使用 __attribute__((section("SDRAM_USER_DATA_AREA"))) (不带 __AT_)来将数据放入用户区,让链接器自动安排具体位置。将堆的定义指向 SDRAM_HEAP_AREA。


总结:
这个错误是由于显式地将两个不同的程序段指定到了SDRAM中重叠的内存地址范围。你需要检查代码中(尤其是 usarthandler.c)和链接器脚本(.sct 文件)中所有使用 __attribute__((section(".ARM.__AT_address"))) 或类似语法的地方,以及FreeRTOS堆的放置配置,找出冲突点并修改地址分配,确保它们不再重叠。对比你修改过的工程和官方例程的相关配置是找到差异的关键。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-10 10:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表