Omap138开发板下以uboot2012.04.01为例分析uboot执行(二)

Omapl138内存和外设分布图

在这里插入图片描述

从下图中的omapl138
top level memory map中可以看出:
DSP专用的内存空间有:
在这里插入图片描述ARM专用的内存空间有:
在这里插入图片描述

Start.s代码分析

1.通过objdump可以查看编译好的反汇编代码,-S显示源代码和反汇编代码。



.globl _start

_start:

       b            reset              c1080054<reset> 

c1080000      ea000013

c1080000是程序加载的地址,在MAKEFILE中定义的。

c1080054是由reset的机器指令而产生与之对应的汇编指令。

       ldr          pc,_undefined_instruction

c1080004:     e59ff014
      ldr         pc,[pc,#20];c1080020 <_undefined_instruction>

这句的意思是从当前跳转20个字节,执行_undefined_instruction。(再考虑到指令的流水线操作,要再加8,才是pc指向的位置)

.global _TEXT_BASE

_TEXT_BASE:

       .word
CONFIG_SYS_TEXT(Uboot 被拷贝到DDR内存中的起始地址)

       c1080000

下面是uboot中一些段的位置

_bss_start_ofs:      0x00053da0

_bss_end_ofs:       0x00092330

_end_ofs:              0x0005adf8


2.reset指令及相关代码会使CPU为SVC32mode,一边运行大多数的内核代码,禁止中断和快速中断。
3.宏定义:CONFIG_SKIP_LOWLEVEL_INIT(ARM926EJ-S基于ARMv5TE架构)这个宏定义在不同的boot loader中,状况是不一样的。它下面的函数:cpu_init_crit会运行一些非常底层的初始化过程。uboot分成了两部分,一部分叫second program loader,一部分叫uboot的主体部分。当程序把自己加载到主内存DDR中运行的时候,底层的这些初始化过程就已经做了,就不需要运行这些东西了。在片内SRAM中运行的那一小段bootloader会运行这段代码。(bootloard引导Linux的过程如下:CPU当中固化的ROM一段小代码把FLASH中关于bootloader的一小段代码加载到RAM中,然后再把bootloader的大部分代码加载到RAM当中去运行。)

cpu_inti_crit()函数的作用如下:

(1)
flush D Cache

(2)
invalidate TLB

(3)
invalidate I Cache

invalidate和flush的区别如下:

ICACHE中缓存了很多条的数据,一条数据可能缓存了128位,每当经过RAM读取或者运行一条指令,都会缓存到cache当中,CACHE中每条数据的最后设置了一个或者两个位,标明这个CACHE是有效还是无效,invalidate就是把所有的这些数据条的最后一位设置位无效,就不会再从CACHE中取了,而是从RAM中取,然后放在CACHE中。flush就是把数据全部清空。

(4)
disable MMU and D Cache, enable I Cache
4.

/* Set stackpointer in internal RAM to call
board_init_f */



call_board_init_f:

#ifdef CONFIG_NAND_SPL /* deprecated, use instead CONFIG_SPL_BUILD */(没有定义)

       ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR)

#else

#ifdef CONFIG_SPL_BUILD(没有定义)

       ldr   sp, =(CONFIG_SPL_STACK)

#else

       ldr   sp, =(CONFIG_SYS_INIT_SP_ADDR)

#endif

#endif

       bic   sp, sp, #7 /* 8-byte alignment for ABI compliance */汇编

       ldr   r0,=0x00000000

       bl    board_init_f


/* 跳转到board_init_f*/

顶层目录下:arch/arm/lib/board.c

为什么在调用C语言的函数之前要先设置好堆栈:

如果是汇编语言的跳转,把lr保存起来即可,但是如果是向c语言的跳转,不仅要保存lr,比如有一个函数func(int a, int b){

   int c;

   char b;

   …

   return;

}

c语言中设置好堆栈,把第一个局部变量放在r0中,第二个局部变量放在r1中,把多余的变量放在堆栈指针中,并进行下移。当把这些形参变量放完之后,把链接寄存器lr,放在紧接着的形参变量的下一个位置。然后开始放函数里面定义的哪些变量,在函数运行完之后,通过pop指令将这些函数里面定义的变量一个个弹出,指针就又指向了lr,然后把lr的值取出来,放回pc,就回到调用它的地方了。

猜你喜欢

转载自blog.csdn.net/qq_40788950/article/details/83956784