Uboot启动分析笔记Stage1(start.S与lowlevel_init.S详解)
- 格式:pdf
- 大小:234.37 KB
- 文档页数:18
uboot启动代码详解编辑整理:尊敬的读者朋友们:这里是精品文档编辑中心,本文档内容是由我和我的同事精心编辑整理后发布的,发布之前我们对文中内容进行仔细校对,但是难免会有疏漏的地方,但是任然希望(uboot启动代码详解)的内容能够给您的工作和学习带来便利。
同时也真诚的希望收到您的建议和反馈,这将是我们进步的源泉,前进的动力。
本文可编辑可修改,如果觉得对您有帮助请收藏以便随时查阅,最后祝您生活愉快业绩进步,以下为uboot启动代码详解的全部内容。
·1 引言在专用的嵌入式板子运行 GNU/Linux 系统已经变得越来越流行。
一个嵌入式 Linux 系统从软件的角度看通常可以分为四个层次:1。
引导加载程序.固化在固件(firmware)中的 boot 代码,也就是 Boot Loader,它的启动通常分为两个阶段。
2。
Linux 内核。
特定于嵌入式板子的定制内核以及内核的启动参数。
3. 文件系统。
包括根文件系统和建立于 Flash 内存设备之上文件系统,root fs。
4。
用户应用程序。
特定于用户的应用程序。
有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面.常用的嵌入式 GUI 有:MicroWindows 和 MiniGUI 等。
引导加载程序是系统加电后运行的第一段软件代码。
回忆一下 PC 的体系结构我们可以知道,PC 机中的引导加载程序由 BIOS(其本质就是一段固件程序)和位于硬盘 MBR 中的 OS Boot Loader(比如,LILO 和 GRUB 等)一起组成。
BIOS 在完成硬件检测和资源分配后,将硬盘 MBR 中的 Boot Loader 读到系统的 RAM 中,然后将控制权交给 OS Boot Loader。
Boot Loader 的主要运行任务就是将内核映象从硬盘上读到 RAM 中,然后跳转到内核的入口点去运行,也即开始启动操作系统.而在嵌入式系统中,通常并没有像 BIOS 那样的固件程序(注,有的嵌入式 CPU 也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由 Boot Loader 来完成.比如在一个基于 ARM7TDMI core 的嵌入式系统中,系统在上电或复位时通常都从地址 0x00000000 处开始执行,而在这个地址处安排的通常就是系统的 Boot Loader 程序。
2014.4.16 u-boot学习笔记u-boot版本:u-boot-2014.01-rc1作者:charles.lu参考资料:《ARM嵌入式系统开发:软件设计与优化》,《S3C2440手册》,《嵌入式linux应用开发完全手册》韦东山教学视频,《嵌入式bootloader技术内幕》。
目的:1)分析源码; 2)移植到飞凌嵌入式S3C2440开发板首先看第一阶段的u-boot代码。
打开文件arch/arm/cpu/arm920t/start.S.globl _start_start: b start_codeldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq代码从_start处开始执行。
b start_code即跳转到start_code(b还有后面常有的bl是ARM9跳转指令,若要学习指令可参考《ARM嵌入式系统开发:软件设计与优化》)。
我们往下走,找到start_code,可知首先是硬件初始化,分别做如下工作:1.设置CPU为SVC32模式2.关看门狗3.禁止所有中断4.设置时钟分频这里,对于具体的硬件初始化细节,可以参考《S3C2440手册》,为什么要这么做就不讲了,可以参考上述的书籍。
#if defined(CONFIG_AT91RM9200DK)||defined(CONFIG_AT91RM9200EK) 在头文件include/configs/smdk2410.h中没有这个宏定义,所以这个#if 和#endif里的代码不用管。
后面又有一个宏定义,区分S3C2440和S3C2410。
#ifndef CONFIG_SKIP_LOWLEVEL_INITbl cpu_init_crit5.跳转到cpu_init_crit,代码在下面。
lowlevel_init过程注释了一遍恩,大概以后再也不想看这块过程了。
解析的有点犯恶心了。
如果有问题,请各位看官斧正。
非常感谢。
#include <config.h>#include <version.h>#include <s3c6410.h>#include "smdk6410_val.h"_TEXT_BASE:.word TEXT_BASE.globl lowlevel_initlowlevel_init:mov r12, lr;保存当前链接寄存器地址,等跳转回start.s时继续执行使用ldr r0, =ELFIN_GPIO_BASE ;定基地址 0x7f008000ldr r1, =0x55555555str r1, [r0, #GPKCON0_OFFSET]; 0x7f008000 + 0x800 ;设置引脚GPIO-K[0-7]管脚为cfdata 模式ldr r1, =0x55555555str r1, [r0, #GPKCON1_OFFSET];0x7f008000 + 0x804 ;设置引脚GPIO-K[8-14]管脚为cfdata 模式ldr r1, =0x22222666 ;0010 0010 0010 0010 0010 0110 0110 0110str r1, [r0, #GPLCON0_OFFSET];0x7f008000 + 0x810;设置引脚GPIO-L;打开CF卡串口通信的0-2号三根地址线,其余不变,保持默认值ldr r1, =0x04000000 ;01 00 00 00 00 00 00 00 00 00 00 00 00 00str r1, [r0, #GPFCON_OFFSET];0x7f008000 + 0xA0;设置引脚GPIO-F14为输出;GPIO-F14连接CLKOUT输出ldr r1, =0x2000; 10000000000000str r1, [r0, #GPFDAT_OFFSET];0x7f008000 + 0xA4;通过向GPIO锁存器写1,维持一个高电平信号。
背景:Board →ar7240(ap93)Cpu →mips1、首先弄清楚什么是u-bootUboot是德国DENX小组的开发,它用于多种嵌入式CPU的bootloader程序, uboot不仅支持嵌入式linux系统的引导,当前,它还支持其他的很多嵌入式操作系统。
除了PowerPC系列,还支持MIPS,x86,ARM,NIOS,XScale。
2、下载完uboot后解压,在根目录下,有如下重要的信息(目录或者文件):以下为为每个目录的说明:Board:和一些已有开发板有关的文件。
每一个开发板都以一个子目录出现在当前目录中,子目录存放和开发板相关的配置文件。
它的每个子文件夹里都有如下文件(以ar7240/ap93为例):MakefileConfig.mkAp93.c 和板子相关的代码Flash.c Flash操作代码u-boot.lds 对应的链接文件common:实现uboot命令行下支持的命令,每一条命令都对应一个文件。
例如bootm命令对应就是cmd_bootm.ccpu:与特定CPU架构相关目录,每一款Uboot下支持的CPU在该目录下对应一个子目录,比如有子目录mips等。
它的每个子文件夹里都有入下文件:MakefileConfig.mkCpu.c 和处理器相关的代码sInterrupts.c 中断处理代码Serial.c 串口初始化代码Start.s 全局开始启动代码Disk:对磁盘的支持Doc:文档目录。
Uboot有非常完善的文档。
Drivers:Uboot支持的设备驱动程序都放在该目录,比如网卡,支持CFI的Flash,串口和USB等。
Fs:支持的文件系统,Uboot现在支持cramfs、fat、fdos、jffs2和registerfs。
Include:Uboot使用的头文件,还有对各种硬件平台支持的汇编文件,系统的配置文件和对文件系统支持的文件。
该目下configs目录有与开发板相关的配置文件,如ar7240_soc.h。
大多数bootloader都分为stage1和stage2两部分,u-boot也不例外。
依赖于CPU体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
1、Stage1 start.S代码结构u-boot的stage1代码通常放在start.S文件中,他用汇编语言写成,其主要代码部分如下:(1)定义入口。
由于一个可执行的Image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在ROM(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
(2)设置异常向量(Exception Vector)。
(3)设置CPU的速度、时钟频率及终端控制寄存器。
(4)初始化内存控制器。
(5)将ROM中的程序复制到RAM中。
(6)初始化堆栈。
(7)转到RAM中执行,该工作可使用指令ldr pc来完成。
2、Stage2 C语言代码部分lib_arm/board.c中的start arm boot是C语言开始的函数也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数只要完成如下操作:(1)调用一系列的初始化函数。
(2)初始化Flash设备。
(3)初始化系统内存分配函数。
(4)如果目标系统拥有NAND设备,则初始化NAND设备。
(5)如果目标系统有显示设备,则初始化该类设备。
(6)初始化相关网络设备,填写IP、MAC地址等。
(7)进去命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
3、U-Boot的启动顺序(示例,其他u-boot版本类似)cpu/arm920t/start.S@文件包含处理#include <config.h>@由顶层的mkconfig生成,其中只包含了一个文件:configs/<顶层makefile中6个参数的第1个参数>.h#include <version.h>#include <status_led.h>/********************************************************** ****************** Jump vector table as in table 3.1 in [1]********************************************************** *****************/注:ARM微处理器支持字节(8位)、半字(16位)、字(32位)3种数据类型@向量跳转表,每条占四个字节(一个字),地址范围为0x0000 0000~@0x0000 0020@ARM体系结构规定在上电复位后的起始位置,必须有8条连续的跳@转指令,通过硬件实现。
U-boot 启动流程(Linux 内核)的分析(三)U-boot 属于两阶段的Bootloader ,第一阶段的文件为cpu/arm920t/start.S 和board\samsung\smdk2410/lowlevel_init.S,前者是平台相关的,后者是开发板相关的。
1.U-Boot 第一阶段代码分析(1)硬件设备初始化依次完成如下设置:将CPU 的工作模式设为管理模式(SVC ),关闭WATCHDOG ,设置FCLK ,HCLK ,PCLK 的比例,关闭MMU ,CACHE 。
代码在cpu/arm920t/start.S 中,(2)为加载Bootloader 的第二阶段代码准备RAM 空间。
所谓准备RAM 空间,就是初始化内存芯片,使它可用,对于S3C24x0,通过在Start.S 中调用lowlevel_init 函数来设置存储控制器,使得外接 SDRAM 可用,lowlevel_init.S,文件是与开发板相关的,这表示如果外接的设备不一样,可以修改lowlevel_init.S 文件中的相关的宏。
(3)复制Bootloader 的第二阶段代码到RAM 空间中 这里将整个U-Boot 代码都复制到SDRAM 中,这在cpu/arm920t/start.s 中实现上面这段程序,在使用NANDFlash 启动时,需要修改。
(4)设置好栈 /*栈的设置灵活性很大,只要让sp 寄存器指向一段没有使用的内存即可*/.word TEXT_BASE //这里是获得代码段的起始地址,我的是0x33F80000(在board/xxx/config.mk中//可到找到“TEXT_BASE=0x33F80000”.globl lowlevel_init //这里相当于定义一个全局的lowlevel_init以方便调用lowlevel_init :/* memory control configuration *//* make r0 relative the current location so that it *//* reads SMRDATA out of FLASH rather than memory ! */ldr r0, =SMRDATA //SMDATA表示这 13个寄存器的值存放的开始地址,值为0x33F8xxxx,处于内//存中,这一句的作用是把其值加载到r0中ldr r1, _TEXT_BASE // 把代码的起始地址(0x33F80000)加载到r1中sub r0, r0, r1 //r0减去r1其结果存入r0,也即SMDATA中的起始地址0x33F8xxxx减去//0x33F80000,其结果就是13个寄存器的值在NOR Flash存放的开始地址ldr r1, =BWSCON /* Bus Width Status Controller */ //存储控制器的基地址add r2, r0, #13*4 //在计算出来的存放地址加上#13*4,然后其结果保存在r2中//13 个寄存器,每个寄存器占4个字节0:ldr r3, [r0], #4 //内存中r0的值加载到r3中,然后r0加4,即下一个寄存器的str r3, [r1], #4 //读出寄存器的值保存到r1中,然后r1也偏移4cmp r2, r0 //比较r0与r2的值,如果不等继续返回0:执行,也即13个寄存器的值// 是否读完bne 0b/* everything is fine now */mov pc , lr //程序跳转,返回到cpu_init_crit中.ltorg/* the literal pools origin */SMRDATA :...................relocate : /* 将U-Boot复制到RAM中 */adr r0, _start /* r0:当前代码的开始地址 */ldr r1, _TEXT_BASE /* r1:代码段的连接地址*/cmp r0, r1 /* 测试现在是在FLash中,还在是RAM中,如果要从NandFlash启动的话,这里要根据需要修改 */beq stack_setup /*如果已经在RAM中,则不需要复制*/ldr r2, _armboot_start /*_armboot_start在前面定义,是第一条指令的运行地址*/ldr r3, _bss_start /*在连接脚本U-Boot.lds中定义,是代码段的结束地址*/sub r2, r3, r2 /* r2 <- 代码段长度 */add r2, r0, r2 /* r2 <-代码段的结束地址 */copy_loop :ldmia {r3-r10} /* 从地址[r0]处获得数据 */stmia {r3-r10} /* 复制到地址[r1]处 */cmp r0, r2 /* 判断是否复制完毕 */ble copy_loop /*没有复制完,则继续*/#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ldr r0, _TEXT_BASE /* _TEXT_BASE 为代码段的开始地址,值为0x33F80000 */sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* 代码段下面,留出一段内存以实现malloc */sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* 再留出一段内存,存一些全局参数 */#ifdef CONFIG_USE_IRQsub r0, r0, #(CONFIG_STACKSIZE_IRQ +CONFIG_STACKSIZE_FIQ )#endifsub sp , r0, #12 /* 最后,留出12字节的内存给abort异常 */clear_bss :(5)跳转到第二阶段代码的C 入口点 在跳转之前,还要清除BSS 段(初始值0,无初始值的全局变量,静态变量放在BSS 段。
u-boot-1.1.6 start.S代码笔记收藏u-boot 1.1.6 start.S 代码学习/*参考了别人的一些笔记,看完了启动代码。
本文档记录在看代码时碰到的困难,将这些曾经困扰的问题记录下来,以备今后之用。
分析时不重要的代码被删除了。
*/.globl _start_start: b resetldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq_undefined_instruction: .word undefined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word fiq.balignl 16,0xdeadbeef/*_start是整个u-boot程序的入口点,即链接后,该处是整个程序的第一条指令。
程序的入口点是由链接脚本所指定,比如对于smdk2410的板子(下面都以smdk241为例),脚本文件位于board\smdk2140\u-boot.ld s。
在该脚本文件中:ENTRY(_start) 即指定程序的入口地址。
globl _start 定义一个外部可以引用的变量,比如说,在其它源代码文档中,就可以直指引用_start这个变量。
如int entry=_start; 那此处en try值将是多少呢?因为_start相当于一个变量,entry的值就是_start处存储的值,即 b reset机器码值。
cpu/arm920t/start.S/****************************************************** ********************** Jump vector table as in table 3.1 in [1]****************************************************** *********************/;定义变量_start,然后跳转到处理器复位代码.globl _start_start: b reset;产生中断则利用pc来跳转到对应的中断处理程序中ldr pc, _undefined_instructionldr pc, _software_interruptldr pc, _prefetch_abortldr pc, _data_abortldr pc, _not_usedldr pc, _irqldr pc, _fiq;利用.word来在当前位置放置一个值,这个值实际上就用对应的中断处理函数的地址;.word的意义为在当前地址处放入一个16bits值_undefined_instruction: .word undefined_instruction_software_interrupt: .word software_interrupt_prefetch_abort: .word prefetch_abort_data_abort: .word data_abort_not_used: .word not_used_irq: .word irq_fiq: .word fiq.balignl 16,0xdeadbeef/****************************************************** ********************** Startup Code (reset vector)** do important init only if we don't start from memory!* relocate armboot to ram* setup stack* jump to second stage****************************************************** *********************/;定义变量_TEXT_BASE:.word TEXT_BASE.globl _armboot_start_armboot_start:.word _start/** These are defined in the board-specific linker script.*/.globl _bss_start_bss_start:.word __bss_start.globl _bss_end_bss_end:.word _end#ifdef CONFIG_USE_IRQ/* IRQ stack memory (calculated at run-time) */.globl IRQ_STACK_STARTIRQ_STACK_START:.word 0x0badc0de/* IRQ stack memory (calculated at run-time) */.globl FIQ_STACK_STARTFIQ_STACK_START:.word 0x0badc0de#endif/** the actual reset code*/;实际处理代码reset:/** set the cpu to SVC32 mode*/mrs r0,cpsr;bic清除指定为1的位bic r0,r0,#0x1f;orr逻辑或操作orr r0,r0,#0xd3;经过以上两步r0值控制位位11010011,第0~4位标识处理器当前所处模式为10011(32位管理模式),第6、7位;为1标识禁止IRQ和FIQ中断,第5位为0标识程序运行为arm状态,若其为1则运行在thumb状态;设置处理器为32位管理模式,并运行与arm状态msr cpsr,r0/* turn off the watchdog */#if defined(CONFIG_S3C2400)# define pWTCON 0x15300000# define INTMSK 0x14400008 /* Interupt-Controller base addresses */# define CLKDIVN 0x14800014 /* clock divisor register */#elif defined(CONFIG_S3C2410);看门狗寄存器地址# define pWTCON 0x53000000;中断掩码寄存器,决定那个中断源被屏蔽,某位为1则屏蔽中断源,初始值为0xFFFFFFFF,屏蔽所有中断# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */;中断子掩码寄存器,该寄存器只能屏蔽11个中断源,因此其仅低11位有效,初始值为0x7FF# define INTSUBMSK 0x4A00001C;时钟分频控制寄存器# define CLKDIVN 0x4C000014 /* clock divisor register */#endif#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410);将看门狗寄存器清空,其各位含义为,第0位为1则当看门狗定时器溢出时重启,为0则不重启,初值为1;第2位为中断使能位,初值为0;第3、4位为时钟分频因子,初值为00,;第5位为看门狗的使能位初值为1;第8~15位为比例因子,初值为0x80ldr r0, =pWTCONmov r1, #0x0;将看门狗寄存器所有位置零,关闭看门狗,其实只要将第5位置0即可str r1, [r0];屏蔽所有中断,实际上中断屏蔽掩码寄存器初值即为0xFFFFFFFmov r1, #0xffffffffldr r0, =INTMSKstr r1, [r0]# if defined(CONFIG_S3C2410);设置子中断掩码寄存器ldr r1, =0x3ffldr r0, =INTSUBMSKstr r1, [r0]# endif;设置时钟寄存器,CLKDIVN第0位为PDIVN,为0则PCLK=HCLK,为1则PCLK=HCLK/2;第1位为HDIVN,为0则HCLK=FCLK,为1则HCLK=FCLK/2;这里两位均为1,则FCLK:HCLK:PCLK = 4:2:1/* default FCLK is 120 MHz ! */ldr r0, =CLKDIVNmov r1, #3str r1, [r0]#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 *//** we do sys-critical inits only at reboot,* not when booting from ram!*/;对临界寄存器的初始化,如果从ram中启动则不执行,如果重启则执行#ifndef CONFIG_SKIP_LOWLEVEL_INITbl cpu_init_crit#endif;重定向代码,也就是从flash中复制到ram中#ifndef CONFIG_SKIP_RELOCATE_UBOOTrelocate: /* relocate U-Boot to RAM */;当前代码地址,adr获取当前代码的地址信息,若从ram运行则_start=TEXT_BASE,否则_start=0x00000000adr r0, _start /* r0 <- current position of code */;获取_TEXT_BASEldr r1, _TEXT_BASE /* test if we run from flash or RAM */cmp r0, r1 /* don't reloc during debug */ ;两者相等,表示从ram运行则跳转到堆栈设置beq stack_setup;不相等则表示从flash中运行,重定向代码ldr r2, _armboot_start;获取未初始化数据段地址ldr r3, _bss_start;计算代码段大小sub r2, r3, r2 /* r2 <- size of armboot */;计算代码段终止地址add r2, r0, r2 /* r2 <- source end address */;复制代码,r0为代码的起始地址,r1为ram中地址,r2为代码的终止地址 ;每次copy后将r0值递增同r2比较来判断是否复制完成copy_loop:ldmia r0!, {r3-r10} /* copy from source address [r0] */stmia r1!, {r3-r10} /* copy to target address [r1] */cmp r0, r2 /* until source end addreee [r2] */ble copy_loop#endif /* CONFIG_SKIP_RELOCATE_UBOOT *//* Set up the stack */stack_setup:;获取_TEXT_BASEldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */;获取分配区域起始指针,CFG_MALLOC_LEN=128*1024+CFG_ENV_SIZE=128*1024+0x1000 0=192Ksub r0, r0, #CFG_MALLOC_LEN /* malloc area */ ;另外分配128bytes来存储开发板信息sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */#ifdef CONFIG_USE_IRQsub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ) #endif;再减去12bytes用于栈起点sub sp, r0, #12 /* leave 3 words for abort-stack */;清空未初始化数据段clear_bss:ldr r0, _bss_start /* find start of bss segment */ldr r1, _bss_end /* stop here */mov r2, #0x00000000 /* clear */clbss_l:str r2, [r0] /* clear loop... */add r0, r0, #4cmp r0, r1ble clbss_l#if 0;关闭看门狗/* try doing this stuff after the relocation */ldr r0, =pWTCONmov r1, #0x0str r1, [r0]/** mask all IRQs by setting all bits in the INTMR - default*/;禁止中断mov r1, #0xffffffffldr r0, =INTMRstr r1, [r0];设置时钟/* FCLK:HCLK:PCLK = 1:2:4 *//* default FCLK is 120 MHz ! */ldr r0, =CLKDIVNmov r1, #3str r1, [r0]/* END stuff after relocation */#endif;完成复制后跳转到start_armboot,到这里就进入函数lib_arm/board.c的start_armboot函数中ldr pc, _start_armboot_start_armboot: .word start_armboot;这里指的从flash中运行是指的从flash rom中运行,也就是常说的从nor flash中运行程序,现在有很多开发板;都是利用SDRAM和NAND-FLASH共同工作,所以需要添加从nand flash启动的代码。
am335xu-boot启动过程分析 u-boot属于两阶段的bootloader,第⼀阶段的⽂件为 arch/arm/cpu/armv7/start.S 和 arch/arm/cpu/armv7/lowlevel_init.S,前者是平台相关的,后者是开发板相关的。
1. u-boot第⼀阶段代码分析 (1)硬件设备初始化 将CPU的⼯作模式设为管理模式(SVC); 关闭中断; 禁⽤MMU,TLB ; 板级初始化; (2)为加载Bootloader的第⼆阶段代码准备RAM空间 加载u-boot.img,跳转到u-boot.img; 上述⼯作,也就是uboot-spl代码流程的核⼼。
代码如下:arch/arm/cpu/armv7/start.S1/*2 * the actual reset code3*/4reset:5 bl save_boot_params6/*7 * disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,8 * except if in HYP mode already9*/10 mrs r0, cpsr11 and r1, r0, #0x1f @ mask mode bits12 teq r1, #0x1a @ test for HYP mode13 bicne r0, r0, #0x1f @ clear all mode bits14 orrne r0, r0, #0x13 @ set SVC mode15 orr r0, r0, #0xc0 @ disable FIQ and IRQ16 msr cpsr,r017@@ 以上通过设置CPSR寄存器⾥设置CPU为SVC模式,禁⽌中断18@@ 具体操作可以参考《[kernel 启动流程] (第⼆章)第⼀阶段之——设置SVC、关闭中断》的分析1920/* the mask ROM code should have PLL and others stable */21#ifndef CONFIG_SKIP_LOWLEVEL_INIT22 bl cpu_init_cp1523@@ 调⽤cpu_init_cp15,初始化协处理器CP15,从⽽禁⽤MMU和TLB。
2 uboot源码分析2.5.1.start。
S引入2。
5.1.start。
S引入2.5。
1.1、u-boot。
lds中找到start.S入口(1)在C语言中整个项目的入口就是main函数(这是C语言规定的),所以譬如说一个有10000个.c文件的项目,第一个要分析的文件就是包含了main函数的那个文件.(2方。
ENTRY(_start)因此_start符号所在的文件就是整个程序的起始文件,_start所在处的代码就是整个程序的起始代码。
2。
5.1.2、SourceInsight中如何找到文件(1)当前状况:我们知道在uboot中的1000多个文件中有一个符号叫_start,但是我们不知道这个符号在哪个文件中。
这种情况下要查找一个符号在所有项目中文件中的引用,要使用SourceInsight的搜索功能。
(2)start。
s 在cpu/arm_cortexa9/start.s(3)然后进入start。
S文件中,发现57行中就是_start标号的定义处,于是乎我们就找到了整个uboot的入口代码,就是第57行。
2.5。
1.3、SI中找文件技巧(1)以上,找到了start.S文件,下面我们就从start。
S文件开始分析uboot第一阶段。
(2)在SI中,如果我们知道我们要找的文件的名字,但是我们又不知道他在哪个目录下,我们要怎样找到并打开这个文件?方法是在SI中先打开右边的工程项目管理栏目,然后点击最左边那个(这个是以文件为单位来浏览的),然后在上面输入栏中输入要找的文件的名字。
我们在输入的时候,SI在不断帮我们进行匹配,即使你不记得文件的全名只是大概记得名字,也能帮助你找到你要找的文件。
2。
5。
2。
start.S解析12。
5。
2。
1、不简单的头文件包含(1)#include 〈config.h>.config.h是在include目录下的,这个文件不是源码中本身存在的文件,而是配置过程中自动生成的文件。