当前位置:首页 > 嵌入式 > 嵌入式软件
[导读]通用的linux内核,启动时需要很多参数 ,这些参数必须通过Bootloader传递。而且内核一半是压缩存放在外存上的,从外存到内存的复制也是由Bootloader完成。从Bootloader的第二个功能就知道,Bootloader时不能与内核放在一起的。由于Bootloader的实现依赖于CPU的体系结构,因此大多数的Bootloader都分为Stage1和Stage2l辆大部分。

通用的linux内核,启动时需要很多参数 ,这些参数必须通过Bootloader传递。而且内核一半是压缩存放在外存上的,从外存到内存的复制也是由Bootloader完成。从Bootloader的第二个功能就知道,Bootloader时不能与内核放在一起的。由于Bootloader的实现依赖于CPU的体系结构,因此大多数的Bootloader都分为Stage1和Stage2l辆大部分。

依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在Stage1中,而且通常用汇编语言来实现,以达到短小精悍的目的。而Stage2则通常用C语言来实现,这样可以实现复杂的功能,并且代码会具有更好的可读性和可移植性。

(1)Bootloader的Stage1通常包括以下步骤:

1:硬件设备初始化

2:为加载Bootloader的Stage2准备RAM空间

3:将Bootoader的Stage2复制到RAM空间中

4:设置好堆栈

5:跳转到Stage2的C入口点

(2)Bootloader的Stage2通常包括以下步骤:

1:初始化本阶段要使用到的硬件设备

2:检测系统内存映射(Memory Map)

3:将Kernel映像和根文件系统映像从Flash上读到RAM空间中

4:为内核设置启动参数

5:调用内核。

Stage1:汇编阶段

1:基本硬件初始化

(1)屏蔽所有中断。

(2)设置CPU的速度和时钟频率。

(3)RAM初始化。包括正确地设置系统的内存控制器的功能寄存器以及各内存控制寄存器等。

(4)初始化LED。(或者初始化串口,用于表示当前状态)

(5)关闭CPU内部指令/数据Cache。

2:为加载Stage2准备RAM空间

为了获得更快的执行速度,通常把Stage2加载到RAM空间中来执行**,因此必须为加载Bootloader的Stage2准备好一段可用的RAM空间范围。主要工作是对预备空间进行读写测试。

3:复制Stage2到RAM中

复制时注意两点:Stage2的可执行映像在固态存储设备的存放起始位地址和终止地址。RAM空间的起始地址。

4:设置堆栈指针sp

堆栈指针设置是为执行C语言代码做准备。通常可把sp的值设置为(stage2_end-4),也即1MB的RAM空间的最顶端(堆栈向下生长)。此外,在设置堆栈指针sp之前,也可以关闭LED灯,以提示用户我们准备跳转到Stage2。经过上述这些执行步骤后,系统的内存物理布局如下图所示。

5:跳转到Stage2的C入口点

在上述一切都就绪后,就可以跳转到Bootloader的Stage2去执行了。比如,在ARM系统中,这可以通过修改PC寄存器为合适的地址来实现。

Stage2:C语言阶段

正如之前所说,Stage2代码通常用C语言来实现,以便于实现更加复杂的功能和取得更好的代码可读性和可移植性。但是与通常C语言应用程序不同的是,在编译和链接Bootloader这样的程序时,我们不能使用glibc库中国年的任何支持函数。原因显而易见。

这就给我们带来一个问题,那就是从哪里跳转进main()函数呢?直接把main()函数的起始地址作为整个Stage2执行映像的入口点或许是最直接的想法。但是这样做有两个缺点:

- 无法通过mian()函数传递函数参数

- 无法处理main()函数的返回值情况

一种更为巧妙的方法是利用Trampoline(弹簧床)的概念。也即,用汇编语言写一段Trampoline小程序,并将这段小程序作为Stage2可执行映像的执行入口点。然后我们可以在Trampoline汇编小程序中用CPU跳转指令跳入main()函数中去执行;而当main()函数返回时,CPU执行路径显然再次回到我们的Trampoline程序。简而言之,这种方法的思想就是用这段Trampoline小程序最为mian()函数的外部包裹(External Wrapper)。

下面给出一个简单的Trampoline程序示例(来自Blob):

.text

.globl _trampoline

_trampoline:

bl main

/*if main ever returens we just call it again */

b _trampoline

可以看到,当main()函数返回之后,我们又重新调用trampoline,也就相当于循环调用mian(),这就是弹簧床的概念。

1:初始化系统本阶段需要用到的硬件

需要初始化的设备包括:

- 至少一个串口,以便于终端用户进行I/O信息输出

- 计时器等

2:检测系统的内存映射(Memory Map)

所谓内存 映射,就是指在整个4GB物理地址空间中有哪些地址范围被分配用来寻址系统的RAM单元。比如,在Samsung S3C44B0X中,从0x0c000000到0x10000000之间的64MB地址空间被用作系统的RAM地址空间。

虽然CPU通常预留出一大段足够的地址空间给系统RAM,但是在搭建具体的嵌入式系统时却不一定会实现CPU预留的全部RAM地址空间。也就是说,具体的嵌入式系统往往只把CPU预留的全部RAM空间的一部分映射到RAM单元上,而让剩下的那部分预留RAM地址空间处于未使用状态,不挂满可节省成本。由于上述事实,因此Bootloader的Stage2必须在它想干点什么(比如,将存储在Flash上的内核映像独到RAM空间中)之前检测整个系统的内存映射情况,也即它必须知道CPU预留的全部RAM地址空间中的哪些呗真正映射到物理RAM地址单元,哪些是处于unused状态的。

3:加载内核映像和根文件系统映像

规划内存占用的布局。这里面就包括两个方面:

-内核映像所占用的内存范围。

-根文件系统所占用的内存范围。在规划内存范围占用的布局时,主要考虑基地址和映像的大小两个方面。

对于内核映像,一般将其复制到从(MEM_START + 0x8000)这个地址开始的大约1MB大小的内存范围内(嵌入式LINUX的内核一般都不超过1MB)。

为什么把从MEM_START到MEM_START + 0x8000这段32KB大小的内存空出来呢?这是因为LINUX内核要在这段内存中放置一些全局数据结构,如启动参数和内核页表等信息。

而对于根文件系统映像,则一般将其复制到MEM_START + 0x0010 0000开始的地方。如果用Ramdisk作为根文件系统映像,则其解压后的大小一般是1MB。

4:从Flash上复制

由于像ARM这样的嵌入式CPU通常都是在同一的内存地址空间中国年寻址Flash等固态存储设备的,因此从Flash上读取数据与从RAM单元中读取数据并没有什么不同。用一个简单的循环就可以完成从Flash设备上复制映像的工作:

while(count){

*dest++ = *src++; /*they are all aligned with word boundary */

count -= 4; /* byte number */

};

5:设置内核的启动参数

应该说,在讲内核映像和根文件系统映像复制到RAM空间中后,就可以准备启动Linux内核了。但是在调用内核之前,应该做一步准备工作,即设置Linux内核的启动参数。

Linux 2.4以后的内核期望以标记列表(Tagged List)的形式来传递启动参数。启动参数标记列表以标记ATAG_CORE开始,以标记ATAG_NONE结束。每个标记由北传递参数tag_header结构以及随后的参数值数据结构来组成。数据结构tag和tag_header定义在Linux内核源码的include/asm/setup.h头文件中。

在嵌入式Linux系统中,通常要由Bootloader设置的常用启动参数有ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD等。

Linux内核在启动时可以以命令行参数的形式来接受信息,利用这一点我们可以向内核提供哪些内核不能自己检测的硬件参数信息,活着重载(override)内核自己检测到的信息。比如,我们用这样一条命令行参数字符串“console=ttyS0,115200n8”来通知内核以ttyS0作为控制台,且用串口采用“115200bps,无奇偶校验、8位数据位”这样的设置。

6:掉用内核

Bootloader调用Linux内核的方法是直接跳转到内核的第一条指令处,也即直接跳转到MEM_START + 0x8000地址处。在跳转时要满足下列条件。

- CPU寄存器的设置:R0=0; R1=机器类型ID; R2=启动参数标记列表在RAM中的起始基地址。

- CPU模式:必须禁止中断(IRQs和FIQs);CPU必须处于SVC模式。

- Cache和MMU的设置:MMU必须关闭;指令缓存可以打开也可以关闭;数据缓存必须关闭。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

2024年4月18日 – 提供超丰富半导体和电子元器件™的业界知名新品引入 (NPI) 代理商贸泽电子 (Mouser Electronics) 很荣幸地宣布与Edge Impulse建立新的全球合作关系。Edge Im...

关键字: 机器学习 MCU CPU

无论您是在研究如何使用 10GigE 还是寻求所需考虑事项的建议,本文均提供有实践,帮助确保单相机 10GigE 视觉系统设置顺利并拥有良好性能。 我们列出了主机系统配置、布线和相机设置的实践。

关键字: 视觉系统 CPU 存储器

Apr. 16, 2024 ---- NVIDIA新一代平台Blackwell,包含B系列GPU及整合NVIDIA自家Grace Arm CPU的GB200等。TrendForce集邦咨询指出,GB200的前一代为GH2...

关键字: CPU GPU

人工智能是集合众多方向的综合性学科,在诸多应用领域均取得了显著成果[1]。随着航空领域人工智能技术研究的不断深入,面向开放式机载智能交互场景,人工智能的应用可解决诸多问题。例如智能感知、辅助决策等,可利用人工智能算法对多...

关键字: 人工智能 PCIe CPU

据韩联社报道,上周三星电子发布业绩报告显示,随着芯片价格反弹,预计今年第一季度营业利润同比骤增931.25%,为6.6万亿韩元(当前约合人民币354.6亿元),已经超过了2023年全年营业利润6.57万亿韩元。

关键字: 内存 三星

TDK 株式会社(TSE:6762)进一步扩充 Micronas 嵌入式电机控制器系列 HVC 5x,完全集成电机控制器与 HVC-5222D 和 HVC-5422D,以驱动小型有刷(BDC)、无刷(BLDC)或步进电机...

关键字: 嵌入式 电机控制器 内存

Apr. 04, 2024 ---- TrendForce集邦咨询针对403震后各半导体厂动态更新,由于本次地震大多晶圆代工厂都位属在震度四级的区域,加上台湾地区的半导体工厂多以高规格兴建,内部的减震措施都是世界顶尖水平...

关键字: 晶圆代工 内存

CPU针脚弯了,用工具调正就不会有影响。开机自检也通过,CPU 再出问题就不是针脚引起的问题。针脚只要不断就没有问题,有的CPU出厂的时候针脚就有点弯,这并不是什么大问题,只要用镊子轻轻地弄直就可以了。

关键字: CPU 针脚 开机自检

美光坚持多元、平等、包容的企业文化,携手社区推行公益

关键字: 内存 存储 美光

瑞典乌普萨拉,2024年3月27日 – 全球领先的嵌入式系统开发软件解决方案供应商IAR自豪地宣布:公司备受全球数百万开发者青睐的开发环境再次升级,已率先支持瑞萨首款通用32位RISC-V MCU,该 MCU 搭载了瑞萨...

关键字: MCU RISC-V CPU
关闭
关闭