news 2026/8/15 22:49:22

第四篇 STM32MP157-M4:Makefile 完整详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第四篇 STM32MP157-M4:Makefile 完整详解

STM32MP157-M4:Makefile 完整逐段详解

【高危前置提醒】必须开启--gc-sections死代码回收避免 SRAM 溢出;编译参数必须携带-DCORE_CM4os_config/必须在-I列表首行。

0 前言

纯 GNU Make 构建工程,不依赖任何 IDE。Makefile 自动遍历源码目录(支持递归子文件夹)、区分大小写汇编文件(.svs.S),一键生成.elf/.bin/.hex/.map文件,并且内置make flash一键 OpenOCD 烧录。

1 工具链基础定义

CROSS_COMPILE ?= arm-none-eabi- CC := $(CROSS_COMPILE)gcc AS := $(CROSS_COMPILE)gcc -x assembler-with-cpp LD := $(CROSS_COMPILE)gcc OBJCOPY := $(CROSS_COMPILE)objcopy OBJDUMP := $(CROSS_COMPILE)objdump SIZE := $(CROSS_COMPILE)size TARGET := m4_liteos PROJ_ROOT := . BUILD_DIR := build

关键设计:

  • AS重用gcc而非as:带预处理器的汇编(.S后缀)需要经过 C 预处理
  • PROJ_ROOT设为.:Makefile 和工程根目录同层,所有路径相对引用

2 核心编译参数

# CPU 浮点配置(M4 + 硬浮点 + FPv4-SP-D16) CPUFLAGS := -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 # 芯片宏(CORE_CM4 必须!缺失会导致 HAL/CMSIS 丢失 M4 相关定义) CHIP_DEFS := -DSTM32MP157Cxx -DSTM32MP1 -DCORE_CM4 # LiteOS 场景宏 LITEOS_DEFS := -DLOSCFG_LIB_CONFIG="-los_builddef.h" # C 编译标志(-Os 空间优化 + debug 符号 + 段分离用于 gc-sections) CFLAGS := $(CPUFLAGS) $(CHIP_DEFS) $(LITEOS_DEFS) $(INCLUDES) CFLAGS += -Wall -Wextra -g3 -Os CFLAGS += -ffunction-sections -fdata-sections # 每个函数/变量独立一个段 CFLAGS += -fno-common -fmessage-length=0 CFLAGS += --specs=nano.specs # 使用 newlib-nano 减小体积 # 汇编标志 ASFLAGS := $(CPUFLAGS) $(CHIP_DEFS) $(INCLUDES) # 链接标志 LDFLAGS := $(CPUFLAGS) -T$(PROJ_ROOT)/stm32mp157_m4.lds LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref # 生成完整 map LDFLAGS += -Wl,--gc-sections # 死代码回收 LDFLAGS += --specs=nano.specs -lnosys # nano 库+无系统调用

--gc-sections的作用:编译器把每个函数 / 全局变量放进独立段(-ffunction-sections -fdata-sections),链接时未被引用的段自动丢弃。开启前固件可能超过 SRAM 上限,开启后省下几十 KB。

3 源文件收集规则

# ========== 汇编源文件(手动指定,避免 wildcard 漏抓 ========== ASM_SRC += Core/Startup/startup_stm32mp15xx.s # 启动文件(纯汇编 .s) ASM_SRC += kernel_liteos_m/kernel/arch/arm/cortex-m4/gcc/los_dispatch.S ASM_SRC += kernel_liteos_m/kernel/arch/arm/cortex-m4/gcc/los_exc.S # ========== HAL 驱动(过滤 ll_ 文件)========== HAL_SRC := $(filter-out %ll_%, $(wildcard Drivers/STM32MP1xx_HAL_Driver/Src/*.c)) # ========== LiteOS 内核 C 源码 ========== LITEOS_SRC := $(wildcard kernel_liteos_m/kernel/src/*.c) LITEOS_SRC += $(wildcard kernel_liteos_m/kernel/arch/arm/cortex-m4/gcc/*.c) # ========== 用户应用 C 源码 ========== APP_SRC := $(wildcard Core/Src/*.c) APP_SRC += $(wildcard Drivers/BSP/**/*.c) APP_SRC += $(wildcard Drivers/SYSTEM/**/*.c)

注意:GNU Make 的wildcard不支持**递归通配符。深层子目录需要分层单独写 wildcard,或使用foreach+shell find组合。

4 编译规则(大小写汇编分开)

# C 文件编译 $(BUILD_DIR)/%.o: %.c @mkdir -p $(dir $@) $(CC) -c $(CFLAGS) -MMD -MP $< -o $@ # 大写 .S 汇编(含预处理,需要传递 INCLUDES) $(BUILD_DIR)/%.o: %.S @mkdir -p $(dir $@) $(AS) -c $(ASFLAGS) $< -o $@ # 小写 .s 纯汇编(无预处理) $(BUILD_DIR)/%.o: %.s @mkdir -p $(dir $@) $(CC) -c $(CPUFLAGS) $< -o $@

大写.S和小写.s必须分开.S文件含 C 宏和#include,必须经过 C 预处理(-x assembler-with-cpp),并且需要-I头文件路径;.s是纯汇编,直接汇编即可。

5 链接与产物生成

$(BUILD_DIR)/$(TARGET).elf: $(OBJS) @echo "Linking $(BUILD_DIR)/$(TARGET).elf..." $(LD) $(OBJS) $(LDFLAGS) -o $@ @echo " BUILD SUCCESS: $(TARGET).elf" $(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf $(OBJCOPY) -O binary $< $@ $(BUILD_DIR)/$(TARGET).hex: $(BUILD_DIR)/$(TARGET).elf $(OBJCOPY) -O ihex $< $@

6 内置命令一览

命令功能
make完整编译,生成 elf/bin/hex
make clean清空 build 目录
make flash调用 OpenOCD 自动下载并运行(需 OpenOCD 已安装)
make info打印源码数量、工具链版本、固件大小

7 flash 目标:OpenOCD 一键烧录

OPENOCD ?= D:/tools/xpack-openocd-0.12.0-5-win32-x64/xpack-openocd-0.12.0-5/bin/openocd.exe OCD_SCRIPTS ?= D:/tools/xpack-openocd-0.12.0-5-win32-x64/xpack-openocd-0.12.0-5/openocd/scripts # 从 elf 动态取 Reset_Handler 符号地址,避免硬编码 ENTRY = $(shell $(OBJDUMP) -t $(BUILD_DIR)/$(TARGET).elf | grep " Reset_Handler" | awk '$$2!=""{print "0x"$$1}') READELF = $(CROSS_COMPILE)readelf flash: all "$(OPENOCD)" -s "$(OCD_SCRIPTS)" \ -f openocd/board_stm32mp157_m4.cfg \ -c "init" -c "targets stm32mp15x.cm4" -c "halt" \ -c "load_image $(BUILD_DIR)/$(TARGET).elf" \ -c "reg pc $(ENTRY)" \ -c "resume" -c "shutdown"

关键设计ENTRY从 elf 符号表动态解析Reset_Handler地址,永不硬编码。每次make后入口地址可能因代码量变化而漂移,硬编码必翻车。


⚠️ 本节踩坑速览

现象根因修复
wildcard 无法递归遍历内核多层文件夹GNU Make 不支持**分层单独写 wildcard 子目录
大写.S汇编头文件找不到误用小写.s编译规则分开编写.s.S两套规则
编译后固件过大、SRAM 溢出未开启--gc-sectionsCFLAGS + LDFLAGS 成对添加
大量 GPIO / UINT32 未定义缺失-DCORE_CM4CHIP_DEFS 添加-DCORE_CM4
printf 打印浮点数运行崩溃未链接 nano 浮点库LDFLAGS 增加-u _printf_float
make flashPC 地址错误硬编码 Reset_Handler 地址改用 elf 符号表动态解析
编译 memcpy/memset 等函数未定义--specs=nano.specs依赖 newlib-nano确认工具链已安装 newlib-nano
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/15 22:38:57

基于MiniCPM5-1B构建本地研究智能体:从模型部署到ReAct框架实战

最近在尝试将大语言模型&#xff08;LLM&#xff09;与特定领域研究结合时&#xff0c;发现一个痛点&#xff1a;很多前沿的AI研究工具或智能体平台要么依赖云端API&#xff0c;存在数据隐私和网络延迟问题&#xff1b;要么对硬件要求极高&#xff0c;个人开发者难以负担。有没…

作者头像 李华
网站建设 2026/8/15 22:38:07

第2章 坤•承载 二维的答案与三维的深渊

扎尔在MIT待了两个月。那两个月里&#xff0c;悦儿和他在同一个走廊上隔了两道门&#xff0c;每天碰面至少三次&#xff0c;有时候在茶水间&#xff0c;有时候在复印机旁边&#xff0c;有时候在洗手台前面刷牙——数学系三楼的洗手间只有两个水龙头&#xff0c;早晚高峰时段不可…

作者头像 李华
网站建设 2026/8/15 22:33:46

Git分支管理:从创建、拉取到跟踪的完整实践指南

1. 从“拉取新分支”说起&#xff1a;一个被低估的日常操作每次看到有同事在终端里敲下git checkout -b feature-xxx&#xff0c;然后紧接着就是一连串的git push --set-upstream origin feature-xxx&#xff0c;我总会想起自己刚接触 Git 那会儿。那时候觉得&#xff0c;“拉取…

作者头像 李华
网站建设 2026/8/15 22:31:26

MMKV原理与实战:高性能键值存储组件深度解析

1. 项目概述&#xff1a;为什么我们需要MMKV&#xff1f; 在移动端开发&#xff0c;尤其是Android和iOS平台上&#xff0c;数据持久化是一个绕不开的话题。如果你做过几年开发&#xff0c;肯定对 SharedPreferences &#xff08;Android&#xff09;和 NSUserDefaults &…

作者头像 李华
网站建设 2026/8/15 22:29:03

钉钉直播教学全流程26个常见问题解决方案与实战指南

1. 项目概述&#xff1a;一场直播教学背后的技术交响曲 如果你是一名老师、培训师&#xff0c;或者任何需要通过线上实时互动来传递知识的人&#xff0c;那么“钉钉直播教学”这个场景你一定不陌生。它早已不是疫情期间的应急方案&#xff0c;而是融入了日常教学、企业内训的常…

作者头像 李华