2. 嵌入式系统基础
做嵌入式移植,第一件事不是看代码,而是看芯片。我见过太多工程师拿到开发板就开干,结果发现外设地址映射不对、中断控制器不兼容,回头再翻手册,白白浪费两周。这一章,咱们就把硬件平台这件事聊透。
一、主流嵌入式处理器架构对比
先看一张总览图,把几个主流架构的定位搞清楚。
二、ARM Cortex-M/A/R 三兄弟
ARM 的 Cortex 系列分三条线,每条线的定位完全不同。我刚开始做移植时,以为 Cortex-M 和 Cortex-A 只是性能差异,后来发现中断模型、内存管理、启动流程完全是两套东西。
| 系列 | 典型场景 | 中断延迟 | MMU/MPU | 操作系统 |
|---|---|---|---|---|
| Cortex-M | 传感器、电机控制、IoT 终端 | 12~15 个时钟周期 | MPU(可选) | RTOS(FreeRTOS/RT-Thread) |
| Cortex-R | 汽车制动、基站控制、硬盘控制器 | 8~10 个时钟周期 | MPU(硬实时) | 实时 Linux / 裸机 |
| Cortex-A | 智能手机、网关、HMI 显示 | 50~100 个时钟周期 | MMU(虚拟内存) | Linux / Android |
个人经验:选型时别只看主频。Cortex-M7 跑到 400MHz 也不一定能替代 Cortex-A35 跑 200MHz,因为 M 系列没有 MMU,跑不了 Linux。我有个项目把 M7 当主控,结果客户要跑 TCP/IP 协议栈 + Web 界面,最后硬生生加了个 A 核芯片。
三、RISC-V:开源架构的机遇与坑
RISC-V 这几年很火,但说实话,生态还没完全成熟。我去年帮客户移植过一个 RISC-V 内核的 BSP,踩了不少坑。
RISC-V 的核心优势:
- 指令集开源,没有授权费,适合定制化芯片
- 模块化设计:RV32I 是基础,M 扩展做乘法,F/D 做浮点,A 做原子操作
- 没有历史兼容性包袱,指令编码干净
实际移植中要注意的问题:
- 不同厂商的 RISC-V 核,CSR(控制状态寄存器)地址可能不同
- 中断控制器没有统一标准,CLIC、PLIC、CLINT 各有各的玩法
- 调试接口(JTAG)的扫描链实现差异大
避坑指南:我曾经遇到一个 RISC-V 芯片,手册说支持 RV32IMAC,结果实际跑浮点运算时发现 F 扩展没完全实现,编译器生成的浮点指令直接触发非法指令异常。后来只能加软浮点库,性能掉了 40%。所以选 RISC-V 芯片时,一定要确认扩展指令集的实际实现情况。
四、芯片选型原则:别只看数据手册
选芯片这件事,我总结了五个维度,按优先级排序:
- 功能匹配:外设接口够不够?UART、SPI、I2C、CAN、Ethernet 数量是否满足?
- 性能余量:CPU 利用率留 30%~50% 余量,RAM 留 20% 以上
- 功耗约束:工作模式、休眠模式、唤醒时间是否达标
- 供货稳定:交期、第二供应商、生命周期状态
- 工具链支持:IDE、调试器、RTOS 移植难度、社区活跃度
我的习惯:选型时先列一个「必须满足」清单和一个「加分项」清单。比如必须要有双 CAN 接口,加分项是支持低功耗触摸唤醒。然后拿着清单去对比,而不是被厂商的「主频 1GHz」这种参数带偏。
五、开发板硬件资源分析:以 STM32MP157 为例
STM32MP157 是 ST 推出的双核异构处理器,一个 Cortex-A7(跑 Linux)加一个 Cortex-M4(跑 RTOS)。这种架构在工业 HMI、边缘网关里很常见。
咱们拆开看看这块板子的硬件资源:
| 资源类别 | 具体配置 | 用途说明 |
|---|---|---|
| CPU | 1×Cortex-A7 @ 650MHz 1×Cortex-M4 @ 209MHz |
A7 跑 Linux 应用层 M4 做实时控制 |
| 内存 | DDR3L 512MB(板载) | Linux 系统运行空间 |
| 存储 | SD 卡 / eMMC / NAND | 根文件系统存放 |
| 显示 | MIPI-DSI / RGB-LCD / HDMI | HMI 界面输出 |
| 网络 | 1×Gigabit Ethernet | 工业以太网通信 |
| 外设 | UART×8, SPI×5, I2C×5, CAN×2, USB×2 | 传感器、执行器、通信模块 |
| 调试 | ST-LINK/V2-1 集成 | 板载调试器,无需外接 |
异构通信机制:
A7 和 M4 之间通过共享内存(IPCC)和硬件信号量(HSEM)通信。我调试时发现,很多人把数据放在共享内存里,但没做缓存一致性处理,导致 A7 写的数据 M4 读不到。解决办法是在共享内存区域关闭 MMU 的 cache 属性,或者用 DMA 搬运。
实战建议:拿到 STM32MP157 开发板后,先做三件事:
1. 用 STM32CubeProgrammer 读一下 OTP 区域,确认芯片版本
2. 用 TF-A(Trusted Firmware-A)启动,检查 DDR 初始化时序
3. 跑一个简单的 M4 裸机程序,验证 IPCC 中断通路
这三步走完,基本能排除 80% 的硬件问题。
1. 用 STM32CubeProgrammer 读一下 OTP 区域,确认芯片版本
2. 用 TF-A(Trusted Firmware-A)启动,检查 DDR 初始化时序
3. 跑一个简单的 M4 裸机程序,验证 IPCC 中断通路
这三步走完,基本能排除 80% 的硬件问题。
六、开发板资源分析流程
不管拿到什么开发板,我建议按这个流程走一遍:
- 读原理图:找到电源树、时钟树、复位电路,确认各模块供电电压
- 看数据手册:重点关注 memory map、中断向量表、启动模式选择
- 测基础外设:GPIO 点灯、UART 回环、定时器中断
- 验证内存:跑 memtest 检查 DDR/SRAM 的读写稳定性
- 确认调试接口:SWD/JTAG 信号是否正常,调试器能否识别芯片
我曾经踩过的坑:有一次拿到一块新板子,原理图上看电源都正常,但 UART 就是不出数据。查了两天,发现是板子上的 RS232 电平转换芯片的使能引脚被拉低了。所以,别只盯着主芯片,板级的外围电路也要仔细看。