1. STM32MP平台与Linux驱动体系概览
STM32MP1 与 STM32MP2 是 ST 面向嵌入式 Linux 场景推出的异构多核微处理器系列。理解这套平台,关键不是先背寄存器,而是先建立一张“硬件—内核—驱动—应用”的整体地图:谁负责实时控制,谁负责操作系统与外设管理,驱动代码又挂在内核的哪一层。只有把这张地图建立起来,后续的字符设备、平台设备、设备树、总线与子系统学习才不会变成零散知识点的堆叠。
一、硬件架构:双核异构是理解一切的起点
以 STM32MP157 为例,芯片内部同时存在两个 Cortex-A7 核(可组成 SMP 双核 Linux 运行环境)和一个 Cortex-M4 核。A7 侧运行 Linux,负责内存管理、文件系统、网络、图形与复杂外设;M4 侧通常运行裸机或 RTOS 固件,承担电机控制、采样闭环、硬实时中断等任务。两者不是主从替代关系,而是分工协作:A7 提供生态与算力,M4 提供确定性与低延迟。
两核之间通过共享内存与 IPCC 邮箱中断通信。典型做法是:在设备树中保留一段 no-map 的 reserved-memory 作为共享缓冲区,A7 侧用 rpmsg 字符设备或 remoteproc 框架加载 M4 固件,M4 侧用 OpenAMP 收发消息。这样,Linux 应用可以通过标准文件接口向 M4 下发控制参数,M4 把采集结果回传,形成“Linux 管策略、M4 管实时”的结构。
STM32MP2 在此基础上进一步强化:Cortex-A35 双核替代 A7,加入 NPU、M33 实时核与更丰富的高速接口,但异构协作模型与驱动分层思想保持一致。因此本章以 MP1 为主线建立概念,MP2 的差异在后续章节按外设展开。
二、Linux 内核驱动模型分层
Linux 不是“一个驱动对应一个外设”的扁平结构,而是分层模型。最上层是用户空间:应用通过 /dev、/sys、/proc 访问设备。其下是内核中的子系统层,例如 tty、input、iio、net、mmc、drm;子系统向上提供统一接口,向下定义驱动需要实现的 ops 集合。再往下是核心层与总线层:platform、i2c、spi、usb 等总线负责设备与驱动的匹配。最底层才是具体 SoC 的控制器驱动,例如 STM32 的 USART、I2C、SPI、DMA 控制器驱动。
设备树(Device Tree)是这条链路的“配置描述层”。它不写代码逻辑,只描述“哪个地址、哪个中断、哪个时钟、哪个引脚、挂在哪个总线”。驱动通过 of_match_table 与设备树节点匹配,匹配成功后 probe() 被调用,完成寄存器映射、时钟使能、中断注册与子系统注册。因此,一个外设能否工作,往往取决于三件事是否同时正确:设备树节点、驱动匹配表、子系统注册路径。
三、从“能启动”到“能集成”的关键判断
很多初学者把驱动开发理解为“写一个模块然后 insmod”。在 STM32MP 平台上,更常见的路径是:先确认设备树节点是否存在且 status = "okay",再确认内核配置中对应驱动是否编译进内核或模块,然后看 dmesg 中 probe 是否成功。若 probe 失败,常见原因包括:时钟未使能、pinctrl 引脚冲突、中断号错误、reg 地址与 reserved-memory 重叠、依赖的 regulator 未就绪。这些都不是“代码写错”,而是平台集成信息不完整。
因此,学习路径应当按“先结构、后接口、再调试”推进:先理解 A7/M4 分工与内核分层,再掌握设备树与 platform 驱动匹配,然后进入字符设备、GPIO、I2C、SPI、IIO、DMA 等具体外设,最后回到 rpmsg/remoteproc 完成异构协同。每一层都要能回答三个问题:输入是什么、内核发生了什么、结果如何验证。
四、学习路径与阶段目标
第一阶段:能读懂 STM32MP157 的设备树,找到 UART、I2C、SPI 节点,理解 compatible、reg、interrupts、clocks、pinctrl 的含义。第二阶段:能编写并加载一个 platform 驱动,通过 of_match_table 匹配设备树节点,在 probe 中完成寄存器映射与字符设备注册。第三阶段:能针对具体外设选择正确子系统,例如用 IIO 做 ADC 采集、用 input 做按键、用 tty 做串口。第四阶段:能通过 rpmsg 让 A7 应用与 M4 固件交换数据,完成“Linux 策略 + 实时控制”的闭环。