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

调用__udivsi3触发MSPM0C1104硬故障,如何将写入操作移至RAM?

MSPM0C1104调用__udivsi3触发硬故障问题

故障现象

调用__udivsi3函数时触发硬故障:进入该函数后经过几次跳转,尝试在Flash区域(地址0x992)执行.word 0xff1ee8bd操作,直接触发硬故障。

复现情况

  • 复现代码:
    volatile uint32_t test; 
    test = 24000000; 
    test /= 24000000;
    
    实际运算值来自控制器库的可配置宏/变量,其他除法运算也能复现该问题。
  • 无论函数是否添加__attribute__((optimize("-O0"))),或者使用-O2优化,故障都会出现。

链接器内存段配置

FLASH           (RX)  : ORIGIN = 0x00000000, LENGTH = 0x00003BFF
SRAM            (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00000400
DEVICE_CONFIG   (RW!x) : ORIGIN = 0x00003C00, LENGTH = 0x000001FF
BCR_CONFIG      (R)   : ORIGIN = 0x41C00000, LENGTH = 0x000000FF

编译器设置

"C:/TI/gcc_arm_none_eabi_9_2_1/bin/arm-none-eabi-gcc-9.2.1.exe" 
-c 
@"device.opt" 
-mcpu=cortex-m0plus 
-march=armv6-m 
-mthumb 
-mfloat-abi=soft 
-I"C:/TI/mspm0_sdk_2_09_00_01/source/third_party/CMSIS/Core/Include" 
-I"C:/TI/mspm0_sdk_2_09_00_01/source" 
-I"C:/MYPROJ/src" 
-I"C:/MYPROJ/src/modules" 
-I"C:/MYPROJ/src/modules/comp1" 
-I"C:/MYPROJ/src/modules/communication" 
-I"C:/MYPROJ/src/modules/mylib" 
-I"C:/MYPROJ/src/modules/battery" 
-I"C:/MYPROJ/src/modules/accelerometer" 
-I"C:/MYPROJ" 
-I"C:/MYPROJ/Debug" 
-O2 
-ffunction-sections 
-fdata-sections 
-gdwarf-3 
-gstrict-dwarf 
-Wall 
-fno-math-errno 
-MMD 
-MP 
-MF"src/modules/communication/communication.d_raw" 
-MT"src/modules/communication/communication.o" 
-std=c99 
@"./device.opt" 
-o"src/modules/communication/communication.o" 
"../src/modules/communication/communication.c" 

链接器设置

"C:/TI/gcc_arm_none_eabi_9_2_1/bin/arm-none-eabi-gcc-9.2.1.exe" 
@"device.opt" 
-O2
-ffunction-sections 
-fdata-sections 
-gdwarf-3
-gstrict-dwarf 
-Wall
-fno-math-errno 
-mthumb
-mfloat-abi=soft 
-Wl,-Map,"myproj.map" 
-nostartfiles 
-nostdlib
-static 
-Wl,--gc-sections 
-L"C:/TI/mspm0_sdk_2_09_00_01/source/ti/driverlib/lib/gcc/m0p/mspm0c110x" 
-L"C:/TI/mspm0_sdk_2_09_00_01/source" 
-L"C:/MYPROJ" 
-L"C:/MYPROJ/Debug/syscfg" 
-L"C:/TI/gcc_arm_none_eabi_9_2_1/lib/gcc/arm-none-eabi/9.2.1" 
-L"C:/TI/gcc_arm_none_eabi_9_2_1/arm-none-eabi/lib/thumb/v6-m/nofp" 
-march=armv6-m 
-mthumb
--specs=nano.specs 
-o"myproj.out" 
"./ti_msp_dl_config.o" 
"./startup_mspm0c110x_gcc.o" 
"./main.o" 
"./src/modules/accelerometer/accelerometer.o" 
"./src/modules/battery/battery.o" 
"./src/modules/mylib/communication/communication.o" 
"./src/modules/rear_light/comp1.o" 
-Wl,-T"../make/myproj.lds" 
-Wl,-Tdevice.lds.genlibs 
-lm
-lgcc 
-lc 
-l:driverlib.a 

相关映射信息

.text          0x000004e8      0x114 C:/TI/gcc_arm_none_eabi_9_2_1/lib/gcc/arm-none-eabi/9.2.1\libgcc.a(_udivsi3.o)
                0x000004e8                __aeabi_uidiv
                0x000004e8                __udivsi3

最小复现代码

// 控制器配置头文件,示例即使不显式包含也能运行
#include "ti_msp_dl_config.h"

#include <stdint.h>

int main (void)
{
    volatile uint32_t test;  

    test = 24000000;
    test /= 100; // 执行到该行后触发硬故障
    while(1);
}

核心问题

  1. 为什么GCC ARM库会将写入操作放在Flash中?
  2. 如何将这些写入操作移至RAM?

问题解答

原因分析

Cortex-M0+架构没有硬件除法指令,GCC会调用__udivsi3(对应无符号32位除法)这类软件除法库函数。你使用的9.2.1版本GCC ARM库实现中,__udivsi3采用了位置无关代码(PIC)的实现方式,会在函数内部尝试向当前代码段(Flash)写入临时指令——但Flash是只读存储,直接写入会触发内存访问错误,导致硬故障。同时你的链接器配置中FLASH段仅标记为RX(只读可执行),无写权限,进一步触发故障。

解决方法

  1. 升级GCC ARM工具链
    10.x及以上版本的GCC ARM已经修复了该问题,软件除法函数会使用栈(RAM)存放临时数据,不再尝试写入Flash。直接替换为TI提供的新版本工具链即可解决。

  2. 将除法库函数移至RAM执行
    修改链接脚本,指定__udivsi3等相关函数存放到RAM段:

    • 在链接脚本中添加:
      PROVIDE(__start_ram_functions = .);
      .ram_functions :
      {
          *libgcc.a(_udivsi3.o)
          *libgcc.a(_divsi3.o)
          *libgcc.a(__aeabi_uidiv.o)
          *libgcc.a(__aeabi_idiv.o)
      } > SRAM AT> FLASH
      PROVIDE(__end_ram_functions = .);
      
    • 在启动代码中添加复制逻辑,将ram_functions段从Flash复制到RAM,确保函数运行前完成复制。
  3. 禁用PIC库编译
    编译时添加-fno-pic选项,强制GCC使用非位置无关的除法库实现,避免向Flash写入临时代码。

  4. 替换为自定义除法函数
    自行实现无符号32位除法函数,通过链接选项替换默认库函数:

    • 自定义函数示例:
      uint32_t my_udivsi3(uint32_t num, uint32_t den) {
          if (den == 0) return 0; // 按需处理除零场景
          uint32_t quotient = 0;
          while (num >= den) {
              num -= den;
              quotient++;
          }
          return quotient;
      }
      
    • 链接时添加-Wl,--wrap=__udivsi3选项,让编译器使用自定义函数替代默认的__udivsi3。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 10:37:33