日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

u-boot分析之两阶段代码分析(三)

發布時間:2025/4/5 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 u-boot分析之两阶段代码分析(三) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • u-boot(三)啟動文件
  • 1,概述
  • 2,uboot第一階段代碼分析:
  • 匯編
  • 2,uboot第二階段代碼分析
  • C:_start_armboot
  • C:main_loop

u-boot(三)啟動文件

?

1,概述

本書使用的uboot從nor flash啟動,下面以開發板100ask24x0的uboot為例。

uboot屬于兩階段的bootloader,第一階段的文件為cpu/arm920t/start.S和board/100ask24x0/lowlevel_init.S,前者是平臺相關的,后者是開發板相關的,主要是匯編實現,主要完成一些依賴于cpu體系結構的初始化,并調用第二階段的代碼;第二階段的文件從lib_arm/board.c開始,主要是c語言實現,實現更復雜的功能。

2,uboot第一階段代碼分析:

(1)硬件設備初始化

將cpu設為svc模式,關閉watchdog,設置時鐘,關閉MMU,CACHE,代碼在cpu/arm920t/start.S中。

(2)為加載bootloader的第二階段代碼準備RAM空間

初始化RAM空間,通過在調用start.S中調用lowlevel_init函數來設置存儲控制器,使得sdram可用,代碼在board/100ask24x0/lowlevel_init.S中。

(3)復制bootloader的第二階段代碼到RAM空間中

將整個uboot代碼(包括第一、第二階段)都復制到SDRAM中,在cpu/arm920t/start.S中實現。(注意:100ask24x0改為用c函數實現的)。

(4)設置好棧

棧的設置靈活性很大,只要讓sp指向一段沒有使用的內存即可,下面分析可以看到內存的使用情況。

(5)跳轉到第二階段代碼的C入口點

跳轉之前清除bss段(初始值為0、無初始值的全局變量,靜態變量放在bss段),c函數的運行環境準備好后,通過調用lib_arm/board.c中的start_armboot跳到c函數的入口點,這是第二階段的入口點。

匯編:_start

cpu/arm920t/start.S

u-boot也是一個牛逼的單片機程序,所以也就需要:

  • 硬件相關初始化
  • 看門狗
  • 時鐘
  • sdram
  • nand copy程序
  • 設置sp
  • 接下去就是讀取內核,啟動內核等
  • 程序實際的步驟是:

    1.set the cpu to SVC32 mode 2.turn off the watchdog 3.mask all IRQs 4.clock_init board\100ask24x0\boot_init.c 5.cpu_init_crit do sys-critical inits only at reboot,not when booting from ram!判斷 是不是從內部ram啟動還是仿真直接燒寫到鏈接地址,如果不在正確的加載地址的話,執行cpu_init_critcpu_init_crit執行SDRAM初始化flush v4 I/D caches,disable MMU stuff and caches,lowlevel_init 這個會去初始化sdram,這個函數在lowlevel_init.S in your board directory也就是board\100ask24x0\lowlevel_init.S 6.Set up the stack 7.relocate CopyCode2Ram中自動識別當前是nor還是nand啟動,nand啟動時自動cp到內部ram中運行,所以可寫,CopyCode2Ram位于board\100ask24x0\boot_init.c 8.bss段清零 9.調用C函數 _start_armboot

    堆棧設置如下

    0x33F80000uboot程序
    ·=-CFG_MALLOC_LENmalloc area
    .=-CFG_GBL_DATA_SIZEbdinfo
    .=-CONFIG_STACKSIZE_IRQIRQ 的棧
    .=-CONFIG_STACKSIZE_FIQFRQ的棧
    .=-12leave 3 words for abort-stack
    sp的初始位置?

    內存圖:

    2,uboot第二階段代碼分析

    (1)初始化本階段要使用到的硬件設備

    (2)檢測系統內存映射(memory map)?

    (3)uboot命令的格式

    (4)為內核設置啟動參數

    第二階段從lib_arm/board.c中的start_armboot函數開始,程序流程如下:

    C:_start_armboot

    文件路徑:lib_arm\board.c,這里就是u-boot執行C代碼的地方了.

    • 分配了一個gd的結構體內存
    gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));//在這里,_armboot_start=_start,根據鏈接腳本,這也就是代碼段的起始=0x33F80000 //也就是指向了內存圖128的地方了
    • 執行init_sequence數組里預先定義的一些初始化函數

    board_init中設置了gd->bd->bi_arch_number = MACH_TYPE_S3C2440;,設置了一個參數gd->bd->bi_boot_params =? ? ? ? ? ? 0x30000100;這個就是啟動內核參數的地址

    • flash_init、nand_init:flash/nand 初始化
    • 堆棧初始化
    • env_relocate:環境變量的設置存儲(環境變量來源有兩種:一種是代碼寫死(也就是默認),一種在FLASH上保存,uboot啟動后會檢查flash上是否有可用的環境變量,有就用flash上的,否則使用默認)
    • main_loop:進入主循環

    代碼摘要

    void start_armboot (void) { //-----/* Pointer is writable since we allocated a register for it */gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t)); //----- //函數指針,初始化設備for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {if ((*init_fnc_ptr)() != 0) {hang ();}} //---- flash初始化,識別 #ifndef CFG_NO_FLASH/* configure available FLASH banks */size = flash_init ();display_flash_config (size); #endif /* CFG_NO_FLASH */ ---- nand初始化 #if (CONFIG_COMMANDS & CFG_CMD_NAND)puts ("NAND: ");nand_init(); /* go init the NAND */ #endif //------//分配堆/* armboot_start is defined in the board-specific linker script */mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); //-----//uboot的環境變量/* initialize environment */env_relocate (); //-----//經過一系列的初始化/* main_loop() can return to retry autoboot, if so just run it again. */for (;;) {main_loop ();}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 */ #if defined(CONFIG_DISPLAY_CPUINFO)print_cpuinfo, /* display cpu info (and speed) */ #endif #if defined(CONFIG_DISPLAY_BOARDINFO)checkboard, /* display board info */ #endifdram_init, /* configure available RAM banks */display_dram_config,NULL, };int board_init (void) {---/* support both of S3C2410 and S3C2440, by www.100ask.net */if (isS3C2410){/* arch number of SMDK2410-Board */gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;}else{/* arch number of SMDK2440-Board */gd->bd->bi_arch_number = MACH_TYPE_S3C2440;}/* adress of boot parameters */gd->bd->bi_boot_params = 0x30000100;}

    C:main_loop

    common/main.c

    main_loop兩種選擇:

    ①在bootdelay減到零之前敲下任意鍵將進入uboot控制界面(命令行模式),不過這里100ask24x0自定義一個menu命令,所以此時進入的是自己實現的菜單模式,可輸入‘q’退出此模式轉而進入命令行模式,readline (CFG_PROMPT)不斷接收串口傳過來的命令,run_command (lastcommand, flag)執行這些命令 。

    ②若倒計時結束前沒有敲下任意鍵,將根據參數bootcmd來啟動內核,getenv ("bootcmd")獲得參數bootcmd值,可知bootcmd = read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0,其中read.jffs2和bootm均為uboot命令,所以uboot核心是命令,要繼續分析uboot是如何將內核從flash上搬到sdram并啟動內核,必須深入分析這些命令才能清楚。

    內核啟動

    這里實現了u-boot的倒計時,有打印命令,獲取環境變量等,最關鍵的代碼是

    s = getenv ("bootcmd"); if(倒計時結束) {printf("Booting Linux ...\n"); run_command (s, 0);}

    實際的環境變量是bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0,讀取內核,啟動內核

    菜單處理(自定義實現)

    如果倒計時結束前輸入了空格,進入命令模式run_command("menu", 0);

    命令處理

  • 死循環
  • 讀取串口輸入len = readline (CFG_PROMPT);
  • 執行命令rc = run_command (lastcommand, flag);
  • 轉載:https://www.cnblogs.com/zongzi10010/p/10023676.html

    總結

    以上是生活随笔為你收集整理的u-boot分析之两阶段代码分析(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

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