从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.h和FreeRTOS/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 文件夹)。
-
只包含算法层代码。
-
编写 Stub(存根) :
创建一个simulation_stubs.h,定义你需要的函数原型,但内容为空或输出假数据。c// 仅供 Simulink 仿真使用 void HAL_GPIO_WritePin(...) { /* Do nothing */ } void vTaskDelay(...) { /* Do nothing */ } -
配置 Simulink :
- 在 仿真目标 的包含路径中:只加算法文件夹和 Stub 文件夹。屏蔽掉 驱动和 RTOS 文件夹。
-
生成代码时 :
利用 HSP 的功能或者 TLC 文件,让生成的代码去链接真实的 HAL 库。
方案 B:只做 Processor-in-the-Loop (PIL) 仿真
如果你必须在仿真中运行真实的底层代码(比如要验证驱动时序)。
- 不要在 Simulink 里点"运行(Normal 模式)"。
- 配置并运行 PIL 模式 。
- 这会强迫代码下载到 STM32 板子上运行(使用 ARM Compiler)。
- Simulink 只负责收发数据,不负责编译底层 C 代码(PC 端只编译通信桩,这通常是兼容的)。
- 缺点:每次仿真都要下载,速度慢,需要硬件连接。
方案 C:修改你的 C 库,使其"兼容 PC 编译器"
如果你坚持要在 Normal 模式下跑真实代码(不推荐,除非是纯算法库),你必须手动修改你的 G:\converter\... 下的代码:
-
在头文件中加入大量的宏判断:
c#if defined(_MSC_VER) || defined(__GNUC__) // PC 仿真环境:使用普通 struct 或 简单模拟 typedef int TaskHandle_t; #define vPortYieldProcessor() #else // STM32 真实环境:使用 ARMCC 原始定义 #include "portmacro.h" #endif -
这其实就是你自己把 HSP 开发者做过的事(做适配层)在你的私有代码库里重做一遍。
总结
STM32 HSP 不能帮你绕过 GCC 无法编译 ARMCC 的问题。
因为 ARMCC 生成的代码在 PC 上根本跑不起来 。HSP 的作用是帮你把代码"搬"到板子上用 ARMCC 跑,而不是让 ARMCC 在 PC 上跑。
建议 :
立即停止在 Simulink 仿真中直接引用 FreeRTOS/Source/portable/RVDS/... 这种硬件强依赖路径。改用 Stub(存根函数) 将你的算法与硬件隔离,这是基于模型设计(MBD)的标准最佳实践。