u-boot-1.1.6第2階段入口函數start_armboot分析

来源:https://www.cnblogs.com/053179hu/archive/2019/03/28/10615552.html
-Advertisement-
Play Games

學習目標: 1、分析u-boot-1.1.6第2階段入口函數void start_armboot (void),熟悉該函數所實現的功能 2、為後面能夠掌握u-boot-1.1.6如何啟動內核過程打下基礎 前面通過對uboot第一階段代碼的分析,我們瞭解的uboot第一階段所做的一些工作,並且找到了其 ...


學習目標:

1、分析u-boot-1.1.6第2階段入口函數void start_armboot (void),熟悉該函數所實現的功能

2、為後面能夠掌握u-boot-1.1.6如何啟動內核過程打下基礎


前面通過對uboot第一階段代碼的分析,我們瞭解的uboot第一階段所做的一些工作,並且找到了其第二階段的入口函數void start_armboot(void)。為了能夠在清楚理解uboot啟動內核的機制,還需要對第二階段代碼進行分析。第二階段入口函數void start_armboot(void)存放在board.c文件中,該文件位於uboot根目錄下的lib_arm文件夾中。

1.gd_t數據結構分配記憶體

/* Pointer is writable since we allocated a register for it */
gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));  //為gd_t結構體變數開闢空間     
/* compiler optimization barrier needed for GCC >= 3.4 */      //並使得gd指針指向該空間初始位置
__asm__ __volatile__("": : :"memory");

memset ((void*)gd, 0, sizeof (gd_t));       //gd獲取記憶體塊清零     
gd->bd = (bd_t*)((char*)gd - sizeof(bd_t)); //為bd_t結構體變數開闢空間,並使得gd->bd指針指向bd_t的初始位置 
memset (gd->bd, 0, sizeof (bd_t));          //bd_t記憶體範圍清零

start_armboot函數首先為gd_t數據類型分配相應的記憶體空間,並使得gd指針指向這塊記憶體空間。gd指針在global_data.h文件(位於uboot根目錄下的include/asm-arm文件夾)中聲明,在start_armboot函數中定義,聲明形式為:

  #define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

這個聲明告訴編譯器使用CPU寄存器r8來存儲gd_t類型的指針gd,即這個定義聲明瞭一個指針,並且指明瞭它的存儲位置。register表示變數放在機器的寄存器,volatile的作用是作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次使用直接讀值。gd_t數據結構緊接在uboot自定義的堆區域下的全局變數區域進行存放,分配完成後使用memset函數對這塊記憶體進行清零,uboot存儲器映射圖如下所示:

2.硬體的初始化

for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {          
    if ((*init_fnc_ptr)() != 0) {
        hang ();                                             
    }
}

init_fnc_ptr是在start_armboot函數中定義的局部變數,該變數是一個二級指針,指向int (init_fnc_t) (void)類型函數的指針。init_sequence是一個指針數組的名稱,指針數組init_sequence[]存放硬體初始化函數的地址。使用這種方式調用函數的好處是如果要添加初始化一些新的硬體時,只需寫出新硬體初始化函數,將編寫初始化函數名放在init_sequence[]中,不用修改其他代碼,便能調用新的硬體初始化函數。指針數組內容如下:

init_fnc_t *init_sequence[] = {
    cpu_init,        /* basic cpu dependent setup */
    board_init,        /* basic board dependent setup */
    interrupt_init,        /* set up exceptions */
    env_init,        /* initialize environment */
    init_baudrate,        /* initialze baudrate settings */
    serial_init,        /* serial communications setup */
    console_init_f,        /* stage 1 init of console */
    display_banner,        /* say that we are here */
/* 未定義CONFIG_DISPLAY_CPUINFO巨集,print_cpuinfo不被編譯 */
#if defined(CONFIG_DISPLAY_CPUINFO)
    print_cpuinfo,        /* display cpu info (and speed) */
#endif
/* 未定義CONFIG_DISPLAY_BOARDINFO巨集,checkboard不被編譯 */
#if defined(CONFIG_DISPLAY_BOARDINFO)
    checkboard,        /* display board info */
#endif
    dram_init,        /* configure available RAM banks */
    display_dram_config,
    NULL,
};

cpu_init函數功能:如果配置文件使能IRQ中斷和FIQ中斷,那麼就獲取uboot存儲器映射中IRQ、FIQ堆棧的地址,將其保存在全局變數IRQ_STACK_START和FIQ_STACK_START中。

board_init函數功能:設置系統時鐘,初始化相應的GPIO埠,設置全局變數gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;(arch number of SMDK2410-Board),gd->bd->bi_boot_params =   0x30000100(傳給內核啟動參數的地址),使能指令緩存和數據緩存。

interrupt_init函數功能:初始化系統定時器

env_init函數功能:從flash中讀取環境變數併進行crc校驗,校驗成功使用flash中環境變數的地址,校驗失敗使用預設環境變數的地址gd->env_addr  = (ulong)&default_environment[0];

init_baudrate函數功能:讀取環境變數中波特率的值

serial_init函數功能:根據讀取的波特率數值初始化串口

console_init_f函數功能:設置串口控制台

display_banner函數功能:串口列印uboot版本信息,以及uboot代碼段、bss段鏈接地址

dram_init函數功能:將sdram起始地址和大小存入gt指針所指向全局變數 gd->bd->bi_dram[0].start = PHYS_SDRAM_1;gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;

display_dram_config函數功能:串口列印sdram其實地址和大小的信息

3.初始化nor flash和nand flash

/* 未定義CFG_NO_FLASH巨集,執行flash_init()初始化函數,列印flash容量 */
#ifndef CFG_NO_FLASH
    /* configure available FLASH banks */
    size = flash_init ();                         //讀出板載flash大小
    display_flash_config (size);                  //串口列印flash容量大小
#endif /* CFG_NO_FLASH */

/* 未定義CONFIG_VFD巨集,不支持VFD液晶屏,此處代碼不用分析 */
#ifdef CONFIG_VFD                                 //液晶屏(不執行)
#    ifndef PAGE_SIZE
#      define PAGE_SIZE 4096
#    endif
    /*
     * reserve memory for VFD display (always full pages)
     */
    /* bss_end is defined in the board-specific linker script */
    addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
    size = vfd_setmem (addr);
    gd->fb_base = addr;
#endif /* CONFIG_VFD */

/* 未定義CONFIG_LCD巨集,不支持LCD液晶屏,此處代碼不用分析 */
#ifdef CONFIG_LCD                                //液晶屏(不執行) 
#    ifndef PAGE_SIZE
#      define PAGE_SIZE 4096
#    endif
    /*
     * reserve memory for LCD display (always full pages)
     */
    /* bss_end is defined in the board-specific linker script */
    addr = (_bss_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
    size = lcd_setmem (addr);
    gd->fb_base = addr;
#endif /* CONFIG_LCD */

    /* 將malloc連接地址指定在指定記憶體位置 */
    /* armboot_start is defined in the board-specific linker script */
    mem_malloc_init (_armboot_start - CFG_MALLOC_LEN);     

/* 未定義CFG_CMD_NAND巨集,此處代碼不被編譯 */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)             //開發板是否板載nand flash,若對nand flash 進行初始化
    puts ("NAND:  ");
    nand_init();        /* go init the NAND */
#endif

這段代碼根據include/configs/smdk2410.h文件中的配置巨集,選擇性編譯代碼,初始化nor flash和nand flash,並讀出flash的大小,通過串口列印相關信息到控制台。

5.配置網路和使能中斷

    devices_init ();    /* get the devices list going. */

/* 未定義CONFIG_CMC_PU2,此處代碼不編譯 */
#ifdef CONFIG_CMC_PU2
    load_sernum_ethaddr ();
#endif /* CONFIG_CMC_PU2 */

    jumptable_init ();

    console_init_r ();    /* fully init console as a device */

/* 未定義CONFIG_MISC_INIT_R,此處代碼不編譯 */
#if defined(CONFIG_MISC_INIT_R)
    /* miscellaneous platform dependent initialisations */
    misc_init_r ();
#endif

    /* enable exceptions */
    enable_interrupts ();

    /* Perform network card initialisation if necessary */
#ifdef CONFIG_DRIVER_CS8900
    cs8900_get_enetaddr (gd->bd->bi_enetaddr);
#endif

/* 未定義CONFIG_DRIVER_SMC91111和CONFIG_DRIVER_LAN91C96,此處代碼不編譯 */
#if defined(CONFIG_DRIVER_SMC91111) || defined (CONFIG_DRIVER_LAN91C96)
    if (getenv ("ethaddr")) {
        smc_set_mac_addr(gd->bd->bi_enetaddr);
    }
#endif /* CONFIG_DRIVER_SMC91111 || CONFIG_DRIVER_LAN91C96 */

    /* Initialize from environment */
    if ((s = getenv ("loadaddr")) != NULL) {
        load_addr = simple_strtoul (s, NULL, 16);
    }
#if (CONFIG_COMMANDS & CFG_CMD_NET)
    if ((s = getenv ("bootfile")) != NULL) {
        copy_filename (BootFile, s, sizeof (BootFile));
    }
#endif    /* CFG_CMD_NET */

/* 未定義BOARD_LATE_INIT,不編譯此處代碼 */
#ifdef BOARD_LATE_INIT
    board_late_init ();
#endif

/* 未定義CFG_CMD_NET,此處不編譯 */
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#if defined(CONFIG_NET_MULTI)
    puts ("Net:   ");
#endif
    eth_initialize(gd->bd);
#endif

5.跳轉到main_loop函數

/* main_loop() can return to retry autoboot, if so just run it again. */
    for (;;) {
        main_loop ();
    }
}

start_armboot函數經過一系列初始化之後,會再次跳轉到main_loop函數中執行後續的操作。

總結:start_armboot函數

1、在uboot存儲映射的全局變數區為全局結構gt_t分配記憶體空間,並讓全局指針gt指向該分配記憶體空間入口地址

2、完成一些硬體的初始化,例如:設置系統時鐘和GPIO埠,使能指令Cache和數據Cache,設置串口,初始化flash等

3、讀取後續過程使用的信息,將其存儲到gt指針指向的gt_t結構的記憶體空間中

4、會再次跳轉到main_loop函數中執行其他後續操作

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在網站開發中,時常需要使用消息推送功能,http協議是無狀態連接,我們需要一個類似桌面程式中socket保持伺服器和客戶端連接的技術。signalr就是這樣一個技術,他能保持網站頁面和伺服器的一個長連接,時刻監聽伺服器端的信息。實現一個簡單的signalr功能步驟如下。 1.新建一個.net項目,使 ...
  • 調用: ...
  • 1.問題描述 這兩天使用ef6.0查詢mariaDB出現了數據查詢不到的情況 2.問題分析 後來發現除了這段數據查詢不到,其他都能查詢,於是逐步對比代碼,發現其他數據都是英文的,而這句是中文的於是把條件換成英文果然能夠查詢到了 3.問題驗證 接著開始考慮到底是ef的編碼問題還是mariaDB的編碼問 ...
  • 第一步,首先準備反彙編工具 ildasm.exe,找到VisualSVN的安裝路徑,一般先備份,在備份裡面操作。 第二步,轉儲 , 得到同名的il文件:VisualSVN.Core.L.il,用記事本打開得到的 VisualSVN.Core.L.il 文件,在其中搜索 “KeyToLicenseUn ...
  • 聲明:通過一個js的實例來告訴你C#也可以實現這樣的效果。 在JS中是這樣實現的: 你是否見過JS中給系統預設Array對象增加一個自定義查重方法contains 在沒有給Array原型上增加contains之前,通過vs編輯器是無法通過點的方式來調用contains 當給Array原型上增加con ...
  • ㈠ 概念 ① 物理CPU 實際Server中插槽上的CPU個數 物理cpu數量,可以數不重覆的 physical id 有幾個 ② 邏輯CPU Linux用戶對 /proc/cpuinfo 這個文件肯定不陌生. 它是用來存儲cpu硬體信息的 信息內容分別列出了processor 0 – n 的規格。 ...
  • 1. 簡單sql語句使用: 在任意目錄下新建一個資料庫,比如student 。 命令: sqlite3 student.db 出現如下提示: 輸入sql語句create table user(username text primary key, password text); 建一張user表 輸入 ...
  • 第一部份:一般模式可用的按鈕說明,游標移動、複製貼上、搜尋取代等 移動游標的方法 h 或 向左箭頭鍵(←) 游標向左移動一個字元 j 或 向下箭頭鍵(↓) 游標向下移動一個字元 k 或 向上箭頭鍵(↑) 游標向上移動一個字元 l 或 向右箭頭鍵(→) 游標向右移動一個字元 如果你將右手放在鍵盤上的話 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...