Windows CE 休眠唤醒全面解析(基于2440平台)(3)

那么当CPU 唤醒之后,它运行的第一段程序是什么呢?这点很重要,因为唤醒=Power Reset,那么Reset CPU之后,运行第一段程序自然就是Bootloader了,那么我们看看,Bootloader里是怎么处理的。

       这里我以常用的三星提供的Nboot为例。Bootloader的入口点是

       ENTRY

 

    ;1)The code, which converts to Big-endian, should be in little endian code.

    ;2)The following little endian code will be compiled in Big-Endian mode.

    ; The code byte order should be changed as the memory bus width.

    ;3)The pseudo instruction,DCD can't be used here because the linker generates error.

    ASSERT :DEF:ENDIAN_CHANGE

   

    b   ResetHandler    ; 0x00 Reset

    b   .               ; 0x04 Undefined

    b   .               ; 0x08 Supervisor

    b   .               ; 0x0c Prefetch Abort

    b   .               ; 0x10 Data Abort

    b   .               ; 0x14 Reserved

    b   .               ; 0x18 IRQ

b   .               ; 0x1c FIQ

在这里,如果是Reset复位,那么就会跳转到0地址,也就是ResetHandler    去执行。

ResetHandler

      ldr     r0, = GPFCON

      ldr     r1, = 0x55aa     

      str     r1, [r0]

 

    ldr r0,=WTCON       ;watch dog disable

    ldr r1,=0x0        

    str r1,[r0]

 

    ldr r0,=INTMSK

    ldr r1,=0xffffffff ;all interrupt disable

    str r1,[r0]

 

    ldr r0,=INTSUBMSK

    ldr r1,=0x7ff       ;all sub interrupt disable

    str r1,[r0]

 

    ldr     r0, = INTMOD

    mov r1, #0x0        ; set all interrupt as IRQ (not FIQ)

    str     r1, [r0]

 

    ; configure GPIO pins

    bl Port_Init

 

    ; CLKDIVN

    ldr r0,=CLKDIVN

    ldr r1,=0x7     ; 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

 

    str r1,[r0]

    ; delay

    mov     r0, #DELAY

5   subs    r0, r0, #1

    bne     %B5

 

    ; MMU_SetAsyncBusMode FCLK:HCLK= 1:2

    ands r1, r1, #0x2

    beq %F1

    mrc p15,0,r0,c1,c0,0

    orr r0,r0,#R1_nF:OR:R1_iA

    mcr p15,0,r0,c1,c0,0

1

 

    ;To reduce PLL lock time, adjust the LOCKTIME register.

    ldr r0,=LOCKTIME

    ldr r1,=0xffffff

    str r1,[r0]

    ; delay

    mov     r0, #DELAY

5   subs    r0, r0, #1

    bne     %B5

 

    ;Configure MPLL

    ldr r0,=MPLLCON         

    ldr r1,=((110<<12)+(3<<4)+1) ;Fin=16MHz,Fout=399MHz

;    ldr r1,=((0xf6<<12)+(0xd<<4)+0x0) ;Fin=12MHz,Fout=200MHz

    str r1,[r0]

    ; delay

    mov     r0, #DELAY

5   subs    r0, r0, #1

    bne     %B5

 

    ;Configure UPLL

    ldr     r0, =UPLLCON         

    ldr     r1, =((60<<12)+(4<<4)+2) ;Fin=16MHz, Fout=48MHz

;  ldr     r1, =((0x48<<12)+(0x3<<4)+0x2) ;Fin=12MHz, Fout=48MHz

    str     r1, [r0]

    ; delay

    mov     r0, #0x200

5   subs    r0, r0, #1

    bne     %B5

 

以上部分无论是HardReset还是PowerReset都要执行,主要是做的初始化CPU时钟的工作,接下来

 

; :::::::::::::::::::::::::::::::::::::::::::::

;           BEGIN: Power Management

; - - - - - - - - - - - - - - - - - - - - - - -

      ldr       r1, =GSTATUS2           ; Determine Booting Mode

      ldr       r10, [r1]

      tst       r10, #0x2

      beq       %F2                     ; if not wakeup from PowerOffmode Skip

                                ;    MISCCR setting

 

 

      LED_ON 0xc

     str r10, [r1]                      ; Clear Test

 

;     B .

 

 

      ldr        r1, =MISCCR         ; MISCCR's Bit 17, 18, 19 -> 0

      ldr       r0, [r1]                ; I don't know why, Just fallow Sample Code.

      bic       r0, r0, #(3 << 17)      ; SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H

      str       r0, [r1]

 

      ; Set memory control registers

      add        r0, pc, #SMRDATA - (. + 8)

      ldr       r1, =BWSCON ; BWSCON Address

      add       r2, r0, #52       ; End address of SMRDATA

loop10

      ldr       r3, [r0], #4

      str r3, [r1], #4

      cmp       r2, r0

      bne loop10

 

      mov r1, #256

loop11

      subs r1, r1, #1              ; wait until the SelfRefresh is released.

      bne loop11

 

 

      ldr          r2, =0x201000                               ; offset into the RAM

      add        r2, r2, #0x30000000                            ; add physical base

      mov     pc, r2                                               ; & jump to StartUp address

      nop

      nop

      nop

      b .

 

      b       %F3                                          ; if wakeup from PowerOff mode

                                                       ;       goto Power-up code.

; Watchdog reset

2

      tst           r10, #0x4                            ; In case of the wake-up from Watchdog reset,

                                                              ;      go to SDRAM start address(0x3000_0000)

      b            %F4                                          ; If not wakeup from Watchdog reset,

;     beq        %F4                                          ; If not wakeup from Watchdog reset,

                                                              ;      goto Normal Mode.

 

      mov       r0, #4

      str       r0, [r1]                               ; Clear the GSTATUS2. Because same code is located in memory address.

 

      ; Set memory control registers

      ldr       r0, =SMRDATA

      ldr       r1, =BWSCON ; BWSCON Address

      add       r2, r0, #52       ; End address of SMRDATA

loop0

      ldr       r3, [r0], #4

      str r3, [r1], #4

      cmp       r2, r0

      bne loop0

 

      mov r1, #256

loop1

      subs r1, r1, #1              ; wait until the SelfRefresh is released.

      bne loop1

 

      ldr          r2, =0x201000                               ; offset into the RAM

      add        r2, r2, #0x30000000                            ; add physical base

      mov     pc, r2                                               ; & jump to StartUp address

      b .

 

; Case of Power off reset

3

      ldr        r1, =MISCCR         ; MISCCR's Bit 17, 18, 19 -> 0

      ldr       r0, [r1]                ; I don't know why, Just fallow Sample Code.

      bic       r0, r0, #(3 << 17)      ; SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H

      str       r0, [r1]

; - - - - - - - - - - - - - - - - - - - - - - -

;           END: Power Management

; :::::::::::::::::::::::::::::::::::::::::::::

4

 

    ; Configure memory controller

    ;ldr    r0,=SMRDATA

    add     r0, pc, #SMRDATA - (. + 8)

    ldr r1,=BWSCON ;BWSCON Address

    add r2, r0, #52 ;End address of SMRDATA

0      

    ldr r3, [r0], #4   

    str r3, [r1], #4   

    cmp r2, r0     

    bne %B0

 

BringUpWinCE   

……..

……..

……..

…….

这段代码,首先通过读取 GSTATUS2 寄存器里的数值,来判断Reset的原因,我们之前提到过,如果这个值是0x2,那么就是唤醒引起的PowerReset.

ldr r1, =GSTATUS2           ; Determine Booting Mode

      ldr       r10, [r1]

      tst       r10, #0x2

      beq       %F2                     ; if not wakeup from PowerOffmode Skip

                                ;    MISCCR setting

判断GSTATUS2 里的数值是否为0x2,如果是的话,继续向下执行唤醒的恢复操作,否则就跳转到标签为2的程序段去执行。

标签2的程序中,判断GSTATUS2里的数值是否为0x4,如果是的话,说明发生了看门狗reset,那么要执行看门狗reset的恢复过程。

如果二者都不是的话,那么就认为是发生了Hard Reset,那么就按照正常的步骤,去加载Wince系统。

好,我们接着看看,假如GSTATUS2里的数值为2的话。那么就不会跳转到标签2的程序段中,而是向下执行这段程序。

LED_ON 0xc

     str r10, [r1]                      ; Clear Test

 

;     B .

 

 

      ldr        r1, =MISCCR         ; MISCCR's Bit 17, 18, 19 -> 0

      ldr       r0, [r1]                ; I don't know why, Just fallow Sample Code.

      bic       r0, r0, #(3 << 17)      ; SCLK0:0->SCLK, SCLK1:0->SCLK, SCKE:L->H

      str       r0, [r1]

 

      ; Set memory control registers

      add        r0, pc, #SMRDATA - (. + 8)

      ldr       r1, =BWSCON ; BWSCON Address

      add       r2, r0, #52       ; End address of SMRDATA

loop10

      ldr       r3, [r0], #4

      str r3, [r1], #4

      cmp       r2, r0

      bne loop10

 

      mov r1, #256

loop11

      subs r1, r1, #1              ; wait until the SelfRefresh is released.

      bne loop11

 

 

      ldr          r2, =0x201000                               ; offset into the RAM

      add        r2, r2, #0x30000000                            ; add physical base

      mov     pc, r2                                               ; & jump to StartUp address

      nop

      nop

      nop

      b .

这段程序的意义,就是恢复CPU的时钟,开启RAM的自刷新然后跳转到 RAM中的一个地址去执行,这个地址是0x32001000。那么熟悉2440 WINCE启动的朋友们应该明白了,这个地址就是BootloaderNandFlash里的数据装载完毕后,跳转执行的地址。那么在这里,跳转到0x30201000这个地址后,WINCE系统就会被装载了,也就是说WINCE的操作系统被唤醒了。(全文完)

posted on 2008-09-05 15:00  张强  阅读(1670)  评论(1编辑  收藏  举报