您的位置:首页 > 编程语言

UBOOT 的 lowlevel_init.S,代码分析,底层分析,底层初始化

2010-04-22 15:04 441 查看
这个文件主要是设置系统时钟,初始化flash,以及SDRAM。。。

../u-boot-1.3.1/cpu/arm920t/at91rm9200/lowlevel_init.S

#include <config.h>

#include <version.h>
//CONFIG_SKIP_LOWLEVEL_INIT定义见../u-boot-1.3.1/include/configs/at91rm9200dk.h

#ifndef CONFIG_SKIP_LOWLEVEL_INIT

/*

* some parameters for the board

*

* This is based on rm9200dk.cfg for the BDI2000 from ABATRON which in

* turn is based on the boot.bin code from ATMEL

*

*/
//flash相关寄存器

/* flash */

#define MC_PUIA 0xFFFFFF10

#define MC_PUP 0xFFFFFF50

#define MC_PUER 0xFFFFFF54

#define MC_ASR 0xFFFFFF04

#define MC_AASR 0xFFFFFF08

#define EBI_CFGR 0xFFFFFF64

#define SMC2_CSR 0xFFFFFF70

//系统时钟相关寄存器

/* clocks */

#define PLLAR 0xFFFFFC28

#define PLLBR 0xFFFFFC2C

#define MCKR 0xFFFFFC30

#define AT91C_BASE_CKGR 0xFFFFFC20

#define CKGR_MOR 0

//sdram相关寄存器

/* sdram */

#define PIOC_ASR 0xFFFFF870

#define PIOC_BSR 0xFFFFF874

#define PIOC_PDR 0xFFFFF804

#define EBI_CSA 0xFFFFFF60

#define SDRC_CR 0xFFFFFF98

#define SDRC_MR 0xFFFFFF90

#define SDRC_TR 0xFFFFFF94

_MTEXT_BASE:

#undef START_FROM_MEM//从flash,还是从sdram启动, 这里定义从sdram启动

#ifdef START_FROM_MEM

.word TEXT_BASE-PHYS_FLASH_1

#else

.word TEXT_BASE//TEXT_BASE在../u-boot-1.3.1/board/at91rm9200dk/config.mk

#endif
.globl lowlevel_init

lowlevel_init:

/* Get the CKGR Base Address */

ldr r1, =AT91C_BASE_CKGR //初始化系统时钟

/* Main oscillator Enable register */

#ifdef CFG_USE_MAIN_OSCILLATOR

ldr r0, =0x0000FF01 /* Enable main oscillator, OSCOUNT = 0xFF */

#else

ldr r0, =0x0000FF00 /* Disable main oscillator, OSCOUNT = 0xFF */

#endif

str r0, [r1, #CKGR_MOR]

/* Add loop to compensate Main Oscillator startup time */

ldr r0, =0x00000010//这个地方相当与一段延时,保证系统时钟设置正常

LoopOsc:

subs r0, r0, #1

bhi LoopOsc
/* memory control configuration *///初始化flash

/* this isn't very elegant, but what the heck */

ldr r0, =SMRDATA //将标号SMRDATA所标识的地址写入r0
ldr r1, _MTEXT_BASE //将标号_MTEXT_BASE处的数据写入r1
sub r0, r0, r1 //得到相对起始地址 我总觉得这个地方有些问题,可很多人认为没有问题。。。。有待深究,是不是我多了呢?

add r2, r0, #80 //得到相对结束地址

0:

/* the address */
//不仔细的看,你还真发现不了这个地方的妙处,哈哈,想法挺好。。。。
//需要配合下面的表一起看,估计你就能明白了。

ldr r1, [r0], #4 //R1 ← [R0] , R0 ← R0 + 4

/* the value */

ldr r3, [r0], #4

str r3, [r1]

cmp r2, r0

bne 0b

/* delay - this is all done by guess */

ldr r0, =0x00010000

1:

subs r0, r0, #1

bhi 1b

ldr r0, =SMRDATA1//初始化sdram

ldr r1, _MTEXT_BASE

sub r0, r0, r1

add r2, r0, #176

2:

/* the address */

ldr r1, [r0], #4

/* the value */

ldr r3, [r0], #4

str r3, [r1]

cmp r2, r0

bne 2b
/* switch from FastBus to Asynchronous clock mode */
//结合datasheet看,有详细的描述

mrc p15, 0, r0, c1, c0, 0 //将读出的数据放到r0中

orr r0, r0, #0xC0000000 @ set bit 31 (iA) and 30 (nF)
//主要是设置C1,异步模式;C0是只读的

mcr p15, 0, r0, c1, c0, 0
/* everything is fine now */

mov pc, lr
.ltorg

SMRDATA:

.word MC_PUIA

.word MC_PUIA_VAL//../u-boot-1.3.1/include/configs/at91rm9200dk.h有定义

.word MC_PUP

.word MC_PUP_VAL

.word MC_PUER

.word MC_PUER_VAL

.word MC_ASR

.word MC_ASR_VAL

.word MC_AASR

.word MC_AASR_VAL

.word EBI_CFGR

.word EBI_CFGR_VAL

.word SMC2_CSR

.word SMC2_CSR_VAL

.word PLLAR

.word PLLAR_VAL

.word PLLBR

.word PLLBR_VAL

.word MCKR

.word MCKR_VAL

/* SMRDATA is 80 bytes long */

/* here there's a delay of 100 */

SMRDATA1:

.word PIOC_ASR

.word PIOC_ASR_VAL

.word PIOC_BSR

.word PIOC_BSR_VAL

.word PIOC_PDR

.word PIOC_PDR_VAL

.word EBI_CSA

.word EBI_CSA_VAL

.word SDRC_CR

.word SDRC_CR_VAL

.word SDRC_MR

.word SDRC_MR_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRC_MR

.word SDRC_MR_VAL1

.word SDRAM

.word SDRAM_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRC_MR

.word SDRC_MR_VAL2

.word SDRAM1

.word SDRAM_VAL

.word SDRC_TR

.word SDRC_TR_VAL

.word SDRAM

.word SDRAM_VAL

.word SDRC_MR

.word SDRC_MR_VAL3

.word SDRAM

.word SDRAM_VAL

/* SMRDATA1 is 176 bytes long */

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */
//------------------这有另一篇文章:-----------------------------
来自:http://blog.csdn.net/sunrock/archive/2008/03/27/2223562.aspx

本文主要分析与U-Boot启动过程相关的汇编代码lowlevel_init.S,目标平台以PXA270为例。

文件位于board/myboard/lowlevel_init.S,主要执行内存相关的初始化
把链接寄存器LR(即R14)的值转存到寄存器R10中,以便lowlevel_init完成后恢复执行

.globl lowlevel_init

lowlevel_init:

mov r10, lr
按顺序初始化GPIO寄存器: GPSR GPCR GRER GFER GPDR GAFR PSSR

/* Set up GPIO pins first */

ldr r0, =GPSR0

ldr r1, =CFG_GPSR0_VAL

str r1, [r0]

.....

初始化内存控制器

/* Initlialize Memory Controller */

@ skip memory init if we're run in ram(must be a JTAG run)

mov r0, pc

ldr r1, =0xa0000000

and r0, r0, r1 /* 把当前PC寄存器的值与0xa0000000逻辑与*/

cmp r0, r1 /* 如果结果等于0xa0000000,说明uboot是从RAM启动的 */

beq mem_init_done /* 那么就需要跳过RAM初始化, 直接跳转到mem_init_done执行 */
/* 具体的初始化操作与目标板有很大相关性,下面以我的PXA270开发板为例 */
mem_init:

@ get memory controller base address

ldr r1, =MEMC_BASE /* 内存控制器基地址 */
初始化内存控制器 Step 1
@****************************************************************************

@ Step 1

@

@ Step 1a

/* Initlialize Static Memory Control register */

/* 初始化MSCx寄存器需要设置 */

/* RBUFFx —— Return Data Buffer vs. Streaming Behavior */

/* RRRx —— ROM/SRAM Recovery Time */

/* RDNx —— ROM Delay Next Access */

/* RDFx —— The ROM Delay First Access */

/* RBWx —— ROM Bus Width */

/* RTx —— ROM Type */

@ write msc0, read back to ensure data latches

ldr r2, =CFG_MSC0_VAL

str r2, [r1, #MSC0_OFFSET]

ldr r2, [r1, #MSC0_OFFSET] /* Ensure that the new value has been accepted and programmed */

......
@ Step 1b

/* 配置PCMCIA和CF需要设置下面这些寄存器 */

@ MECR —— Expansion Memory (PC Card/CompactFlash) Bus Configuration register

@ MCMEMx —— PC Card Interface Common Memory Space Socket 0/1 Timing Configuration register

@ MCATTx —— PC Card Interface Attribute Space Socket 0/1 Timing Configuration register

@ MCIOx —— PC Card Interface I/O Space Socket 0/1 Timing Configuration register
@ Step 1c

@ fly-by-dma is defeatured on this part

@ write flycnfg —— Fly-by DMA DVAL<1:0> polarities

@ldr r2, =CFG_FLYCNFG_VAL

@str r2, [r1, #FLYCNFG_OFFSET]
@ Step 1d

@ fetch platform value of mdcnfg —— SDRAM Configuration register

@

ldr r2, =CFG_MDCNFG_VAL
@ disable all sdram banks

@

bic r2, r2, #(MDCNFG_DE0 | MDCNFG_DE1)

bic r2, r2, #(MDCNFG_DE2 | MDCNFG_DE3)

str r2, [r1, #MDCNFG_OFFSET]
@ Step 1e

@ write MDREFR —— SDRAM Refresh Control register

ldr r3, = CFG_MDREFR_VAL

ldr r2, = 0xFFF /* DRI mask */

and r3, r3, r2

ldr r4, [r1, #MDREFR_OFFSET] /* reset value */

bic r4, r4, r2 /* clear DRI field —— SDRAM Refresh Interval for All Partitions */

orr r4, r4, r3

orr r4, r4, #MDREFR_K0RUN /* SDCLK0 Run Control/Status */

bic r4, r4, #MDREFR_K0DB2 /* SDCLK0 Divide by 2 Control/Status */

bic r4, r4, #MDREFR_K0DB4 /* SDCLK0 Divide by 4 Control/Status */

bic r4, r4, #MDREFR_K2FREE /* SDCLK<2> Free-Running Control */

bic r4, r4, #MDREFR_K1FREE

bic r4, r4, #MDREFR_K0FREE

orr r4, r4, #MDREFR_SLFRSH /* SDRAM Self-Refresh Control/Status, Self-refresh enabled */

/* write back MDREFR */

str r4, [r1, #MDREFR_OFFSET]
初始化内存控制器 Step 2

@ Step 2

@ Configure synchronus flash memory
初始化内存控制器 Step 3
@ Step 3

@ Configure SDRAM

ldr r2, =CFG_MDREFR_VAL

bic r2, #MDREFR_APD /* SDRAM/Synchronous Static Memory Auto-Power-Down Enable */

str r2, [r1, #MDREFR_OFFSET]

ldr r3, [r1, #MDREFR_OFFSET] @ read back to make sure write action completed

初始化内存控制器 Step 4
@ Step 4

@ write initial value of mdcnfg, w/o enabling sdram banks

@

ldr r2, =CFG_MDCNFG_VAL

bic r2, r2, #(MDCNFG_DE0 | MDCNFG_DE1)

bic r2, r2, #(MDCNFG_DE2 | MDCNFG_DE3)

str r2, [r1, #MDCNFG_OFFSET]
@ldr r2, = CFG_MDREFR_VAL

@str r2, [r1, #MDREFR_OFFSET]
初始化内存控制器 Step 5

@ Step 5

@ pause for 200 uSecs

@

ldr r3, =OSCR @ reset the OS Timer Count to zero

mov r2, #0

str r2, [r3]

ldr r4, =0x300 @ really 0x2E1 is about 200usec, so 0x300 should be plenty ——3.25MHz clock

1:

ldr r2, [r3] /* r2读OS Timer Count*/

cmp r4, r2 /* 比较OS Timer Count和r4 */

bgt 1b /* 如果时间没到就循环 */
初始化内存控制器 Step 6
@ Step 6

@ Disable XScale Data Cache

mov r0, #0x78 @turn everything off

mcr p15, 0, r0, c1, c0, 0 @(caches off, MMU off, etc.) /* 设置协处理器P15 */
初始化内存控制器 Step 7 - 11
@ Step 7

@ Access memory *not yet enabled* for CBR refresh cycles (8) *NOTE: hardware reset only

@ - CBR is generated for all banks
ldr r2, =CFG_DRAM_BASE

str r2, [r2]

str r2, [r2]

str r2, [r2]

str r2, [r2]

str r2, [r2]

str r2, [r2]

str r2, [r2]

str r2, [r2]
@ Step 8

@ Enable data cache
@ Step 9

@ Enable SDRAM
@fetch current mdcnfg value

ldr r3, [r1, #MDCNFG_OFFSET]

orr r3, r3, #MDCNFG_DE0 /* enable sdram bank0 */
@write back mdcnfg, enabling the sdram bank(s)

str r3, [r1, #MDCNFG_OFFSET]
@ Step 10

@ write mdmrs —— SDRAM Mode Register Set Configuration Register

@

ldr r2, =CFG_MDMRS_VAL

str r2, [r1, #MDMRS_OFFSET]
@ Step 11

@ Enable MDREFR[APD] optionally

ldr r2, =CFG_MDREFR_VAL

str r2, [r1, #MDREFR_OFFSET]
Done Memory Init

mem_init_done:
@********************************************************************

@ Disable (mask) all interrupts at the interrupt controller

@
@ clear the interrupt level register (use IRQ, not FIQ)

@

mov r1, #0

ldr r2, =ICLR

str r1, [r2]
@ Set interrupt mask register

@

ldr r1, =CFG_ICMR_VAL /* set ICMR = 0, no interrupts enabled */

ldr r2, =ICMR

str r1, [r2]
@ ********************************************************************

@ Disable the peripheral clocks, and set the core clock

@
@ Turn Off ALL on-chip peripheral clocks for re-configuration

@

ldr r1, =CKEN /*clock enable register */

mov r2, #0

str r2, [r1]
@ set core clocks

@

ldr r1, =CCCR /* core clock configuration register */

ldr r2, [r1, #0]

ldr r3, =(CCCR_L_MASK | CCCR_2N_MASK)

bic r2, r2, r3

/* Run-Mode-to-Oscillator Ratio (L) creates the nominal run mode
frequency by multiplying the 13-MHz processor oscillator by L. */

/* Turbo-Mode-to-Run-Mode Ratio (N) creates the nominal turbo-mode frequency by multiplying the run-mode frequency by N. */

/* core freq: Normal 208MHz, Turbo 312MHz */

ldr r3, =(16 | 3<<7) /* Turbo-Mode-to-Run-Mode Ratio, N = 3/2 */

orr r2, r2, r3 /* Run-Mode-to-Oscillator Ratio = 16*13 MHz, */

str r2, [r1]
#ifdef ENABLE32KHZ

@ enable the 32Khz oscillator for RTC and PowerManager

@

ldr r1, =OSCC /* oscillator configuration register */

mov r2, #OSCC_OON /* 32.768kHz OON (write-once only bit) */

str r2, [r1]
@ NOTE: spin here until OSCC.OOK get set,

@ meaning the PLL has settled.

@

60:

ldr r2, [r1]

ands r2, r2, #1 /* r2 = r2 & 0x1, 取出最低位数据 */

beq 60b

#endif
@ Turn on needed clocks

@

ldr r1, =CKEN

ldr r2, =CFG_CKEN_VAL

str r2, [r1]
lowlevel_init完成

mov pc, r10 /* 恢复链接寄存器的值到PC,返回start.S调用lowlevel_init处继续执行 */

@ End lowlevel_ini
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: