从C到Simulink: 使用STM32硬件支持包后为什么还不支持PC仿真ARM建模程序

从C到Simulink: 使用STM32硬件支持包后为什么还不支持PC仿真ARM建模程序


1. 为什么 HSP 救不了 PC 仿真?

Simulink 的运行机制决定了这一点:

  • 当你点击"运行仿真"时
    Simulink 必须将模型(包括你引用的 C 代码)编译成 能在你电脑 CPU(Intel/AMD x64)上运行 的程序(即 .mexw64 文件)。
    • ARM Compiler (ARMCC) 只能生成 ARM 芯片 能跑的指令集。
    • 它无法生成 Windows 电脑 能跑的指令集。
    • 因此,无论你是否安装了 STM32 HSP,只要是在电脑上跑仿真,Simulink 强制使用你电脑上的编译器(MSVC 或 MinGW/GCC)。
  • STM32 HSP 的作用是什么
    HSP 主要是为了 "代码生成""PIL 仿真" 阶段服务的。
    • 生成代码时:它会帮你配置好 Keil/IAR 的工程,调用 ARM Compiler 来编译。
    • PIL 仿真时 :它会将代码下载到板子上(用 ARM 编译),让板子跑算法,然后把结果传回电脑。
      结论:HSP 无法改变"PC 仿真必须用 PC 编译器"这一物理铁律。因此,如果你的 C 代码里包含 ARMCC 特有的语法,在 PC 仿真阶段依然会报错。

2. 为什么你用 C Caller 调用底层代码会这么痛苦?

问题的根源在于你混合了两个不兼容的世界:

  • Simulink 仿真世界:需要编译器无关、平台无关的纯 C 代码(或者适配 PC 编译器的代码)。
  • STM32 驱动/FreeRTOS 世界 :充满了针对 ARM Compiler (RVDS/ARMCC) 或特定硬件寄存器的强依赖代码。
    当你使用 C Caller Block 直接把 stm32f7xx.hFreeRTOS/portmacro.h 拉进 Simulink 仿真时,就等于强行要求 PC 编译器去翻译"写给 ARM 芯片看的方言",所以必定报错。
    STM32 HSP 提供的模块(如 ADC Read, Digital Write)之所以能在仿真里跑,是因为 ST 和 MathWorks 的工程师已经帮你写好了"仿真适配层"
  • 在仿真时:这些模块内部只是产生虚拟信号,并不包含真实的 HAL_GPIO_WritePin 或 ARM 汇编指令。
  • 生成代码时:这些模块才会替换成真实的 HAL 库调用。
    但你现在是绕过了 HSP 的封装,直接用 C Caller 去啃最底层的、没做过仿真适配的原始代码。

3. 正确的解决路径

既然 HSP 不能解决编译器问题,你有以下三种选择:

方案 A:仿真与底层彻底解耦(最推荐)

不要在 Simulink 仿真中包含真实的 STM32 驱动文件和 FreeRTOS 移植层(portable 文件夹)。

  1. 只包含算法层代码

  2. 编写 Stub(存根)
    创建一个 simulation_stubs.h,定义你需要的函数原型,但内容为空或输出假数据。

    c 复制代码
    // 仅供 Simulink 仿真使用
    void HAL_GPIO_WritePin(...) { /* Do nothing */ }
    void vTaskDelay(...) { /* Do nothing */ }
  3. 配置 Simulink

    • 仿真目标 的包含路径中:只加算法文件夹和 Stub 文件夹。屏蔽掉 驱动和 RTOS 文件夹。
  4. 生成代码时
    利用 HSP 的功能或者 TLC 文件,让生成的代码去链接真实的 HAL 库。

方案 B:只做 Processor-in-the-Loop (PIL) 仿真

如果你必须在仿真中运行真实的底层代码(比如要验证驱动时序)。

  1. 不要在 Simulink 里点"运行(Normal 模式)"。
  2. 配置并运行 PIL 模式
    • 这会强迫代码下载到 STM32 板子上运行(使用 ARM Compiler)。
    • Simulink 只负责收发数据,不负责编译底层 C 代码(PC 端只编译通信桩,这通常是兼容的)。
    • 缺点:每次仿真都要下载,速度慢,需要硬件连接。

方案 C:修改你的 C 库,使其"兼容 PC 编译器"

如果你坚持要在 Normal 模式下跑真实代码(不推荐,除非是纯算法库),你必须手动修改你的 G:\converter\... 下的代码:

  1. 在头文件中加入大量的宏判断:

    c 复制代码
    #if defined(_MSC_VER) || defined(__GNUC__)
       // PC 仿真环境:使用普通 struct 或 简单模拟
       typedef int TaskHandle_t;
       #define vPortYieldProcessor() 
    #else
       // STM32 真实环境:使用 ARMCC 原始定义
       #include "portmacro.h" 
    #endif
  2. 这其实就是你自己把 HSP 开发者做过的事(做适配层)在你的私有代码库里重做一遍。

总结

STM32 HSP 不能帮你绕过 GCC 无法编译 ARMCC 的问题。

因为 ARMCC 生成的代码在 PC 上根本跑不起来 。HSP 的作用是帮你把代码"搬"到板子上用 ARMCC 跑,而不是让 ARMCC 在 PC 上跑。
建议

立即停止在 Simulink 仿真中直接引用 FreeRTOS/Source/portable/RVDS/... 这种硬件强依赖路径。改用 Stub(存根函数) 将你的算法与硬件隔离,这是基于模型设计(MBD)的标准最佳实践。

相关推荐
NULL指向我6 小时前
STM32F407VET6学习笔记14:Bootloader程序笔记
笔记·stm32·学习
别了,李亚普诺夫6 小时前
定时器与输出比较-学习笔记
笔记·stm32·学习
Dillon Dong7 小时前
从C到Simulink: ARM Compiler 5 (RVDS) 为什么simulink 不能使用arm编译
c语言·arm开发·simulink
黎雁·泠崖7 小时前
Java底层探秘进阶:JIT汇编逐行拆解!Java方法栈帧与C语言深度对标
java·c语言·汇编
无限进步_9 小时前
【C语言】用队列实现栈:数据结构转换的巧妙设计
c语言·开发语言·数据结构·c++·链表·visual studio
Dillon Dong9 小时前
从C到Simulink: 使用 `simulation_stubs`(仿真存根)处理MBD中的硬件依赖
c语言·stm32·matlab
代码游侠10 小时前
应用——基于C语言实现的简易Web服务器开发
运维·服务器·c语言·开发语言·笔记·测试工具
墨辰JC11 小时前
STM32架构基于调度器的非阻塞按键状态机设计
stm32·microsoft·架构·状态机·调度器
zhangx1234_11 小时前
C语言 题目2
c语言·开发语言