正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-6.2uboot启动流程-lowlevel_init,s_init,_main函数执行

devtools/2025/3/20 9:21:17/

 前言:

本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记,在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。

引用:

正点原子IMX6U仓库 (GuangzhouXingyi) - Gitee.com

《【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.5.2.pdf》

正点原子资料下载中心 — 正点原子资料下载中心 1.0.0 文档

正点原子imx6ull-mini-Linux驱动之Linux I2C 驱动实验(21)-CSDN博客

正文:

本文是 “Arm(iMX6U)Linux系统移植和根文件系统构键篇--6.2 讲uboot顶层Makefile分析创建VSCode工程。本节将参考正点原子的视频教程和配套的正点原子开发指南文档进行学习

0. 概述

1 reset函数源码详解

从u-boot.lds中我们已经知道了入口点是 arch/arm/lib/vectors.S文件中的 _start,代码如下

 第48行 _start开始的是中断向量表,其中 54~61行就是中断向量表,和我们裸机例程里面一样。54行跳转到 reset函数里面, reset函数在 arch/arm/cpu/armv7/start.S里面,代码如下:

arch/arm/cpu/armv7/start.S

第 35行就是 reset函数。
第 37行从 reset函数跳转到了 save_boot_params函数,而 save_boot_params函数同样定义在start.S里面,定义如下:

 save_boot_params函数也是只有一句跳转语句,跳转到 save_boot_params_ret函数,save_boot_params_ret函数代码如下:

 第 43行,读取寄存器 cpsr中的值,并保存到 r0寄存器中。

第 44行,将寄存器 r0中的值与 0X1F进行与运算,结果保存到 r1寄存器中,目的就是提取 cpsr的 bit0~bit4这 5位,这 5位为 M4 M3 M2 M1 M0 M[4:0]这五位用来设置处理器的工作模式,如表32.2.1.1所示:

 第 45行,判断 r1寄存器的值是否等于 0X1A(0b11010),也就是判断当前处理器模式是否处于 Hyp模式。

第 46行,如果 r1和 0X1A不相等,也就是 CPU不处于 Hyp模式的话就将 r0寄存器的bit0~5进行清零,其实就是清除模式位

bicne 指令是 bic + ne 

bic 是bitclean 位清除指令,加上条件 ne (non-equal)不相等条件满足时执行 bic 指令

 第 47行,如果处理器不处于 Hyp模式的话就将 r0的寄存器的值与 0x13进行或运算,0x13=0b10011,也就是设置处理器进入 SVC模式。

orrne 指令时 orr + ne

orr 时或运算指令,加上条件 ne (non-equal)不相等条件满足时执行 orr 指令

第 48行, r0寄存器的值再与 0xC0进行或运算,那么 r0寄存器此时的值就是 0xD3 cpsr的 I为和 位分别控制 IRQ和 FIQ这两个中断的开关,设置为 1就关闭了 FIQ和 IRQ

第 49行,将 r0寄存器写回到 cpsr寄存器中。完成设置 CPU处于 SVC32模式,并且关闭
FIQ和 IRQ这两个中断

ARMv7 CPSR寄存器

ARMv7 的CPSR 寄存器的定义,bit[0-4] 这5位控制ARMv7 CPU的工作模式,bit[6]控制FIQ中断,开关bit[7]控制FIQ中断开关。

继续执行执行下面的代码:

第56行,如果没有定义 CONFIG_OMAP44XX和 CONFIG_SPL_BUILD的话条件成立,此处条件成立。 

第58行读取 CP15中 c1寄存器的值到 r0寄存器中,根据 17.1.4小节可知,这里是读取SCTLR寄存器的值

第59行, CR_V在 arch/arm/include/asm/system.h中有如下所示定义:

 arch/arm/include/asm/system.h

#define CR_V (1 << 13) /* Vectors relocated to 0xffff0000 */

 因此这一行的目的就是清除SCTLR寄存器中的 bit13,SCTLR寄存器结构如图 32.2.1.1所示:

 从图 32.2.1.1可以看出,

  • bit13为 V位,此位是向量表控制位当为 0的时候向量表基地址为 0X00000000,软件可以重定位向量表
  • 为 1的时候向量表基地址为 0XFFFF0000,软件不能重定位向量表。

这里将 V清零,目的就是为了接下来的向量表重定位,这个我们在第十七章有过详细的介绍了。

第 60行将 r0寄存器的值重写写入到寄 存器 SCTLR中。

第63行设置 r0寄存器的值为 _start,_start就是整个 uboot的入口地址,其值为 0X87800000相当于 uboot的起始地址,因此 0x87800000也是向量表的起始地址。

第64行将 r0寄存器的值 (向量表值 )写入到 CP15的 c12寄存器中,也就是 VBAR寄存器。因此第 58~64行就是设置向量表重定位的

代码继续往下执行:

第 68 行如果没有定义 CONFIG_SKIP_LOWLEVEL_INIT 的话条件成立。我们没有定义CONFIG_SKIP_LOWLEVEL_INIT,因此条件成立,执行下面的语句。

示例代码 32.2.1.6 中的内容比较简单,就是分别调用函数 cpu_init_cp15、 cpu_init_crit 和_main。

函数 cpu_init_cp15 用来设置 CP15 相关的内容,比如关闭 MMU 啥的,此函数同样在 arch/arm/cpu/armv7/start.S文件中定义的,代码如下:

arch/arm/cpu/armv7/start.S

函数 cpu_init_cp15 都是一些和 CP15 有关的内容,我们不用关心,有兴趣的可以详细的看一下。

函数 cpu_init_crit 也在是定义在 start.S 文件中,函数内容如下:

arch/arm/cpu/armv7/start.S

   可以看出函数 cpu_init_crit 内部仅仅是调用了函数 lowlevel_init,接下来就是详细的分析一下 lowlevel_init 和_main 这两个函数

2 lowlevel_init 函数详解

函数 lowlevel_init 在文件 arch/arm/cpu/armv7/lowlevel_init.S 中定义,内容如下:

arch/arm/cpu/armv7/lowlevel_init.S

第 22 行设置 sp 指向 CONFIG_SYS_INIT_SP_ADDR, CONFIG_SYS_INIT_SP_ADDR 在include/configs/mx6ullevk.h 文件中,在 mx6ullevk.h 中有如下所示定义:

include/configs/mx6ullevk.h


 

 示 例 代 码 32.2.2.2 中 的 IRAM_BASE_ADDR 和 IRAM_SIZE 在 文 件arch/arm/include/asm/arch-mx6/imx-regs.h 中有定义,如下所示,其实就是 IMX6UL/IM6ULL 内部 ocram (On-Chip-RAM,芯片片上RAM) 的首地址和大小

arch/arm/include/asm/arch-mx6/imx-regs.h

 

   如果 408 行的条件成立的话 IRAM_SIZE=0X40000,当定义了 CONFIG_MX6SX、CONFIG_MX6U、 CONFIG_MX6SLL 和 CONFIG_MX6SL 中的任意一个的话条件就不成立,在.config 中定义了 CONFIG_MX6UL所以条件不成立,因此 IRAM_SIZE=0X20000=128KB。

结合示例代码 32.2.2.2,可以得到如下值:

CONFIG_SYS_INIT_RAM_ADDR = IRAM_BASE_ADDR = 0x00900000。
CONFIG_SYS_INIT_RAM_SIZE = 0x00020000 =128KB。

还需要知道GENERATED_GBL_DATA_SIZE的值,在文件include/generated/generic-asm-offsets.h中有定义,如下:

include/generated/generic-asm-offsets.h

 GENERATED_GBL_DATA_SIZE=256, GENERATED_GBL_DATA_SIZE 的含义为(sizeof(struct global_data) + 15) & ~15 。

综上所述, CONFIG_SYS_INIT_SP_ADDR 值如下:
 

CONFIG_SYS_INIT_SP_OFFSET = 0x00020000 – 256 = 0x1FF00。
CONFIG_SYS_INIT_SP_ADDR = 0x00900000 + 0X1FF00 = 0X0091FF00,

 


http://www.ppmy.cn/devtools/168586.html

相关文章

Java集合

文章目录 集合的理解和好处数组集合 集合的框架体系Collection 接口和常用方法Collection 接口实现类的特点Collection 接口遍历元素方式1-使用IteratorCollection 接口遍历对象方式2-for 循环增强 List 接口和常用方法List 接口基本介绍List 接口的常用方法List 接口课堂练习L…

Linux 文件操作-标准IO函数4-fseek设置文件偏移量、ftell获取当前偏移量、rewind使文件偏移量(为0)定位到开头

目录 1.fseek设置文件偏移量 2.ftell获取当前偏移量 3.rewind使文件偏移量&#xff08;为0&#xff09;定位到开头 4.程序验证 1.fseek设置文件偏移量 函数原型&#xff1a; /* 功能&#xff1a;设置文件位置指针的偏移量 参数&#xff1a; stream&#xff1a;文件指针 of…

言简意赅 Linux部署elasticsearch7.15.2

目录 下载 zip 包 在 linux 里面解压 进入bin目录 创建用户useres 授权到es目录 切换到useres用户 bin 目录启动 配置 端口开放 配置 jdk 单节点启动 一定要配置 说明成功 byd折磨了我两天 下载 zip 包 通过网盘分享的文件&#xff1a;elasticsearch-7.15.2-linux…

【SpringCloud】服务注册/服务发现

文章目录 前言什么是注册中心CAP理论Eureka搭建Eureka Server服务注册服务发现 前言 在生活中&#xff0c;我们不可避免地与各种医院、学校、政府等机构打交道&#xff0c;那么要想与这些机构取得联系&#xff0c;就需要知道这些机构的电话号码&#xff0c;但是这些机构的电话…

掌握些许 IPv6 要点,windows 远程桌面安全便利两相宜!

掌握这些要点&#xff0c;Windows 远程桌面安全便利两相宜&#xff01; 在日常办公中&#xff0c;许多人会用到 Windows 系统的远程桌面功能。但在实际使用时&#xff0c;会遇到内网计算机难以通过运营商的动态 ip 与多层 NAT 向互联网暴露端口的技术问题&#xff0c;和计算机…

Oracle ASM Failgroup故障组

Oracle ASM Failgroup故障组 1. 故障组的核心作用2. 故障组的配置规则3. 故障组的设计最佳实践4. 故障组的实际示例场景1&#xff1a;普通冗余&#xff08;2个故障组&#xff09;场景2&#xff1a;高冗余&#xff08;3个故障组&#xff0c;跨数据中心&#xff09; 关键注意事项…

pfsense部署三(snort各版块使用)

在上篇文章上我们已经进行了snort的基础配置了&#xff0c;接下来需要进行snort的具体配置&#xff0c;其中包括各板块的设置&#xff0c;例&#xff1a;白名单&#xff0c;警报&#xff0c;规则设置等 规则库配置 点击 service > snort > Global Settings ,在code值…

python函数的多种参数使用形式

目录 1. 位置参数&#xff08;Positional Arguments&#xff09; 2. 关键字参数&#xff08;Keyword Arguments&#xff09; 3. 默认参数&#xff08;Default Arguments&#xff09; 4. 可变参数&#xff08;Variable Positional Arguments&#xff09; 5. 关键字可变参数&…