_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 //中斷向量 … /* the actual reset code */ reset: //復位啓動子程序 /* 設置CPU爲SVC32模式 */ mrs r0,cpsr bic r0,r0,#0x1f ;;位清除,將某些位的值置0:r0 = r0 AND ( !0x1f) orr r0,r0,#0xd3 ;;邏輯或,將r0與立即數進行邏輯或,放在r0中(第一個) msr cpsr,r0 /* 關閉看門狗 */ /* turn off the watchdog */ #if defined(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 /* Interupt-Controller base addresses */ # define CLKDIVN 0x14800014 /* clock divisor register */ #elif defined(CONFIG_S3C2410) # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ #endif
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* 禁止所有中斷和設置CPU頻率 */ /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] # endif
/* FCLK:HCLK:PCLK = 1:2:4 */ ;;FCLK用於CPU,HCLK用於AHB,PCLK用於APB /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN ;;根據硬件手冊來設置CLKDIVN寄存器 mov r1, #3 ;;用戶手冊的推薦值 str r1, [r0] #endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */
/* 這些初始化代碼在系統重起的時候執行,運行時熱復位從RAM中啓動不執行 */ /* * we do sys-critical inits only at reboot, * not when booting from */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit ;;跳轉去初始化CPU #endif ;;#ifdef CONFIG_INIT_CRITICAL 原文中的,估計是1.1.16版本的 ;; bl cpu_init_crit ;;#endif
/* CPU和RAM兩個關鍵的初始化子程序 */ /* 初始化CPU */ cpu_init_crit: /* * flush v4 I/D caches 設置CP15 */ mov r0, #0 mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */ ;;使I/D cache失效:將寄存器r0的數據傳送到協處理器p15的c7中。C7寄存器位對應cp15中的cache控制寄存器 mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */ ;;使TLB操作寄存器失效:將r0數據送到cp15的c8、c7中。C8對應TLB操作寄存器
/* * disable MMU stuff and caches 禁止MMU和caches */ mrc p15, 0, r0, c1, c0, 0 ;;先把c1和c0寄存器的各位置0(r0 = 0) bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS) bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM) ;;這裏我本來有個疑問:爲什麼要分開設置。因爲arm彙編要求的立即數格式所決定的 orr r0, r0, #0x00000002 @ set bit 2(??) (A) Align ;;上一條已經設置bit1爲0,這一條又設置爲1?? orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache mcr p15, 0, r0, c1, c0, 0 ;;用上面(見下面)設定的r0的值設置c1??(cache類型寄存器)和c0(control字寄存器),以下爲c0的位定義 ;;bit8: 0 = Disable System protection ;;bit9: 0 = Disable ROM protection ;;bit0: 0 = MMU disabled ;;bit1: 0 = Fault checking disabled 禁止糾錯 ;;bit2: 0 = Data cache disabled ;;bit7: 0 = Little-endian operation ;;bit12: 1 = Instruction cache enabled
/* 配置內存區控制寄存器 ??有待分析,是1.1.4版本的 * before relocating, we have to setup RAM timing * because memory timing is board-dependend, you will * find a lowlevel_init.S in your board directory. */ mov ip, lr bl lowlevel_init ;;位於board/smdk2410/lowlevel_init.S:用於完成芯片存儲器的初始化,執行完成後返回 mov lr, ip mov pc, lr
relocate: /* 把U-Boot重新定位到RAM */ adr r0, _start /* r0是代碼的當前位置 */ ;;adr僞指令,彙編器自動通過當前PC的值算出 如果執行到_start時PC的值,放到r0中: 當此段在flash中執行時r0 = _start = 0;當此段在RAM中執行時_start = _TEXT_BASE(在board/smdk2410/config.mk中指定的值爲0x33F80000,即u-boot在把代碼拷貝到RAM中去執行的代碼段的開始) ldr r1, _TEXT_BASE /* 測試判斷是從Flash啓動,還是RAM */ ;;此句執行的結果r1始終是0x33FF80000,因爲此值是又編譯器指定的(ads中設置,或-D設置編譯器參數) cmp r0, r1 /* 比較r0和r1,調試的時候不要執行重定位 */ beq stack_setup /* 如果r0等於r1,跳過重定位代碼 */ /* 準備重新定位代碼 */ ;;以上確定了復位啓動代碼是在flash中執行的(是系統重啓,而不是軟復位),就需要把代碼拷貝到RAM中去執行,以下爲計算即將拷貝的代碼的長度 ldr r2, _armboot_start ;;前面定義了,就是_start ldr r3, _bss_start ;;所謂bss段,就是未被初始化的靜態變量存放的地方,這個地址是如何的出來的?根據board/smsk2410/u-boot.lds內容? sub r2, r3, r2 /* r2 得到armboot的大小 */ add r2, r0, r2 /* r2 得到要複製代碼的末尾地址 */ copy_loop: /* 重新定位代碼 */ ;;開始循環拷貝啓動的代碼到RAM中 ldmia {r3-r10} /*從源地址[r0]複製 */ ;;r0指向_start(=0) stmia {r3-r10} /* 複製到目的地址[r1] */ ;;r1指向_TEXT_BASE(=0x33F80000) cmp r0, r2 /* 複製數據塊直到源數據末尾地址[r2] */ ble copy_loop ;;這裏附上u-boot各存儲區域的映射圖,從網上找的,這下對於這幾個地址的位置就一目瞭然了!
|