1 RK3568框图
阅读模块框图能够帮我快速建立整体系统框架。我个人理解是懂得越多,你面对一个系统框图越能快速的绘制出它的整个神经脉络,掌握系统的数据流图。
- 访问地址:https://www.rock-chips.com/uploads/pdf/2022.8.26/191/RK3568%20Brief%20Datasheet.pdf
- 硬件IP
- 处理器相关
- CPU
- NPU
- Multi-Media Process:VPU,ISP,GPU
- 高速外设
- 低速外设
- 高速存储
- 处理器相关
- 总线
- AXI:高速高带宽设备接入到AXI矩阵中
- AXI Lite:寄存器配置数据流接入到AXI Lite总线
- AXI to AHB Bridge:AHB总线协议
- AXI to APB Bridge:APB总线协议
2 启动顺序
- 基本概念概述
- U-Boot,TPL,SPL
- U-Boot:嵌入式系统的开源引导加载程序,负责在芯片上电后初始化硬件设备(尤其是DDR内存)并加载启动操作系统内核。由于太大,无法被BootROM一次性加载,于是分成了多级boot,包括TPL,VPL,SPL
- TPL:Tertiary Program Loader。作用是初始化DDR内存
- VPL:Verifying Program Loader。作用是运行安全启动流程
- SPL:Secondary Program Loader。作用是初始化硬件,并加载U-Boot
- ddr.bin:在RK中,指的是TPL
- miniloader.bin:在RK中,指的是SPL
- MiniLoaderAll.bin:在RK中,是TPL + SPL
- U-Boot,TPL,SPL
- 存储器角度
BootROM -> SRAM(TPL) -> SRAM(SPL) -> DDR(Uboot) -> DDR(Kernel)- 镜像角度
Maskrom -> Pre-loader -> Trust -> U-Boot -> Kernel- 镜像角度:next-dev版本,MiniloaderAll.bin = TPL + SPL
BootROM -> TPL(ddr.bin) -> SPL(miniloader.bin) -> U-Boot -> Kernel- 镜像角度:rkdevelop版本
BootROM -> ddr.bin -> miniloader.bin -> U-Boot -> Kernel3 目录
- BootROM启动:负责加载TPL - TPL:开源U-Boot中的功能,主要功能是DDR初始化。运行在SRAM中。闭源版本是RK提供的rkxxx_ddr_xxMHz_Version.bin;开源版本在编译U-Boot源码版本是生成 - SPL:开源U-Boot中的功能,主要功能是加载和引导trust/U-Boot两个模块。运行在DDR中, - Uboot - Kernel4 BootROM启动
- 关键概念概述
- BootROM:存储RK3568芯片上电后执行的第一个程序。硬件设计强制CPU从0xFFFF000读取第一条指令。CPU通过AXI总线访问BootROM
- 0xFFFF0000:在Address Mapping小节中提到,0xFFFF0000可以被两个SRAM重映射 - PMU_SRAM(使用在低功耗场景下运行一些程序)和SYSTEM_SRAM。刚上电的时候,默认的状态是BootROM被映射到0xFFFF0000
- ID BLOCK
- Identification Block,对应固件idbloader.img
- 是瑞芯微RK全系列芯片专属的一级引导头+预加载程序块
- 是BootROM识别合法启动固件的唯一标识载体
- 包含魔数,固件校验和,芯片平台,安全启动签名
- 地址映射
- 虚拟地址:MMU启动后,CPU访问的是虚拟地址
- 物理地址:MMU启动前,CPU直接使用物理地址访问BootROM、SRAM等
- 启动方式
- 存储遍历加载镜像: SPI NOR Flash -> SPI NAND Flash -> NAND Flash -> eMMC -> SD卡
- USB OTG下载镜像执行方式
- RK3568 BootROM执行流程图
- 访问地址:https://opensource.rock-chips.com/images/2/26/Rockchip_RK3568_TRM_Part1_V1.3-20220930P.PDF
- 启动流程概述
- CPU上电,从0xFFFF0000读取第一条指令去运行
- 按照SPI NOR Flash -> SPI NAND Flash -> NAND Flash -> eMMC -> SD卡的顺序读取ID BLOCK,并校验
- 校验通过,按顺序读取镜像并运行:加载SDRAM初始化镜像,加载DDR初始化镜像,加载boot镜像
4.1 ID Block:idblock.bin,idbloader.img
4.1.1 ID Block的组成: 结合源码说明
- 打包脚本: u-boot\make.sh
./tools/mkimage -n ${PLAT} -T rksd -d ${TPL_BIN}:${SPL_BIN} idblock.bin- uboot\tools\mkimage: u-boot\tools\mkimage.c
- Rockchip四种镜像:主要是头部信息不同
- IH_TYPE_RKIMAGE: mkimage.c中没有涉及
- IH_TYPE_RKSD: SD/MMC卡启动镜像
- IH_TYPE_RKSPI: SPI Flash启动镜像
- IH_TYPE_RKNAND: NAND Flash启动镜像
- 不同的存储介质特性对应不同的镜像文件
- 填写头部数据
- 根据存储器特性填写bin文件数据
- Rockchip四种镜像:主要是头部信息不同
- RKSD: idblock.bin = tpl.bin + spl.bin
- 数据分布:2KB头部 + TPL + SPL
- 2KB头部:存在不同版本的差异。头部记录魔数,引导程序的位置等信息
- 写入TPL数据:2KB对齐填充
- 写入SPL数据:2KB对齐填充
- 尾部填充
struct image_entry { uint32_t size_and_off; //大小和扇区位置 uint32_t address; uint32_t flag; uint32_t counter; uint8_t reserved[8]; uint8_t hash[64]; //哈希值 }; struct header0_info_v2 { uint32_t magic; //魔数 uint8_t reserved[4]; uint32_t size_and_nimage; //镜像数和 uint32_t boot_flag; uint8_t reserved1[104]; struct image_entry images[4]; //镜像入口信息 uint8_t reserved2[1064]; uint8_t hash[512]; }; struct header0_info { uint32_t magic; uint8_t reserved[4]; uint32_t disable_rc4; uint16_t init_offset; uint8_t reserved1[492]; uint16_t init_size; uint16_t init_boot_size; uint8_t reserved2[2]; };4.2 TPL:Tertiary Program Loader
- 开源:集成在U-Boot源码中
- 闭源:RK3568以ddr.bin的二进制文件形式提供
4.3 SPL:Secondary Program Loader
- 开源:集成在U-Boot源码中
- 闭源:RK3568以spl.bin的二进制文件形式提供
4.4 BootROM启动总结
- BootROM(32KB)的作用是在存储器中加载TPL到SRAM(64KB)中运行
- TPL的作用是初始化DDR内存,解决SRAM空间不足无法运行SPL或U-Boot问题
- 为什么不直接在Flash中运行,比如NOR Flash:因为慢,效率低;因为性价比低(容量小,价格高)
- SPL的作用是完成U-Boot运行前的硬件初始化工作,加载U-Boot到DDR内存中,并将控制权移交给它
- U-Boot的作用是准备Kernel运行的硬件环境,加载Kernel到内存中运行
5 TPL:DDR初始化
- uboot源码仓库:https://github.com/rockchip-linux/u-boot.git5.1 DDR内存:基于物质基础分析
- DDR内存组成:DDR3/DDR3L/DDR4,LPDDR3/LPDDR4/LPDDR4X
- 外部引脚
- 数据:输入,输出
- 地址/命令
- 控制
- 时钟
- 校准
- 电源
- 详细信息
- 类型:DDR3/DDR3L/DDR4,LPDDR3/LPDDR4/LPDDR4X
- 频率:内存芯片内部时钟的实际运行频率
- 通道信息:一个独立的完整数据通道包含自己的数据、地址、命令和控制信号
- 总线数据位宽
- 行数量:每个Bank内部,存储单元按行和列排列成一个矩阵。寻址一个存储单元需要先指定行,再指定列
- 列数量:行地址和列地址分时复用同一组地址信号线
- bank数量:DDR颗粒内部被划分为多个独立的存储块,可以并行访问以提高速率
- 片选数量:选择当前于控制器通信的特点颗粒或颗粒组
- 单颗颗粒的数据位宽:每个颗粒一次能输入/输出的数据位数
- 单个通道的DDR总容量
- 外部引脚
5.2 DMC:DDR内存控制器,集成在SoC上
/*DDR性能监控模块:DFI(DDR Performance Monitor)*/ dfi: dfi@fe230000 { reg = <0x00 0xfe230000 0x00 0x400>; compatible = "rockchip,rk3568-dfi"; rockchip,pmugrf = <&pmugrf>; status = "disabled"; }; /*频率属性是可操作性最高的属性*/ dmc: dmc { compatible = "rockchip,rk3568-dmc"; interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = "complete"; devfreq-events = <&dfi>, <&nocp_cpu>; clocks = <&scmi_clk 3>; clock-names = "dmc_clk"; operating-points-v2 = <&dmc_opp_table>; vop-bw-dmc-freq = < ... >; vop-frame-bw-dmc-freq = < ... >; cpu-bw-dmc-freq = < ... >; upthreshold = <40>; downdifferential = <20>; system-status-level = < ... >; auto-min-freq = <324000>; auto-freq-en = <1>; #cooling-cells = <2>; status = "disabled"; }; /*FSP(Frequency Scaling Policy,频率缩放策略),定义不同频率下的时序参数*/ dmc_fsp: dmc-fsp { compatible = "rockchip,rk3568-dmc-fsp"; debug_print_level = <0>; ddr3_params = <&ddr3_params>; ddr4_params = <&ddr4_params>; lpddr3_params = <&lpddr3_params>; lpddr4_params = <&lpddr4_params>; lpddr4x_params = <&lpddr4x_params>; status = "okay"; }; /*定义DDR可用的频率和电压的组合*/ dmc_opp_table: dmc-opp-table { compatible = "operating-points-v2"; mbist-vmin = <825000 900000 950000>; nvmem-cells = <&log_leakage>, ... ; ... /* RK3568 dmc OPPs */ opp-1560000000 { opp-supported-hw = <0xf9 0xffff>; opp-hz = /bits/ 64 <1560000000>; opp-microvolt = <900000 900000 1000000>; ... }; opp-j-m-1560000000 { opp-supported-hw = <0x06 0xffff>; opp-hz = /bits/ 64 <1560000000>; opp-microvolt = <875000 875000 1000000>; }; ... };5.3 DDR初始化:都做了哪些工作
提示词:请分别从物质决定意识的哲学角度和电子信息角度,介绍DDR初始化都做了哪些工作- 物质决定意识:物质是第一性,意识是第二性
- 物质世界
- DDR颗粒
- PCB走线: 走线长度差
- DMC
- 供电: 电源波纹
- 时钟
- 阻抗
- 意识世界
- DDR初始化程序
- DDR初始化程序的所有操作都是适配硬件物质,通过可编程的逻辑去拟合不可编程的物理链路,将模式世界混沌转变为数字世界的确定性
- 物质世界
- 上电、供电稳定与硬件复位
- 阻抗匹配、VTT端接、时钟训练
- 物质世界
- PCB走线存在寄生电容、寄生电阻、传输效应
- DDR差分时钟、地址数据线高速传输会产生信号反射、串扰、时序偏移
- VTT分压电阻、终端电阻是固定硬件物质
- 不同内存插槽,不同批次DDR颗粒的驱动能力,输入电容存在客观差异
- 意识世界
- ZQ校准(对抗物理离散性):芯片温度上升导致电阻变化, 驱动能力下降,ZQ校准周期性执行;DDR内部有一个可变电阻阵列, 会对外部240欧姆精密参考电阻, 通过逐次逼近调整输出驱动器的阻抗,对抗芯片制造工艺的偏差和实时温度变化,保证输出高/低电平的电压幅值在标准范围内
- CLK时钟训练:解决走线不等长造成的时钟相位偏移;解决信号反射、衰减导致的采样窗口变窄
- DQS数据选通同步训练:写通路,控制器内部增加延迟,控制DDR端CLK上升沿与DQS边沿精准对齐;读通路,调整控制器内部采样窗口延迟,在DQS眼图最开阔位置抓取DQ数据,保证读写采样裕量
- Write Leveling:补偿 CPU 内存控制器到 DDR 颗粒之间 CLK 时钟与 DQS 数据选通线的走线长度差。
- 物质世界
- 模式寄存器 MRS 配置
- 物质世界
- MRS 是 DDR 颗粒内部的硬件寄存器,存储时序、突发长度、CL/CWL、电压模式、自刷新、读写驱动强度等核心参数
- 意识世界
- 初始化代码发送 MRS 指令,往颗粒内置硬件寄存器写入时序、频率、突发长度、刷新周期等配置值
- 据读取到的 SPD 芯片(硬件存储介质,物质)内固化的厂商参数,自动匹配合规时序
- 物质世界
- Read Leveling & Eye Training
- MRS 写入 CL/CWL、驱动强度、突发长度等基础时序后,才能发起读写测试波形
- 意识世界
- Read Leveling:调整 DQS 采样延迟,匹配内存颗粒回传数据与控制器采样时钟的相位
- Eye Training(眼图训练):精细化扫描采样窗口,找出信号最干净、无串扰反射的采样点,最大化时序裕量
- 行 / 列寻址、Bank、Rank 拓扑初始化
- 物质世界
- DDR 内部由 Bank 阵列、行存储单元、列电容阵列组成物理硬件结构
- 多内存条构成多 Rank、多通道拓扑,通道间走线长度、颗粒数量是 PCB 与内存条固定的物质布局
- 意识世界
- 初始化代码读取 SPD 识别 Rank 数量、Bank 数量、行列地址位数,配置内存控制器地址译码逻辑
- 配置周期性自刷新周期,补偿电容漏电的物理缺陷
- 划分通道独立控制逻辑,匹配多内存条硬件拓扑
- 物质世界
- 内存自检、ECC 初始化、地址掩码校验
- 物质世界
- 存储电容存在漏电、高低温下晶体管出错、数据线存在随机干扰,硬件物质本身存在出错可能性
- ECC 内存额外带校验存储颗粒
- 意识世界
- 初始化执行内存读写遍历测试:向全部物理存储单元写入测试数据,再读出对比,检测硬件单元损坏
- 若为 ECC 内存,初始化启用校验硬件通路,配置纠错逻辑
- 设置地址掩码,屏蔽硬件损坏的存储块
- 物质世界
- 关闭初始化、开放内存地址空间
- 所有电气、时序、寻址、校验参数匹配硬件物质特性后,内存控制器退出初始化流程,把 DDR 物理存储地址映射给 CPU 系统总线,操作系统即可读写内存硬件
5.4 TPL源码:以RK3568为例
- 源码位置
- u-boot\arch\arm\mach-rockchip\tpl.c
- 执行流程
BootROM 启动 │ ▼ board_init_f() ← TPL 入口 │ ├── rockchip_stimer_init() ── 初始化系统定时器 ├── arch_cpu_init() ── CPU 初始化(空,可覆盖) ├── debug_uart_init() ── 初始化调试串口 ├── 打印 TPL 版本信息 ├── spl_early_init() ── SPL 早期初始化(DM) ├── timer_init() ── ARM 架构定时器 ├── DRAM 初始化 ── 初始化 DDR 内存 │ ├── [DM模式] uclass_get_device(UCLASS_RAM) │ └── [精简模式] sdram_init() │ ▼ back_to_bootrom(BROM_BOOT_NEXTSTAGE) ── 返回 BootROM 加载 SPL │ ▼ SPL 阶段启动- uclass_get_device
- 通过device_probe完成硬件初始化
- 从设备树中获取DMC节点,根据节点中的参数完成DRAM初始化
- sdram_init:u-boot\arch\arm\mach-rockchip\rk3066\sdram_rk3066.c
sdram_init():DMC控制器初始化 │ ├── ① 频率检查 ├── ② 设置 DDR 时钟:clk_set_rate() ├── ③ PHY + 控制器复位:phy_pctrl_reset() ├── ④ DLL 旁路配置(按频率):phy_dll_bypass_set(),根据频率配置DLL(延迟锁定环)旁路。DDL的作用是生成精确的、与时钟同步的时序信号。 ├── ⑤ DFI 接口配置:dfi_cfg(),配置 DFI (DDR PHY Interface)接口 ├── ⑥ 控制器时序配置:pctl_cfg(),配置控制器时序 ├── ⑦ PHY 参数配置:phy_cfg() ├── ⑧ PHY 初始化触发:phy_init() ├── ⑨ DDR 上电: ├── ⑩ DRAM 初始化序列:memory_init() ├── ⑪ 切换到 CONFIG 状态:move_to_config_state() ├── ⑫ 设置初始参数(32bit/双Rank/ZQ):32bit 位宽、双 Rank、ZQ 校准参数 ├── ⑬ Rank + 位宽自动检测:自动检测 Rank 和位宽 ├── ⑭ 切换到 ACCESS 状态:move_to_access_state(),切换到访问状态 ├── ⑮ 行列地址自动检测:sdram_col_row_detect() ├── ⑯ NIU 配置表查找:sdram_get_niu_config() └── ⑰ 写入全局配置到 PMU:dram_all_config()6 SPL:Secondary Program Loader
- 物质决定意识
- 物质世界
- DDR内存
- CPU
- 存储外设:eMMC/SD,NAND,SPI Nor/NAND
- 意识世界
- 完成最小硬件初始化,把U-Boot加载到内存中,安全启动链
- 如果编译过程中没有定义TPL,则SPL会完成DDR的初始化
- 物质世界
- 编译配置
- 基础支持
- CONFIG_SPL_LIBCOMMON_SUPPORT
- CONFIG_SPL_LIBGENERIC_SUPPORT
- CONFIG_SPL_SERIAL_SUPPORT
- CONFIG_SPL_DRIVERS_MISC_SUPPOR
- CONFIG_SPL_LIBDISK_SUPPORT
- CONFIG_SPL_BOARD_INIT
- CONFIG_SPL_SEPARATE_BSS
- 内存与存储介质支持
- CONFIG_SPL_NAND_SUPPORT
- CONFIG_SPL_SPI_FLASH_SUPPORT
- CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
- CONFIG_MTD
- 镜像格式与加载方式支持
- CONFIG_FIT
- CONFIG_SPL_RAW_IMAGE_SUPPORT is not set:禁用RAW镜像,也就是无头的,纯二进制指令和代码
- CONFIG_SPL_LEGACY_IMAGE_SUPPORT is not set
- 安全启动与校验
- CONFIG_SPL_SHA256_SUPPORT
- CONFIG_SPL_CRYPTO_SUPPORT
- CONFIG_SPL_HASH_SUPPORT
- CONFIG_SPL_ATF
- CONFIG_FIT_HW_CRYPTO
- CONFIG_SPL_FIT_HW_CRYPTO
- DDR内存相关
- CONFIG_DM_DMC
- CONFIG_ROCKCHIP_DMC_FSP
- CONFIG_RAM
- CONFIG_SPL_RAM
- CONFIG_TPL_RAM
- CONFIG_ROCKCHIP_SDRAM_COMMON
- CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE=0:DDR初始化已经由TPL完成
- 调试与优化
- 基础支持
- 功能分析
- 管理DDR内存
- 加载并校验UBoot
- 加载并校验ATF(安全固件)
6.1 板级SPL源码:u-boot\arch\arm\mach-rockchip\spl.c
- 执行流程
board_init_f() ← SPL 入口 │ ├── ① 保存启动标志 ├── ② 初始化系统定时器 ├── ③ 初始化调试串口 ├── ④ 记录启动 tick ├── ⑤ PCIe EP 初始化(可选) ├── ⑥ SPL 早期初始化 (DM/控制台) ├── ⑦ [无 TPL] DRAM 初始化 ├── ⑧ 控制台初始化 ├── ⑨ BootROM 下载模式检测 ├── ⑩ CPU 初始化 ├── ⑪ 板级初始化 ├── ⑫ [PCIe] 获取固件 └── ⑬ 返回 BootROM 加载下一阶段 │ ▼ SPL 框架继续执行 → spl_boot_device() 确定启动源 → 加载镜像 → spl_board_init() ├── 点亮 LED ├── 板级特定初始化 └── [可选] 返回 BootROM → spl_next_stage() 决策 ├── SPL_NEXT_STAGE_KERNEL → 直接启动内核 └── SPL_NEXT_STAGE_UBOOT → 加载 U-Boot → spl_board_prepare_for_jump() ├── 写入回滚版本到 OTP └── 硬件解压缩清理 → 跳转到下一阶段- 关键模块
- 下一阶段决策
- spl_rockchip_dnl_key_pressed():检测音量上键是否按下,用于强制进入下载模式
- spl_is_low_power():通过 Fuel Gauge(电量计)检测电池电压是否过低
- spl_next_stage():决定 SPL 的下一阶段是 U-Boot(普通启动)还是直接启动 Kernel(快速启动)
- 音量上键按下:强制进入 U-Boot(可用于刷机)
- 电量过低:低电量时进入 U-Boot 处理
- BOOT_COLD/PANIC/WATCHDOG/NORMAL/RECOVERY:冷启动、Panic 后重启等场景,直接启动内核
- 其他启动模式:REBOOT_FLAG未设置,直接启动内核;REBOOT_FLAG已设置,进入U-Boot
- 分区选择:spl_kernel_partition()
- 从 MISC 分区读取 BCB(Bootloader Control Block)消息
- 若BCB命令为“boot-recovery",返回PART_RECOVERY恢复分区
- 否则根据启动模式寄存器的值判断是从恢复分区启动还是普通分区启动
- FIT 回滚保护
- 下一阶段决策
6.2 通用SPL源码:u-boot\common\spl\spl.c
- 规定了 SPL 的标准执行流程:初始化 → 获取启动设备 → 加载镜像 → 跳转 - 定义了大量的 __weak函数接口,供板级代码实现 - 实现了镜像解析、加载、跳转的通用逻辑- 执行流程
board_init_f() (板级) │ └── spl_early_init() └── spl_common_init(true) ├── spl_dcache_enable() ← 模块6 ├── bootstage_init() ← 模块7 ├── fdtdec_setup() ← 模块7 └── dm_init_and_scan() ← 模块7 └── spl_setup_relocate() ← 模块8 board_init_r() (板级 → 此文件的 board_init_r) │ ├── spl_initr_dm() ← 模块11 ├── spl_set_bd() ← 模块9 ├── 完整 malloc 初始化 ├── spl_init() ← 模块9 ├── timer_init() ├── spl_board_init() │ ├── board_boot_order() ← 模块10 ├── spl_next_stage() ← 模块1 │ ├── boot_from_devices() ← 模块10 │ ├── spl_ll_find_loader() ← 模块10 │ └── spl_load_image() ← 模块10 │ └── loader->load_image() │ ├── spl_perform_fixups() ← 模块1 │ └── 跳转分支 ├── IH_OS_U_BOOT → jump_to_image_no_args() ├── IH_OS_ATF → spl_invoke_atf() ├── IH_OS_OPTEE → spl_optee_entry() └── IH_OS_LINUX → jump_to_image_linux() 跳转前 spl_cleanup_before_jump() ← 模块16 ├── spl_board_prepare_for_jump() ├── disable_interrupts() ├── icache_disable() / dcache_disable() └── 打印启动耗时- 关键模块
- SPL地址空间:u-boot\include\configs\rk3568_common.h
- CONFIG_SPL_TEXT_BASE:0x00000000
- CONFIG_SPL_MAX_SIZE:0x00040000
- CONFIG_SPL_BSS_START_ADDR:0x03fe0000
- CONFIG_SPL_STACK:0x03fe0000
- CONFIG_SYS_INIT_SP_ADDR:0x00c00000
- CONFIG_SYS_LOAD_ADDR:0x00c00800
- 把栈空间从SRAM搬到DRAM:spl_relocate_stack_gd()
- board_init_f()在SRAM的栈中运行
- board_init_r()需要更多的栈空间(比如MMC子系统),于是搬移到SDRAM中
- 镜像加载:boot_from_devices
- U-Boot镜像加载地址
- FIT镜像:CONFIG_SPL_LOAD_FIT_ADDRESS
- RAW镜像:CONFIG_SYS_TEXT_BASE
- Legacy格式镜像:image_get_load(),从镜像头中读取
- Linux内核镜像加载地址
- CONFIG_SYS_LOAD_ADDR
- 镜像加载驱动
- spl_boot_list记录了可以启动的设备列表:BOOT_DEVICE_MMC1(eMMC),BOOT_DEVICE_MMC2(SD卡),BOOT_DEVICE_SPI(SPI Flash)
- 根据设备类型,获取对应的加载镜像的驱动,调用驱动完成镜像加载:获取加载地址,设备树地址,程序入口地址
- U-Boot镜像加载地址
- 跳转路径
- U-Boot
- ATF:通过ATF再跳转U-Boot
- OP-TEE:通过OP-TEE跳转到U-Boot或Kernel
- Kernel
- SPL地址空间:u-boot\include\configs\rk3568_common.h
U-Boot
- 关键函数:board_init_f()和board_init_r() - 指导文档:Rockchip_Developer_Guide_UBoot_Nextdev_CN.pdf参考博文
- 存储角度理解启动流程
- https://blog.csdn.net/weixin_43390831/article/details/163141252?spm=1011.2415.3001.5331
- TPL,SPL,UBoot实战
- https://blog.csdn.net/weixin_43390831/article/details/163174044?spm=1011.2415.3001.5331
- UBoot实战
- https://blog.csdn.net/weixin_43390831/article/details/163573548?spm=1011.2415.3001.5331
Kernel
- 操作系统:进程管理,内存管理,文件系统,设备管理问题锚点
- DDR内存结构
- 对于一个硬件IP,需要考虑的组成:供电,时钟,寄存器,输入,输出,中断
- 如果从这些角度去考虑,DDR是什么样的结构图,从内存的本质功能结合结构图去考虑DDR初始化过程
- 需要一篇详细介绍DDR内存的博文
- 多设备树场景下的镜像匹配问题
- 如何理解返回BootROM行为
- 如何理解SPL的跳转决策,快速启动一般用于什么场景
- 关于安全跳转:在RK3568和GD32芯片的使用过程中,在跳转到另一个镜像去执行时,通常都需要关闭中断
- 在复杂的SoC中,还包含了D-Cache清理(避免新镜像程序执行时读取到脏数据),MMU关闭(使用新的虚拟地址空间)
- 关闭中断时为了防止跳转过程中被打断
- 如何理解多处理器引导
- A/B分区,recover分区和普通分区问题