DM368开发 -- Bootloader 开发(转毕设)
參看:基于 DM368 的高清視頻監控系統設計與實現 -- 文波
DM368 的啟動過程大致如下: 首先進行啟動代碼的加載與執行, 主要是指 Bootloader啟動階段,其次啟動系統內核并掛載文件系統,最后運行應用程序。其過程如圖 4.1 所示。本系統中 Bootloader 分為 3 個階段:RBL(Rom Boot Loader),UBL(Use Boot Loader)和 U-boot(Universal Bootloader)。
一、 Bootloader 簡介
Bootloader 是嵌入式系統的引導加載程序,主要存放在 DM368 目標板的非易失性存儲器中(通常為 FLASH 存儲器) ,作用類似于 PC 機上的 BIOS[50]。它是系統上電后最先運行的第一段程序,主要用于對硬件設備進行初始化并建立內存空間映射,為 Linux操作系統內核的運行準備合適的軟硬件運行環境[51]。在完成對系統的初始化任務后,它會將存儲器中的 Linux 內核拷貝到 RAM 中, 然后跳轉到內核的第一條指令處繼續執行,從而啟動 Linux 內核。由此可見,Bootloader 和 Linux 內核之間有著密不可分的聯系,對于嵌入式操作系統來說發揮著很重要的作用。Bootloader 雖然具有初始化系統和執行用戶輸入的命令的作用,但它最根本的功能就是為了啟動 Linux 內核。Bootloader 的操作模式分為自啟動模式和交互模式。自啟動模式是指操作系統的內核和文件系統已燒寫到目標板的某個固態存儲器芯片上,Bootloader 從目標板上的固態存儲設備上將操作系統加載到 RAM 中運行,整個過程自行完成,不需要用戶介入,自啟動模式主要用于產品開發完成后[52]。交互模式主要應用在系統的開發調試階段,通過串口和以太網將內核映像和文件系統從主機上下載到目標板的內存中。系統調試完成后,可以通過固定的命令將這些文件燒寫到存儲器芯片中,實現系統自啟動。二、系統啟動方式
DM368 有兩種啟動模式, 第一種是從外部的異步存儲器 AEMIF (NOR /One FLASH)啟動,無需引導程序引導; 第二種是 ARM內部的 ROM自帶 RBL引導程序引導 bootloader方式啟動,首先啟動 RBL,其次啟動 UBL,最后啟動 U-boot。DM368 中 ARM 內部的ROM 大小為 16KB,在出廠時已燒寫好一段固件代碼,稱為 RBL(Rom Boot Loader) 。此方式支持 7 種啟動方式分別為:NAND 啟動方式、MMC/SD 啟動方式、UART 啟動方式、USB 啟動方式、SPI 啟動方式、EMAC 啟動方式和 HPI 啟動方式。DM368 的啟動方式示意圖如下圖 4.2 所示:當 DM368 上電后,芯片會檢測 BOOT 模式配置引腳 BTSEL[2:0]的狀態,根據其具體值來決定采取哪種啟動方式。 當 BTSEL[2:0]=001 時, 系統采用第一種啟動方式, ARM處理器從 AFMIF 執行引導啟動程序,即從外部存儲器 One Nand 或 Nor Flash 啟動。通過 AEMIF 接口從 Nor/One NAND 里讀取已經固化好的代碼,起始地址從 0x02000000開始。同時通過寄存器 AECFG[2:0]對 Nor/One NAND 的地址線位數進行配置。當BTSEL[2:0]≠001 時, 系統采用第二種啟動方式, 即 RBL 引導 bootloader 方式啟動模式。ARM 處理器從其內部 ROM 地址 0x00008000 處開始執行 RBL 程序,之后 RBL 根據BTSEL[2:0]的值決定啟動方式。Boot 引腳值對應的啟動模式如表 4.1 所示。
硬件系統選用 NAND FLASH 作為外部存儲器, BTSEL[2:0]設定為 000,AECFG[2:0]設定為 000,所以系統采用 RBL 引導的 8 位 NAND FLASH 啟動方式。此過程需要三個階段,分別為 RBL、UBL 和 U-boot[53],啟動過程的流程圖如圖 4.3 所示。
根據以上分析,DM368 的啟動需要 3 級引導,即 RBL→UBL→U-boot。之所以使用UBL,是因為 DM368 的內部 RAM 空間只有 32KB,而一般的 U-boot 要大于 32KB[54]。
三、RBL 啟動過程分析
RBL 是 TI 公司在芯片出廠時固化在 ARM 內部 ROM 中的一段啟動程序, 起始地址為 0x00008000,終止地址為 0x0000BFFF。啟動開始后,系統會從該地址讀取數據,運行 RBL 程序。 RBL 從 NAND FLASH 中讀取 UBL 描述符, 隨后復制 UBL 到內部 RAM,并跳轉到 UBL 的入口地址 0x00000020 運行 UBL。RBL 工作流程如下圖 4.4 所示。
啟動開始后,RBL 首先通過 EM_CE0 和 AECFG[2:0]搜索到 NAND FLASH 設備,并獲取到 FLASH 的相關信息,如設備的 ID。通過此 ID 可以獲得 NAND FLASH 相對應的信息。 其次 RBL 開始在 NAND FLASH 中搜索有效的 UBL 描述符, 從 NAND FLASH中第 1 塊的第 0 頁開始依次搜索,至到最后一塊的最后一頁為止。如果全部搜索完畢沒有發現有效的 UBL 描述符,則系統嘗試轉入 MMC/SD 卡啟動方式啟動。如果 RBL搜索到合法的 UBL,則對 UBL 的描述符采取讀入和執行措施,同時將有效的塊號寫入到 ARM 內部 RAM 最后的 32 位地址中,從 0x00007FFC 到 0x00008000[55]。UBL 描述符包含有 UBL 特殊信息描述符 MagicNumber、入口地址、頁數、開始塊數和結束塊等基本信息。當 RBL 找到 UBL 描述符信息后,會讀取并處理該信息,并完成 UBL 啟動配置, 之后 RBL 會把 UBL 從 NAND FLASH 中拷貝到 ARM 內部的 RAM 中, 執行 UBL的地址從 0x00000020 開始。在 RBL 對 UBL 拷貝過程過程中,RBL 對 UBL 進行 4 位的ECC 錯誤校驗和檢測機制,如果 RBL 檢測出拷貝的數據出錯,UBL 會通過 ECC 檢驗算法糾整錯誤。如果糾錯失敗,RBL 放棄當前塊,繼續從下一塊開始搜索有效地 UBL描述符。最后當 RBL 完成 UBL 的搬運工作后,RBL 會將系統指針指向 UBL 起始地址,并將控制權交給 UBL,UBL 程序接著開始運行。
四、UBL 啟動過程分析
UBL 主要功能是實現將 U-boot 代碼拷貝到 DDR2 內存中,建立運行環境并引導U-boot。在嵌入式操作系統中,U-boot 的大小一般都較大,基本上都在 100KB 以上。本系統中 DM368 中 ARM 核內置的 RAM 大小僅為 32KB,RBL 無法直接將 U-boot 代碼拷貝到 RAM 中,只能加載到 DDR2 外部存儲器中,用 UBL 引導 U-boot 的方式進行啟動。UBL 存放在 DVSDK_DM368_4_02_00_06/psp/flash-utils/DM36X 和flash-uyils/common 目錄下。common 目錄里存放通用程序信息,包括 UBL 的驅動源碼、工具、腳本等,DM36x 存放與平臺相關的程序信息。UBL 的工作流程如下圖 4.5 所示。轉到 ubl.c 中的 main 函數, main 函數主要調用 LOCAL_boot 函數進行實質的引導。 UBL對系統的外圍硬件進行初始化設置并且判斷系統的啟動方式, 進而完成 U-boot 向 DDR2的拷貝工作。UBL 工作完成并退出,DDR2 中的 U-boot 接管系統的管理權開始工作運行。ubl.c 中的 main 函數里面有三個重要的函數涉及到系統啟動方式、硬件初始化和U-boot 拷貝,對應的函數分別為 DEVICE_bootMode()、DVICE_init()和 nandboot_copy。
以下對三個主要函數的功能做出分析:
DEVICE_bootMode 函數通過讀取寄存器的值可獲取系統的啟動信息。UBL 會判斷系統的啟動方式,UBL 程序支持 NAND FLASH、NOR FLASH、MMC/SD 和 UART 啟動方式。在 4.2.2 小節中,系統采用 NAND 啟動方式。
DEVICE_init 函數對系統設備的最底層硬件平臺進行初始化,包括中斷的屏蔽和清除、電源時鐘使能、復用引腳功能選擇、時鐘頻率設定、DDR2 控制器相關參數設定、EMIF 初始化、串口初始化、I2C 初始化等。NANDBOOT_copy 函數采用 NAND 啟動方式,搜索 U-boot 描述符,通過此描述符配置 U-boot。UBL 完成 U-boot 從 NAND 到 DDR 內存的拷貝工作。
1.硬件設備初始化
對硬件平臺最底層設備進行初始化是 UBL 工作中最重要的一部分,DEVICE_init 函數對系統硬件的初始化流程如下圖 4.6 所示。根據 DM368硬件外圍設備的不同, DEVICE_init函數對硬件做出相應的修改和配置。包括系統屏蔽清除所有中斷、初始化電源時鐘使能 PSC、管腳復用寄存器 PINMUX 的配置、系統 IO 設置、系統時鐘 PLL 的配置以及對 DDR2、外部存儲器、串口、定時器以及 I2C 總線的初始化。在系統對底層硬件的初始化中,屏蔽清除所有中斷、電源時鐘使能、系統時鐘 PLL、串口以及 I2C 總線初始化在系統引導程序中設置基本一致,故在此不做修改。以下對管腳復用和 I/O 口的配置、DDR2、EMIF、定時器初始化做出詳細設計。
(1)管腳復用寄存器配置如下表 4.2 所示。
(2)外部存儲器(NAND FLASH)的初始化配置如下表 4.3 所示。
(3)定時器(TIMERO)的初始化配置如下表 4.4 所示
(4)DDR2 初始化
UBL 在對底層硬件初始化的過程中,對 DDR2 的初始化是最為重要的部分。U-boot在由 UBL 拷貝到 DDR2 內存之前必須對 DDR2 進行初始化工作并對其進行相應的配置,這是因為在系統上電后, ARM 內核中的 ROM 固化程序 RBL 沒有對 DDR2 進行初始化。UBL 對 DDR2 的初始化工作主要由 DEVICE_DDR2Init 函數完成,UBL 對 DDR2 的初始化流程圖如圖 4.7 所示。
首先,通過電源時鐘管理模塊 PSC 中的 DEVICE_LPSCTransition(LPSC_DDR2,0,PSC_ENABLE)函數實現對 DDR2 模塊的供電和時鐘使能。其次,在上電或復位后,DM368 會對 VPT IO 進行校正以實現對 DDR2 模塊 IO 輸出阻抗的自動調節。在有關DDR2 硬件設計部分 3.3.2 節中,DDR_PADREFP 引腳通過精度為 0.5%、大小為 50 歐姆的高精度電阻接地為 VPT IO 的校正提供參考。等待 150 個時鐘周期后完成對 VPTIO的 校 正 。 接 下 來 再 次 通 過 電源 時 鐘 管 理 模 塊 PSC 中 的 函 數 DEVICE_LPSCTTransition(LPSC_DDR2,0,PSC_SYNCRESET) 對 DDR2 進 行 同 步 重 啟 , 通 過 函 數DEVICE_LPSCTTransition(LPSC_DDR2,0,PSC_ENABLE)對電源時鐘模塊重新使能。然后對 DDR2 的 PHY、參數、時鐘和外圍總線優先級進行設置。在 DDR2 的 PHY 設置中,配置 DDRPHYCR 寄存器為 0x000080C6,表示選擇外部選通門,接收器斷電。DDR2 參數的設置與 DM368 所外接的具體的 DDR2 芯片有關,根據實際所使用的 DDR2 芯片的頁大小、塊數和總線寬度對 DDR SDCR 寄存器進行設置。系統所選用的 DDR2 的頁大小為 1024,共 8 塊,使用的總線寬度為 16 位,列選通延遲為 5。根據以上分析將 DDRSDBCR 設置為0x00D34A32 和 0x0053CA32。 DDR2 的時鐘配置通過 SDTIMR 和SDTIMR2 實現,分別設置為 0x45246412 和 0x4225C742。總線突發優先級設置中,對PBBPR 寄存器設置為 0x000000FE。刷新控制寄存器設置中通過對寄存器 SDRCR 設置為 0X83A 來實現。最后對 DDR2 同步重啟,電源時裝模塊重新使能,返回到 DDR2 的初始化狀態,初始化結束。
2.UBL 對 U-boot 的啟動引導
UBL 在完成對底層硬件的初始化后,接下來就是將 NAND FLASH 中的 U-Boot 拷貝到 DDR2 內存中,引導 U-Boot 啟動。UBL 對 U-Boot 啟動引導流程圖如圖 4.8 所示。在 UBL 對 U-Boot 的有效描述符開始搜索之前,首先應該進行對描述符搜尋的起始地址和讀取描述符所需內存空間進行設置。在此設置描述符的起始搜尋地址為BANK8~BANK10。使用函數 rxBuf=(Uint8*)UTIL_allocMem((APP_IMAGE_SIZE))對內存空間進行設置,在此對 APP_IMAGE_SIZE 的取值為( ( (Uint32)&DDRSize)>>3。在不超出最大內存值的情況下,為 U-Boot 的描述符分配 16MB 的內存空間以保證內存空間不會溢出。內存空間分配完成后,可通過函數 NAND_open 獲取并配置 NAND Flash的信息,包括 NAND Flash 的塊數和頁數信息、起始地址、數據總線位數以及校驗信息。上述配置工作完成后, UBL 通過函數 NAND_readPage 對 U-Boot 的描述符進行搜索,搜索的范圍從起始塊號的第 0 頁開始直至最后塊號的最后一頁結束。當搜索到的描述符為有效時, UBL 會通過該有效描述符獲取 U-Boot 向 DDR2 寫入所需參數。通過該參數,UBL 可以完成以下兩個任務:U-Boot 向 DDR2 內存的拷貝所需完成的準備工作以及分配 U-Boot 在 DDR2 內存中實際所在的空間位置。然后 UBL 通過函數 NAND_readPage將 U-Boot 搬運到 DDR2 內存中。搬運過程中的數據都會進行 ECC 校驗糾錯。如果數據拷貝失敗,會進行第二次拷貝。如果第二次拷貝還未成功,UBL 會重新跳到 UBL 搜索頁繼續搜索 U-Boot 有效描述符,直到終止塊號的最后一頁完全拷貝到 DDR2 內存中。五、U-Boot 啟動過程分析
U-Boot(Univesal Boot Loader)是遵循 GPL 條款開發的開放源碼項目[56],廣泛應用于嵌入式系統開發中。它不僅支持嵌入式 Linux 系統的引導,同時還支持 NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS 等嵌入式操作系統,而且 U-Boot 對硬件的適應性也很好,支持 Power PC、MIPS、x86、ARM、NIOS、XScale 等多種處理器架構[57]。
U-boot 具有以下優點:
1.源代碼對外開放,開發人員可以進行修改并共享;
2.支持多種處理器系列和嵌入式操作系統。
3.技術成熟、性能穩定,以及非常高的可靠性。
4.功能設置靈活,引導產品需求與發布。
5.設備驅動源碼豐富,支持常見的外圍設備如:串口、以太網、SDRAM、FLASH、LCD、鍵盤、EEPROM 等。
6.開發調試文檔非常豐富,網絡支持強大。
U-Boot 的啟動過程大致可分為兩個階段。第一階段代碼一般使用匯編語言代碼實現,執行啟動代碼 start.s,主要完成部分硬件設備初始化、設置異常入口地址和異常處理函數、配置 PLL 確定系統主頻、屏蔽中斷、初始化 I/O 寄存器、關閉 MMU、初始化存儲空間、加載 U-Boot 的第二段代碼到 DDR 內存中、設置堆棧大小,并最終跳轉到 C代碼的 start_armboot()函數繼續執行。第二階段代碼采用 C 語言實現,主要完成包括中斷的處理、環境變量設置、串口設置等。采用 C 語言的好處是能夠較好的實現復雜的功能,而且程序具有較高的可讀性,代碼的移植也比較方便。第一階段主要功能主要是通過函數 start.s 來實現的,它對部分硬件設備進行初始化,函數 start.s 啟動過程如下圖 4.9 所示。
函數 start.s 首先進行復位使系統進入 SVC32 超級保護模式。接著對時鐘和處理器的主頻進行設置,依靠 cpu_init_crit 代碼實現,cach 和 MMU 的關閉也依靠此代碼實現。處理器工作頻率、總線頻率和存儲器時鐘頻率的調節及初始化工作依據cpu_init_crit 代碼中的函數 lowlevel_init 進行實現。函數 relocate 對 U-Boot 進行重新定位,完成第二階段代碼的拷貝工作。實際拷貝函數 copy_loop 將 U-Boot 程序拷貝到 TEXT_BASE 開始地址的空間中。初始化堆棧函數 stack_setup 實現對堆棧的初始化。函數 clear_bass 對未初始化全局變量的 bass 段進行初始化,通過函數 clbss_1 循環清除 bass。最后跳轉到第二階段起始代碼入口函數_star_armboot。第二階段中函數 start_armboot 是 Bootloader 代碼中第一個被執行的 C 語言函數,它也是 C 語言代碼的主函數。start_armboot 中的主要函數功能如下表 4.5 所示。
當所有的第一階段 start.s 和第二階段 start_armboot 函數代碼執行完成后,系統進入main_loop 中,循環等待用戶從串口輸入的命令并執行該命令。
總結
以上是生活随笔為你收集整理的DM368开发 -- Bootloader 开发(转毕设)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringCloud Eureka服务
- 下一篇: DM368开发 -- uboot 使用