花了三个晚上弄清楚整个流程之后,累翻了。我想,写完这份注释以后,大概我再也不想看到这块的启动分析了。今天到此为止,明天开始做最后一个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, * * 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 #include #include #include "smdk6410_val.h"_TEXT_BASE: .word TEXT_BASE .globl lowlevel_initlowlevel_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#endif1: ldr r0, =ELFIN_UART_BASE ldr r1, =0x4b4b4b4b str r1, [r0, #UTXH_OFFSET] mov lr, r12 mov pc, lr#if 1wakeup_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>