ARM-1176 S3C6410 lowlevel_init过程注释

http://blog.csdn.net/viviod/article/details/7351324

 

花了三个晚上弄清楚整个流程之后,累翻了。我想,写完这份注释以后,大概我再也不想看到这块的启动分析了。

今天到此为止,明天开始做最后一个mem_ctrl_init的解析。两天内结束。


/*
 * 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 ch="" elsoft="" mueller="">
 *
 * 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 <S3C6410 h="">
#include "smdk6410_val.h"

_TEXT_BASE:
    .word    TEXT_BASE

    .globl lowlevel_init
lowlevel_init:
    mov    r12, lr
;保存当前链接寄存器地址,等跳转回start.s时继续执行使用

    ldr    r0, =ELFIN_GPIO_BASE ;定基地址 0x7f008000
    ldr     r1, =0x55555555   
    str     r1, [r0, #GPKCON0_OFFSET]; 0x7f008000 + 0x800
;设置引脚GPIO-K[0-7]管脚为cfdata 模式

    ldr     r1, =0x55555555
    str     r1, [r0, #GPKCON1_OFFSET];0x7f008000 + 0x804
;设置引脚GPIO-K[8-14]管脚为cfdata 模式


    ldr     r1, =0x22222666 ;0010 0010 0010 0010 0010 0110 0110 0110
    str     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 00
    str     r1, [r0, #GPFCON_OFFSET];0x7f008000 + 0xA0
;设置引脚GPIO-F14为输出

;GPIO-F14连接CLKOUT输出

    ldr     r1, =0x2000;    10000000000000
    str     r1, [r0, #GPFDAT_OFFSET];0x7f008000 + 0xA4

;通过向GPIO锁存器写1,维持一个高电平信号。
   
    /* LED on only #8 */
    ldr    r0, =ELFIN_GPIO_BASE ;0x7f008000
    ldr    r1, =0x00111111 ;0001 0001 0001 0001 0001 0001
    str    r1, [r0, #GPMCON_OFFSET] ;0x7f008000 + 0x820

;GPIO0-5引脚使能为输出

    ldr    r1, =0x00000555 ;010101010101
    str    r1, [r0, #GPMPUD_OFFSET]

;由于刚启动上电信号不稳定,GPIO0-5引脚下拉电阻保证信号毛刺消除?为何要接下拉,下拉一般是输入时用啊

    ldr    r1, =0x002a;  101010
    str    r1, [r0, #GPMDAT_OFFSET] ;0x7f008000 + 0x824
;点亮第二个LED和第4个LED


    ldr    r1, =0  /*0x55555555 phantom*/ ;1010101010101010101010101010101
    str    r1, [r0, #MEM1DRVCON_OFFSET]    ;0x7f008000 + 0x1D4
;内存驱动控制设置为默认值


    /* Disable Watchdog */
    ldr    r0, =0x7e000000        @0x7e004000
    orr    r0, r0, #0x4000
    mov    r1, #0
    str    r1, [r0]
;关看门狗

    @ External interrupt pending clear
    ldr    r0, =(ELFIN_GPIO_BASE+EINTPEND_OFFSET)    /*EINTPEND*/;0x7f008000 + 0x924
    ldr    r1, [r0]
    str    r1, [r0]
;外部中断挂起

    ldr    r0, =ELFIN_VIC0_BASE_ADDR     @0x71200000
    ldr    r1, =ELFIN_VIC1_BASE_ADDR     @0x71300000
;中断向量表0和中断向量表1地址

    @ Disable all interrupts (VIC0 and VIC1)
    mvn    r3, #0x0;反转为1
    str    r3, [r0, #oINTMSK];中断向量表0的中断使能清0
    str    r3, [r1, #oINTMSK];中断向量表1的中断是能清0
;
    @ Set all interrupts as IRQ
    mov    r3, #0x0
    str    r3, [r0, #oINTMOD];0x7120000c
    str    r3, [r1, #oINTMOD];0x7130000c
;中断选择寄存器,设置为0,选择IRQ中断模式

    @ Pending Interrupt Clear
    mov    r3, #0x0
    str    r3, [r0, #oVECTADDR]
    str    r3, [r1, #oVECTADDR]
;中断地址寄存器挂起清零。注意,手册上写,这里无论设置任何值都将挂起中断。
;务必在中断服务程序执行完毕之后进行清零
;否则将会导致不可预知的异常

 


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;运行至此处,做完了下面几件事情
;1,gpio使能并设置为CF卡功能模式
;2,led灯点亮
;3,关闭看门狗
;4,关闭外部中断并挂起
;5,关闭中断并挂起
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 


    /* init system clock */
    bl system_clock_init
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;运行至此处,做完了下面几件事情
; 运行至此处,时钟分频全部完成,设置为同步模式
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


    /* for UART */
    bl uart_asm_init
    @至此,uart串口使能完毕。

    ldr    r0, =ELFIN_UART_BASE
    ldr    r1, =0x4b4b4b4b
    str    r1, [r0, #UTXH_OFFSET]

#if defined(CONFIG_NAND)
    /* simple init for NAND */
    bl nand_asm_init
#endif

    bl    mem_ctrl_asm_init
    @跳到cpu_init.s文件中执行。执行完毕,跳转回此处,再跳转回kernel流程

#if 1
        ldr     r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
        ldr     r1, [r0]
        bic     r1, r1, #0xfffffff7
        cmp     r1, #0x8
        beq     wakeup_reset

#endif

1:
    ldr    r0, =ELFIN_UART_BASE
    ldr    r1, =0x4b4b4b4b
    str    r1, [r0, #UTXH_OFFSET]

    mov    lr, r12
    mov    pc, lr
#if 1
wakeup_reset:

    /*Clear wakeup status register*/
    ldr    r0, =(ELFIN_CLOCK_POWER_BASE+WAKEUP_STAT_OFFSET)
    ldr    r1, [r0]
    str    r1, [r0]

        /*LED test*/
        ldr     r0, =ELFIN_GPIO_BASE
        ldr     r1, =0x3000
        str     r1, [r0, #GPNDAT_OFFSET]

    /*Load return address and jump to kernel*/
    ldr    r0, =(ELFIN_CLOCK_POWER_BASE+INF_REG0_OFFSET)
    ldr    r1, [r0]    /* r1 = physical address of s3c6400_cpu_resume function*/
    mov    pc, r1        /*Jump to kernel (sleep-s3c6400.S)*/
    nop
    nop
#endif
/*
 * system_clock_init: Initialize core clock and bus clock.
 * void system_clock_init(void)
 */
system_clock_init:
    ldr    r0, =ELFIN_CLOCK_POWER_BASE  @0x7e00f000;APLL时钟地址

#ifdef    CONFIG_SYNC_MODE
    ldr    r1, [r0, #OTHERS_OFFSET]    ;0x7e00f000 + 0x900
    mov    r2, #0x40                   ;100 0000
    orr    r1, r1, r2                 
;设置为异步模式,不修改其他设置
    str    r1, [r0, #OTHERS_OFFSET]
;开始浮空,等待指令生效
    nop
    nop
    nop
    nop
    nop

    ldr    r2, =0x80      ; 1000 0000
;不理解此句,第八位开始是只读选项
    orr    r1, r1, r2
    str    r1, [r0, #OTHERS_OFFSET] ;0x7e00f000 + 0x900地址里的内容

check_syncack:
    ldr    r1, [r0, #OTHERS_OFFSET]
    ldr    r2, =0xf00                  ;1111 0000 0000
    and    r1, r1, r2
    cmp    r1, #0xf00
    bne    check_syncack; bne 非零则跳转
#else    /* ASYNC Mode */

#endif

    mov    r1, #0xff00
    orr    r1, r1, #0xff
    str    r1, [r0, #APLL_LOCK_OFFSET]
    str    r1, [r0, #MPLL_LOCK_OFFSET]
    str    r1, [r0, #EPLL_LOCK_OFFSET]
;使A,M,E三个时钟使能

/* CLKUART(=66.5Mhz) = CLKUART_input(532/2=266Mhz) / (UART_RATIO(3)+1) */
/* CLKUART(=50Mhz) = CLKUART_input(400/2=200Mhz) / (UART_RATIO(3)+1) */
/* Now, When you use UART CLK SRC by EXT_UCLK1, We support 532MHz & 400MHz value */

#if defined(CONFIG_CLKSRC_CLKUART)
    ldr       r1, [r0, #CLK_DIV2_OFFSET]              ;0x28
    ;取时钟分频地址
    bic    r1, r1, #0x70000                            ;0111 0000 0000 0000 0000
    orr    r1, r1, #0x30000                            ;0011 0000 0000 0000 0000
    str    r1, [r0, #CLK_DIV2_OFFSET]
#endif


    ldr       r1, [r0, #CLK_DIV0_OFFSET]    /*Set Clock Divider*/
    bic    r1, r1, #0x30000
    bic    r1, r1, #0xff00
    bic    r1, r1, #0xff
    ldr    r2, =CLK_DIV_VAL;时钟频率设置,
;#if defined(CONFIG_CLK_800_133_66)
;#define Startup_APLLdiv        0
;#define Startup_HCLKx2div    2
;#elif defined(CONFIG_CLK_400_133_66)
;#define Startup_APLLdiv        1
;#define Startup_HCLKx2div    2
;#else
;#define Startup_APLLdiv        0
;#define Startup_HCLKx2div    1
;#endif   
    ;#define    Startup_PCLKdiv        3
    ;#define Startup_HCLKdiv        1
    ;#define Startup_MPLLdiv        1
    ;#define CLK_DIV_VAL    ((Startup_PCLKdiv<<12)|(Startup_HCLKx2div<<9)|(Startup_HCLKdiv<<8)|(Startup_MPLLdiv<<4 startup_aplldiv="" orr="" r1="" r1="" r2="" str="" r1="" r0="" clk_div0_offset="" ldr="" r1="" apll_val="" str="" r1="" r0="" apll_con_offset="" ldr="" r1="" mpll_val="" str="" r1="" r0="" mpll_con_offset="" ldr="" r1="" 0x80200203="" fout="" of="" epll="" is="" 96mhz="" str="" r1="" r0="" epll_con0_offset="" ldr="" r1="" 0x0="" str="" r1="" r0="" epll_con1_offset="" ldr="" r1="" r0="" clk_src_offset="" apll="" mpll="" epll="" select="" to="" fout="" if="" defined="" config_clksrc_clkuart="" ldr="" r2="" 0x2007="" else="" ldr="" r2="" 0x7="" endif="" orr="" r1="" r1="" r2="" str="" r1="" r0="" clk_src_offset="" wait="" at="" least="" 200us="" to="" stablize="" all="" clock="" mov="" r1="" 0x10000="" 1:="" subs="" r1="" r1="" 1="" bne="" 1b="" 2000="" ifdef="" config_sync_mode="" synchronization="" for="" vic="" port="" ldr="" r1="" r0="" others_offset="" orr="" r1="" r1="" 0x20="" str="" r1="" r0="" others_offset="" else="" ldr="" r1="" r0="" others_offset="" bic="" r1="" r1="" 0x20="" str="" r1="" r0="" others_offset="" endif="" mov="" pc="" lr="" bl="" uart_asm_init="" uart_asm_init:="" initialize="" uart="" in="" asm="" mode="" 115200bps="" fixed="" void="" uart_asm_init="" void="" uart_asm_init:="" set="" gpio="" to="" enable="" uart="" gpio="" setting="" for="" uart="" ldr="" r0="" elfin_gpio_base="" 0x7f008000="" ldr="" r1="" 0x220022="" 0000="" 0000="" 0010="" 0010="" 0000="" 0000="" 0010="" 0010="" str="" r1="" r0="" gpacon_offset="" 0x00="" uart1="" gpio-a2="" gpio-a3="" uart2="" gpio-a6="" gpio-a7="" ldr="" r1="" 0x2222="" 0000="" 0000="" 0000="" 0000="" 0010="" 0010="" 0010="" 0010="" str="" r1="" r0="" gpbcon_offset="" 0x7f008000="" 0x20="" uart2="" uart3="" gpio-b3="" gpio-b7="" ok="" 4="" 32="" ldr="" r0="" elfin_uart_console_base="" 0x7f005000="" mov="" r1="" 0x0="" str="" r1="" r0="" ufcon_offset="" define="" ufcon_offset="" 0x08="" str="" r1="" r0="" umcon_offset="" define="" umcon_offset="" 0x0c="" mov="" r1="" 0x3="" was="" 0="" str="" r1="" r0="" ulcon_offset="" 8bit="" 1="" if="" defined="" config_clksrc_clkuart="" ldr="" r1="" 0xe45="" uartclk="" src="11"> EXT_UCLK1*/
#else
    ldr    r1, =0x245            /* UARTCLK SRC = x0 => PCLK */
#endif

    str    r1, [r0, #UCON_OFFSET]               ;0x04 ,按照硬件手册配时钟频率

#if defined(CONFIG_UART_50)
    ldr    r1, =0x1A
#elif defined(CONFIG_UART_66)
    ldr    r1, =0x22
#else
    ldr    r1, =0x1A
#endif
    str    r1, [r0, #UBRDIV_OFFSET]             ;0x28 设置串口波特率

#if defined(CONFIG_UART_50)
    ldr    r1, =0x3
#elif defined(CONFIG_UART_66)
    ldr    r1, =0x1FFF
#else
    ldr    r1, =0x3
#endif
    str    r1, [r0, #UDIVSLOT_OFFSET]           ;波特率

    ldr    r1, =0x4f4f4f4f
    str    r1, [r0, #UTXH_OFFSET]        @'O'           ;0x20
    @设置串口缓冲寄存器
    mov    pc, lr
    @跳转回主干继续往下走

/*
 * Nand Interface Init for SMDK6400 */
nand_asm_init:
    ldr    r0, =ELFIN_NAND_BASE             ;nand flash 基址#define ELFIN_NAND_BASE0x70200000
    ldr    r1, [r0, #NFCONF_OFFSET]         ;#define NFCONF_OFFSET           0x00;
    orr    r1, r1, #0x70                    ; 0 0000 0 00 000000000 111 0 111 0 111 0000
    orr    r1, r1, #0x7700
    str     r1, [r0, #NFCONF_OFFSET];nandflash控制寄存器配置完成

    ldr    r1, [r0, #NFCONT_OFFSET]
    orr    r1, r1, #0x03                     ;0 0000 0 00 000000000 111 0 111 0 111 0000 AND 11
    str     r1, [r0, #NFCONT_OFFSET]        ;0 0000 0 00 000000000 111 0 111 0 111 0011

    mov    pc, lr
    @至此,nandflash简单的配置了一下,其实我觉得这里可以不用配置,在mm control过程中配置也是可以的。
    从链接寄存器取出当前PC指针,跳回主干流程,执行mem_ctrl_asm_init过程。当前ARM芯片工作模式为SVC模式,现在还没回到启动代码kernel中。


</4></S3C6410></VERSION></CONFIG></D>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值