欢迎光临
我们一直在努力

【系统移植】

一、什么是系统移植

        系统移植(System Porting)是将通用 / 开源的系统(或中间件、协议栈)从原始硬件平台 / 开发环境,通过针对性的适配、修改和编译,使其稳定运行在目标硬件平台上的过程。这个过程可能涉及到许多不同的方面,包括硬件适配、驱动程序开发、 引导加载程序(Bootloader)配置、文件系统适配、内核参数设置等等。核心是屏蔽不同硬件的底层差异,让成熟系统的上层功能在新硬件上直接复用,无需从零开发。

        系统移植的主要目的是使一个操作系统能够在不同的硬件平台上正常运行,并充分发挥其功能。在嵌 入式领域,不同的硬件平台可能有不同的处理器架构、外设、内存布局等,因此需要进行适当的调整和配 置,以确保操作系统能够正确地与硬件交互。

        移植的核心逻辑是上层功能完全复用,仅对底层与硬件强相关的部分做适配修改,也是嵌入式开发中 “高效复用成熟代码、降低开发成本” 的核心手段。

  • 上层:系统 / 中间件的核心功能(如 FreeRTOS 的任务调度、Linux 的进程管理、LWIP 的 TCP 协议)与硬件无关,100% 复用,无需修改;
  • 底层:仅对与硬件 / 架构强相关的部分(时钟、中断、外设驱动、内存地址)做针对性适配,这是移植的唯一工作。

        系统移植的难度取决于目标硬件与原始平台的架构差异(同架构移植简单,跨架构移植复杂)和系统的复杂度(RTOS 移植简单,Linux 内核移植复杂),核心适配层主要分为:硬件内核层(CPU、时钟、中断)、外设驱动层、编译链接层(工具链、链接脚本)、系统核心层(调度、内存管理)。

通常情况下,系统移植需要进行以下工作

选择操作系统版本: 首先需要选择适合目标硬件平台的操作系统版本,确保其支持目标架构和硬件特性。

硬件适配:修改操作系统的源代码,以适配新的硬件平台。这可能涉及修改底层驱动程序、中断处理、外设配置等。

驱动程序开发: 编写或适配适合目标硬件的驱动程序,使操作系统能够与硬件进行通信。

引导加载程序配置: 配置引导加载程序,使其能够正确加载和启动操作系统内核。

文件系统适配: 调整文件系统以适应新的硬件存储和文件结构

内核参数设置: 配置操作系统内核参数,以适应硬件资源和性能需求。

调试和测试: 进行测试,确保操作系统在新硬件平台上稳定运行。调试可能涉及硬件问题、驱动程序问题、性能问题等。

二、Flash分区映射与Linux系统启动流程

在学习系统移植前徐先了解Flash的分区映射与Linux系统的启动流程,以下所有内容均基于Cortex-A系列下的STM32MP157A开发板进行讲解

2.1、Flash分区映射

Flash具体分区如下:

上述图片部分主要总结如下:

启动加载器
(Bootloader)

系统启动的第一阶段是启动加载器的运行。在你的配置中,有两个级别的

启动加载器:第一级
(FSBL)
和第二级
(SSBL)
。这些启动加载器负责加载和运行更高级别的启动加载 器,以及最终加载内核和文件系统。

内核
(Kernel)

内核是操作系统的核心,它负责管理硬件资源、进程管理、文件系统等。在配置中,

内核文件通常被放置在
bootfs
或者
rootfs
中。内核必须能够正确地加载和解释设备树
(Device Tree)

设备树
(Device Tree)

设备树是一种描述硬件的机制,使内核能够根据硬件的不同配置进行正确的初

始化。在你的配置中,设备树文件可能会附加在启动加载器
(ssbl

fsbl)
后面,作为启动加载器的一 部分。

文件系统:不同的分区被用来存放不同类型的文件系统。
userfs

rootfs

vendorfs
等都是不同类型的文 件系统,存放着用户数据、Linux
根文件系统以及第三方专有文件等。

OP-TEE

这是一个安全框架,分为
teeh

teed

teex
三个部分,用于提供安全和信任的执行环境。

2.2、Linux 系统启动流程

1. 最底层:ROM Code(固化在芯片内部的启动代码)

  • 存储位置:芯片内置的 ROM(容量 < 128KB),是硬件出厂时就固化的代码。
  • 核心作用:
    • 完成最基础的时钟初始化,让芯片的时钟模块正常工作。
    • 从启动设备(如闪存、串口)加载第一阶段启动加载器 FSBL。
    • 启动 FSBL,将系统控制权交给它。
  • 这是整个启动流程的 “起点”,仅负责唤醒硬件最基础的功能,并找到下一级启动程序。

2. 第一阶段启动加载器:FSBL(First Stage Boot Loader)

  • 核心功能:

    • 最小化硬件初始化:仅初始化启动必需的硬件,无任何冗余功能,包括:
      • 芯片核心:时钟树(PLL / 晶振)、CPU 核、MMU / 缓存基础配置;
      • 存储相关:DDR(SDRAM/DDR3/4)初始化(关键!让系统有可运行的内存)、eMMC/SD 卡 / NOR Flash 的底层驱动;
      • 调试相关:串口(UART)初始化(仅用于打印简单启动日志,无交互);
      • 其他:电源管理(PMIC)、启动介质检测(识别从 eMMC/SD/ 网口启动)。
    • 加载 SSBL 到 DDR:从指定启动介质(如 eMMC BOOT1 分区、SD 卡指定扇区)读取 SSBL(U-Boot)的二进制文件,将其拷贝到 DDR 的指定内存地址(如 STM32MP1 的0x80000000)。
    • 权限移交:FSBL 自身不驻留内存,完成加载后直接跳转到 SSBL 在 DDR 的内存地址,将 CPU 执行权完全交给 SSBL,自身执行结束。
  • 关键特点

    • 极致轻量:代码量极小(通常几十 KB 到几百 KB),编译后体积远小于 SSBL,适配芯片引导区的小容量空间;
    • 不可定制 / 极少定制:由原厂基于芯片底层架构开发(如 STM32MP1 的 FSBL 由 ST 官方基于 STM32Cube 开发),开发者无需修改,仅需按板卡手册烧写到指定介质即可;
    • 无交互 / 无配置:无命令行、无环境变量、无用户交互,执行流程固化,仅打印简单的 “初始化成功 / 加载 SSBL 完成” 日志;
    • 存储位置固定:必须烧写到芯片指定的 “专用引导分区”(如 eMMC 的 BOOT0/BOOT1 分区、SD 卡的前 128/256 个扇区),否则 ROM Boot 无法识别加载;
    • 运行位置:先在芯片内部的 SRAM(片上小内存)运行(DDR 未初始化前无外部内存),DDR 初始化后自身仍在 SRAM,仅将 SSBL 加载到 DDR
  • 这一步的核心目标是 “解锁” 外部大容量内存,为后续复杂程序的运行做准备。

3. 第二阶段启动加载器:SSBL(Second Stage Boot Loader)

  • 核心功能

    • 系统级硬件初始化:在 FSBL 基础上,初始化所有系统运行需要的硬件,包括:
      • 扩展硬件:网口(Ethernet)、USB、SPI/I2C、LCD、NAND Flash;
      • 存储高级配置:eMMC/SD 卡的分区识别、文件系统驱动(如 FAT32/ext4);
      • 内存高级配置:DDR 全区域管理、内存映射(MMU)完整配置;
    • 提供交互式命令行:这是 SSBL(U-Boot)的核心特征,支持各种调试 / 配置命令,比如你熟悉的:
      • 存储操作:mmc list/mmc read/ums 0 mmc 1(UMS 模式);
      • 网络操作:ping/tftp/nfs(加载内核 / 根文件系统);
      • 启动配置:setenv bootcmd/saveenv(修改启动命令、保存环境变量);
    • 加载并启动 Linux 内核 / 根文件系统:
      • 从 eMMC/SD/ 网口(TFTP/NFS)读取 Linux 内核(zImage/Image)和设备树(dtb),加载到 DDR 指定地址;
      • 传递启动参数(如根文件系统路径root=/dev/mmcblk1p2),跳转到内核地址,启动 Linux;
    • 启动环境管理:提供非易失性环境变量(保存在 eMMC/SD 的专用分区),可定制启动流程(如从 NFS 挂载根文件系统、默认启动内核版本);
    • 系统调试 / 救砖:支持中断内核启动、进入命令行,可修复损坏的内核 / 根文件系统,是嵌入式开发中 “救砖” 的核心工具(比如 eMMC Bootloader 损坏后,用 SD 卡的 SSBL 启动并修复 eMMC)。
  • 关键特点

    • 功能丰富、高度可定制:开发者可通过修改 U-Boot 源码、配置make menuconfig添加 / 删减功能(如开启 NFS/UMS/TFTP),适配自研板卡;
    • 有交互、有配置:提供完整的命令行交互,支持环境变量配置,可灵活修改启动逻辑;
    • 运行位置固定:全程在DDR 内存中运行(由 FSBL 加载到 DDR,自身不占用片上 SRAM);
    • 存储位置灵活:可烧写到 eMMC/SD 的用户区分区(非专用引导区),只要 FSBL 能识别其存储地址即可;
    • 代码量较大:编译后体积通常几 MB,包含各种硬件驱动和命令逻辑。
  • 这是连接硬件与 Linux 内核的 “桥梁”,负责准备内核启动所需的文件和环境。

4. Linux Kernel(Linux 内核)

  • 存储位置:外部 RAM。
  • 核心作用:
    • 初始化平台驱动等内核级硬件支持,让内核能管理硬件设备。
    • 挂载根文件系统(rootfs)(包含系统的基础文件、目录结构,是用户空间的 “根”)。
    • 加载并启动用户空间初始化进程(如 /sbin/init),将控制权交给用户空间。
  • 内核启动后,系统进入受内核管理的状态,开始构建用户空间的运行环境。

5. 最上层:Linux User Space(Linux 用户空间)

  • 存储位置:外部 RAM。
  • 核心作用:
    • 加载并运行用户空间的各种服务和应用程序(如桌面环境、网络服务、用户自定义应用等)。
    • 这是用户能直接交互的层面,所有上层功能都在这里运行

标准 Linux 启动过程的主要步骤:

上电和自检
(Power On and Power-On Self-Test, POST)

        计算机上电,开始进行硬件初始化和自检。

        自检程序会检查硬件是否正常工作,并进行初始化。

引导加载器
(Bootloader)

        引导加载器负责加载操作系统内核和根文件系统。

        常见的引导加载器包括 GRUB

U-Boot
等。

        引导加载器从引导设备(如硬盘、闪存)读取配置和内核映像。

内核启动
(Kernel Boot)

        内核加载后,会被解压和初始化。

        内核首先会设置基本硬件参数,如内存管理、处理器模式等。

        初始化后,内核会启动第一个用户态进程 init

初始化
(Init)

        内核启动 init
进程(通常是
/bin/init

/sbin/init
)作为第一个用户态进程。

        init 负责启动和管理其他用户态进程,并初始化系统的各种资源。

        在现代系统中,init
通常被替代为更先进的
init
系统,如
systemd

Upstart
等。

系统初始化
(System Initialization)

        在 init

init
系统的管理下,系统会进行初始化,包括加载系统配置、设置网络、加载驱动程序等。

        用户空间初始化 (User Space Initialization)

        用户空间初始化涉及启动各种用户态进程和服务。

        启动登录管理器(如 GDM

LightDM
),以便用户登录。

        用户登录后,登录管理器启动 X
服务器(如
Xorg
)以及用户的窗口管理器或桌面环境。

用户登录
(User Login)

        用户通过登录界面输入用户名和密码。

        登录管理器验证用户信息,如果正确,会创建用户的会话环境。

用户会话
(User Session)

        一旦用户成功登录,桌面环境启动并提供一个用户界面。

        用户可以运行应用程序、访问文件、使用系统资源等。

STM32MP1启动流程

        与标准流程基本一致,多提供了一种安全监控的模式,可以由 FSBL 或者 SSBL 启动。由于该开发板 采用异核架构,有 A 核和 M 核,如果要加载 M 核的固件,可以在 SSBL 或者 linux 启动。

STM32MP1 非安全启动流程

STM32MP1
安全启动流程

2.3、启动过程中的外设初始化

2.3.1、ROM Code

流程总览

ROM Code 是芯片上电 / 复位后执行的第一段代码,核心作用是初始化硬件、选择启动路径、加载并验证启动镜像,最终完成系统启动。整个流程按功能分为 5 个核心模块:

  • 安全启动子流程(左上)
  • 主启动分支判断(中间)
  • 待机唤醒处理(右侧)
  • 特殊模式启动(左下:RMA/ENGI)
  • 错误处理(底部)

核心模块详解

1. 安全启动子流程(左上灰色模块)

这是正常冷启动的核心路径,负责从外部设备加载并验证启动镜像:

  • Select boot device
    • 功能:遍历启动设备列表(如 SPI Flash、eMMC、SD 卡),选择当前优先级最高的设备。
    • 触发:冷启动时进入,或前一个设备认证失败后重试。
  • Load image from boot device
    • 功能:从选中设备读取启动镜像(如 BL1、U-Boot)到内部 RAM。
  • Authenticate the boot image
    • 功能:校验镜像签名 / 哈希值,确保镜像未被篡改、来源合法。
  • Auth Ok?(判断)
    • ✅ Yes → Jump to image:跳转到验证通过的镜像入口,执行后续启动(如加载内核)。
    • ❌ No → 回到 Select boot device:切换到下一个设备重试,直到所有设备尝试完毕。

  • 2. 主启动分支判断(中间核心逻辑)

    系统复位后,先区分主核 / 从核,再根据复位原因选择启动模式:

  • Get reset reason
    • 功能:读取复位状态寄存器,判断复位类型(冷复位、待机唤醒、看门狗复位等)。
  • CPU#0?(判断是否为主核)
    • ✅ Yes → System init:主核(A7 主核)执行硬件初始化(时钟、RAM、外设复位等)。
    • ❌ No → Secondary A7 core boot:从核进入从核启动流程,等待主核同步。

  • 3. 复位原因分支(System init 之后的判断)

    主核初始化完成后,根据复位原因进入不同模式:

  • Standby Exit?(是否为待机唤醒?)
    • ✅ Yes → 进入右侧「待机唤醒处理流程」
    • ❌ No → 继续判断
  • RMA?(是否为售后维修模式?)
    • ✅ Yes → RMA boot process → RMA boot:加载维修专用镜像,跳过部分安全校验,用于硬件检测 / 修复。
    • ❌ No → 继续判断
  • ENGI boot?(是否为工程调试模式?)
    • ✅ Yes → ENGI boot process → ENGI boot:加载未签名的调试镜像,开放调试接口,用于研发验证。
    • ❌ No → Cold boot:进入正常冷启动,触发「安全启动子流程」。

  • 4. 待机唤醒处理流程(右侧灰色模块)

    处理系统从深度待机(CSTANDBY)唤醒的场景,此时 A7 休眠,需优先恢复低功耗的 M4 核:

  • A7 in CSTANDBY(初始状态):唤醒前 A7 处于深度低功耗状态。
  • Suspend boot:暂停 A7 启动,优先处理唤醒源(如 M4 触发的唤醒)。
  • Boot A7?(判断是否立即启动 A7)
    • ❌ No → 先处理 M4 唤醒:
      • Boot M4?(判断是否启动 M4)
        • ✅ Yes → Get M4 wakeup request:读取 M4 唤醒请求参数。
        • ❌ No → Standby exit:直接退出待机,恢复到唤醒前状态。
      • M4 wakeup process:初始化 M4 时钟、RAM,加载并启动 M4 镜像。
      • M4 boot ok(判断 M4 启动是否成功)
        • ✅ success → 回到 Boot A7? 再次判断。
        • ❌ failed → M4 boot ko:回到主流程(如触发冷启动或启动失败)。
    • ✅ Yes → Cold boot:触发正常冷启动流程。

  • 5. 错误处理流程

    • Endless loop:启动失败(如所有设备认证失败、核心初始化失败)时进入无限循环,防止系统异常跳转。
    • Boot Failed:循环后标记启动失败,通过硬件引脚 / 日志通知外部。

    2.3.2、TF-A

    1. ROM code
    加载
    TF-A
    可执行文件并跳转到
    BL2

    2. BL2
    准备
    BL32
    运行时环境(
    BL32
    是安全相关服务)

    3. BL2
    加载
    BL33
    程序(
    BL33
    是非安全固件)

    4. BL2
    跳转到
    BL32

    5. BL32
    跳转到
    BL33

    启动阶段介绍

            BL1 是执行的第一个阶段,并被设计作为
    ROM
    代码
    ;
    它在内部
    RAM
    中加载和执行。
    TF-A
    中的 BL1 在
    STM32MP1
    系统中没有被使用。因为
    STM32MP1
    在片内的
    ROM
    中有自己的专有
    ROM
    代码, 所以可以删除这一部分,然后 BL2
    是要执行的第一个
    TF-A
    二进制文件

            BL2(受信任的引导固件)负责加载下一阶段的映像(安全和非安全)。为了实现此作用,
    BL2
    必 须初始化所有必要的外围设备。

            初始化安全组件:

                    OTP 管理:BSEC
    外设用于控制
    OTP
    (一次性可编程)熔丝位,该熔丝位用于片上非易

    失性存储,用于设备配置和安全参数。

                    TrustZone 保护控制器:为提高系统的安全性,ARM
    早在
    ARMv6
    架构中就引入了

    TrustZone
    技术,且在
    ARMv7

    ARMv8
    中得到增强,
    TrustZone
    技术能提供芯片级别对硬件

    资源的保护和隔离,当前在手机芯片领域已被广泛应用。

                    TrustZone 技术之所以能提高系统的安全性,是因为对外部资源和内存资源的硬件隔离。 这些硬件隔离包括中断隔离、片上 RAM

    ROM
    的隔离、片外
    RAM

    ROM
    的隔离、外围

    设备的硬件隔离、外部
    RAM

    ROM
    的隔离等。

    外围设备:

            初始化 DDR
    和时钟树。

            初始化外围引导设备接口。(SDCard

    eMMC

    NAND

    NOR

    USB

    OTG

            BL2 还集成了镜像验证和身份验证。通过调用
    BootROM
    验证服务来实现认证。

            在执行结束时,在加载 BL32
    和下一个引导阶段(
    BL33
    )之后,
    BL2
    跳至
    BL32

            BL32 提供运行时安全服务。在
    TF-A
    中,
    BL32
    的默认实现是
    SP-MIN
    解决方案。这一

    部分可以用可信任的
    OS
    或可信任的环境执行(例如
    OP-TEE
    )代替这种最小的实现。
    STM32MP1
    支持这两种解决方案(SP-MIN

    OP-TEE
    )。

    BL33
    加载
    u-boot
    并执行。

            a) U-boot

                    U-Boot 是用于 STM32 MPU
    平台的引导链的第二阶段引导加载程序(SSBL

                    它具有简单的命令行界面(CLI),允许用户通过串行端口控制台进行交互。

                    它提供脚本功能

                    加载 linux 内核并执行

                    初始化外部设备:例如:USB、
    eMMC
    、网卡

            b) linux

                    是一种开源的类 Unix 操作系统宏内核。整个
    Linux
    操作系统家族基于该内核部署在传统计算机 平台(如个人计算机和服务器,以 Linux
    发行版的形式)和各种嵌入式平台,如路由器、无线接 入点、专用小交换机、机顶盒、智能电视、数字视频录像机等。工作于平板电脑、智能手机及智 能手表的 Android
    操作系统同样通过
    Linux
    内核提供的服务完成自身功能。虽然桌面电脑的占有 率较低,但是基于 Linux
    的操作系统统治了几乎从移动设备到主机的其他全部领域。截至
    2017
    年 11 月,世界前
    500
    台最强的超级计算机全部使用
    Linux

    三、什么是U-Boot

            U-Boot 全称 Universal Boot Loader,是一款开源的、跨平台的嵌入式系统引导加载程序(Bootloader),也是嵌入式领域应用最广泛的 Bootloader 之一,你在 STM32MP1 上接触到的 U-Boot 就是其针对该异构多核平台的移植版本,它是嵌入式系统上电启动后,介于硬件裸机和操作系统内核之间的核心程序。

            简单来说,嵌入式设备(如 STM32MP1、嵌入式开发板、工业控制器等)没有 PC 的 BIOS/UEFI,U-Boot 就承担了类似 BIOS 的核心作用,同时功能更贴合嵌入式场景的定制化需求。

    3.1、核心定位

            嵌入式系统启动流程的关键中间层:上电后 CPU 先执行片内 ROM 中的固化引导程序(如 STM32MP1 的 ROM Boot),由其加载 U-Boot 到内存中运行;U-Boot 完成硬件初始化后,再加载 Linux/RTOS 内核、根文件系统等,最终将系统控制权交给内核,完成整个启动流程。

    3.2、U-Boot 的核心功能(贴合 STM32 开发场景)

  • 硬件底层初始化这是最基础的功能:上电后硬件处于裸机状态,U-Boot 会初始化核心硬件(CPU、内存 SDRAM/DDR、时钟、串口、MMC/SD/eMMC、NAND Flash 等),为后续加载内核搭建可用的硬件环境(比如你之前用mmc dev命令,前提是 U-Boot 已经初始化了 MMC 控制器)。
  • 加载并启动系统镜像从存储设备(MMC、NAND、SPI Flash、网络等)读取系统镜像(Linux 的 zImage/uImage、裸机程序、根文件系统 ramdisk 等),加载到指定的内存地址,并执行启动(这也是你之前接触的go/bootz/bootm命令的核心作用)。
  • 提供交互式命令行环境这是 U-Boot 的特色功能:启动后会进入串口命令行,支持各种操作命令(如 MMC 设备管理、内存读写、镜像烧写、网络下载、环境变量配置等),方便开发、调试和系统配置(比如你之前用到的mmc dev、go都是 U-Boot 命令行的常用命令)。
  • 环境变量管理支持自定义环境变量(如bootcmd启动命令、bootargs内核启动参数、mmcdev默认 MMC 设备号等),保存在非易失性存储中,无需修改 U-Boot 源码即可定制启动逻辑(比如设置bootcmd为mmc dev 1;bootz,即可实现上电自动从 eMMC 启动 Linux)。
  • 辅助开发 / 调试功能支持网络下载(tftp、nfs)、镜像烧写(将内核 / 文件系统烧写到 MMC/NAND)、内存查看 / 修改(md/mw 命令)、分区管理等,大幅降低嵌入式系统的开发和调试成本。
  • 3.3、U-Boot 的核心特点

    • 开源免费:基于 GPL 协议,可根据硬件平台自由移植和修改;
    • 跨平台:支持 ARM、x86、MIPS 等几乎所有嵌入式 CPU 架构,适配各种嵌入式硬件;
    • 可定制化:按需裁剪功能(比如仅保留 MMC 和串口功能,减小 U-Boot 镜像体积),适配资源受限的嵌入式设备;
    • 支持多种存储 / 网络:兼容嵌入式领域几乎所有的存储设备和网络协议。

    3.4、对 STM32MP1 开发的实际意义

            STM32MP1 是异构多核平台(A7 核 + M4 核),其 U-Boot 不仅完成 A7 核侧的硬件初始化、Linux 内核加载,还能实现对 M4 核的引导(加载 M4 核的 FreeRTOS / 裸机程序),是 STM32MP1 异构系统启动和调试的核心工具,你之前接触的 MMC 命令、启动命令,都是其在该平台上的具体应用。

            简单总结:U-Boot 是嵌入式系统的 “启动管家”,也是开发调试的 “便捷工具”,是嵌入式 Linux 开发(包括 STM32MP1)的必备基础。

    赞(0)
    未经允许不得转载:171主机测评 » 【系统移植】
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址