一、系统移植介绍:
嵌入式Linux系统移植是一个复杂但重要的过程,它涉及将Linux操作系统从一种硬件平台或环境迁移到另一种硬件平台或环境上,以确保Linux系统能够在新的嵌入式设备上正常运行。以下是对嵌入式Linux系统移植的详细介绍:
1、嵌入式Linux系统概述
嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可裁剪,适用于应用系统,对功能、可靠性、成本、体积、功耗等方面有特殊要求的专用计算机系统。嵌入式Linux系统作为其中的一种,因其稳定性、可靠性、安全性和灵活性等优点,在嵌入式领域得到了广泛应用。
2、嵌入式Linux系统移植的必要性
由于嵌入式设备的硬件环境与传统计算机存在显著差异,直接将Linux操作系统应用于嵌入式设备往往无法正常工作。因此,需要进行系统移植,对Linux进行适配和优化,以确保其能够在新硬件上正常运行。
3、嵌入式Linux系统移植的步骤
嵌入式Linux系统移植主要包括以下几个步骤:
- 搭建交叉编译环境:
- 在PC上安装适用于目标平台的交叉编译器,并将其添加到环境变量中。
- 交叉编译器允许在一种平台上编译出可在另一种平台上运行的程序。
- BootLoader的选择和移植:
- BootLoader是操作系统内核运行之前运行的一段小程序,用于初始化硬件设备、建立内存空间映射等。
- 常见的BootLoader有U-Boot等,需要根据目标硬件选择合适的BootLoader并进行移植。
- 内核的配置、编译和移植:
- 使用make menuconfig等工具对Linux内核进行配置,以满足嵌入式设备的特定需求。
- 编译内核,生成可在目标硬件上运行的内核镜像。
- 将内核镜像下载到目标硬件上,并进行调试以确保其能够正常启动和运行。
- 根文件系统的制作:
- 根文件系统是Linux系统启动后挂载的第一个文件系统,包含了系统运行所需的基本文件和目录。
- 需要根据目标硬件和需求选择合适的根文件系统,并制作相应的镜像文件。
- 设备驱动程序的移植和调试:
- 设备驱动程序是操作系统与硬件之间的接口,负责控制和管理硬件设备。
- 需要根据目标硬件编写或移植相应的设备驱动程序,并进行调试以确保其能够正常工作。
4、嵌入式Linux系统移植的注意事项
- 硬件兼容性:
- 在进行系统移植前,需要确保Linux内核和目标硬件之间的兼容性。
- 不同的硬件平台可能需要不同的内核配置和驱动程序支持。
- 性能优化:
- 嵌入式设备通常对性能有较高要求,因此需要对Linux系统进行优化以满足需求。
- 可以通过裁剪不必要的内核模块、优化内核参数等方式来提高系统性能。
- 安全性考虑:
- 嵌入式设备往往应用于关键领域,因此需要考虑系统的安全性问题。
- 可以通过启用内核的安全特性、加强系统访问控制等方式来提高系统的安全性。
——————————————————————————————————————————
二、FLASH内存映射
启动加载器 (Bootloader):系统启动的第一阶段是启动加载器的运行。在你的配置中,有两个级别的 启动加载器:第一级 (FSBL) 和第二级 (SSBL)。这些启动加载器负责加载和运行更高级别的启动加载器,以及最终加载内核和文件系统。
内核 (Kernel):内核是操作系统的核心,它负责管理硬件资源、进程管理、文件系统等。在配置中, 内核文件通常被放置在 bootfs 或者 rootfs 中。内核必须能够正确地加载和解释设备树 (Device Tree)。
设备树 (Device Tree):设备树是一种描述硬件的机制,使内核能够根据硬件的不同配置进行正确的初 始化。在你的配置中,设备树文件可能会附加在启动加载器 (ssbl 或 fsbl) 后面,作为启动加载器的一部分。
文件系统:不同的分区被用来存放不同类型的文件系统。userfs、rootfs、vendorfs 等都是不同类型的文 件系统,存放着用户数据、Linux 根文件系统以及第三方专有文件等。
tf-a:TF-A的主要目的就是提供安全启动环境。
——————————————————————————————————————————
三、Linux系统的启动流程
标准 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 启动流程
一、启动准备
STM32MP1内部包含一段ROM(只读存储器),这段ROM空间不开放给用户使用,仅供ST存放自己编写的ROM代码。ROM空间在A7内核(CA7)中有128KB,起始地址为0x00000000。STM32MP157还有三个BOOT引脚(BOOT0-BOOT2),这些引脚通过拉高/拉低电平来控制从何种设备启动。
二、上电后ROM代码执行
- 读取BOOT引脚电平:
- 上电后,STM32MP1首先运行ROM代码。ROM代码会读取BOOT0-BOOT2三个引脚的电平,根据电平组合判断启动模式。
- 确定启动模式:
- 根据BOOT引脚电平的不同组合,STM32MP1可以从多种设备启动,如EMMC、SD卡、NAND、NOR、USB、UART等。
三、启动模式选择
STM32MP1的ROM代码支持多种启动模式,包括但不限于以下几种:
- 安全启动(Secure Boot):
- 当设置好拨码盘,选择从外部闪存设备启动时,会进入安全启动模式。ROM代码从选定的闪存设备中加载FSBL(First Stage Boot Loader,第一阶段启动文件)镜像文件,并进行鉴权。鉴权成功后,跳转到FSBL镜像的入口地址开始运行。
- 开发者模式启动(Engineering Boot):
- 当BOOT2~BOOT0设置为特定组合(如100)时,可以通过ST-LINK访问A7或M4内核,一般用于调试M4内核代码。
- 第二内核启动(Secondary Core Boot):
- 复位后,STM32MP1的每个A7内核都会启动,但ROM代码会分离执行流,只有Core0会运行ROM代码,另一个内核会处于死循环状态,等待应用程序发送信号进行下一步操作。
- 串行启动(Serial Boot):
- 包括USB启动和UART启动。ROM代码会搜索所有可用的UART和USB OTG接口,当扫描到活动的串口后,就使用此接口启动。
四、FSBL和SSBL阶段
- FSBL阶段:
- FSBL镜像文件一般是TF-A镜像或A7裸机代码,用于初始化时钟树和外部RAM控制器(DDR)。FSBL会将SSBL(Second Stage Boot Loader,第二阶段启动文件)加载到DDR中并运行。
- SSBL阶段:
- SSBL通常是U-Boot,负责启动Linux内核。SSBL将Linux内核加载到DDR上并运行,同时使能USB、网络、显示等外设。
五、Linux内核启动
- Linux内核启动后,会进行内核的初始化,包括各种外设的初始化。
- 接着挂载根文件系统(rootfs),初始化根文件系统内的各种框架和服务。
- 最后,系统通过init进程切换到用户空间,用户可以通过图形界面或命令行界面登录系统。
——————————————————————————————————————————
五、硬件资源:
FS-MP1A开发板
1、FS-MP1A是基于ST(意法半导体)公司的STM32MP1系列微处理器而设计的开发板, 该系列处理器提供了集成 Arm® Cortex®-A7 和 Cortex®-M4 两种内核的异构架构,在实现高 性能且灵活的多核架构以及图像处理能力基础上,还能保证低功耗的实时控制和高功能集成 度。FS-MP1A 开发板采用该系列中性能与资源最丰富STM32MP157AAA3 芯片,双核 ARM Cortex-A7/@650MHz 处理性能、3D GPU 及 MIPI 接口是区别于该系列其它产品的主要性能 差异。
2、提供 Arm®双核 ARM Cortex A7/ 650MHz 和 Cortex®-M4/ 209MHz 两种内核的异构架构 开发,在复杂的多任务处理与运算同时,兼顾硬实时性。
3、FS-MP1A 主板还配套了一块资源扩展板。该扩展板 I2C 总线挂 载了空气温湿度传感器、心率血氧传感器、环境光\接近传感器,SPI 总线挂载了数码管驱动芯片,基于 ADC 的电流、电压检测电路,基于 PWM 脉冲调制的风扇、震动马达,还有常用的 3 颗用户自定义的 LED 指示灯,3 路用户自定义按键,人体红外传感器,光电开关、火焰检测传感器,此外还对外引出了 CAN 总线和 RS485 总线。
——————————————————————————————————————————
六、软件资源
1、安全引导程序:TF-A(第一引导阶段)
在系统移植中,TF-A(Trusted Firmware-A)扮演着至关重要的角色。TF-A的主要目的就是提供安全启动环境。TF-A是一个基于ARM架构的可信固件,它为系统提供了安全的启动环境,并确保从硬件启动到操作系统加载的整个过程中,系统的安全性和完整性得到保护。
一、TF-A的作用
- 安全启动:TF-A负责系统的初步硬件初始化和安全启动流程,确保只有经过验证的软件才能被执行。
- 硬件抽象:它提供了一个硬件抽象层,使得操作系统能够更容易地与底层硬件交互。
- TrustZone支持:在支持TrustZone的设备上,TF-A负责设置安全世界和非安全世界的边界,确保敏感操作在安全的环境中执行。
二、TF-A的移植步骤
- 准备工作
- 下载TF-A的源码,通常可以从ARM官方网站或半导体厂商提供的资源中获取。
- 准备交叉编译工具链,确保能够为目标硬件平台编译代码。
- 源码解压与配置
- 解压TF-A源码,并阅读相关的README文件和文档,了解编译和配置的要求。
- 根据目标硬件平台的特性,修改Makefile.sdk或其他配置文件,设置交叉编译工具链和编译选项。
- 源码打补丁
- 如果半导体厂商提供了针对特定硬件的补丁文件,需要将这些补丁应用到TF-A源码中。
- 补丁文件通常包含了对源码的修改或新增配置信息,以适配特定的硬件平台。
- 设备树配置
- 修改设备树(Device Tree)文件,以反映目标硬件平台的硬件配置。
- 设备树是一种数据结构,用于描述硬件组件之间的连接和配置信息。
- 编译TF-A
- 使用修改后的Makefile.sdk文件编译TF-A源码。
- 编译成功后,会生成TF-A的镜像文件(如BL1、BL2等),这些文件将被用于启动目标硬件平台。
- 烧录与测试
- 将TF-A的镜像文件烧录到目标硬件平台的存储介质中(如SD卡、eMMC等)。
- 重新启动硬件平台,验证TF-A是否能够正确加载并启动操作系统。
三、注意事项
- 硬件兼容性:在移植TF-A之前,需要确保目标硬件平台与TF-A的兼容性。这包括处理器架构、外设支持等方面。
- 安全性考虑:TF-A的主要目的是提供安全启动环境,因此在移植过程中需要特别注意安全性问题。例如,确保所有敏感操作都在安全世界中执行,并防止未经验证的代码被执行。
- 调试与测试:在移植过程中可能会遇到各种问题,如启动失败、硬件初始化错误等。因此,需要充分利用调试工具和测试手段来定位和解决问题。
2、Bootloader:Uboot(第二引导阶段)
Bootloader
Bootloader,称为引导加载程序,是嵌入式系统加电后运行的第一段代码,其作用相当于PC机的BIOS。Bootloader在操作系统内核或用户应用程序运行之前执行,主要负责对硬件进行相应的初始化和设定,为操作系统准备好环境。以下是对Bootloader的详细解析:
一、Bootloader的基本概念
- 定义:Bootloader是系统加电启动后运行的第一段软件代码,通过这段代码,我们可以初始化硬件设备、建立内存空间的映射,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
- 依赖性:Bootloader严重依赖于硬件而实现,特别是在嵌入式系统中。因此,在嵌入式领域建立一个通用的Bootloader几乎是不可能的。Bootloader的实现依赖于CPU的体系结构,同时也依赖于嵌入式系统板级设备的配置。
二、Bootloader的主要功能
- 初始化硬件设备:在系统上电或复位后,Bootloader首先会进行硬件设备的初始化,包括CPU、内存、外设等。
- 建立内存空间映射:Bootloader会建立内存空间的映射图,使得CPU能够正确地访问内存和外设。
- 加载程序:Bootloader负责将非易失性存储器(如Flash、ROM等)中的特定软件(如操作系统内核、根文件系统映像等)拷贝到RAM中,并运行它们。
三、Bootloader的启动模式
大多数Bootloader都包含两种不同的操作模式:“启动加载”模式和“下载”模式。
- 启动加载模式:也称为“自举”(Autonomous)模式。在这种模式下,Bootloader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程没有用户的介入。这是Bootloader的正常工作模式,在嵌入式产品发布时,Bootloader必须工作在这种模式下。
- 下载模式:在这种模式下,目标机上的Bootloader会通过串口连接或网络连接等通信手段从主机下载文件(如内核映像、根文件系统映像等)。这种模式通常在系统更新或首次安装内核与根文件系统时被使用。
四、Bootloader的启动过程
Bootloader的启动过程通常分为两个阶段(stage1和stage2),特别是在嵌入式系统中。
- stage1:这一阶段通常使用汇编语言编写,以实现短小精悍的目的。它主要负责硬件设备的基本初始化、为加载Bootloader的stage2准备RAM空间、拷贝Bootloader的stage2到RAM空间中、设置好堆栈,并跳转到stage2的C入口点。
- stage2:这一阶段则通常使用C语言编写,以实现更复杂的功能。它主要负责初始化本阶段要使用的硬件设备、检测系统内存映射、将内核映像和根文件系统映像从Flash等存储设备上读到RAM空间中,并最终调用内核。
——————————————————————————————————————————