日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

uboot源码——汇编阶段的start.S文件

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 uboot源码——汇编阶段的start.S文件 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以下內容源于朱有鵬嵌入式課程的學習,如有侵權,請告知刪除。

?

一、相關內容

(1)?階段的定義

  • 第一階段,即在內部SRAM運行的階段,簡單地理解為匯編階段,此階段主要涉及start.S文件,在cpu/s5pc11x/目錄下。第一階段以ldr pc _start_armboot為結束。
  • 第二階段,即在DDR中運行的階段,簡單地理解為C語言階段,此階段主要涉及start_armboot函數,在uboot/lib_arm/board.c文件的444~908行。

(2)總結第一階段主要完成的任務

  • 異常向量表的實現; ? ??
  • 設置進入特權模式,即SVC模式;
  • 檢查恢復狀態; ? ? ? ? ? ??
  • IO狀態恢復;
  • 關看門狗; ? ? ? ? ? ? ? ? ? ??
  • 一些與SRAM、SROM相關的GPIO設置;
  • 開發板的供電鎖存; ? ??
  • 時鐘的初始化;
  • DDR的初始化; ? ? ? ? ?
  • 重新設置棧空間;
  • uboot的重定位;? ? ??
  • 轉換表的建立;
  • 使能MMU。

可見,uboot的第一階段初始化了SoC內部的一些部件,初始化DDR并且重定位。

另外,學完整個uboot內容后,回過頭來看。uboot被分割成兩部分,即前8kb和整個ubooot。則前8k內容肯定包括了第一階段的操作任務,其中很重要的操作有重定位。

(3)程序入口和SI工具

  • uboot中整個程序的入口取決于鏈接腳本中ENTRY聲明的地方。因為鏈接腳本(即board\samsung\x210\u-boot.lds)中有ENTRY(_start),因此_start符號所在的文件就是起始文件,所處的位置就是起始位置。
  • SI工具的使用:search—>lookup reference.


二、start.S解析1

(1)config.h文件在mkconfig腳本中生成,此文件內容為#include <configs/x210.h>;

(2)version.h文件中的內容是#include "version_autogenerated.h。

  • version_autogenerated.h文件是在主Makefile中自動生成的,相關的生成代碼:

?

  • version_autogenerated.h文件中內容為:#define U_BOOT_VERSION "U-Boot 1.3.4"

(3)由于定義了宏CONFIG_ENABLE_MMU,因此包含asm/proc/domain.h,實際包含include\asm-arm\proc-arm\domain.h文件。


三、start.S解析2

1、啟動代碼的16字節頭部


(1)arm7和arm9的arm指令集,一個字類型是32bit。

(2)此段代碼用16個字節填充占位(這些數字貌似可以任意?字節內容后續計算重新填充?)。這里填充的原因是SD卡需要16字節的校驗?

(3).word是arm匯編的偽指令,含義是當前地址的值為XX,XX的內容一般為數值或者地址。

  • 如:.word 0x2000表示當前地址的值為0x2000;.word _start 表示當前地址的值為_start。


2、構建異常向量表

?

(1)異常向量表由硬件決定,軟件只是參照硬件設計來實現。

(2)此向量表只是虛有其表,并未做非常細致的異常處理。

(3)復位異常處理代碼是b reset,reset是個函數。

(4)上圖中的最后一句是讓內存16字節對齊,如果不對齊,用0xdeadbeef這個數字填充。

(5)學完裸機中的中斷向量表可知,這里類似的處理。

?

3、一些地址值

?

(1)_TEXT_BASE(4字節)這個內存地址出的值為TEXT_BASE(即0xc3e00000)。

(2)_TEXT_PHY_BASE(4字節)這個內存存放的值為CFG_PHY_UBOOT_BASE(uboot的物理基地址)。

(3)CFG_PHY_UBOOT_BASE(定義在x210_sd.h中)為 MEMORY_BASE_ADDRESS + 0x3e00000

  • 在x210_sd.h中有#define MEMORY_BASE_ADDRESS 0x30000000;
  • 因此CFG_PHY_UBOOT_BASE為0x33e00000,這個是uboot在DDR中的物理地址。

(4)總結,即標簽表示地址,.word后面的表示此內存地址中存儲的值。

  • 如_bss_end: .word _end表示地址_bss_end上存放的值是_end。


四、start.S解析3?

1、reset中斷處理函數

?

(1)由博客http://blog.csdn.net/oqqhutu12345678/article/details/71215628可知,因為0xd3=1101 0011,則cpu設置為SVC模式、arm狀態,禁止FIQ、IRQ中斷。

(2)整個uboot工作時,cpu一直處于SVC模式。

?

2、Cpu的初始化(設置l1,l2cache和MMU等內容)



3、識別并暫存啟動介質選擇

(1)啟動介質由SoC的OM0:OM5這6個引腳的高低電平決定?

(2)由#define PRO_ID_BASE 0xE0000000和#define OMR_OFFSET 0x04得到寄存器0xE000 0004

  • 這個寄存器會根據OM引腳狀況,硬件自動設置值。

(3)此三行代碼后,r2存儲了一個數字,后續通過該數字進行啟動介質的判斷。

??

(4)通過判斷r2中的值,來確定是從哪里啟動的。

  • 如果r2中的值為0xc,那從SD卡啟動,然后把#BOOT_MMCSD(#define ?BOOT_MMCSD? 0x3)賦給r3。

(5)最后兩行中,因為有#define INF_REG_BASE 0xE010F000和#define INF_REG3_OFFSET 0x0c,則合成寄存器0xE010F00C,然后把r3中的值放入其中。

?

4、第一次設置棧


(1)這次設置棧是在SRAM中設置的,因為當前整個代碼還在SRAM中運行,此時DDR還未被初始化還不能用。

  • 棧地址0xd0036000是自己指定的,指定的原則就是這塊空間只給棧用,不會被別人占用。

(2)之所以要初始化棧,是因為接下來調用的lowlevel_init函數中還要調用其他函數。

  • bl只會將返回地址存儲到LR中,但是只有一個LR,所以在第二層調用函數前要先將LR入棧,否則函數返回時第一層的返回地址就丟了。


---------------------------------------lowlevel_init函數--------------------------------------------

五、start.S解析4?

1、lowlevel_init函數

(1)lowlevel_init在uboot\board\samsung\x210\lowlevel_init.S中。

(2)檢查復位狀態

  • 因為復雜CPU支持多種復位狀態(冷上電、休眠復位等),因此在復位代碼中檢查復位狀態,判斷到底是哪一種。
  • 冷上電時DDR需要初始化,而休眠狀態下復位不需要再次初始化DDR。

(3)IO狀態恢復;

(4)關看門狗;

(5)一些與SRAM、SROM相關的GPIO設置(下圖);

?

(6)開發板的供電鎖存(下圖)

?


六、start.S解析5?

1、判斷當前代碼執行位置(判斷在SRAM還是DDR中)


為什么要判斷?

  • BL1在SRAM中有一份,在DDR中也有一份。
  • 如果是冷啟動,則當前代碼是在SRAM中運行的BL1;如果是低功耗狀態的復位,則當前代碼是在DDR中運行的。
  • 判斷的目的是指導后面代碼的運行。
  • 譬如在lowlevel_init.S中判定當前代碼的運行地址,就是為了確定是否執行時鐘初始化和初始化DDR的代碼。
  • 如果當前代碼是在SRAM中,說明是冷啟動,則需要初始化時鐘和DDR;
  • 如果當前代碼是在DDR中,說明是熱啟動,則時鐘和DDR都不用再次初始化。

2、時鐘初始化:system_clock_init

  • 詳細可以查閱代碼http://blog.csdn.net/oqqhutu12345678/article/details/73188932

3、內存的初始化:mem_ctrl_asm_init

  • 代碼見博客http://blog.csdn.net/oqqhutu12345678/article/details/73189059

(1)在uboot/cpu/s5pc11x/s5pc110中。該函數和裸機中初始化DDR代碼是一樣的。實際裸機中初始化DDR的代碼就是從這里抄的。

(2)配置值中有一個和裸機中講的不一樣,即DMC0_MEMCONFIG_0

  • 它在裸機中配置值為0x20E01323,在uboot中配置為0x30F01313。
  • 在裸機中DMC0的256 MB內存地址范圍是0x20000000-0x2FFFFFFF;
  • 在uboot中DMC0的256MB內存地址范圍為0x30000000-0x3FFFFFFF
  • DMC0上允許的地址范圍是20000000-3FFFFFFF(一共是512MB),而實際只接了256MB物理內存,SoC允許我們給這256MB挑選地址范圍。
  • 在uboot中,可用的物理地址范圍為:0x30000000-0x4FFFFFFF,一共512MB,其中30000000-3FFFFFFF為DMC0,40000000-4FFFFFFF為DMC1。
  • 注意條件編譯的條件,配置頭文件中考慮了不同時鐘配置下的內存配置值,主要目的是讓不同時鐘需求的客戶都能找到合適自己的內存配置值。

4、串口初始化:打印一個“O”

  • uart_asm_init函數


5、pop {pc}返回前通過串口打印“K”

?

----------------------------------lowlevel_init函數結束----------------------------------------


七、start.S詳解6

1、第二次設置棧

?

(1)第一次設置棧,是在調用lowlevel_init函數前。那時程序在SRAM中執行,所以在SRAM中分配了一部分內存作為棧。

(2)第二次因為DDR已經被初始化,因此要把棧挪移到DDR中,所以要重新設置棧。

  • 實際設置的棧的地址是33E00000,剛好在uboot的代碼段的下面緊挨著。
  • 因為是滿減棧,所以棧向下增長。注意uboot基地址在0x33e00000,向上增長。

(3)為什么要再次設置棧?

  • DDR已經初始化了,已經有大片內存可以用了,沒必要再把棧放在SRAM中;
  • 原來SRAM中內存大小空間有限,棧放在那里要注意不能使用過多,否則棧會溢出;
  • 我們及時將棧遷移到DDR中也是為了盡可能避免使用棧時的諸多不便。

?

2、再次判斷運行地址是在SRAM中還是DDR中

(1)上次判斷是為了決定是否要執行初始化時鐘和DDR的代碼,本次判斷是為了決定是否進行uboot的重定位。上圖中最后一行代碼如果不執行,則說明需要重定位。

  • 冷啟動時,uboot的前一部分(16kb或者8kb)開機自動從SD卡加載到SRAM中運行,uboot的第二部分(其實第二部分是整個uboot)還躺在SD卡的某個扇區開頭的N個扇區中。此時uboot的第一階段即將結束(第一階段該做的事基本做完了),結束之前要把第二部分加載到DDR中鏈接地址處(0x33e00000),這個加載過程就叫重定位。
(2)如下圖:
  • D0037488這個內存地址在SRAM中,這個地址中的值是被硬件自動設置的。硬件根據我們實際電路中SD卡在哪個通道中,會將這個地址中的值設置為相應的數字。譬如我們從SD0通道啟動時,這個值為EB000000;從SD2通道啟動時,這個值為EB200000。
  • 我們確定是從MMCSD啟動,因此最終跳轉到mmcsd_boot函數中去執行重定位動作,即把SD卡中相應的內容復制到內存中。
  • 真正的重定位是通過調用movi_bl2_copy函數完成的,在uboot/cpu/s5pc11x/movi.c中。
  • 此函數包含copy_bl2(2, MOVI_BL2_POS, MOVI_BL2_BLKCNT,CFG_PHY_UBOOT_BASE, 0)函數。
  • 參數2表示通道2;
  • MOVI_BL2_POS是uboot的第二部分在SD卡中的開始扇區,這個扇區數字必須和燒錄uboot時燒錄的位置相同;
  • MOVI_BL2_BLKCNT是uboot的長度占用的扇區數;
  • CFG_PHY_UBOOT_BASE是重定位時將uboot的第二部分復制到DDR中的起始地址(33E00000)。

?

?

八、start.S詳解7

最后一段代碼,作用是配置MMU、重新設置棧、清bss、跳轉到start_armboot函數中去執行BL2階段。




1、MMU(memory management unit),內存管理單元。

  • MMU實際上是SOC中一個硬件單元,它的主要功能就是實現虛擬地址到物理地址的映射。
  • MMU單片在CP15協處理器中進行控制,也就是說要操控MMU進行虛擬地址映射,方法就是對cp15協處理器的寄存器進行編程。

2、第三次設置棧

  • 這次設置棧還是在DDR中,之前雖然已經在DDR中設置過一次棧了,但是本次設置棧的目的是將棧放在比較合適(安全,緊湊而不浪費內存)的地方。
  • 我們實際將棧設置在uboot起始地址上方2MB處,這樣安全的棧空間是:2MB-uboot大小-0x1000=1.8MB左右。這個空間既沒有太浪費內存,又足夠安全。

3、清理bss

  • 注意表示bss段的開頭和結尾地址的符號是從鏈接腳本u-boot.lds得來的。

4、ldr pc, _start_armboot

  • start_armboot函數在uboot/lib_arm/board.c中,這是一個C語言實現的函數。這個函數就是uboot的第二階段。
  • 這句代碼的作用就是將uboot第二階段執行的函數的地址傳給pc,實際上就是使用一個遠跳轉直接跳轉到DDR中的第二階段開始地址處。
  • 遠跳轉的含義就是這句話加載的地址和當前運行地址無關,而和鏈接地址有關。因此這個遠跳轉可以實現從SRAM中的第一階段跳轉到DDR中的第二階段。
  • 這里這個遠跳轉就是uboot第一階段和第二階段的分界線。



總結

以上是生活随笔為你收集整理的uboot源码——汇编阶段的start.S文件的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。