加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

u-boot启动过程分解 1

发布时间:2020-12-15 06:13:38 所属栏目:百科 来源:网络整理
导读:这篇文章是tiny6410到手以后分析的第一个程序后写下的记录,由于各种原因整理一半以后就被搁置了,有些未解决问题, U-Boot 启动代码分析第一部分(汇编语言): ?????? 主要完成 cpu 初始化所涉及到寄存器设置,并将第二部分 C 语言代码复制到 RAM 中; ???

这篇文章是tiny6410到手以后分析的第一个程序后写下的记录,由于各种原因整理一半以后就被搁置了,有些未解决问题,

U-Boot启动代码分析第一部分(汇编语言):

?????? 主要完成cpu初始化所涉及到寄存器设置,并将第二部分C语言代码复制到RAM中;

?????? 此部分内容起始于/cpu/s3c64xx/S3c6410/start.S

涉及文件:

?????? /cpu/s3c64xx/S3c6410/start.S

?????? /board/Samsung/Mini6410/lowlevel_init.S???

?????? Note:此文件夹为FriendlyARM针对Mini6410修改代码,移植于Smdk6410

?????? /include/s3c6410.h

定义中断向量表

/cpu/start.S

_start: b?? reset

?????? ldr?? pc,_undefined_instruction

?????? ldr?? pc,_software_interrupt

?????? ldr?? pc,_prefetch_abort

?????? ldr?? pc,_data_abort

?????? ldr?? pc,_not_used

?????? ldr?? pc,_irq

?????? ldr?? 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

/*

?* exception handlers

?*/

?????? .align?????? 5

undefined_instruction:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_undefined_instruction

?

?????? .align?????? 5

software_interrupt:

?????? get_bad_stack_swi

?????? bad_save_user_regs

?????? bl???? do_software_interrupt

在跳转中断服务程序前,首先要有两个宏操作,一个是对stack的操作,一个是对用户reg保存;

?????? .align?????? 5

prefetch_abort:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_prefetch_abort

?

?????? .align?????? 5

data_abort:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_data_abort

?

?????? .align?????? 5

not_used:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_not_used

?

#ifdef CONFIG_USE_IRQ

?

?????? .align?????? 5

irq:

?????? get_irq_stack

?????? irq_save_user_regs

?????? bl???? do_irq

?????? irq_restore_user_regs

?

?????? .align?????? 5

fiq:

?????? get_fiq_stack

?????? /* someone ought to write a more effiction fiq_save_user_regs */

?????? irq_save_user_regs

?????? bl???? do_fiq

?????? irq_restore_user_regs

?

#else

?

?????? .align?????? 5

irq:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_irq

?

?????? .align?????? 5

fiq:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_fiq

?

#else

?

?????? .align?????? 5

irq:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_irq

?

?????? .align?????? 5

fiq:

?????? get_bad_stack

?????? bad_save_user_regs

?????? bl???? do_fiq

对应的中断子程序将在 /cpu/$(ARCH)/interrupts.c中执行

存储器映射定义:

_TEXT_PHY_BASE:

?????? .word????? CFG_PHY_UBOOT_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_START

IRQ_STACK_START:

?????? .word????? 0x0badc0de

?

/* IRQ stack memory (calculated at run-time) */

?

.globl FIQ_STACK_START

FIQ_STACK_START:

?????? .word 0x0badc0de

#endif


上电后执行动作:

1. 上电后执行reset:设置CPUSVC模式:

reset:

?????? /*

?????? ?* set the cpu to SVC32 mode

?????? ?*/

?????? mrs? r0,cpsr

?????? bic?? r0,r0,#0x1f

?????? orr?? r0,#0xd3

?????? msr? cpsr,r0

2. CPU初始化循环:

?????? 2.1 无效caches,关闭cachesMMU

cpu_init_crit:

?????? /*

?????? ?* flush v4 I/D caches

?????? ?*/

?????? mov r0,#0

?????? mcr p15,c7,0????? /* flush v3/v4 cache */

?????? mcr p15,c8,0????? /* flush v4 TLB */

?????? /*

?????? ?* disable MMU stuff and caches

?????? ?*/

?????? mrc p15,c1,c0,0

?????? bic?? r0,#0x00002300????? @ clear bits 13,9:8 (--V- --RS)

?????? bic?? r0,#0x00000087????? @ clear bits 7,2:0 (B--- -CAM)

?????? orr?? r0,#0x00000002????? @ set bit 2 (A) Align

?????? orr?? r0,#0x00001000????? @ set bit 12 (I) I-Cache

?????? mcr p15,0

?

?????? /* Peri port setup bank0 and bank1 set to 1 as 16bits mode*/

?????? ldr?? r0,=0x70000000??? /*70000000-SROM bus width and wait control*/

?????? orr?? r0,#0x13???????? /*bank0 and bank1 setting 16-bit*/

??? mcr p15,c15,c2,4??

@ 256M(0x70000000-0x7fffffff)

注:此处无效掉I/D caches,关闭cachesMMU,同时设置用于bank0bank1的数据总线宽度控制器为16-bit模式;


S3c64xxs3c24xx此处初始化有些诧异:在S3c64xx中强制进行了cpu_init_crit

s3c24xx中首先判断,若未定义CONFIG_SKIP_LOWLEVEL_INIT,则进入cpu_init_crit

2.2 配置ONENAND控制器:

#ifdef CONFIG_BOOT_ONENAND

????? ldr?? r0,=0x70000000?????????? @ onenand controller setup

????? orr?? r0,#0x100000

????? ldr?? r1,=0x4000

????? orr?? r1,r1,#0xe0

????? str?? r1,[r0]

?

#if defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)

????? orr?? r0,#300?????????? @ disable watchdog

????? mov r1,#1

????? str?? r1,[r0]

?

????? mov r1,#0x23000000?????????? @ start buffer register

????? orr?? r1,#0x30000

????? orr?? r1,#0xc800

#else

????? mov r1,=0x20000000?????????? @ start buffer register

????? orr?? r1,#0xc30000

????? orr?? r1,#0xc800

#endif

?

????? sub? r0,#0x0400???????????? @ start address1 register

?

????? ldr?? r2,[r1,#0x84]????????????? @ ecc bypass

????? orr?? r2,r2,#0x100

????? str?? r2,#0x84]

?

????? mov r3,#0x0???????? @ DFS,FBA

????? str?? r3,[r0,#0x00]

????? str?? r3,#0x04]????????????? @ select dataram for DDP as 0

?

????? mov r4,#0x104???????????? @ interrupt register

????? mov r5,#0x0002?????????? @ FPA,FSA

????? mov r6,#0x0800?????????? @ BSA

?

onenand_bl1_load:

????? str?? r5,#0x1c]????????????? @ save FPA,FSA

????? orr?? r6,r6,#0x02???????? @ BSC

????? str?? r6,#0x00]????????????? @ save BSA,BSC

????? str?? r3,r4]???????????? @ clear interrupt

????? str?? r3,#0x80]????????????? @ write load command

?

????? mov r7,#0x100???????????? @ need small delay

?

onenand_wait_loop1:

????? subs r7,r7,#0x1

????? bne? onenand_wait_loop1

?

????? add? r5,r5,#0x2?????????? @ next FPA,FSA

????? sub? r6,#0x2

????? add? r6,#0x200??????? @ next BSA

????? cmp r5,#0x8

????? bne? onenand_bl1_load

#endif

若启动定义了CONFIG_BOOT_ONENAND,对ONENAND flash 初始化,此类型ROM暂时不涉及,内容跳过。

?

2.3 调用lowlevel_init对底层的初始化:

lowlevel_init:

?????? mov r12,lr???? /*保存程序返回地址,待调用执行完成后返回原地址*/

?

?????? /* LED on only #8 */

?????? ldr?? r0,=ELFIN_GPIO_BASE

?????? ldr?? r1,=0x55540000

?????? str?? r1,#GPNCON_OFFSET]

?

?????? ldr?? r1,=0x55555555

?????? str?? r1,#GPNPUD_OFFSET]

?

?????? ldr?? r1,=0xf000

?????? str?? r1,#GPNDAT_OFFSET]

?

?????? ldr?? r0,=0x1

?????? str?? r1,#GPECON_OFFSET]

?????? ldr?? r1,=0x0

?????? str?? r1,#GPEDAT_OFFSET]

?

?????? ldr?? r0,=0x2A5AAAAA

?????? str?? r1,#GPPCON_OFFSET]

?????? ldr?? r1,#GPPDAT_OFFSET]

??????

?

?????? ldr?? r1,#MEM1DRVCON_OFFSET]

?????? /*以上为配置GPNIOGPEIOGPPIO端口输出*/

?????? /* Disable Watchdog关闭看门狗 */

?????? ldr?? r0,=0x7e000000?????????? @0x7e004000

?????? orr?? r0,#0x4000

?????? mov r1,#0

?????? str?? r1,[r0]

?

?????? @ External interrupt pending clear清除外部中断标志

?????? ldr?? r0,=(ELFIN_GPIO_BASE+EINTPEND_OFFSET)??? /*EINTPEND*/

?????? ldr?? r1,[r0]

?????? str?? r1,[r0]

?

?????? ldr?? r0,=ELFIN_VIC0_BASE_ADDR ?????? @0x71200000

?????? ldr?? r1,=ELFIN_VIC1_BASE_ADDR ?????? @0x71300000

?

?????? @ Disable all interrupts (VIC0 and VIC1)关闭中断

?????? mvn r3,#0x0

?????? str?? r3,#oINTMSK]

?????? str?? r3,#oINTMSK]

?

?????? @ Set all interrupts as IRQ设置所有中断类型为IRQ

?????? mov r3,#oINTMOD]

?????? str?? r3,#oINTMOD]

?

?????? @ Pending Interrupt Clear清除中断标志

?????? mov r3,#oVECTADDR]

?????? str?? r3,#oVECTADDR]

?????? /*

* 以下为系统时钟初始化、串口初始化、NAND flash初始化调用,均为

* 对寄存器相应位设置,参考用户手册

*/

/*

* init system clock :关闭看门狗、屏蔽中断、设置FCLK:HCLK:PCLK* 钟比例

*/

?????? bl system_clock_init

?

?????? /* for UART */

?????? bl uart_asm_init

?

#if defined(CONFIG_NAND)

?????? /* simple init for NAND */

?????? bl nand_asm_init

#endif

/*

* 猜测:此部分已屏蔽判断初始化地址,转为跳转至电源唤醒模式处

*/

#if 0

?????? ldr?? r0,=0xff000fff

?????? bic?? r1,pc,r0??????? /* r0 <- current base addr of code */

?????? ldr?? r2,_TEXT_BASE???????? /* r1 <- original base addr in ram */

?????? bic?? r2,r0??????? /* r0 <- current base addr of code */

?????? cmp ????? r1,r2??????????????????? /* compare r0,r1????????????????? */

?????? beq? 1f????????????????? /* r0 == r1 then skip sdram init?? */

#endif

?

?????? bl???? mem_ctrl_asm_init

?

#if 1

??????? ldr???? r0,=(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)

??????? ldr???? r1,[r0]

??????? bic???? r1,#0xfffffff7

??????? cmp???? r1,#0x8

??????? beq???? wakeup_reset

?

#endif

/*

* UART channel 0 transmit buffer register setting 0x4b4b4b4b

*/

1:

?????? ldr?? r0,=ELFIN_UART_BASE

?????? ldr?? r1,=0x4b4b4b4b

?????? str?? r1,#UTXH_OFFSET]

?

?????? mov lr,r12

?????? mov pc,lr

?

此刻lowlevle_inti执行完成,返回start.Sline240


2.4 判断启动地址并复制程序至RAM

????? ldr?? r0,=0xff000fff

????? bic?? r1,r0??????? /* r0 <- current base addr of code */

????? ldr?? r2,_TEXT_BASE???????? /* r1 <- original base addr in ram */

????? bic?? r2,r0??????? /* r0 <- current base addr of code */

????? cmp???? r1,r2????????????????? /* compare r0,r1????????????????? */

????? beq???? after_copy???????????? /* r0 == r1 then skip flash copy?? */

?

此处判断程序运行地址是否在RAM中,如果没有,复制启动程序否则调用after_copy

?

2.5 不同ROM设备的程序复制工作

??????? Line252-line364针对NOR FLASH/NAND FLASH/MOVINAND FLASH/ONE NAND FLASH设备启动的代码复制进行区分设置,此部分代码量较大,不再附上;

?

2.6 copy code 后进行的工作(line365-line393):

?????? 1. GPP输出0xc00why??)

?????? 2. enable domain accesswhy??)

3. 设置TTB寄存器

4. 使能MMU

?

2.7 清除RAM空间(line397-line423):

?????? 1. 通过_TEXT_BASE地址推算出映像的起始地址;

?????? 2. 设置_bss_start_bss_end地址;

?????? 3. 清除bss空间;

?

2.8 程序跳转到_start_armboot处。


U-Boot启动第二部分(C语言):

?????? 继续汇编程序后的_start_armboot衔接部分,此部分已复制到RAM中,转为C语言启动过程继续;

?????? 此部分内容起始于:/Lib_arm/Board.c

?????? 涉及文件:

????????????? /Lib_arm/Board.c


C语言的入口函数:/board/Lib_arm/board.c void start_armboot(void);

1.?????? 定义所需变量并为全局变量指针gd初始化:

????? init_fnc_t **init_fnc_ptr;

????? char *s;

#ifndef CFG_NO_FLASH

????? ulong size;

#endif

?

#if defined(CONFIG_VFD) || defined(CONFIG_LCD)

????? unsigned long addr;

#endif

?

#if defined(CONFIG_BOOT_MOVINAND)

????? uint *magic = (uint *) (PHYS_SDRAM_1);

#endif

?

????? /* Pointer is writable since we allocated a register for it */

#ifdef CONFIG_MEMORY_UPPER_CODE /* by scsuh */

????? ulong gd_base;

?

????? gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);

#ifdef CONFIG_USE_IRQ

????? gd_base -= (CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ);

#endif

????? gd = (gd_t*)gd_base;

#else

????? gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

#endif

?

????? /* compiler optimization barrier needed for GCC >= 3.4 */

????? __asm__ __volatile__("": : :"memory");

?

????? memset ((void*)gd,sizeof (gd_t));

????? gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

????? memset (gd->bd,sizeof (bd_t));

?

monitor_flash_len = _bss_start - _armboot_start;

?????? 此处定义init_fnc_ptrs指针;

如果未定义CFG_NO_FLASH定义size

如果定义CONFIG_VFDCONFIG_LCD则定义addr

如果定义CONFIG_BOOT_MOVI_NAND则定义magic并初始化为PHYS_SDRAM_1

?

如果定义CONFIG_MEMORY_UPPER_ CODE则定义gd_base并初始化为SDRAM起始地址;如果定义CONFIG_USE_IRQ重新计算,减去IRQFIQ长度,并将gd_base计算值作为地址对gd初始化;

gd指针初始化设置内存空间;

gd->bd指针初始化地址,并设置内存空间;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读