带long_call属性的函数放置到非缓存段时代码运行挂起问题咨询
问题原因分析
- 地址跳转与内存属性配置错误:
long_call属性会强制编译器生成跨地址范围的长跳转指令,若链接脚本中.mysection对应的内存区域未被标记为可执行,或是地址指向了未实际挂载、未开启总线时钟的存储区间,CPU跳转后无法正常取指,就会直接挂起。 - 非缓存区域访问参数不匹配:非缓存段通常挂载在独立总线,若未提前配置对应内存区域的访问等待周期、总线权限,CPU读取该区域指令时会触发总线错误,进入硬件异常导致挂起。
- 长跳转的上下文处理异常:部分架构(如ARM Cortex系列)下,
long_call生成的跳转指令会修改链接寄存器(LR)的值,若函数返回时没有匹配的长返回指令,会导致返回地址错误,程序跑飞挂起。 - 缓存一致性问题:若目标地址区域之前被缓存过,即使函数被放到非缓存段,CPU仍可能从指令缓存中读取旧的无效指令,导致执行错误。
解决建议
- 核查链接脚本配置:确认
.mysection段被分配到真实存在、已开启时钟、带有EXECUTABLE可执行属性的内存区间,避免分配到保留地址或未初始化的存储区域。 - 调整跳转属性配置:根据所用架构适配属性参数,可将
__long_call__替换为对应架构的远调用属性(如部分架构的far关键字),或在调用函数的位置手动插入符合架构要求的长跳转汇编指令。 - 提前配置内存访问参数:在启动代码中初始化非缓存段对应区域的MPU权限、总线等待周期,确保CPU可以正常访问该区域的指令和数据。
- 跳转前清空指令缓存:在调用该非缓存段函数之前,手动清空指令缓存(ICache),避免CPU读取到缓存中的旧指令。
- 校验生成的指令逻辑:编译后导出反汇编文件,检查跳转该函数的指令格式、函数内部的地址访问逻辑是否匹配实际内存映射,排除编译器生成错误指令的问题。
内容的提问来源于stack exchange,提问作者Adarsh Patil
相关产品推荐
相关产品推荐

