u-boot第一阶段start.s分析:lowlevel_init部分

  u-boot一般分为两个阶段:

  第一阶段:硬件相关初始化、初始化内存芯片为bootloader做好准备、复制bootloader到RAM空间中、设置好栈方便调用C语言、跳转到C代码入口。这个部分是汇编语言部分,只是为调用C语言做好准备。

  第二阶段:初始化该阶段需要使用到的硬件设备、检测内存映射(MMU)、u-boot命令格式、为内核设置启动参数。这个部分就是C语言部分了。

以下是作者自己整理出的第一阶段流程图:u-boot分析第一阶段流程图:lowlevel_init,搭配着本文章阅读更香哦~

  start.s文件位置:cpu\s3c64xx\start.s,怎么知道这是开机运行的第一个程序呢?见u-boot顶层Makefile分析

.globl _start
_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
_pad:
	.word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:

	.balignl 16,0xdeadbeef

  第一句,跳转到reset,设置CPU模式为管理模式(svc),如下:

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

  然后关闭关闭数据和指令缓存,如下:

  为什么要关闭数据和指令缓存呢?

  因为Caches是CPU内部的一个2级缓存,它的作用是将常用的数据和指令放在CPU内部。Caches是通过CP15管理的,刚上电的时候,CPU还不能管理Caches。上电的时候指令Cache可关闭,也可不关闭,但数据Cache一定要关闭,否则可能导致刚开始的代码里面,去取数据的时候,从Cache里面取,而这时候RAM中数据还没有Cache过来,导致数据预取异常 。

	/*
	 * flush v4 I/D caches
	 */
	mov	r0, #0
	mcr	p15, 0, r0, c7, c7, 0	/* flush v3/v4 cache */
	mcr	p15, 0, r0, c8, c7, 0	/* flush v4 TLB */

  然后对端口进行设置:

	/* Peri port setup */
	ldr	r0, =0x70000000
	orr	r0, r0, #0x13
    	mcr	p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)

然后配置ONENAND控制器,若启动定义了CONFIG_BOOT_ONENAND,对ONENAND flash 初始化,此类型ROM暂时不涉及,内容跳过:

#ifdef CONFIG_BOOT_ONENAND
	ldr	r0, =0x70000000		@ onenand controller setup
	orr	r0, r0, #0x100000
	ldr	r1, =0x4000
	orr	r1, r1, #0xe0
	str	r1, [r0]

#if defined(CONFIG_S3C6410) || defined(CONFIG_S3C6430)
	orr	r0, r0, #300		@ disable watchdog
	mov	r1, #1
	str	r1, [r0]

	mov	r1, #0x23000000		@ start buffer register
	orr	r1, r1, #0x30000
	orr	r1, r1, #0xc800
#else
	mov	r1, =0x20000000		@ start buffer register
	orr	r1, r1, #0xc30000
	orr	r1, r1, #0xc800
#endif

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

	ldr	r2, [r1, #0x84]		@ ecc bypass
	orr	r2, r2, #0x100
	str	r2, [r1, #0x84]

	mov	r3, #0x0		@ DFS, FBA
	str	r3, [r0, #0x00]
	str	r3, [r0, #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, [r0, #0x1c]		@ save FPA, FSA
	orr	r6, r6, #0x02		@ BSC
	str	r6, [r1, #0x00]		@ save BSA, BSC
	str	r3, [r1, r4]		@ clear interrupt
	str	r3, [r1, #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, r6, #0x2
	add	r6, r6, #0x200		@ next BSA
	cmp	r5, #0x8
	bne	onenand_bl1_load
#endif

  然后调用lowlevel_init对底层的初始化:

	bl	lowlevel_init	/* go setup pll,mux,memory */

  而在start.s并未找到关键字lowlevel_init,这个关键字在board\samsung\mini6410\lowlevel_init.s中被定义:

  主要做的工作就是:配置GPNIO、GPEIO、GPPIO端口输出、关闭看门狗、清除外部中断标志、关闭所有的中断、设置所有中断类型为IRQ、清除中断标志、system_clock_init系统时钟初始化:(关闭看门狗、屏蔽中断、设置FCLK:HCLK:PCLK时* 钟比例)、uart_asm_init串口初始化、nand_asm_init是NAND FLASH初始化。

#include <config.h>
#include <version.h>

#include <s3c6410.h>
#include "mini6410_val.h"

_TEXT_BASE:
	.word	TEXT_BASE

	.globl lowlevel_
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值