Uboot start.s阶段分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Hanani_Jia/article/details/82558120

   最近接触arm课程,了解了一些硬件的一些东西。最近给大家介绍一下arm里边了解的一些东西。

  首先这里介绍一些uboot,什么是uboot,uboot是干什么的有什么作用呢?

UBOOT的主要作用是用来启动linux内核,因为CPU不能直接从块设备中执行代码,需要把块设备中的程序复制到内存中,而复制之前还需要进行很多初始化工作,如时钟、串口、dram等;

  如要想让CPU启动linux内核,只能通过另外的程序,进行必要的初始化工作,在把linux内核中代码复制到内存中,并执行这块内存中的代码,即可启动linux内核;一般情况下,我们把linux

  镜像储存在块设备中如SD卡、iNand、Nandflash等块设备中,首先执行UBOOT带码,在UBOOT中把块设备中的内核代码复制到内存地址0x30008000地址处,然后在执行bootm 0x30008000

  Uboot启动的时候有两个阶段一个是start.s另一个是board.c,今天我们介绍的是start.s阶段。start.s做的事情主要是对系统各个方面的初始化。主要做的事情有以下几个:设置cpu模式、关闭看门狗、关闭中断、设置堆栈指针、清楚bss段、异常处理中断。

Uboot中的start.s做的第一件事就是把cpu设置成我们的SVC模式也就是管理模式

.globl _start
_start: b    reset
reset:
         /*
          * set the cpu to SVC32 mode
          */
         mrs   r0, cpsr
         bic     r0, r0, #0x1f
         orr     r0, r0, #0xd3
         msr   cpsr,r0

arm中是有七种CPU的模式的分别是:用户模式(usr)、系统模式(sys)、快中断模式(fiq)、中断模式(irq)、管理模式(svc)、中止模式(abt)、未定义模式(und),相比较来说svc模式下我们的uboot能获取到更多的权限,所以uboot最初的时候是设置cpu为svc模式从而方便去操作硬件,初始化硬件。

第二件做的事情是关闭看门狗

   那什么是看门狗,通常来说看门狗是我们的一个硬件模块,在嵌入式操作系统中很多情况是系统长期运行但是却没有人看守的,所以如果出现了死机的情况,那后果是很严重的,这时候看门狗也就是watchdog就会帮你重启系统,实际上他就是硬件的一个记录超时的功能,他有一个初始值会一直做减减操作,用户需要每隔一段时间就要到对其进行一个操作,如果说没有操作那我就认为电脑死机了,会发送一个reset信号,就帮你重启了,通俗来讲就是这条狗你需要定期喂食,如果不喂那你的家就乱了。明白看门狗的原理之后就很容易想清楚我们为什么要关闭它,我们根本不需要这个机制,有了它反倒让我们很麻烦所以我们自然要关闭它。

第三件要做的事情是关闭中断

   在系统还没有开始之前,中断并没有什么作用,在这段时间里边并没有什么中断处理程序,并且我们还要防止我们在初始化的这段时间,中断打断我们的工作,所以我们选择关闭中断。这里我们实现关闭中断的方法是将我们的中断使能清零寄存器置为1来实现的。

第四件事是设置堆栈指针

   我们在学习c语言的时候经常会说到堆栈,在uboot系统初始化的时候也有初始化堆栈这个动作,那为什么要初始化堆栈呢?其实也就是为什么我们的c语言运行函数是需要调用堆栈的,但是我们的汇编代码却不需要。简单的来说我们堆栈的作用就是保护现场,传递参数,保护现场将就是我们在运行函数的时候,经常会跳转到其他函数,最明显的就是我们的递归,我们在进入下一层递归之前就需要把当前函数的运行状态,或者寄存器中的值都保存起来,等调用函数结束之后,再恢复现场我们就可以继续我们之前的函数了。第二个作用就是我们的传递参数,还是在函数调用的时候我们经常会传递参数到被调用的函数,但是这些都是c语言这个级别的参数,在转换成汇编代码的时候就需要有地方存储,并且存储的地方还能让我们被调用的函数能够访问到,否则我们传递的参数就没有意义了,这时候就分为两种情况,第一种就是我们的参数很少,我们就可以通过寄存器来传递我们的参数,因为上边说到了,我们在函数调用的时候会让栈保存寄存器中的值,那这时候寄存器就是空的了,我们就可以放数据进去,我们把我们的参数放进去就可以了,但是说如果我们传入的参数比较多,那寄存器根本就不够我们使用,这时候我们就会使用堆栈来保存我们多余的参数。这就是为什么我们要去设置我们的堆栈指针。所谓的设置堆栈sp指针,就是设置堆栈,而所谓的设置堆栈,要做的事情,看起来很简单,就只是一个很简单的动作:让sp等于某个地址值,即可。 

 第五件事情是去清楚我们的bss段

   一般来说一个可执行程序都包括bss段、数据段、代码段(也称作文本段),bss全称是 Block Started by Symbol segment 通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域,这里要清楚bss段和数据段之间的区别,bss段存放的是未初始化的全局变量和静态变量而数据段中存放的是初始化之后的全局变量和静态变量。在每个程序执行前bss都会进行清0操作,所以未初始化的全局变量在程序执行前都变成了0.c语言中主要有两种数据一种是全局变量一种是局部变量,如果我们不对局部变量进行初始化那么他的值是不确定的,并且在栈中的位置也是不固定的,但是全局变量就不一样全局变量会有专门的数据段存储,并且初始化是0而且位置也是固定的。所以说我们的程序在存储到内存中的时候,对应的bss段内的数据情况是未知的,所以将对应bss段,都设置为,0,即清零。

第六件事情也就是最后一件就是我们的异常处理中断

  就是实现对应的常见的那些处理中断的部分内容。说白了就是实现一个个中断函数

  对于uboot在start.s阶段所做的事情简单介绍这么多。

 

猜你喜欢

转载自blog.csdn.net/Hanani_Jia/article/details/82558120