TI Sitara AM335x系统之AM335x uboot spl分析
生活随笔
收集整理的這篇文章主要介紹了
TI Sitara AM335x系统之AM335x uboot spl分析
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
本文轉載自nidetech的Blog
芯片到uboot啟動流程 ? ? ROM → SPL→ uboot.img 簡介 ? ? 在335x 中ROM code是第一級的bootlader。mpu上電后將會自動執行這里的代碼,完成部分初始化和引導第二級的bootlader,第二級的bootlader引導第三級bootader,在ti官方上對于第二級和第三級的bootlader由uboot提供。 SPL ? ? To unify all existing implementations for a secondary program loader (SPL) and to allow simply adding of new implementations this generic SPL framework has been created. With this framework almost all source files for a board can be reused. No code duplication or symlinking is necessary anymore. ? ? 1> Basic ARM initialization ? ? 2> UART console initialization ? ? 3> Clocks and DPLL locking (minimal) ? ? 4> SDRAM initialization ? ? 5> Mux (minimal) ? ? 6> BootDevice initialization(based on where we are booting from.MMC1/MMC2/Nand/Onenand) ? ? 7> Bootloading real u-boot from the BootDevice and passing control to it. ? ??? uboot spl源代碼分析 ? ? 一、makefile分析 ? ? 打開spl文件夾只有一個makefile 可見spl都是復用uboot原先的代碼。 ? ? 主要涉及的代碼文件為u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7 ? ?? ?? ?? ?? ?? ?? ?u-boot-2011.09-psp04.06.00.03/arch/arm/lib ? ?? ?? ?? ?? ?? ?? ?u-boot-2011.09-psp04.06.00.03/drivers ? ? LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-spl.lds ? ? 這個為鏈接腳本 二、u-boot-spl.lds
__start 為程序開始 __image_copy_end _end 三、代碼解析 ? ? __start 為程序開始 (arch/arm/cpu/armv7/start.S) ? ? .globl _start??這是在定義u-boot的啟動定義入口點,匯編程序的缺省入口是?start標號,用戶也可以在連接腳本文件中用ENTRY標志指明其它入口點。 .global是GNU ARM匯編的一個偽操作,聲明一個符號可被其他文檔引用,相當于聲明了一個全局變量,.globl和.global相同。該部分為處理器的異常處理向量表。地址范圍為0x0000 0000 ~ 0x0000 0020,剛好8條指令。 為什么是8條指令呢?這里來算一算。首先,一條arm指令為32bit(位),0x0000 0020換算成十進制為2^5=32B(字節),而32(B) = 4 * 8(B) = 4 * 8 * 8( bit),所以剛好8條指令(一個字節Byte包含8個位bit)。 ? ??下面是在匯編程序種經常會遇到的異常向量表。Arm處理器一般包括復位、未定義指令、SWI、預取終止、數據終止、IRQ、FIQ等異常,其中U-Boot中關于異常向量的定義如下: _start:? ?b? ?? ? reset? ? _start?標號表明?oot程序從這里開始執行。 b是不帶返回的跳轉(bl是帶返回的跳轉),意思是無條件直接跳轉到reset標號出執行程序。b是最簡單的分支,一旦遇到一個?b指令,ARM?處理器將立即跳轉到給定的地址,從那里繼續執行。注意存儲在分支指令中的實際的值是相對當前的?R15?的值的一個偏移量;而不是一個絕對地址。它的值由匯編器來計算,它是?24?位有符號數,左移兩位后有符號擴展為?32?位,表示的有效偏移為?26?位。 ? ?? ? ldr??pc, _undefined_instr tion? ?//未定義指令 ? ?? ? ldr??pc, _software_interrupt? ?//軟中斷SWI ? ?? ? ldr??pc, _prefetch_abort? ?//預取終止 ? ?? ? ldr??pc, _data_abort??//數訪問終止 ? ?? ? ldr??pc, _not_used ? ?? ? ldr??pc, _irq? ? //中斷請求IRQ ? ?? ? ldr??pc, _fiq? ? //快速中斷FIQ #ifdef CONFIG_SPL_BUILD??//該階段為spl執行下面代碼 _undefined_instruction: .word _undefined_instruction _software_interrupt: .word _software_interrupt _prefetch_abort:??.word _prefetch_abort _data_abort:? ?? ?.word _data_abort _not_used:? ? .word _not_used _irq:? ?? ?? ?.word _irq _fiq:? ?? ?? ?.word _fiq _pad:? ?? ?? ?.word 0x12345678 /* now 16*4=64 */ #else _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort:??.word prefetch_abort _data_abort:? ?? ?.word data_abort _not_used:? ? .word not_used _irq:? ?? ?? ?.word irq _fiq:? ?? ?? ?.word fiq _pad:? ?? ?? ?.word 0x12345678 /* now 16*4=64 */ #endif /* CONFIG_SPL_BUILD */ .word為ARM匯編特有的偽操作符,語法如下: .word {,} … 作用:插入一個32-bit的數據隊列。(與armasm中的DCD功能相同) .balignl 16,0xdeadbeef .align偽操作用于表示對齊方式:通過添加填充字節使當前位置滿足一定的對齊方式。 接下來是對各個段代碼的定義 略 Rest:?(arch/arm/cpu/armv7/start.S) ? ? bl??save_boot_params ? ? save_boot_params:?(arch/arm/cpu/armv7/ti81xx/lowlevel_init.S) #ifdef CONFIG_SPL_BUILD ? ? ldr r4, =ti81xx_boot_device? ?? ?? ?? ? ? ?? ? //ti81xx_boot_device = BOOT_DEVICE_NAND ? ?? ? //啟動方式 ? ? ldr r5, [r0, #BOOT_DEVICE_OFFSET] ? ? and r5, r5, #BOOT_DEVICE_MASK ? ? str r5, [r4] #endif ? ? bx??lr 回到reset:(arch/arm/cpu/armv7/start.S)? ? ? ? //設置cpu的工作模式?設置CPU的狀態類型為SVC特權模式 ? ? mrs r0, cpsr ? ? bic r0, r0, #0x1f ? ? orr r0, r0, #0xd3 ? ? msr cpsr,r0 cpu_init_crit: (arch/arm/cpu/armv7/start.S) ? ? mov r0, #0? ?? ???@ set up for MCR ? ? mcr p15, 0, r0, c8, c7, 0? ? @ invalidate TLBs ? ? mcr p15, 0, r0, c7, c5, 0? ? @ invalidate icache ? ? mcr p15, 0, r0, c7, c5, 6? ? @ invalidate BP array ? ? mcr? ???p15, 0, r0, c7, c10, 4??@ DSB ? ? mcr? ???p15, 0, r0, c7, c5, 4? ?@ ISB //關閉mmu?緩存 ? ? mrc p15, 0, r0, c1, c0, 0 ? ? bic r0, r0, #0x00002000??@ clear bits 13 (--V-) ? ? bic r0, r0, #0x00000007??@ clear bits 2:0 (-CAM) ? ? orr r0, r0, #0x00000002??@ set bit 1 (--A-) Align ? ? orr r0, r0, #0x00000800??@ set bit 11 (Z---) BTB #ifdef CONFIG_SYS_ICACHE_OFF ? ? bic r0, r0, #0x00001000??@ clear bit 12 (I) I-cache #else ? ? orr r0, r0, #0x00001000??@ set bit 12 (I) I-cache #endif ? ? mcr p15, 0, r0, c1, c0, 0 //調用初始化?函數 ? ? mov ip, lr? ?? ???@ persevere link reg across call ? ? bl??lowlevel_init? ???@ go setup pll,mux,memory ? ? lowlevel_init:(arch/arm/cpu/armv7/ti81xx/lowlevel.S) ? ? /* The link register is saved in ip by start.S */ ? ? mov r6, ip ? ? /* check if we are already running from RAM */ ? ? ldr r2, _lowlevel_init ? ??? ?_TEXT_BASE: ? ?? ?? ?.word CONFIG_SYS_TEXT_BASE??/* Load address (RAM) */ ? ?? ?? ?? ?#define CONFIG_SYS_TEXT_BASE? ?? ?0x80800000 ? ?? ?? ?? ?SDRAM的前8MB作為spl的bss段然后前64bytes做為u-boot.img的頭 ? ? ldr r3, _TEXT_BASE ? ? sub r4, r2, r3 ? ? sub r0, pc, r4 ? ? //設置堆棧指針 ? ? /* require dummy instr or subtract pc by 4 instead i''m doing stack init */ ? ? ldr sp, SRAM_STACK mark1: ? ? ldr r5, _mark1 ? ? sub r5, r5, r2 /* bytes between mark1 and lowlevel_init */ ? ? sub r0, r0, r5 /* r0 <- _start w.r.t current place of execution */ ? ? mov r10, #0x0 /* r10 has in_ddr used by s_init() */ ? ? ands r0, r0, #0xC0000000 /* MSB 2 bits <> 0 then we are in ocmc or DDR */ ? ? cmp r0, #0x80000000 ? ? bne s_init_start ? ? mov r10, #0x01 ? ? b s_init_start s_init_start:(arch/arm/cpu/armv7/ti81xx/lowlevel.S) ? ? mov r0, r10 /* passing in_ddr in r0 */ ? ? bl s_init ? ?? ??初始化pll??mux memery ? ? /* back to arch calling code */ ? ? mov pc, r6 call_board_init_f:(arch/arm/cpu/armv7/start.s) ? ? //設置堆棧指針,并調用board_init_f ? ? ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) ? ? bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ ? ? ldr r0,=0x00000000 ? ? bl??board_init_f void board_init_f(ulong dummy) ? ??『u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7/omap-common/spl.c』 ? ??調用relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE); ? ??這里使用了?CONFIG_SPL_STACK ? ?? ? #define CONFIG_SPL_STACK? ? LOW_LEVEL_SRAM_STACK ? ?? ?? ???#define LOW_LEVEL_SRAM_STACK? ? (SRAM0_START + SRAM0_SIZE – 4) ? ?? ???gdata?為.bss?前一段的空間?描述鏡像頭 ? ?? ? #define CONFIG_SPL_TEXT_BASE? ?? ? 0x402F0400 relocate_code:?(arch/arm/cpu/armv7/start.s) ? ?重載定位代碼 jump_2_ram:?(arch/arm/cpu/armv7/start.s) ? ??跳轉到spl的第二階段 board_init_r:(u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7/omap-common/spl.c) ? ??初始化時鐘:?timer_init() ? ? i2c?初始化:?i2c_init(); ? ??獲取啟動方式??omap_boot_device(); ? ??判斷啟動方式從不同的地方裝載鏡像 ? ?? ??從mmc?中裝載鏡像?spl_mmc_load_image(); ? ?? ??從nand?中裝載鏡像? ?spl_nand_load_image(); ? ?? ??從?uart??中裝載鏡像? ?spl_ymodem_load_image(); ? ??判斷鏡像類型 ? ?? ??跳轉到鏡像中執行鏡像?jump_to_image_no_args(); ? ? ? ? 裝載鏡像 將會從配置的存儲介質中讀取數據 及uboot鏡像 ? ? 然后跳轉到uboot中執行uboot
注:文章版權屬于成都萊得科技有限公司所有,轉載請注明出處,保留此行文字。
芯片到uboot啟動流程 ? ? ROM → SPL→ uboot.img 簡介 ? ? 在335x 中ROM code是第一級的bootlader。mpu上電后將會自動執行這里的代碼,完成部分初始化和引導第二級的bootlader,第二級的bootlader引導第三級bootader,在ti官方上對于第二級和第三級的bootlader由uboot提供。 SPL ? ? To unify all existing implementations for a secondary program loader (SPL) and to allow simply adding of new implementations this generic SPL framework has been created. With this framework almost all source files for a board can be reused. No code duplication or symlinking is necessary anymore. ? ? 1> Basic ARM initialization ? ? 2> UART console initialization ? ? 3> Clocks and DPLL locking (minimal) ? ? 4> SDRAM initialization ? ? 5> Mux (minimal) ? ? 6> BootDevice initialization(based on where we are booting from.MMC1/MMC2/Nand/Onenand) ? ? 7> Bootloading real u-boot from the BootDevice and passing control to it. ? ??? uboot spl源代碼分析 ? ? 一、makefile分析 ? ? 打開spl文件夾只有一個makefile 可見spl都是復用uboot原先的代碼。 ? ? 主要涉及的代碼文件為u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7 ? ?? ?? ?? ?? ?? ?? ?u-boot-2011.09-psp04.06.00.03/arch/arm/lib ? ?? ?? ?? ?? ?? ?? ?u-boot-2011.09-psp04.06.00.03/drivers ? ? LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-spl.lds ? ? 這個為鏈接腳本 二、u-boot-spl.lds
__start 為程序開始 __image_copy_end _end 三、代碼解析 ? ? __start 為程序開始 (arch/arm/cpu/armv7/start.S) ? ? .globl _start??這是在定義u-boot的啟動定義入口點,匯編程序的缺省入口是?start標號,用戶也可以在連接腳本文件中用ENTRY標志指明其它入口點。 .global是GNU ARM匯編的一個偽操作,聲明一個符號可被其他文檔引用,相當于聲明了一個全局變量,.globl和.global相同。該部分為處理器的異常處理向量表。地址范圍為0x0000 0000 ~ 0x0000 0020,剛好8條指令。 為什么是8條指令呢?這里來算一算。首先,一條arm指令為32bit(位),0x0000 0020換算成十進制為2^5=32B(字節),而32(B) = 4 * 8(B) = 4 * 8 * 8( bit),所以剛好8條指令(一個字節Byte包含8個位bit)。 ? ??下面是在匯編程序種經常會遇到的異常向量表。Arm處理器一般包括復位、未定義指令、SWI、預取終止、數據終止、IRQ、FIQ等異常,其中U-Boot中關于異常向量的定義如下: _start:? ?b? ?? ? reset? ? _start?標號表明?oot程序從這里開始執行。 b是不帶返回的跳轉(bl是帶返回的跳轉),意思是無條件直接跳轉到reset標號出執行程序。b是最簡單的分支,一旦遇到一個?b指令,ARM?處理器將立即跳轉到給定的地址,從那里繼續執行。注意存儲在分支指令中的實際的值是相對當前的?R15?的值的一個偏移量;而不是一個絕對地址。它的值由匯編器來計算,它是?24?位有符號數,左移兩位后有符號擴展為?32?位,表示的有效偏移為?26?位。 ? ?? ? ldr??pc, _undefined_instr tion? ?//未定義指令 ? ?? ? ldr??pc, _software_interrupt? ?//軟中斷SWI ? ?? ? ldr??pc, _prefetch_abort? ?//預取終止 ? ?? ? ldr??pc, _data_abort??//數訪問終止 ? ?? ? ldr??pc, _not_used ? ?? ? ldr??pc, _irq? ? //中斷請求IRQ ? ?? ? ldr??pc, _fiq? ? //快速中斷FIQ #ifdef CONFIG_SPL_BUILD??//該階段為spl執行下面代碼 _undefined_instruction: .word _undefined_instruction _software_interrupt: .word _software_interrupt _prefetch_abort:??.word _prefetch_abort _data_abort:? ?? ?.word _data_abort _not_used:? ? .word _not_used _irq:? ?? ?? ?.word _irq _fiq:? ?? ?? ?.word _fiq _pad:? ?? ?? ?.word 0x12345678 /* now 16*4=64 */ #else _undefined_instruction: .word undefined_instruction _software_interrupt: .word software_interrupt _prefetch_abort:??.word prefetch_abort _data_abort:? ?? ?.word data_abort _not_used:? ? .word not_used _irq:? ?? ?? ?.word irq _fiq:? ?? ?? ?.word fiq _pad:? ?? ?? ?.word 0x12345678 /* now 16*4=64 */ #endif /* CONFIG_SPL_BUILD */ .word為ARM匯編特有的偽操作符,語法如下: .word {,} … 作用:插入一個32-bit的數據隊列。(與armasm中的DCD功能相同) .balignl 16,0xdeadbeef .align偽操作用于表示對齊方式:通過添加填充字節使當前位置滿足一定的對齊方式。 接下來是對各個段代碼的定義 略 Rest:?(arch/arm/cpu/armv7/start.S) ? ? bl??save_boot_params ? ? save_boot_params:?(arch/arm/cpu/armv7/ti81xx/lowlevel_init.S) #ifdef CONFIG_SPL_BUILD ? ? ldr r4, =ti81xx_boot_device? ?? ?? ?? ? ? ?? ? //ti81xx_boot_device = BOOT_DEVICE_NAND ? ?? ? //啟動方式 ? ? ldr r5, [r0, #BOOT_DEVICE_OFFSET] ? ? and r5, r5, #BOOT_DEVICE_MASK ? ? str r5, [r4] #endif ? ? bx??lr 回到reset:(arch/arm/cpu/armv7/start.S)? ? ? ? //設置cpu的工作模式?設置CPU的狀態類型為SVC特權模式 ? ? mrs r0, cpsr ? ? bic r0, r0, #0x1f ? ? orr r0, r0, #0xd3 ? ? msr cpsr,r0 cpu_init_crit: (arch/arm/cpu/armv7/start.S) ? ? mov r0, #0? ?? ???@ set up for MCR ? ? mcr p15, 0, r0, c8, c7, 0? ? @ invalidate TLBs ? ? mcr p15, 0, r0, c7, c5, 0? ? @ invalidate icache ? ? mcr p15, 0, r0, c7, c5, 6? ? @ invalidate BP array ? ? mcr? ???p15, 0, r0, c7, c10, 4??@ DSB ? ? mcr? ???p15, 0, r0, c7, c5, 4? ?@ ISB //關閉mmu?緩存 ? ? mrc p15, 0, r0, c1, c0, 0 ? ? bic r0, r0, #0x00002000??@ clear bits 13 (--V-) ? ? bic r0, r0, #0x00000007??@ clear bits 2:0 (-CAM) ? ? orr r0, r0, #0x00000002??@ set bit 1 (--A-) Align ? ? orr r0, r0, #0x00000800??@ set bit 11 (Z---) BTB #ifdef CONFIG_SYS_ICACHE_OFF ? ? bic r0, r0, #0x00001000??@ clear bit 12 (I) I-cache #else ? ? orr r0, r0, #0x00001000??@ set bit 12 (I) I-cache #endif ? ? mcr p15, 0, r0, c1, c0, 0 //調用初始化?函數 ? ? mov ip, lr? ?? ???@ persevere link reg across call ? ? bl??lowlevel_init? ???@ go setup pll,mux,memory ? ? lowlevel_init:(arch/arm/cpu/armv7/ti81xx/lowlevel.S) ? ? /* The link register is saved in ip by start.S */ ? ? mov r6, ip ? ? /* check if we are already running from RAM */ ? ? ldr r2, _lowlevel_init ? ??? ?_TEXT_BASE: ? ?? ?? ?.word CONFIG_SYS_TEXT_BASE??/* Load address (RAM) */ ? ?? ?? ?? ?#define CONFIG_SYS_TEXT_BASE? ?? ?0x80800000 ? ?? ?? ?? ?SDRAM的前8MB作為spl的bss段然后前64bytes做為u-boot.img的頭 ? ? ldr r3, _TEXT_BASE ? ? sub r4, r2, r3 ? ? sub r0, pc, r4 ? ? //設置堆棧指針 ? ? /* require dummy instr or subtract pc by 4 instead i''m doing stack init */ ? ? ldr sp, SRAM_STACK mark1: ? ? ldr r5, _mark1 ? ? sub r5, r5, r2 /* bytes between mark1 and lowlevel_init */ ? ? sub r0, r0, r5 /* r0 <- _start w.r.t current place of execution */ ? ? mov r10, #0x0 /* r10 has in_ddr used by s_init() */ ? ? ands r0, r0, #0xC0000000 /* MSB 2 bits <> 0 then we are in ocmc or DDR */ ? ? cmp r0, #0x80000000 ? ? bne s_init_start ? ? mov r10, #0x01 ? ? b s_init_start s_init_start:(arch/arm/cpu/armv7/ti81xx/lowlevel.S) ? ? mov r0, r10 /* passing in_ddr in r0 */ ? ? bl s_init ? ?? ??初始化pll??mux memery ? ? /* back to arch calling code */ ? ? mov pc, r6 call_board_init_f:(arch/arm/cpu/armv7/start.s) ? ? //設置堆棧指針,并調用board_init_f ? ? ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) ? ? bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ ? ? ldr r0,=0x00000000 ? ? bl??board_init_f void board_init_f(ulong dummy) ? ??『u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7/omap-common/spl.c』 ? ??調用relocate_code(CONFIG_SPL_STACK, &gdata, CONFIG_SPL_TEXT_BASE); ? ??這里使用了?CONFIG_SPL_STACK ? ?? ? #define CONFIG_SPL_STACK? ? LOW_LEVEL_SRAM_STACK ? ?? ?? ???#define LOW_LEVEL_SRAM_STACK? ? (SRAM0_START + SRAM0_SIZE – 4) ? ?? ???gdata?為.bss?前一段的空間?描述鏡像頭 ? ?? ? #define CONFIG_SPL_TEXT_BASE? ?? ? 0x402F0400 relocate_code:?(arch/arm/cpu/armv7/start.s) ? ?重載定位代碼 jump_2_ram:?(arch/arm/cpu/armv7/start.s) ? ??跳轉到spl的第二階段 board_init_r:(u-boot-2011.09-psp04.06.00.03/arch/arm/cpu/armv7/omap-common/spl.c) ? ??初始化時鐘:?timer_init() ? ? i2c?初始化:?i2c_init(); ? ??獲取啟動方式??omap_boot_device(); ? ??判斷啟動方式從不同的地方裝載鏡像 ? ?? ??從mmc?中裝載鏡像?spl_mmc_load_image(); ? ?? ??從nand?中裝載鏡像? ?spl_nand_load_image(); ? ?? ??從?uart??中裝載鏡像? ?spl_ymodem_load_image(); ? ??判斷鏡像類型 ? ?? ??跳轉到鏡像中執行鏡像?jump_to_image_no_args(); ? ? ? ? 裝載鏡像 將會從配置的存儲介質中讀取數據 及uboot鏡像 ? ? 然后跳轉到uboot中執行uboot
注:文章版權屬于成都萊得科技有限公司所有,轉載請注明出處,保留此行文字。
總結
以上是生活随笔為你收集整理的TI Sitara AM335x系统之AM335x uboot spl分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 神舟十四号飞船即将发射:8吨重巨物、安全
- 下一篇: Scrum之 回顾会议