ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

# STM32MP157+LiteOS-M GCC极简工程:启动源码适配+Windows Make终极避坑

# STM32MP157+LiteOS-M GCC极简工程:启动源码适配+Windows Make终极避坑 本文适用人群需要落地MP157 M4 GCC工程、适配LiteOS-M、VSCodeMakefile开发、Windows编译频繁报错的开发者 GitHub/Gitee 源码下载地址stm32mp157‑liteos‑‑m v3.0‑native‑pendsv核心结论MP157 M4有专属的极简启动流程与编译规范适配SRAM-only架构RTOS运行需求同时可彻底解决Windows Make玄学编译报错提供一套可量产的工程规范与参考实现按规范落地即可稳定运行。配套说明本文与《第一篇·原理避坑篇》为一组。第一篇已论证禁用 Keil→GNU 手转启动文件、用 Cube 包 gcc 原生文件并指出.data 拷不拷取决于链接脚本。本文即采用自定义 LMAVMA 单 SRAM 区简化布局因此删除 .data 拷贝是合法做法与第一篇口径完全统一。一、工程基础文件提取基于官方文件改写非零修改直接从正点原子 V1.2.0 固件 gcc 目录取两份官方原生文件作为模板再按本系列LMAVMA 极简布局改写不是原样零修改startup_stm32mp15xx.sM4 专属 GCC 纯汇编启动文件原厂小写后缀作为改写基底stm32mp15xx_m4.ldM4 内核 SRAM 专属链接脚本作为改写基底。为何必须改写否则零修改会跑不起来官方启动文件含CopyDataInit循环.data 拷贝bl __libc_init_arrayC 构造器而官方 .ld 的.data是LMA≠VMA带AT()——你若原样用官方两份就必须保留 .data 拷贝、且要链 C 库与本系列极简/RTOS目标相反本系列改用单 SRAM 区、.dataLMAVMA布局于是可以删掉 .data 拷贝、删掉__libc_init_array工程更精简。路径核对 与第一篇原样用即可跑的关系本篇改写与第一篇第五节第1条初学者原样用即可跑取的是同一份 Cube 包 gcc 目录原生文件Templates/gcc/startup_stm32mp15xx.s与Templates/gcc/linker/stm32mp15xx_m4.ld取文件路径完全相同区别只在改不改第一篇原样用 不改动启动文件、保留官方.data拷贝与bl __libc_init_array并链system_stm32mp1xx.c可直接跑本篇改写 以同一份文件为模板按 LMAVMA 极简布局删改几处删.data拷贝 / 删bl __libc_init_array/bl SystemInit按需更精简、适配 RTOS。务必核对取的是gcc目录非 arm/iar否则语法体系不对。下面第二节给出改写后的完整源码图1MP157 M4 启动文件 —— 原样用 vs 改写注本篇图序承接第一篇从图11起编。二、适配LiteOS-M的标准Reset_Handler最终修正版摒弃网上错误的裸机极简写法完全适配MP157 M4架构与LiteOS-M内核运行机制。本版基于官方startup_stm32mp15xx.s改写相对原厂删两处、留三处、按需一处❌删除CopyDataInit循环本布局.data的 LMAVMA无需拷贝详见配套 .ld❌删除bl __libc_init_array极简/LiteOS 工程不需要 C 构造器留着反而链接报缺符号✅保留VTOR 向量表重定向适配 SRAM0x10000000运行地址✅保留FPU 硬件浮点使能避免浮点指令触发硬件异常✅保留.bss 清零RTOS 内核运行必备⚙️按需bl SystemInit见下方系统初始化说明。核心设计要点❌ 不拷贝 .data 段本布局 M4 SRAM 单区运行.data的 LMAVMA标准 ELF 加载器会把初值写到该同一地址无需启动拷贝若改用官方 LMA≠VMA 的 .ld则必须保留拷贝——见第一篇✅ 强制清零 .bss 段RTOS 内核运行必备✅ VTOR 向量表重定向用ldr r1, g_pfnVectors符号写法自动跟随链接脚本的向量表位置✅ FPU 硬件浮点使能避免浮点指令触发硬件异常⚙️ 按需保留 SystemInit适配纯 M4 独立启动场景保留则需链system_stm32mp1xx.c详见下文✅ 剔除冗余 C 库初始化已删__libc_init_array工程更精简。完整启动汇编源码Reset_Handler: /* 0. 设置栈指针MSP _estack * 手动起跑会绕过硬件复位读向量表必须手动配置栈指针 */ ldr sp, _estack /* 1. 设置向量表偏移SCB-VTOR g_pfnVectors * SRAM运行必须重定向否则中断跳转异常。 * 用 g_pfnVectors 符号而非写死常数自动跟随 .ld 的向量表位置 * 本布局向量表在 0x10000000若换官方 .ld向量表在 0x00000000也无需改此行 */ ldr r0, 0xE000ED08 /* SCB-VTOR 地址 */ ldr r1, g_pfnVectors str r1, [r0] /* 2. 使能 FPUCPACR.CP10|CP11 11 * 未使能浮点会触发 UsageFault 卡死 */ ldr r0, 0xE000ED88 /* CPACR 地址 */ ldr r1, [r0] orr r1, r1, #(0xF 20) /* CP10/CP11 全使能 */ str r1, [r0] dsb isb /* 3. 清零 .bss 段上电 SRAM 数据随机RTOS 必备 * 重点本布局 MP157 M4 无需 .data 拷贝LMAVMA */ ldr r0, __bss_start__ ldr r1, __bss_end__ movs r2, #0 bss_loop: cmp r0, r1 bcs bss_done str r2, [r0], #4 b bss_loop bss_done: /* 4. 系统初始化按需调用与第一篇口径一致 * - 保留此行需把 Cube 包 Templates/system_stm32mp1xx.c 链进工程 * 由它提供 SystemInit 实现仅完成FPU使能、VTOR向量表配置、EXTI外设中断掩码清零等最小初始化**不关闭Cortex-M内核全局中断也不配置系统时钟** * - HSI 默认 64MHz 纯 M4 场景可直接删除此行 * 前面 FPUVTOR 已够免得链接报 undefined reference to SystemInit * - PLL 高频场景需另行配置 RCCHAL_RCC 或寄存器直写与是否调用 SystemInit 无关 */ bl SystemInit /* 纯 HSI 64MHz可删除此行PLL 高频另行配置 RCC与 SystemInit 无关 */ /* 5. 跳转主函数启动 LiteOS 内核 */ bl main b . /* 防御死循环 */图2实战版 Reset_Handler —— 删 2 / 留 3 / 按需 1共六步系统初始化文件来源Cube 包STM32Cube_FW_MP1_V1.2.0/Drivers/CMSIS/Device/ST/STM32MP1xx/Source/Templates/system_stm32mp1xx.c。保留bl SystemInit时务必把它加入编译文件列表走纯 HSI 场景删掉bl SystemInit后则无需此文件。 补充说明消除源码对照困惑本工程system_stm32mp1xx.c的SystemInit为精简版相对官方 ST 文件省略了EXTI_C2-IMR1..EMR3六个寄存器的中断掩码清零原因是 M4 复位后这些寄存器复位值即全 0纯 M4 独立启动无 A7 干预该清零属幂等保险省略不影响行为。其余 FPU 使能、VTOR 重定向与官方一致且同样不配置系统时钟、不关闭Cortex-M内核全局中断。若你直接用官方原版system_stm32mp1xx.c含 HAL则 EXTI 清零会照常执行行为与上文一致。配套链接脚本规范完整可链接版关键符号全部对齐下面是一份完整、可直接用于链接的.ld单 SRAM 区、.dataLMAVMA。注意第一节说的官方文件只是模板这份才是你工程真正使用的脚本——它相对官方stm32mp15xx_m4.ld做了精简合并为单 SRAM 区、去掉AT()。/* stm32mp15xx_m4.ld — 自定义单 SRAM 区布局LMA VMA * 改编自 Cube 包官方 stm32mp15xx_m4.ld精简为 M4 极简裸机/RTOS 布局 * - 官方原版把 m_interrupts / m_text / m_data 分三段、.data 带 AT() 使 LMA≠VMA * - 本脚本合并为单一 SRAM 区.data 的 LMAVMA启动文件可省 .data 拷贝。 */ MEMORY { SRAM (rwx) : ORIGIN 0x10000000, LENGTH 256K /* M4 SRAM 256KB */ } _estack ORIGIN(SRAM) LENGTH(SRAM); /* SRAM 顶端作为 MSP 初值布局无关跟随 MEMORY 定义 */ ENTRY(Reset_Handler) SECTIONS { /* 向量表放在 SRAM 首地址 0x10000000VTOR 指向此处 */ .isr_vector : { . ALIGN(4); KEEP(*(.isr_vector)) . ALIGN(4); } SRAM /* 代码与只读数据 */ .text : { . ALIGN(4); *(.text) *(.text*) *(.rodata) *(.rodata*) . ALIGN(4); _etext .; } SRAM /* .data 段LMA VMA同一 SRAM 区无需 _sidata、无需启动拷贝 */ .data : { . ALIGN(4); _sdata .; *(.data) *(.data*) . ALIGN(4); _edata .; } SRAM /* .bss 段启动文件统一清零汇编/链接脚本符号完全对齐无链接告警 */ .bss : { . ALIGN(4); __bss_start__ .; _sbss .; *(.bss) *(.bss*) *(COMMON) . ALIGN(4); __bss_end__ .; _ebss .; } SRAM }图3单 SRAM 区 .ld 布局 —— LMAVMA 极简0x10000000 ~ 0x10040000256KB 一区到底报错避坑若链接出现undefined reference to _sidata说明你混用了官方启动文件用_sidata做 .data 拷贝 本简化 .ld不定义_sidata。根因是 .s 与 .ld 符号没对齐——按上文把官方启动文件的CopyDataInit循环删掉即可本 .ld 本就不需要它。三、LiteOS-M 标准main函数模板固定规范启动文件适配后必须遵循LiteOS-M官方初始化流程不可裸机直接运行#includelos_kernel.hintmain(void){/* 内核初始化依赖 bss 正确清零 */UINT32 retLOS_KernelInit();if(retLOS_OK){/* 任务创建、外设初始化、中断配置 */LOS_Start();/* 启动任务调度器 */}while(1);}图4LiteOS-M main 标准初始化三步依赖 .bss 正确清零四、最终标准编译命令仅2条无冗余、参数修正全程使用fpv4-sp-d16Cortex-M4F 专属纠正全网 fpv5 错误fpv5 仅适配 M7 内核仅保留无FPU/有FPU两条标准命令。文件后缀说明按本篇第五节 5.3 工程规范Windows 下板级启动文件统一使用大写.S规避 mingw32-make 的 vpath 小写匹配缺陷详见 5.2 节。# 1、普通无FPU编译基础裸机工程文件后缀按 5.3 规范统一为 .Sarm-none-eabi-gcc-c-mcpucortex-m4-mthumbstartup_stm32mp15xx.S-ostartup.o# 2、带FPU硬件加速编译RTOS工程必备标准正确参数# M4F专属 FPv4-SP-D16严禁使用 M7 的 FPv5 参数arm-none-eabi-gcc-c-mcpucortex-m4-mthumb-mfpufpv4-sp-d16 -mfloat-abihard startup_stm32mp15xx.S-ostartup.o图5M4F vs M7 FPU 参数对照fpv4-sp-d16 vs fpv5MP157 M4 唯一正确五、移植终极踩坑复盘.s/.S 玄学报错全解析跨平台机制 Windows 迁移高发5.1 汇编后缀 .s/.S 核心争议原厂规范 vs Windows工程实践折中说明原厂文件默认小写.s符合 GCC 纯汇编语法规范GNU Make 的 vpath/后缀替换为大小写敏感字符串匹配全平台行为完全一致Windows 下因文件系统大小写不敏感文件‘明明存在’却报找不到迷惑性最强、迁移最高频工程落地需要折中适配二者并不矛盾——前者是应该是什么后者是工程上怎么避免踩坑。语法标准定义小写.s纯汇编文件无预处理适合 startup 启动文件原厂规范大写.S带 C 预处理支持宏与头文件适合 LiteOS 内核汇编文件。5.2 Windows Make 致命玄学报错根源报错现象make: *** No rule to make target xxx/startup_stm32mp15xx.o, needed by liteos_m.elf. Stop.根因Windows 文件系统大小写不敏感但 GNU Make vpath 匹配为严格字符串大小写敏感小写%.s无法匹配实际后缀为.S的文件导致编译规则失效Linux/Mac 同样会报错根因差异见 5.2.4Windows 的特殊性仅在于文件系统能正常打开该文件、报错更具迷惑性。5.2.1 最小复现案例构造目录结构demo/ ├── Makefile └── src/ └── startup_stm32mp15xx.S ← 实际文件后缀大写 .S用 PowerShell 验证实际文件名Windows 资源管理器看不出大小写差异PSD:\demoGet-ChildItemsrc|Select-ObjectName Name----startup_stm32mp15xx.S ← 实际是大写.SMakefile 内容vpath %.s src startup.o: startup_stm32mp15xx.s arm-none-eabi-gcc -c $ -o $执行 mingw32-makePS D:\demo mingw32-make make: *** No rule to make target startup_stm32mp15xx.s, needed by startup.o. Stop.文件明明存在make 却报找不到玄学报错由此产生。5.2.2 三种验证方法注意下面三种方法仅用于验证文件存在但 make 找不到的根因均不是工程落地建议。Windows 工程的标准规范统一见 5.3 节启动文件统一大写.S彻底规避大小写匹配坑。验证方法操作预期结果方法 1改 vpath 模式把vpath %.s src改为vpath %.S src重新 make✅ 编译成功方法 2改文件后缀把实际文件startup_stm32mp15xx.S重命名为.s重新 make✅ 编译成功方法 3改 Makefile 依赖把startup.o: startup_stm32mp15xx.s改为%.o: %.S重新 make✅ 编译成功5.2.3 与文件系统能否访问无关注意一个反直觉的现象Windows 文件系统大小写不敏感下面这段 C 代码可以正常打开文件FILE*f1fopen(src/startup_stm32mp15xx.s,r);// 实际文件是大写 .SFILE*f2fopen(src/startup_stm32mp15xx.S,r);// 两者都能成功打开同一个文件但 make 的 vpath 不是用文件系统去列目录再匹配而是先用%.s字符串过滤候选名单字符串层面%.s不匹配startup_stm32mp15xx.S候选名单为空根本没机会到文件系统那一步。这就是 Windows 下 vpath找不到文件的根因所在。图6Windows vpath “找不到文件” 根因 —— FS 不敏感 ! Make 字符串敏感两层机制分离5.2.4 Linux/Mac 对照实验同样的 Makefile 和文件名实际后缀.S在 Linux 下执行 make$ make make: *** No rule to make target startup_stm32mp15xx.s, needed by startup.o. Stop.Linux 同样会报错但根因不同——Linux 文件系统大小写敏感根本就没有startup_stm32mp15xx.s这个文件只有.S。所以 Linux 下你早就会在写 vpath 时意识到要匹配大小写而 Windows 下因为文件系统能访问开发者误以为vpath 也应该能匹配结果栽在 make 的字符串匹配层。5.3 量产级统一工程规范内核汇编文件los_exc.S、los_dispatch.S保留大写.S适配预处理逻辑不修改内核源码板级启动文件Windows 工程统一改为大写.S规避 Make 匹配 BUG文件内容无任何改动、无副作用Makefile 统一单套.S编译规则彻底杜绝混合后缀冲突。5.4 隐藏头文件路径坑LiteOS-M 内核源文件内部大量使用相对引用#include xxx.h仅配置顶层内核头文件路径无法编译通过必须手动添加kernel/src头文件检索路径。该问题属于隐藏编译依赖不会在增量编译暴露仅在全量 clean 编译时触发极易被忽略。六、最终量产总结8条核心规范严禁手动转换 MP157 启动文件原厂 GCC 文件为最优方案取其作模板改写而非 ARMCC→GNU 手转.data 拷不拷取决于链接脚本本篇采用自定义 LMAVMA 简化 .ld.data直接 SRAM故无需 .data 拷贝若用官方 .ldLMA≠VMA仍必须保留拷贝——详见第一篇无论哪种布局.bss 清零绝对不能省略纯 M4 独立启动必须确保时钟正确默认 HSI 64MHz 或显式配置 PLL并完成 FPU/VTOR 初始化保证硬件与 RTOS 正常运行VTOR 用ldr r1, g_pfnVectors符号写法最稳M4F 内核 FPU 参数固定为fpv4-sp-d16禁止使用 M7 的fpv5参数汇编后缀按场景区分纯汇编.s、带预处理.S原厂小写规范合规Windows 工程折中适配启动文件统一大写.S规避 Make 大小写匹配坑链接脚本严格匹配段定义_estack/__bss_start__/__bss_end__等符号齐全杜绝_sidata未定义链接错误、bss 符号不匹配告警LiteOS 工程必须遵循标准初始化流程依赖 .bss 正确清零。原创不易转载请注明出处全套适配 STM32MP157LiteOS-M 的极简参考工程
返回列表