閱讀560 返回首頁    go 阿裏雲 go 技術社區[雲棲]


嵌入式Linux引導過程之1.3——Xloader的sys_init


上一篇文章對XLOADER_ENTRY進行了分析,看到其中調用的第一個標號就是sys_init,本文就對這個標號對應的代碼段進行粗略的分析,這裏我也還有好多沒有搞明白的,就先留著,日後慢慢明白,先把自己目前能夠看明白的東西記下來。

另外,需要說明的是,像sys_init以及後續還要講的ddr_init之類的代碼是與體係結構高度相關的,由於我的文章針對的是SPEArPlus開發板的,因此,上麵提到的所有寄存器的地址以及功能說明要需要參考相應的user manual文檔。
與本文代碼對應的文檔是SPEArPlus 600 PRELIMINARY USER MANUAL。

好, 下麵就開始看代碼。sys_init代碼段位於Xloader目錄下的pll/spear_pll.S代碼中,該代碼段的主要功能是對係統的時鍾頻率以及 工作方式進行初始化,並初始化外設時鍾等,主要對GMAC Ethernet、UART1、UART2以及SMI(Serial Flash Controller)等外設進行了初始化。

對代碼的整個說明以注釋的方式跟源文件一起貼在這裏,其中還有很多不明白的地方,希望以後能夠慢慢明白:

  1 /*      PRESERVE8 */
  2
  3
  4
  5 /*;----------------------------------------------------------------------------------- */
  6 /*
  7     INCLUDE include/mmu946T.s
  8     INCLUDE include/arm.equ
  9 */
 10      #include "splus_pll.h"
 11
 12
 13 #define MISC_BASE              0xFCA80000
 14 #define PHY_CTR_REG            0xA4
 15 #define PERIPHCLK_CFG           0x28
 16 #define PERIPH1_CLKEN           0x2C
 17 #define PERIPH1_RST             0x38
 18 #define AMBA_CLK_CFG            0x24
 19 #define GMAC_SYNTH_CLK          0x68
 20 #define GMAC_CTR_REG            0xA8
 21 #define PLL1_FREQ               0xa600010f
 22 #define PLL1_CNTL_REG           0x00000008
 23 #define PLL1_FRQ_REG            0x0000000C
 24
 25 #define TXCLK_SYNTH             0x00000008 /*enable synth. clock */
 26 #define PLL2_FREQ               0x8500010f 
 27 #define PLL2_CNTL_REG           0x00000014
 28 #define PLL2_FRQ_REG            0x00000018
 29
 30
 31 #define SYSCTL_BASE             0xFCA00000
 32 #define SCCTRL                  0x00000000
 33 #define SCPLLCTRL               0x00000014
 34 #define PLLTIM                  0x1FFFFFF
 35
 36 #define SMI_BASE                0xFC000000
 37 #define SMI_CR1                 0x00
 38
 39 /* CONTROL REG 1 */
 40 #define BANK_EN                 0x0000000F /* enables all banks */
 41 #define DSEL_TIME               0x00000050 /* Deselect time 5+1 SMI_CK periods */
 42 #define PRESCAL3                0x00000300 /* AHB_CK prescaling value */
 43 #define PRESCAL5                0x00000500 /* AHB_CK prescaling value */
 44 #define PRESCALA                0x00000A00 /* AHB_CK prescaling value */
 45 #define PRESCALF                0x00000F00 /* AHB_CK prescaling value */
 46 #define PRESCAL9                0x00000900 /* AHB_CK prescaling value */
 47 #define SW_MODE                 0x10000000 /* enables SW Mode */
 48 #define WB_MODE                 0x20000000 /* Write Burst Mode */
 49 #define FAST_MODE               0x00008000 /* Fast Mode */
 50
 51
 52 #define ARM1_WE                     0x00000001
 53 #define ARM1                        0x00000002
 54 #define ARM2                        0x00000004
 55 #define UART1                       0x00000008
 56 #define UART2                       0x00000010
 57 #define SSP1                        0x00000020
 58 #define SSP2                        0x00000040
 59 #define I2C                         0x00000080
 60 #define JPEG                        0x00000100
 61 #define FSMC                        0x00000200
 62 #define FIRDA                       0x00000400
 63 #define GPT4                        0x00000800
 64 #define GPT5                        0x00001000
 65 #define GPIO4                       0x00002000
 66 #define SSP3                        0x00004000
 67 #define AD                          0x00008000
 68 #define GPT3                        0x00010000
 69 #define RTC                         0x00020000
 70 #define GPIO3                       0x00040000
 71 #define DMA                         0x00080000
 72 #define ROM                         0x00100000
 73 #define SMI                         0x00200000
 74 #define CLCD                        0x00400000
 75 #define GMAC    0x00800000
 76 #define USBDEV                      0x01000000
 77 #define USBHOST1                    0x02000000
 78 #define USBHOST2                    0x04000000
 79 #define DDR_CTRL                    0x08000000
 80 #define RAM_WRAPPER                 0x10000000
 81 #define DDR_CORE                    0x20000000
 82
 83 #define PLL_MODE_NON_DITHERED_M_MASK   0xFF000000
 84 #define PLL_MODE_NON_DITHERED_M_SHIFT  24
 85 #define PLL_VALUE_M_MASK               0xFFFF0000
 86 #define PLL_VALUE_M_SHIFT              16
 87 #define PLL_VALUE_P_MASK               0x00000700
 88 #define PLL_VALUE_P_SHIFT              8
 89 #define PLL_VALUE_N_MASK               0x0000000F
 90 #define PLL_VALUE_N_SHIFT              0
 91 #define SYNTH_XMASK  0XFFFF0000
 92 #define SYNTH_YMASK  0X0000FFFF
 93
 94    
 95 /*   AREA   INIT, CODE, READONLY
 96
 97 ;-----------------------------------------------------------------------------------
 98   
 99 ; ************************************************
100 ; *  Routine to initialize the system controller.
101 ; ************************************************
102 */
103
104
105 .global sys_init
106 sys_init:
107
108  /* SYSTEM PLL INIT */
109
    /* 0xFC880010是WdogRIS寄存器的地址。
     * 該寄存器是一個隻讀的寄存器,當讀出來的內容最低位為1時,
     * 表示由於看門狗計數器到達了0而引發了一次中斷,否則該位為0。
     * 此處一直到114行代碼斷的作用是判斷是否是由於看門狗引發的
     * 中斷而導致了sys_init的調用,如果是,則直接跳轉到
     * normal_mode標號處執行代碼,而不需要對時鍾進行初始化了。
     */
110    LDR     R1, =0xFC880010
111    LDR    R3,[R1, #0x0 ]    /* 讀取WdogRIS寄存器的內容 */
112         AND     R3,R3,#0x1    /* 隻取讀取內容的最低位,該位就表明了當前看門狗的狀態 */
113         CMP     R3,#0x1    /* 看看最低位是否為1,如果是,則表明此時是由看門狗引發的中斷
114         BEQ     normal_mode     * 不需要重新進行時鍾初始化,直接跳轉到normal_mode就行。
                 */
115
    /* 對係統工作模式進行設定,將係統設置為SLOW模式
     * 其中,SYSCTL_BASE==0xFCA00000
     * SCCTRL==0x00000000
     */
116 /* setting SYSCTL to SLOW mode */
117         LDR     R1, =SYSCTL_BASE    /* System Controler registers的基地址 */
118    LDR   R3,[R1, #SCCTRL ]    /* 讀入SCCTRL寄存器的內容 */
119    ORR   R2,R3,#0x00000002    /* 將SCCTRL寄存器的低三位設置成'b01x(x表示任意值),
                 * 當係統reset後,初始時SCCTRL的低三位為'b001。
                 * 當SCCTRL低三位的值為'b01x時,係統將被設置成SLOW模式。
                 */
120    STR   R2,[R1, #SCCTRL]    /* 保存設置之後的值到SCCTRL寄存器 */
121
122 /* setting 100us pll timer */
123    LDR    R4, =PLLTIM    /* PLLTIM==0x01FFFFFF */
124         MOVS   R2,R4,LSL #0x3    /* 由於SCPLLCTRL寄存器的[27:3]位是保存PllTime的,
                     * 因此這裏將PLLTIM左移三位,用來設置SCPLLCTRL中的PllTime。
                     */
125         STR      R2,[R1, #SCPLLCTRL]    /* 將移位之後的PLLTIM的值保存到SCPLLCTRL寄存器 */
126
127 /*
128 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
129 ; programming PLL1
130 ;        LDR     R1,=MISC_BASE
131 ;        LDR     R2,=PLL1_FREQ
132 ;        STR     R2,[R1, #PLL1_FRQ_REG]
133
134
135 /*      ; programming PLL1 */
136         LDR     R1,=MISC_BASE    /* MISC_BASE==0xFCA80000,是各種寄存器的基地址 */
137
138 /*        ; program M value */
139         LDR     R2,[R1, #PLL1_FRQ_REG] /* ; read the PLL1_Frequency register*/
                        /* 距MISC_BASE偏移PLL1_FRQ_REG==0x0000000C處
                         * 是PLL1_FRQ寄存器。此處,首先加載PLL1_FRQ寄存器的值
                         */
140         LDR     R7,=PLL_MODE_NON_DITHERED_M_MASK    /* PLL_MODE_NON_DITHERED_M_MASK==0xFF000000 */
141         MVN     R7,R7    /* 將R7的值按位反轉,也就是R7==0x00FFFFFF */
142         AND     R2,R2,R7 /*; Mask the M value */    /* 將從PLL1_FRQ寄存器中讀出的值的高8位清零,
                             * 這高8位要替換成自己定義的值
                             */
143         LDR     R4,=CONFIG_SYS_PLL1_M_VALUE    /* CONFIG_SYS_PLL1_M_VALUE==166==0xA6,
                         * 這個值定義在spear_pll.h文件中,當我們修改該頭文件中的
                         * CONFIG_SYS_PLL1_M_VALUE的時候,
                         * 就會在初始化的時候改變PLL1_FRQ寄存器中的高8位的值。
                         */
144         MOV     R4,R4, lsl #PLL_MODE_NON_DITHERED_M_SHIFT /* ; Shift and set the M value */
                        /* PLL_MODE_NON_DITHERED_M_SHIFT==24
                         * 這裏是將CONFIG_SYS_PLL1_M_VALUE的值左移24位,
                         * 使其有效位位於32位字中的高8位。
                         */
145         ORR     R2,R2,R4    /* 將PLL1_FRQ寄存器中讀出的值的高8位設置成spear_pll.h中定義的值 */
146         STR     R2,[R1, #PLL1_FRQ_REG] /* ; load the M value*/    /* 將設置保存到PLL1_FRQ寄存器中 */
147
    /* 148-155行所做的事情與139-146行所做的事情類似
     * 隻不過此處設置的是P值,而不是M值
     */
148         LDR     R2,[R1, #PLL1_FRQ_REG]
149         LDR     R7,=PLL_VALUE_P_MASK
150         MVN     R7,R7
151         AND     R2,R2,R7
152         LDR     R4,=CONFIG_SYS_PLL1_P_VALUE
153         MOV     R4,R4, lsl #PLL_VALUE_P_SHIFT
154         ORR     R2,R2,R4
155         STR     R2,[R1, #PLL1_FRQ_REG]
156
    /* 157-164行所做的事情與139-146行所做的事情類似
     * 隻不過此處設置的是N值,而不是M值
     */
157         LDR     R2,[R1, #PLL1_FRQ_REG]
158         LDR     R7,=PLL_VALUE_N_MASK
159         MVN     R7,R7
160         AND     R2,R2,R7
161         LDR     R4,=CONFIG_SYS_PLL1_N_VALUE
162         MOV     R4,R4, lsl #PLL_VALUE_N_SHIFT
163         ORR     R2,R2,R4
164         STR     R2,[R1, #PLL1_FRQ_REG]
165
166
    /* 從這裏開始設置PLL1_CTR寄存器, PLL1_CNTL_REG==0x00000008
     * 我猜應該是先diable再enable使得之前對pll的設置生效。
     */
167 /*; power down : pll1 ctrl programming */
168         LDR     R2,=0x1c0a    /* PLL1_CTR寄存器的第2位清零,disable pll */
169         STR     R2,[R1, #PLL1_CNTL_REG]
170 /*;enable pll1 */
171         LDR     R2,=0x1c0e    /* PLL1_CTR寄存器的第2位置位,enable pll */
172         STR     R2,[R1, #PLL1_CNTL_REG]
173 /* ;strobe */    /* 這一段沒明白什麼意思... */
174         LDR     R2,=0x1c06
175         STR     R2,[R1, #PLL1_CNTL_REG]
176         LDR     R2,=0x1c0e
177         STR     R2,[R1, #PLL1_CNTL_REG]
178 /*;wait for lock   */
    /* PLL1_CTR寄存器的最低位是一個隻讀位,當它為0的時候
     * 表示pll處於unlock狀態,當它為1的時候表示pll處於lock狀態
     * 此處,是在等待,知道pll處於lock狀態。
     */
179 pll1_lock_1:
180         LDR     R2,[R1,#PLL1_CNTL_REG]    /* 讀取PLL1_CTR寄存器的值 */
181         AND     R2,R2,#0x1        /* 屏蔽除最低位之外的所有位 */
182         CMP     R2,#0x1        /* 看看最低位是否為1,為1則表明已經處於lock狀態了 */
183         BNE     pll1_lock_1        /* 否則繼續等待,知道最低位為1 */

    /* 以下代碼所做的工作類似與上麵的代碼
     * 隻不過上麵的代碼是對PLL1進行初始化,
     * 而下麵的代碼是對PLL2進行初始化。原因可能是SPEArPlus這個開發板具有雙ARM核。
     */
184 /*
185 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
186 ; programming PLL2
187 */
188         LDR     R1,=MISC_BASE
189         LDR     R2,=PLL2_FREQ
190         STR     R2,[R1, #PLL2_FRQ_REG]
191
192 /*
193 ; power down : PLL2 ctrl programming
194 */
195         LDR     R2,=0x1c0a
196         STR     R2,[R1, #PLL2_CNTL_REG]
197 /* ;enable pll1*/
198         LDR     R2,=0x1c0e
199         STR     R2,[R1, #PLL2_CNTL_REG]
200 /*;strobe */
201         LDR     R2,=0x1c06
202         STR     R2,[R1, #PLL2_CNTL_REG]
203         LDR     R2,=0x1c0e
204         STR     R2,[R1, #PLL2_CNTL_REG]
205 /*;turn from int to ext. div  */
206 /*;     LDR     R2,=0x1d0f */
207 /*;     STR     R2,[R1, #PLL2_CNTL_REG]*/
208
209 /*;wait for lock */
210 pll2_lock_1:
211         LDR     R2,[R1,#PLL2_CNTL_REG]
212         AND     R2,R2,#0x1
213         CMP     R2,#0x1
214         BNE     pll2_lock_1
215 /*
216 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217 ;GMAC Tx Clock programming
218 ;MISCCntl->PERIPH1_CLKEN  &= ~ PERIPH_GMAC;
219
220 ;MISCCntl->GMAC_SYNTH_CLK = (SYNTH_XMASK & (0x2<<16)) | (SYNTH_YMASK & 0x3); //375*(X/Y)=125
221 ;MISCCntl->GMAC_CTR_REG = TXCLK_SYNTH;
222
223 ;MISCCntl->PERIPH1_CLKEN  |=  PERIPH_GMAC;
224 ;MISCCntl->PERIPH1_RST    |= PERIPH_GMAC;
225 ;MISCCntl->PERIPH1_RST    &= ~PERIPH_GMAC;
226
227
228
229 ;MISCCntl->PERIPH1_CLKEN  &= ~ PERIPH_GMAC;
230 */
    /* PERIPH1_CLKEN==0x2C,此偏移對應的寄存器是PERIP1_CLK_ENB
     * 該寄存器的功能是設置外設時鍾的使能
     * 這裏先關閉gmac的時鍾,然後對gmac進行相關設置之後再打開gmac的時鍾
     */
231         LDR  R1, =MISC_BASE
232         LDR  R2, [R1, #PERIPH1_CLKEN] /*;// read the peripheral-1 clock enable register */
233         BIC  R2,  R2, #GMAC        /* GMAC==0x00800000,也就是將PERIP1_CLK_ENB寄存器中的gmac_clken位清零
                     * disable gmac ethernet的時鍾
                     */
234         STR  R2, [R1, #PERIPH1_CLKEN] /*;// set the enable value */    /* 保存設置到寄存器 */
235        
236 /*;MISCCntl->GMAC_SYNTH_CLK = (SYNTH_XMASK & (0x2<<16)) | (SYNTH_YMASK & 0x3); //375*(X/Y)=125 */
    /* GMAC_SYNTH_CLK==0x68,R1+GMAC_SYNTH_CLK的地址對應與GMAC_CLK_SYNT寄存器。
     * 對GMAC_CLK_SYNT寄存器進行設置,將其設置為0x00020003
     */
237        LDR  R2, =SYNTH_XMASK    /* SYNTH_XMASK==0xFFFF0000 */
238         MOV  R3, #0x02
239         MOV  R3, R3, lsl #16
240         AND  R2, R2, R3        /* R2 = 0xFFFF0000 & 0x00020000 */
241         LDR  R3, =SYNTH_YMASK    /* SYNTH_YMASK==0x0000FFFF */
242         AND  R3, R3, #0x03
243         ORR  R2, R2, R3        /* R2 = 0x00020000 | 0x00000003 */
244         STR  R2, [R1, #GMAC_SYNTH_CLK] /* ;// read the peripheral-1 clock enable register */
245
246 /*;MISCCntl->GMAC_CTR_REG = TXCLK_SYNTH;   */
    /* GMAC_CTR_REG==0xA8,對應於GMAC_CFG_CTR寄存器 */
247         LDR  R2, =0x00
248         STR  R2, [R1, #GMAC_CTR_REG] /*;// read the peripheral-1 clock enable register */
249
250 /*;MISCCntl->PERIPH1_CLKEN  |=  PERIPH_GMAC; */
    /* 重新將gmac對應的外設時鍾使能 */
251         LDR  R2, [R1, #PERIPH1_CLKEN] /* ;// read the peripheral-1 clock enable register*/
252         ORR  R2,  R2, #GMAC
253         STR  R2, [R1, #PERIPH1_CLKEN] /* ;// set the enable value*/
254
255 /*;MISCCntl->PERIPH1_RST    |= PERIPH_GMAC; */
    /* PERIPH1_RST==0x38,對應於PERIP1_SOF_RST寄存器
     * 此處將PERIPH1_RST寄存器中的GMAC位置1是令gmac ethernet執行reset
     * 使得以上對gmac的設置生效
     */
256         LDR  R2, [R1, #PERIPH1_RST] /* ;// read the peripheral-1 clock enable register*/
257         ORR  R2,  R2, #GMAC
258         STR  R2, [R1, #PERIPH1_RST] /* ;// set the enable value */
259
260 /* ;MISCCntl->PERIPH1_RST    &= ~PERIPH_GMAC;*/
    /* 將PERIP1_SOF_RST寄存器中的GMAC複位,即reset完之後關閉reset功能 */
261         LDR  R2, [R1, #PERIPH1_RST] /*;// read the peripheral-1 clock enable register */
262         BIC  R2,  R2, #GMAC
263         STR  R2, [R1, #PERIPH1_RST] /*;// set the enable value */
264
265
266
267
268
269                 
270
271 /* ; enable plltimeen */
    /* 設置PERIP_CLK_CFG寄存器的值為0x82,很奇怪手冊裏麵沒有對該寄存器的具體說明 */
272         LDR     R2,=0x82
273         STR     R2,[R1, #PERIPHCLK_CFG]    /* PERIPHCLK_CFG==0x28 */
274
275 /* ; set pclkdiv & hclkdiv */
    /* 設置CORE_CLK_CFG寄存器的值為0x555 */
276         LDR     R1, =MISC_BASE
277         LDR     R2,=0x555
278         STR     R2,[R1, #AMBA_CLK_CFG]    /* AMBA_CLK_CFG==0x24 */
279
280 /* ; SMI init */
281         LDR R1, =SMI_BASE    /* SMI_BASE==0xFC000000 */
282         LDR R2, =BANK_EN    /* BANK_EN==0x0000000F,低4位每一位代表一個bank
                 * 係統初始化的時候隻有bank0是enable的,以支持
                 * 從外部memory來引導係統
                 */
283         ORR R2, R2, #DSEL_TIME    /* DSEL_TIME==0x00000050 Deselect time 5+1 SMI_CK periods */
284         ORR R2, R2, #PRESCALF    /* PRESCALF==0x00000F00 AHB_CK prescaling value */
285         STR R2, [R1, #SMI_CR1]    /* 保存設置到寄存器SMI_CR1 */
286
    /* 又來一遍一樣的?不明白。。。 */
287         LDR R2, =BANK_EN
288         ORR R2, R2, #DSEL_TIME
289         ORR R2, R2, #PRESCALF
290         STR R2, [R1, #SMI_CR1]
291
292
293 /*; setting SYSCTL to NORMAL mode */
294         LDR     R1, =SYSCTL_BASE    /* SYSCTL_BASE==0xFCA00000,是所有係統控製寄存器的基地址 */
295         LDR     R3,[R1, #SCCTRL ]    /* 讀取SCCTRL寄存器的值保存在R3中 */
296         MOV     R2,#0x00000004
297         STR     R2,[R1, #SCCTRL]    /* 將SCCTRL寄存器的值設置成0x00000004
                     * SCCTRL寄存器中最低3位為'b1xx(x表示任意值)時為NORMAL模式
                     */
298
299 /* ; wait for normal mode */
300         LDR     R1, =SYSCTL_BASE
    /* SCCTRL寄存器的[6:3]位為ModeStatus位,當ModeStatus為'b0100時,
     * 表示係統處於NORMAL模式。
     * 下麵的代碼中,0x20=='b0(0100)000,括號中的4位即與ModeStatus對應。
     * 當從SCCTRL寄存器讀出的內容經過掩碼後與0x20相同,則說明已經為NORMAL模式了
     * 否則說明還沒有切換到NORMAL模式,繼續等待,知道成功切換到NORMAL模式。
     */
301 loop_normal:
302         LDR     R2,[R1, #SCCTRL]
303         AND     R2,R2,#0x20
304         CMP     R2,#0x20
305          BNE     loop_normal
306
    /* 下麵的代碼塊看似想要使能UART1、UART2和SMI的時鍾
     * 可是,感覺又好像沒有必要,因為315行這一句就使能了所有外設的時鍾了
     * 有點詭異。。。沒搞明白為什麼要這麼做
     */
307 /*; enable UART1, UART2, SMI clocks */
308         LDR  R1, =MISC_BASE
309         LDR  R2, [R1, #PERIPH1_CLKEN] /*;// read the peripheral-1 clock enable register */
310 /* ; enable UART1, UART2 & SMI clocks */
311         ORR  R2, R2, #UART1        /* PERIP1_CLK_ENB第3位置1,使能UART1 clock */
312         ORR  R2, R2, #UART2        /* PERIP1_CLK_ENB第4位置1,使能UART2 clock */
313         ORR  R2, R2, #SMI        /* PERIP1_CLK_ENB第21位置1,使能Serial Flash clock */
314         LDR  R3, =0xFFFFFFF8   
315         ORR  R2,R2,R3        /* ???這個比較詭異,看著好像是使能所有的外設時鍾??? */
316         STR  R2, [R1, #PERIPH1_CLKEN] /*;// set the enable value */
317
    /* 這部分跟上麵那部分代碼有的一拚,感覺是想要disable UART1、UART1和SMI的reset,
     * 可是323這一句就清除了所有外設的reset了
     * 所以還是看不明白為什麼要這麼做。。。
     */
318 /* ; remove reset of UART1, UART2, SMI peripherals */
319         LDR R2, [R1, #PERIPH1_RST]
320         BIC R2, R2, #UART1
321         BIC R2, R2, #UART2
322         BIC R2, R2, #SMI
323         MOV R2,#0x00
324         STR  R2, [R1, #PERIPH1_RST]
325
326 /*; remove reset on all IPs */
327 /*;        LDR     R1,=MISC_BASE */
328 /*@;    LDR     R2,=0x0 */
329 /*;     STR     R2,[R1, #PERIPH1_RST_REG] */
330
    /* 這個標號是在Watchdog引發中斷以後,用於直接返回的,在整個sys_init的開頭就進行了判斷
     * 另外,當不是由Watchdog引發中斷時,程序走到這裏也將返回,在我們上下文裏,將返回XLOADER_ENTRY           
     */
331 normal_mode:
332    MOV     PC, R14
333

最後更新:2017-04-03 16:48:40

  上一篇:go Davinci DM6446開發攻略-UBOOT-2009.03移植2 nand flash的燒寫
  下一篇:go 解決VC6下調不出MSDN的問題!