【STM32MP系列】

初学日志

  • MMU内存管理单元
      • [硬件核心:MMU 与页表 (Page Table) 的机制](#硬件核心:MMU 与页表 (Page Table) 的机制)
      • 设备树
      • [一、 核心硬件架构:从 MCU 到 MPU 的跨越](#一、 核心硬件架构:从 MCU 到 MPU 的跨越)
    • **芯片架构与定位**
    • [**STM32MP135F-DK 探索套件核心资源**](#STM32MP135F-DK 探索套件核心资源)
    • [**专属电源管理芯片 (STPMIC1)**](#专属电源管理芯片 (STPMIC1))
      • [二、 内存管理核心:MMU 与页表机制](#二、 内存管理核心:MMU 与页表机制)
    • **物理地址与虚拟地址**
    • [**页表 (Page Table) 与 PTE**](#页表 (Page Table) 与 PTE)
      • [三、 嵌入式 Linux 软件栈 (OpenSTLinux)](#三、 嵌入式 Linux 软件栈 (OpenSTLinux))
    • [**系统启动"接力赛"** 一个完整的嵌入式 Linux 系统启动包含四个严格的阶段:](#系统启动“接力赛” 一个完整的嵌入式 Linux 系统启动包含四个严格的阶段:)
      • [四、 静态硬件映射:设备树 (Device Tree)](#四、 静态硬件映射:设备树 (Device Tree))
      • [五、 动态硬件控制:Linux 驱动模型](#五、 动态硬件控制:Linux 驱动模型)

MMU内存管理单元

硬件核心:MMU 与页表 (Page Table) 的机制

当系统启用 MMU 后,CPU 流水线发出的所有地址将不再直接输出到芯片内部的 AMBA 总线(如 AXI/AHB),而是首先交由 MMU 进行处理。

页表机制 :Linux 内核会在物理内存(DDR)中维护一个树状数据结构,称为页表 (Page Table)。页表的核心单元是 PTE (Page Table Entry)。每个 PTE 记录了"一块虚拟地址空间(通常为 4KB 的页)对应哪一块物理地址空间",同时包含该内存块的访问属性(如可读/可写、用户/超级用户特权级、是否允许缓存等)。

(为什么是 4KB?) 综合来看,4KB 的页大小是一个平衡点:不至于造成太大内存浪费。对于 32 位芯片,其地址空间为 2^32,即 4GB。若按 4KB 分页,总共约有 100 万个页。每个页表项 (PTE) 通常占 4 字节,因此单级页表仅需约 4MB 内存即可映射整个 4GB 地址空间,开销较为合理。

TTBR 寄存器 :Cortex-A7 处理器内部设有特殊的控制寄存器(如 TTBR0TTBR1),用于存放页表在物理内存中的基地址。

地址翻译:当 CPU 访问一个虚拟地址时,硬件 MMU 会自动根据该地址查找页表,将其转换为对应的物理地址,再将寻址信号发送至实际的硬件外设或 DDR 芯片。为了加速这一过程,MMU 内部集成了 TLB(快表),用于缓存最近使用的地址映射关系。

设备树

一、 核心硬件架构:从 MCU 到 MPU 的跨越

芯片架构与定位

复制代码
    **MCU(如 STM32F103/H750)**:运行在扁平物理地址空间,直接操作寄存器,无内存隔离,主要运行裸机或实时操作系统(RTOS)。
复制代码
    **MPU(如 STM32MP135)**:基于 Arm Cortex-A7 核心,主频高达 1 GHz。其最核心的标志是引入了**内存管理单元 (MMU)**,支持虚拟内存技术,从而能够运行复杂的嵌入式 Linux 系统。

STM32MP135F-DK 探索套件核心资源

复制代码
    **存储系统**:由于 Linux 系统的巨大开销,MPU 必须外挂大容量存储。该板载配备了 512MB (4-Gbit) 的 DDR3L 内存,并通过 MicroSD 卡槽加载包含 U-Boot、内核及根文件系统的完整镜像。
复制代码
    **外设接口**:具备双 10/100 Mbit/s 以太网(支持局域网唤醒)、Wi-Fi/蓝牙、多个 USB 接口、MIPI CSI-2 摄像头接口以及 4.3 英寸电容触摸屏。

专属电源管理芯片 (STPMIC1)

复制代码
    **功能**:作为系统的"心脏",STPMIC1 负责将 USB 输入的 5V 电压转换为 MPU 所需的多种精确电压。它包含高效率的 BUCK 通道(如给 CPU 和 DDR 供电)和低噪声的 LDO 通道(如给 ADC、USB PHY 供电)。
复制代码
    **智能唤醒机制**:为追求极致低功耗,系统深度休眠时会切断主 CPU 供电。唤醒按键 (B3) 直接连接至 STPMIC1 的 PONKEY 引脚;STPMIC1 被触发后恢复主板供电,并通过专属引脚向 CPU 发送唤醒指令恢复 Linux 运行。

二、 内存管理核心:MMU 与页表机制

物理地址与虚拟地址

复制代码
    **物理地址**:芯片设计时硬连线定死的客观存在(如外设寄存器的绝对基地址),CPU 在裸机状态下直接对其进行读写。
复制代码
    **虚拟地址**:由操作系统和 CPU 分配的"虚拟门牌号",各个应用进程拥有独立受保护的虚拟地址空间,实现了极高的系统安全性与隔离性。

页表 (Page Table) 与 PTE

复制代码
    **映射机制**:MMU 在内存中维护页表字典。其核心单元 **PTE (Page Table Entry)** 记录了虚拟页到物理页帧的映射关系,并包含读写/特权级/Cache 等内存属性限制。
复制代码
    **黄金折中点 (4KB 页大小)**:Linux 通常采用 4KB 作为基础分页粒度。这一大小巧妙平衡了"页表体积(避免占用过多内存)"与"内部碎片浪费",且完美契合硬盘的 4KB 物理扇区以优化 I/O 效率。

三、 嵌入式 Linux 软件栈 (OpenSTLinux)

系统启动"接力赛"

一个完整的嵌入式 Linux 系统启动包含四个严格的阶段:

复制代码
    **TF-A (Trusted Firmware-A)**:底层安全固件,负责初始化基础硬件和安全环境。
复制代码
    **U-Boot**:引导加载程序,将 Linux 内核和设备树加载到内存。
复制代码
    **Linux Kernel**:操作系统核心,负责内存、进程调度和底层驱动。
复制代码
    **RootFS (根文件系统)**:包含共享库和用户空间工具(如 Python 解释器)。
  1. 开发流模式开发者不需要从零编写 Linux。核心工作是"做减法与定制":通过 Yocto 或 Buildroot 裁剪不需要的内核模块,定制根文件系统,配置设备树,最终在应用层使用标准 POSIX 接口进行业务开发。

四、 静态硬件映射:设备树 (Device Tree)

  1. 核心设计思想为了解决 Linux 内核源码因硬编码不同主板引脚而变得极度臃肿的问题,引入了设备树。它将"硬件配置"与"内核通用代码"彻底剥离。
  2. 设备树的作用 设备树是一份"硬件说明书",它使用特定的语法(.dts 文件)如实记录了外设是否启用、引脚连接方式、中断号以及物理基地址等客观参数。设备树本身不分配任何虚拟地址。
  3. 自动生成在实际工业开发中,开发者通常使用 STM32CubeMX 图形化工具来分配外设和引脚,软件会自动查阅"寄存器字典"并生成对应的设备树文件。

五、 动态硬件控制:Linux 驱动模型

  1. 映射机制 (ioremap)

    驱动程序加载时,会解析设备树获取硬件的物理基地址。随后,驱动调用 ioremap(物理地址, size) 内核函数。

    • 该函数在内核 vmalloc 区域寻找一块空闲的虚拟地址,并修改 MMU 页表 (PTE) 建立物理到虚拟的"虫洞"映射。
    • 在 PTE 属性中,这段内存会被强制标记为 Device Memory,强制绕过 CPU Cache,确保指令按强顺序模型实打实地到达硬件。
  2. 寄存器读写与位运算

    复制代码
     **偏移地址**:寄存器的偏移地址由芯片出厂硬连线定死,通常作为宏定义写在 C 语言驱动代码中(目标操作地址 = `ioremap` 虚拟基地址 + 偏移地址)。
     
    
     
     **原子化位运算**:由于 32 位寄存器内通常打包了多个引脚的状态,直接赋值会干扰其他引脚。因此必须使用"读-改-写"的位运算(如 `val |= (1 << 13)`)实现对目标位(如第 13 位)的精准修改。
    • 内核提供专属的 readl()writel() 宏进行操作,它们底层封装了内存屏障指令,保证时序稳定。
  3. 接口封装与应用调用 底层驱动在完成所有的物理映射与寄存器操作后,将其封装为一个简单的设备节点文件(如 /dev/led)。应用层只需调用 openwrite 等标准文件操作接口即可控制硬件,彻底实现了底层复杂性对上层的透明化。