1. 程式人生 > >UBOOT原始碼分析(詳細)

UBOOT原始碼分析(詳細)

@可知start.S的流程為:異常向量——上電覆位後進入復位異常向量——跳到啟動程式碼處——設定處理器進入管理模式——關閉看門狗——關閉中斷——設定時鐘分頻——關閉MMUCACHE——進入lowlever_init.S——檢查當前程式碼所處的位置,如果在FLASH中就將程式碼搬移到RAM

大多數bootloader都分為stage1stage2兩部分,u-boot也不例外。依賴於CPU體系結構的程式碼(如裝置初始化程式碼等)通常都放在stage1且可以用匯編語言來實現,而stage2則通常用C語言來實現,這樣可以實現複雜的功能,而且有更好的可讀性和移植性。
1
Stage1start.S

程式碼結構
u-boot
stage1程式碼通常放在start.S檔案中,他用匯編語言寫成,其主要程式碼部分如下:1)定義入口。由於一個可執行的Image必須有一個入口點,並且只能有一個全域性入口,通常這個入口放在ROMFlash)的0x0地址,因此,必須通知編譯器以使其知道這個入口,該工作可通過修改聯結器指令碼來完成。2)設定異常向量(Exception Vector)。3)設定CPU的速度、時鐘頻率及終端控制暫存器。4)初始化記憶體控制器。5)將ROM中的程式複製到RAM中。6)初始化堆疊。7)轉到RAM中執行,該工作可使用指令ldr pc來完成。
2
Stage2 C語言程式碼部分

lib_arm/board.c
中的start armbootC語言開始的函式也是整個啟動程式碼中C語言的主函式,同時還是整個u-bootarmboot)的主函式,該函式只要完成如下操作:1)呼叫一系列的初始化函式。2)初始化Flash裝置。3)初始化系統記憶體分配函式。4)如果目標系統擁有NAND裝置,則初始化NAND裝置。5)如果目標系統有顯示裝置,則初始化該類裝置。6)初始化相關網路裝置,填寫IPMAC地址等。7)進去命令迴圈(即整個boot的工作迴圈),接受使用者從串列埠輸入的命令,然後進行相應的工作。
3
U-Boot的啟動順序(示例,其他u-boot版本類似)
cpu/arm920t/start.S

@檔案包含處理

#include <config.h>
@
由頂層的mkconfig生成,其中只包含了一個檔案:configs/<頂層makefile6個引數的第1個引數>.h
#include <version.h>
#include <status_led.h>

/*
*************************************************************************
*
* Jump vector table as in table 3.1 in [1]
*
*************************************************************************
*/

注:ARM微處理器支援位元組(8位)、半字(16位)、字(32位)3種資料型別
@
向量跳轉表,每條佔四個位元組(一個字),地址範圍為0x0000 0000@0x0000 0020
@ARM
體系結構規定在上電覆位後的起始位置,必須有8條連續的跳

@轉指令,通過硬體實現。他們就是異常向量表。ARM在上電覆位後,@是從0x00000000開始啟動的,其實如果bootloader存在,在執行

@下面第一條指令後,就無條件跳轉到start_code,下面一部分並沒@執行。設定異常向量表的作用是識別bootloader。以後系統每當有@異常出現,則CPU會根據異常號,從記憶體的0x00000000處開始查表@做相應的處理

/******************************************************

;當一個異常出現以後,ARM會自動執行以下幾個步驟:
;1.
把下一條指令的地址放到連線暫存器LR(通常是R14).---儲存位置
;2.
將相應的CPSR(當前程式狀態暫存器)複製到SPSR(備份的程式狀態暫存器)---儲存CPSR
;3.
根據異常型別,強制設定CPSR的執行模式位
;4.
強制PC(程式計數器)從相關異常向量地址取出下一條指令執行,從而跳轉到相應的異常處理程式中
*********************************************************/

.globl _start /*系統復位位置,整個程式入口*/
@_start
GNU彙編器的預設入口標籤,.globl_start宣告為外部程式可訪問的標籤,.globlGNU彙編的保留關鍵字,前面加點是GNU彙編的語法
_start: b       start_code   @0x00
@ARM
上電後執行的第一條指令,也即復位向量,跳轉到start_code

@resetb,就是因為resetMMU建立前後都有可能發生
@
其他的異常只有在MMU建立之後才會發生
ldr pc, _undefined_instruction /*
未定義指令異常,0x04*/
   ldr pc, _software_interrupt   /*
軟中斷異常,0x08*/
   ldr pc, _prefetch_abort    /*
記憶體操作異常,0x0c*/
   ldr pc, _data_abort     /*
資料異常,0x10*/
   ldr pc, _not_used     /*
未適用,0x14*/
   ldr pc, _irq      /*
慢速中斷異常,0x18*/
   ldr pc, _fiq      /*
快速中斷異常,0x1c*/

@對於ARM資料從記憶體到CPU之間的移動只能通過L/S指令,如:ldr r0,0x12345678為把0x12345678記憶體中的資料寫到r0中,還有一個就是ldr偽指令,如:ldr r0,=0x12345678為把0x12345678地址寫到r0中,mov只能完成暫存器間資料的移動,而且立即數長度限制在8

_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
@.word
GNU ARM彙編特有的偽操作,為分配一段字記憶體單元(分配的單元為字對齊的),可以使用.word把標誌符作為常量使用。如_fiq:.word fiq即把fiq存入記憶體變數_fiq中,也即是把fiq放到地址_fiq中。

.balignl 16,0xdeadbeef
@.balignl
.balign的變體

@ .align偽操作用於表示對齊方式:通過新增填充位元組使當前位置

@滿足一定的對齊方式。.balign的作用同.align
@ .align {alignment} {,fill} {,max}
@
其中:alignment用於指定對齊方式,可能的取值為2的次

@冪,預設為4fill是填充內容,預設用0填充。max是填充位元組@數最大值,如果填充位元組數超過max, 就不進行對齊,例如:
@ .align 4 /*
指定對齊方式為字對齊 */

/*
*************************************************************************
*
* Startup Code (called from the ARM reset exception vector)
*
* do important init only if we don't start from memory!
* relocate armboot to ram
* setup stack
* jump to second stage
*
*************************************************************************


@
儲存變數的資料區,儲存一些全域性變數,用於BOOT程式從FLASH拷貝@RAM,或者其它的使用。
@
還有一些變數的長度是通過連線腳本里得到,實際上由編譯器算出

@來的


_TEXT_BASE:

@因為linux開始地址是0x30000000,我這裡是64M SDRAM,所以@TEXT_BASE = 0x33F80000 ???
.word TEXT_BASE /*uboot
映像在SDRAM中的重定位地址*/
@TEXT_BASE
在開發板相關的目錄中的config.mk文件中定義, 他定

@義了程式碼在執行時所在的地址, 那麼_TEXT_BASE中儲存了這個地

@址(這個TEXT_BASE怎麼來的還不清楚)

.globl _armboot_start
_armboot_start:
.word _start
@
_start來初始化_armboot_start。(為什麼要這麼定義一下還不明白)

/*
* These are defined in the board-specific linker script.
*/
@
下面這些是定義在開發板目錄連結指令碼中的

.globl _bss_start   
_bss_start:
.word __bss_start
@__bss_start
定義在和開發板相關的u-boot.lds中,_bss_start儲存的是__bss_start標號所在的地址。

.globl _bss_end
_bss_end:
.word _end
@
同上,這樣賦值是因為程式碼所在地址非編譯時的地址,直接取得該標號對應地址。

@中斷的堆疊設定

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de

/* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif


/*
* the actual start code
*/
@
復位後執行程式
@
真正的初始化從這裡開始了。其實在CPU一上電以後就是跳到這裡執行的
reset:
/*
* set the cpu to SVC32 mode
*/
@
更改處理器模式為管理模式
@
對狀態暫存器的修改要按照:讀出-修改-寫回的順序來執行
@
    31 30 29 28 ---   7   6  -   4    3   2   1   0
    N Z C V       I   F       M4 M3 M2 M1 M0
                                  0   0   0 0   0     User26
模式
                                  0   0   0 0   1     FIQ26
模式
                                  0   0   0 1   0     IRQ26
模式
                                  0   0   0 1   1     SVC26
模式
                                  1   0   0 0   0     User
模式
                                  1   0   0 0   1     FIQ
模式
                                  1   0   0 1   0     IRQ
模式
                                  1   0   0 1   1     SVC
模式
                                  1   0   1 1   1     ABT
模式
                                  1   1   0 1   1     UND
模式
                                  1   1   1 1   1     SYS
模式

mrs r0,cpsr
@
cpsr的值讀到r0
bic r0,r0,#0x1f
@
清除M0~M4
orr r0,r0,#0xd3
@
禁止IRQ,FIQ中斷,並將處理器置於管理模式
msr cpsr,r0

@以下是點燈了,這裡應該會牽涉到硬體設定,移植的時候應該可以不要
bl coloured_LED_init
bl red_LED_on

@針對AT91RM9200進行特殊處理
#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)
/*
* relocate exception table
*/
ldr r0, =_start
ldr r1, =0x0
mov r2, #16
copyex:
subs r2, r2, #1
@sub
帶上了s用來更改進位標誌,對於sub來說,若發生借位則C標誌置0,沒有則為1,這跟adds指令相反!要注意。
ldr r3, [r0], #4
str r3, [r1], #4
bne copyex
#endif

@針對S3C2400S3C2410進行特殊處理
@CONFIG_S3C2400
CONFIG_S3C2410等定義在include/configs/下不同開發板的標頭檔案中
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
/* turn off the watchdog */

@關閉看門狗定時器的自動復位功能並遮蔽所有中斷,上電後看門狗為開,中斷為關
# if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#else @s3c2410
的配置
# define pWTCON 0x53000000
@pWTCON
定義為看門狗控制暫存器的地址(s3c2410s3c2440相同)
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
@INTMSK
定義為主中斷遮蔽暫存器的地址(s3c2410s3c2440相同)
# define INTSUBMSK 0x4A00001C
@INTSUBMSK
定義為副中斷遮蔽暫存器的地址(s3c2410s3c2440相同)
# define CLKDIVN 0x4C000014 /* clock divisor register */
@CLKDIVN
定義為時鐘分頻控制暫存器的地址(s3c2410s3c2440相同)
# endif
@
至此暫存器地址設定完畢

ldr     r0, =pWTCON
mov     r1, #0x0
str     r1, [r0]
@
對於S3C2440S3C2410WTCON暫存器的[0]控制允許或禁止看門狗定時器的復位輸出功能,設定為“0”禁止復位功能。

/*
* mask all IRQs by setting all bits in the INTMR - default
*/
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0]
# if defined(CONFIG_S3C2410)
ldr r1, =0x3ff @2410
好像應該為7ff才對(不理解uboot為何是這個數字)
ldr r0, =INTSUBMSK
str r1, [r0]
# endif
@
對於S3C2410INTMSK暫存器的32位和INTSUBMSK暫存器的低11位每一位對應一箇中斷,相應位置“1”為不響應相應的中斷。對於S3C2440INTSUBMSK15位可用,所以應該為0x7fff了。

/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0]
@
時鐘分頻設定,FCLK為核心提供時鐘,HCLKAHBARM920T,記憶體@控制器,中斷控制器,LCD控制器,DMA和主USB模組)提供時鐘,@PCLKAPB(看門狗、IISI2CPWMMMCADCUARTGPIO@RTCSPI)提供時鐘。分頻數一般選擇148,所以HDIVN=2,PDIVN=1@CLKDIVN=5,這裡僅僅是配置了分頻暫存器,關於MPLLCON的配置肯@定寫在lowlevel_init.S中了
@
歸納出CLKDIVN的值跟分頻的關係:
@0x0 = 1:1:1 , 0x1 = 1:1:2 , 0x2 = 1:2:2 , 0x3 = 1:2:4, 0x4 = 1:4:4, 0x5 =1:4:8, 0x6 = 1:3:3,
0x7 = 1:3:6
@S3C2440
的輸出時鐘計算式為:Mpll=(2*m*Fin)/(p*2^s)
S3C2410
的輸出時鐘計算式為:Mpll=(m*Fin)/(p*2^s)
m=M(the value for divider M)+8;p=P(the value for divider P)+2
M,P,S
的選擇根據datasheetPLL VALUE SELECTION TABLE表格進行,我的開發板晶振為16.9344M,所以輸出頻率選為:399.65M的話M=0x6e,P=3,S=1
@s3c2440
增加了攝像頭,FCLKHCLKPCLK的分頻數還受到CAMDIVN[9](預設為0,CAMDIVN[8](預設為0)的影響
#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */

/*
* we do sys-critical inits only at reboot,
* not when booting from ram!
*/
@
選擇是否初始化CPU
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
bl cpu_init_crit
@
執行CPU初始化,BL完成跳轉的同時會把後面緊跟的一條指令地址儲存到連線暫存器LRR14)中。以使子程式執行完後正常返回。
#endif

@除錯階段的程式碼是直接在RAM中執行的,而最後需要把這些程式碼 @固化到Flash中,因此U-Boot需要自己從Flash轉移到
@RAM
中執行,這也是重定向的目的所在。
@
通過adr指令得到當前程式碼的地址資訊:如果U-boot是從RAM @開始執行,則從adr,r0,_start得到的地址資訊為
@r0=_start=_TEXT_BASE=TEXT_BASE=0x33F80000; @
如果U-bootFlash開始執行,即從處理器對應的地址執行,
@
r0=0x0000,這時將會執行copy_loop標識的那段程式碼了。
@ _TEXT_BASE
定義在board/smdk2410/config.mk

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate:    /* relocate U-Boot to RAM    */
adr r0, _start /* r0 <- current position of code   */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp     r0, r1 /* don't reloc duringdebug         */
beq     stack_setup
ldr r2, _armboot_start
@_armboot_start
_start地址
ldr r3, _bss_start
@_bss_start
為資料段地址
sub r2, r3, r2 /* r2 <- size ofarmboot            */
add r2, r0, r2 /* r2 <- source endaddress         */

copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0]    */

@從源地址[r0]讀取8個位元組到暫存器,每讀一個就更新一次r0地址
@ldmia:r0
安位元組增長
stmia r1!, {r3-r10} /* copy to   target address [r1]   */
@LDM(STM)
用於在暫存器所指的一片連續儲存器和暫存器列表的寄存@器間進行資料移動,或是進行壓棧和出棧操作。
@
格式為:LDM(STM){條件}{型別}基址暫存器{},暫存器列表{^}
@
對於型別有以下幾種情況: IA 每次傳送後地址加1,用於移動數

@據塊
    IB
每次傳送前地址加1,用於移動資料塊
    DA
每次傳送後地址減1,用於移動資料塊
    DB
每次傳送前地址減1,用於移動資料塊
    FD
滿遞減堆疊,用於操作堆疊(即先移動指標再操作資料,相當於DB
    ED
空遞減堆疊,用於操作堆疊(即先操作資料再移動指標,相當於DA
    FA
滿遞增堆疊,用於操作堆疊(即先移動指標再操作資料,相當於IB
    EA
空遞增堆疊,用於操作堆疊(即先操作資料再移動指標,相當於IA(這裡是不是應該要涉及到NAND或者NOR的讀寫?沒有看出來)

cmp r0, r2   /* until source end addreee[r2]    */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

/* Set up thestack          */
@
初始化堆疊
stack_setup:


ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot   */

@獲取分配區域起始指標,

sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* mallocarea    */

@CFG_MALLOC_LEN=128*1024+CFG_ENV_SIZE=128*[email protected]=192K

sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /*bdinfo   */

@CFG_GBL_DATA_SIZE    128---size in bytesreserved for initial data 用來儲存開發板資訊
#ifdef CONFIG_USE_IRQ

@這裡如果需要使用IRQ, 還有給IRQ保留堆疊空間, 一般不使用.
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, #12 /* leave 3 words for abort-stack    */

@該部分將未初始化資料段_bss_start----_bss_end中的資料 @清零
clear_bss:
ldr r0, _bss_start /* find start of bsssegment        */
ldr r1, _bss_end /* stophere                       */
mov r2, #0x00000000 /*clear                           */

clbss_l:str r2, [r0] /* clearloop...                   */
add r0, r0, #4
cmp r0, r1
ble clbss_l

@跳到階段二C語言中去
ldr pc, _start_armboot

_start_armboot: .word start_armboot
@start_armboot
/lib_arm/中,到這裡因該是第一階段已經完成了吧,下面就要去C語言中執行第二階段了吧

/*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/
@CPU
初始化

@“relocate: /* relocate U-Boot to RAM */ ”之前被呼叫

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:     
/*
* flush v4 I/D caches
*/
@
初始化CACHES
mov r0, #0
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */

/*
* disable MMU stuff and caches
*/
@
關閉MMUCACHES
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
mcr p15, 0, r0, c1, c0, 0
@
對協處理器的操作還是看不懂,暫時先不管吧,有時間研究一下ARM技術手冊的協處理器部分。

/*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.
*/
@
初始化RAM時鐘,因為記憶體是跟開發板密切相關的,所以這部分在/開發板目錄/lowlevel_init.S中實現
mov ip, lr
@
儲存LR,以便正常返回,注意前面是通過BL跳到cpu_init_crit來的。
@
ARM937個暫存器,ARM727個)
37
個暫存器=7個未分組暫存器(R0R7+ 2×5個分組暫存器R8R12+6×2R13=SPR14=lr 分組暫存器) + 1(R15=PC) +1(CPSR) + 5(SPSR)
用途和訪問許可權:
R0
R7:USR(使用者模式)fiq(快速中斷模式)、irq(中斷模式)、svc(超級用法模式)、abtund
R8
R12R8_usrR12_usrusrirqsvcabtund
         R8_fiq
R12_fiqfiq
R11=fp
R12=IP(
從反彙編上看,fpip一般用於存放SP的值)
R13
R14R13_usr R14_usr(每種模式都有自己的暫存器)
SP
lr R13_fiq R14_fiq
          R13_irq R14_irq
          R13_svc R14_svc
          R13_abt R14_abt
          R13_und R14_und
R15(PC)
:都可以訪問(即PC的值為當前指令的地址值加8個位元組)
R16   
:((Current Program Status Register,當前程式狀態暫存器)
           SPSR_fiq,SPSR_irq,SPSR_abt,SPSR_und(USR
模式沒有)

#if defined(CONFIG_AT91RM9200EK)

#else
bl lowlevel_init

@在重定向程式碼之前,必須初始化記憶體時序,因為重定向時需要將@flash中的程式碼複製到記憶體中lowlevel_init@/board/smdk2410/lowlevel_init.S中。

#endif
mov lr, ip
mov pc, lr
@
返回到主程式

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

/*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/
@
這段沒有看明白,不過好像跟移植關係不是很大,先放一放。
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE 72

#define S_OLD_R0 68
#define S_PSR 64
#define S_PC 60
#define S_LR 56
#define S_SP 52

#define S_IP 48
#define S_FP 44
#define S_R10 40
#define S_R9 36
#define S_R8 32
#define S_R7 28
#define S_R6 24
#define S_R5 20
#define S_R4 16
#define S_R3 12
#define S_R2 8
#define S_R1 4
#define S_R0 0

#define MODE_SVC 0x13
#define I_BIT 0x80

/*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/

.macro bad_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12}   @ Calling r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE)
sub r2, r2, #(CONFIG_SYS_MALLOC_LEN)
sub r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ set base 2 words into abort stack
ldmia r2, {r2 - r3}   @ get pc, cpsr
add r0, sp, #S_FRAME_SIZE @ restore sp_SVC

add r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3}   @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp
.endm

.macro irq_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12}   @ Calling r0-r12
add     r7, sp, #S_PC
stmdb   r7, {sp,lr}^                  @ Calling SP, LR
str     lr, [r7,#0]                   @ Save calling PC
mrs     r6, spsr
str     r6, [r7,#4]                   @ Save CPSR
str     r0, [r7,#8]                   @ Save OLD_R0
mov r0, sp
.endm

.macro irq_restore_user_regs
ldmia sp, {r0 - lr}^   @ Calling r0 - lr
mov r0, r0
ldr lr, [sp, #S_PC]   @ Get PC
add sp, sp, #S_FRAME_SIZE
subs pc, lr, #4   @ return & move spsr_svc into cpsr
.endm

.macro get_bad_stack
ldr r13, _armboot_start @ setup our mode stack
sub r13, r13, #(CONFIG_STACKSIZE)
sub r13, r13, #(CONFIG_SYS_MALLOC_LEN)
sub r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8) @ reserved a couple spots in abortstack

str lr, [r13]   @ save caller lr / spsr
mrs lr, spsr
str     lr, [r13, #4]

mov r13, #MODE_SVC   @ prepare SVC-Mode
@ msr spsr_c, r13
msr spsr, r13
mov lr, pc
movs pc, lr
.endm

.macro get_irq_stack   @ setup IRQ stack
ldr sp, IRQ_STACK_START
.endm

.macro get_fiq_stack   @ setup FIQ stack
ldr sp, FIQ_STACK_START
.endm

相關推薦

UBOOT原始碼分析詳細

@可知start.S的流程為:異常向量——上電覆位後進入復位異常向量——跳到啟動程式碼處——設定處理器進入管理模式——關閉看門狗——關閉中斷——設定時鐘分頻——關閉MMU和CACHE——進入lowlever_init.S——檢查當前程式碼所處的位置,如果在FLASH中就將程

okhttp原始碼分析——基本流程詳細

1.okhttp原始碼分析(一)——基本流程(超詳細) 2.okhttp原始碼分析(二)——RetryAndFollowUpInterceptor過濾器 3.okhttp原始碼分析(三)——CacheInterceptor過濾器 4.okhttp原始碼分析(四)——Conn

(轉)java程序調用內存變化過程分析詳細

舉例 static成員 bsp 根據 執行方法 pip 狀態 font ear 原博地址: https://blog.csdn.net/Myuhua/article/details/81385609 (一)不含靜態變量的java程序運行時內存變化過程分析 代碼: 1 p

Android ADB 原始碼分析

前言 之前分析的兩篇文章 Android Adb 原始碼分析(一) 嵌入式Linux:Android root破解原理(二)   寫完之後,都沒有寫到相關的實現程式碼,這篇文章寫下ADB的通訊流程的一些細節 看這篇文章之前,請先閱讀 Linux的SOCKET

Mybatis 原始碼分析2—— 引數處理

Mybatis對引數的處理是值得推敲的,不然在使用的過程中對發生的一系列錯誤直接懵逼了。 以前遇到引數繫結相關的錯誤我就是直接給加@param註解,也稀裡糊塗地解決了,但是後來遇到了一些問題推翻了我的假設:單個引數不需要使用 @param 。由此產生了一個疑問,Mybatis到底是怎

Mybatis 原始碼分析9—— 事物管理

Mybatis 提供了事物的頂層介面: public interface Transaction { /** * Retrieve inner database connection * @return DataBase connection * @throw

Mybatis 原始碼分析8—— 一二級快取

一級快取 其實關於 Mybatis 的一級快取是比較抽象的,並沒有什麼特別的配置,都是在程式碼中體現出來的。 當呼叫 Configuration 的 newExecutor 方法來建立 executor: public Executor newExecutor(Transac

Mybatis原始碼分析7—— 結果集處理

解析封裝 ResultMap 是和結果集相關的東西,最初在解析 XML 的時候,於 parseStatementNode 方法中,針對每一個 select 節點進行解析,轉換為 MappedStatement(類似 Spring 的 bean 配置和 BeanDefinition 的

Mybatis原始碼分析6—— 從JDBC看Mybatis的設計

Java資料庫連線,(Java Database Connectivity,簡稱JDBC)是Java語言中用來規範客戶端程式如何來訪問資料庫的應用程式介面,提供了諸如查詢和更新資料庫中資料的方法。 六步流程: 載入驅動(5.x驅動包不需要這步了) 建立

Mybatis原始碼分析5—— 外掛的原理

MyBatis 允許你在已對映語句執行過程中的某一點進行攔截呼叫。 預設情況下,可以使用外掛來攔截的方法呼叫包括: Executor (update, query, flushStatements, commit, rollback, getTransaction, cl

Mybatis原始碼分析4—— Mapper的建立和獲取

Mybatis我們一般都是和Spring一起使用的,它們是怎麼融合到一起的,又各自發揮了什麼作用? 就拿這個Mapper來說,我們定義了一個介面,聲明瞭一個方法,然後對應的xml寫了這個sql語句, 它怎麼就執行成功了?這傢伙是怎麼實現的,帶著這個好奇心,我一步步跟蹤,慢慢揭開了它的

Mybatis原始碼分析3—— 從Mybatis的視角去看Bean的初始化流程

不涉及Spring完整的啟動流程,僅僅從Mybatis的視角去分析幾個關鍵的方法,找到Mybatis是如何通過這幾個擴充套件點植入進去的,反過來看Spring是如何設計,埋下這些伏筆,實現其可擴充套件性。 springContext-mybatis.xml的配置: <!--

Mybatis原始碼分析1—— Mapper檔案解析

感覺CSDN對markdown的支援不夠友好,總是伴隨各種問題,很惱火! xxMapper.xml的解析主要由XMLMapperBuilder類完成,parse方法來完成解析: public void parse() { if (!configuration.isRes

Flume NG原始碼分析ChannelSelector

前幾篇介紹了Flume NG Source元件的基本情況,接下來看看Channel相關的元件,Channel相關元件有: 1. Channel 2. ChannelSelector 3. Interceptor / InterceptorChain 4. ChannelProcess

Flume NG原始碼分析應用程式使用的RpcClient設計

上一篇Flume NG原始碼分析(五)使用ThriftSource通過RPC方式收集日誌 介紹了ThriftSource利用Thrfit服務ThriftSourceProtocol來收集日誌。這篇說說flume-ng-sdk中提供給應用層序使用的RpcClient的設計和實現。繼續使用ThriftR

Flume NG原始碼分析使用ThriftSource通過RPC方式收集日誌

上一篇說了利用ExecSource從本地日誌檔案非同步的收集日誌,這篇說說採用RPC方式同步收集日誌的方式。筆者對Thrift比較熟悉,所以用ThriftSource來介紹RPC的日誌收集方式。 整體的結構圖如下: 1. ThriftSource包含了一個Thrift Server,以及一個

Flume NG原始碼分析使用ExecSource從本地日誌檔案中收集日誌

常見的日誌收集方式有兩種,一種是經由本地日誌檔案做媒介,非同步地傳送到遠端日誌倉庫,一種是基於RPC方式的同步日誌收集,直接傳送到遠端日誌倉庫。這篇講講Flume NG如何從本地日誌檔案中收集日誌。 ExecSource是用來執行本地shell命令,並把本地日誌檔案中的資料封裝成Event

Flume NG原始碼分析使用Event介面表示資料流

Flume NG有4個主要的元件: Event表示在Flume各個Agent之間傳遞的資料流 Source表示從外部源接收Event資料流,然後傳遞給Channel Channel表示對從Source傳遞的Event資料流的臨時儲存 Sink表示從Channel中接收儲存的Event

Flume NG原始碼分析支援執行時動態修改配置的配置模組

在上一篇中講了Flume NG配置模組基本的介面的類,PropertiesConfigurationProvider提供了基於properties配置檔案的靜態配置的能力,這篇細說一下PollingPropertiesFileConfigurationProvider提供的執行時動態修改配置並生效的

Flume NG原始碼分析基於靜態properties檔案的配置模組

日誌收集是網際網路公司的一個重要服務,Flume NG是Apache的頂級專案,是分散式日誌收集服務的一個開源實現,具有良好的擴充套件性,與其他很多開源元件可以無縫整合。搜了一圈發現介紹Flume NG的文章有不少,但是深入分析Flume NG原始碼的卻沒有。準備寫一個系列分析一下Flume NG的