lowlevel_init 函数分析

本文详细分析了嵌入式系统启动过程中的关键步骤,包括压栈、复位状态检测、IO恢复、看门狗关闭、供电锁存、时钟初始化、DDR内存配置、串口初始化、tzpc_init模块设置、打印K标识以及最后的出栈操作,全面揭示了系统从启动到运行的底层逻辑。
摘要由CSDN通过智能技术生成
lowlevel_init函数主要用做底层的初始化,在start.S中确定启动介质后就要调用这个函数。uboo\board\samsung\x210/lowlevel_init.S

压栈

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

#include <s5pc110.h>
#include "smdkc110_val.h"

_TEXT_BASE:
	.word	TEXT_BASE

	.globl lowlevel_init
lowlevel_init:
	push	{
   lr}		@@压栈,调用之前有设置栈,所以才能压栈

检测复位状态

/* check reset status  */		@@检测复位状态;复位状态分为多种冷启动热启动休眠状态
	@@判断复位状态;不同的状态硬件的状态不一样比如冷启动DDR还没有初始化
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
	ldr	r1, [r0]
	cmp	r1, #0x10000
	beq	wakeup_reset_pre
	cmp	r1, #0x80000
	beq	wakeup_reset_from_didle

IO状态恢复

/* IO Retention release */		@@IO状态恢复
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)
	ldr	r1, [r0]
	ldr	r2, =IO_RET_REL
	orr	r1, r1, r2
	str	r1, [r0]

关看门狗

/* Disable Watchdog */		@@关看门狗
	ldr	r0, =ELFIN_WATCHDOG_BASE	/* 0xE2700000 */
	mov	r1, #0
	str	r1, [r0]

供电锁存

/* PS_HOLD pin(GPH0_0) set to high */			@@供电锁存
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
	ldr	r1, [r0]
	orr	r1, r1, #0x300		@@两步,因为一步是非法立即数
	orr	r1, r1, #0x1			@@
	str	r1, [r0]

初始化时钟

/* when we already run in ram, we don't need to relocate U-Boot.
	 * and actually, memory controller must be configured before U-Boot
	 * is running in ram.
	 */		@@判断当前代码执行的地址;是通过代码运行的地址就能知道是否是冷启动,要不要 初始化DDR
	ldr	r0, =0xff000fff
	bic	r1, pc, r0		/* r0 <- current base addr of code */		@@ r1 = pc & ~r0	;运行地址
	ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */		@@获取链接地址
	bic	r2, r2, r0		/* r0 <- current base addr of code */
	cmp     r1, r2                  /* compare r0, r1                  */
	beq     1f			/* r0 == r1 then skip sdram init   */		@@ 1 是标号  f 向下找
		@@通过上边的代码判断要不要执行下边这两个函数
	/* init system clock */		@@初始化时钟
	bl system_clock_init

初始化DDR(动态内存)

/* Memory initialize */		@@初始化DDR(初始化动态内存)
	bl mem_ctrl_asm_init

初始化串口

1:
	/* for UART */
	bl uart_asm_init		@@初始化串口

初始化tzpc_init

	bl tzpc_init	

打印K

	/* Print 'K' */
	ldr	r0, =ELFIN_UART_CONSOLE_BASE
	ldr	r1, =0x4b4b4b4b
	str	r1, [r0, #UTXH_OFFSET]

出栈

	pop	{
   pc}

整体

/*
 * Memory Setup stuff - taken from blob memsetup.S
 *
 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
 *                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
 *
 * Modified for the Samsung SMDK2410 by
 * (C) Copyright 2002
 * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */


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

#include <s5pc110.h>
#include "smdkc110_val.h"

_TEXT_BASE:
	.word	TEXT_BASE

	.globl lowlevel_init
lowlevel_init:
	push	{
   lr}		@@压栈,调用之前有设置栈,所以才能压栈

	/* check reset status  */		@@检测复位状态;复位状态分为多种冷启动热启动休眠状态
	@@判断复位状态;不同的状态硬件的状态不一样比如冷启动DDR还没有初始化
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
	ldr	r1, [r0]
	cmp	r1, #0x10000
	beq	wakeup_reset_pre
	cmp	r1, #0x80000
	beq	wakeup_reset_from_didle

	/* IO Retention release */		@@IO状态恢复
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)
	ldr	r1, [r0]
	ldr	r2, =IO_RET_REL
	orr	r1, r1, r2
	str	r1, [r0]

	/* Disable Watchdog */		@@关看门狗
	ldr	r0, =ELFIN_WATCHDOG_BASE	/* 0xE2700000 */
	mov	r1, #0
	str	r1, [r0]

	/* SRAM(2MB) init for SMDKC110 */
	/* GPJ1 SROM_ADDR_16to21 */
	ldr	r0, =ELFIN_GPIO_BASE
	
	ldr	r1, [r0, #GPJ1CON_OFFSET]
	bic	r1, r1, #0xFFFFFF
	ldr	r2, =0x444444
	orr	r1, r1, r2
	str	r1, [r0, #GPJ1CON_OFFSET]

	ldr	r1, [r0, #GPJ1PUD_OFFSET]
	ldr	r2, =0x3ff
	bic	r1, r1, r2
	str	r1, [r0, #GPJ1PUD_OFFSET]

	/* GPJ4 SROM_ADDR_16to21 */
	ldr	r1, [r0, #GPJ4CON_OFFSET]
	bic	r1, r1, #(0xf<<16)
	ldr	r2, =(0x4<<16)
	orr	r1, r1, r2
	str	r1, [r0, #GPJ4CON_OFFSET]

	ldr	r1, [r0, #GPJ4PUD_OFFSET]
	ldr	r2, =(0x3<<8)
	bic	r1, r1, r2
	str	r1, [r0, #GPJ4PUD_OFFSET]


	/* CS0 - 16bit sram, enable nBE, Byte base address */
	ldr	r0, =ELFIN_SROM_BASE	/* 0xE8000000 */
	mov	r1, #0x1
	str	r1, [r0]

	/* PS_HOLD pin(GPH0_0) set to high */			@@供电锁存
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
	ldr	r1, [r0]
	orr	r1, r1, #0x300		@@两步,因为一步是非法立即数
	orr	r1, r1, #0x1			@@
	str	r1, [r0]

	/* when we already run in ram, we don't need to relocate U-Boot.
	 * and actually, memory controller must be configured before U-Boot
	 * is running in ram.
	 */		@@判断当前代码执行的地址;是通过代码运行的地址就能知道是否是冷启动,要不要 初始化DDR
	ldr	r0, =0xff000fff
	bic	r1, pc, r0		/* r0 <- current base addr of code */		@@ r1 = pc & ~r0	;运行地址
	ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */		@@获取链接地址
	bic	r2, r2, r0		/* r0 <- current base addr of code */
	cmp     r1, r2                  /* compare r0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值