WINCE6.0+S3C2443睡眠和唤醒(sleep and wake up)的实现
1. 系統(tǒng)進入睡眠狀態(tài)的過程
1.1 硬件相關電路
我們的產品使用GPF0/EINT0作為系統(tǒng)進入睡眠和從睡眠中喚醒的喚醒源,如下圖所示:
?
EINT0作為喚醒源,而EINT0在S3C2443的datasheet中相關描述如下:
?
那么我們就需要知道觸發(fā)這個中斷(EINT0)的電平變化情況,是低電平觸發(fā)?或是高電平觸發(fā)?或是下降沿觸發(fā)?或是上升沿觸發(fā)?或是上升沿和下降沿觸發(fā)?上面的設計是:在未按下按鍵(S5)時,EINT0是低電平,當按下按鍵時,EINT0是高電平,我們以松開按鍵時作為觸發(fā)條件,也即下降沿時觸發(fā),初始化代碼如下所示
?
1.2 系統(tǒng)進入睡眠的方式
WINCE6.0有三種方式讓系統(tǒng)進入睡眠的狀態(tài),如下所示:
?
我們系統(tǒng)是采用第三種方式使系統(tǒng)進入睡眠狀態(tài)的,
?
1.3 系統(tǒng)進入睡眠狀態(tài)的調用流程
1.3.1 SetSystemPowerState()
在power按鍵驅動的IST中,當我們按下power鍵,在松開按鍵時,會調用SetSystemPowerState()函數,如下:
SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );
下圖是這個函數的定義
?
1.3.2 Power manager的相關調用
當OEM調用了SetSystemPowerState()函數,就轉入power manager的工作流,執(zhí)行下面的動作:
?
⑴ FileSystemPowerFunction():
?
⑵ PowerOffSystem()
?
⑶ Sleep()
?
1.3.3 內核的相關調用
Power manager的以上調用之后,接下來轉入內核的調用流程,執(zhí)行以下操作
?
其中power off GWES和文件系統(tǒng)進程是內核的工作,下面重點介紹OEMPowerOff()函數,這個函數在/Src/Common/Power/off.c下定義,這個函數體所實現的內容就對應到S3C2243 CPU的相關部分了,下圖是系統(tǒng)進入睡眠狀態(tài)之前的工作:
?
?
1.3.4 OEMPowerOff()函數
根據OEMPowerOff函數的流程圖來說明這個函數體的功能。
?
?
下面分別介紹這個函數體主體部分:
⑴BSPPowerOff()函數
à pRTCPort->RTCCON=0x0;
這句主要目的就是在系統(tǒng)進入睡眠之前,禁止RTC控制使能,預防在系統(tǒng)進入睡眠狀態(tài)后意外修改RTC寄存器的值,CPU的相關描述如下
?
à pADCPort->ADCCON|=(1<<2);
設置ADC的工作模式為standby mode,在睡眠狀態(tài)下,觸摸屏不需要工作,所以設置為standy mode,見下圖:
?
à pIOPort->MISCCR|=(1<<12); //USB port = suspend
設置USB port為掛起模式,降低在睡眠時的功耗。
à pCLKPWR->USB_PHYPWR |= (0xf<<0);
見下圖:
?
à pCLKPWR->PWRCFG &= ~(1<<4);
關閉對usb物理端口的供電。
?
à pCLKPWR->USB_CLKCON &= ~(1<<31);
見下圖
?
à pCLKPWR->INFORM0 = 0x2BED;
?
?
?
這個寄存器可用于在進入睡眠前保留一些重要或者特別目的的數據,以便喚醒過程或喚醒后可以使用。
à 關閉背光燈和LCD
?
⑵ save system registers
…………………………………..
saveArea[5]? = INPORT32(&pIOPort->GPCCON);
saveArea[6]? = INPORT32(&pIOPort->GPCDAT);
saveArea[7]? = INPORT32(&pIOPort->GPCUDP);
…………………………………
把GPIO寄存器的值保存在saveArea[]數組中,以便喚醒后恢復寄存器保存的數值。
?
⑶ ConfigStopGPIO函數
在這個函數可以設置好作為喚醒睡眠的GPIO口,比如GPF0/EINT0作為喚醒的GPIO口,就要在這里設置好,也可在OALCPUPowerOff函數中設置好,其他GPIO口一般設置為輸入,已減少系統(tǒng)在睡眠時的功耗。
?
⑷ OALCPUPowerOff函數
這個函數在/Src/Oal/Oallib/startup.s中定義,如下所示
LEAF_ENTRY OALCPUPowerOff
;?????? 1. Push SVC state onto our stack
stmdb?? sp!, {r4-r12}??????????????????
stmdb?? sp!, {lr}
/***************************************************************/
我們知道R13常用作堆棧指針(sp),用于保存當前堆棧地址。SVC:表示處理器模式為管理模式。Stm指令是多寄存器存儲指令,在此表示把r4到r12這9個寄存器中的值存儲到基址寄存器(sp)所指示的一片連續(xù)存儲器中,stm后面的db表示每次傳送前地址值減;!表示數據加載與存儲完畢之后,將最后的地址寫入基址寄存器,如不使用!,則基址寄存器的內容不改變。假設sp=0x90020,stmdb?? sp!, {r4-r12}的操作如下:
第一步:在存儲前,0x90050的值減4(對于ARM指令是4,對Thumb指令是2),也即為0x9004c。
第二步:把寄存器r12的值存儲到0x9004c指向的存儲區(qū)域。
第三步:0x9004c-4=0x90048。
第四步:把寄存器r11的值存儲到0x90048指向的存儲區(qū)域。
……………………………………
最后一步:就是sp=0x90030
?
lr:R14寄存器也稱為子程序連接器(Subroutine Link Register)或連接寄存器LR。
/***************************************************************/
?
;?????? 2. Save MMU & CPU Register to RAM
??? ldr???? r3, =SLEEPDATA_BASE_VIRTUAL???? ; base of Sleep mode storage
?
ldr???? r2, =Awake_address????????????? ; store Virtual return address
str???? r2, [r3], #4
?
mrc???? p15, 0, r2, c1, c0, 0?????????? ; load r2 with MMU Control
ldr???? r0, =MMU_CTL_MASK?????????????? ; mask off the undefined bits
bic???? r2, r2, r0
str???? r2, [r3], #4??????????????????? ; store MMU Control data
?
mrc???? p15, 0, r2, c2, c0, 0?????????? ; load r2 with TTB address.
ldr???? r0, =MMU_TTB_MASK?????????????? ; mask off the undefined bits
bic???? r2, r2, r0
str???? r2, [r3], #4??????????????????? ; store TTB address
?
mrc???? p15, 0, r2, c3, c0, 0?????????? ; load r2 with domain access control.
str???? r2, [r3], #4??????????????????? ; store domain access control
?
str???? sp, [r3], #4??????????????????? ; store SVC stack pointer
?
mrs???? r2, spsr
str???? r2, [r3], #4??????????????????? ; store SVC status register
?
mov???? r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit ; Enter FIQ mode, no interrupts
msr???? cpsr, r1
mrs???? r2, spsr
stmia?? r3!, {r2, r8-r12, sp, lr}?????? ; store the FIQ mode registers
?
mov???? r1, #Mode_ABT:OR:I_Bit:OR:F_Bit ; Enter ABT mode, no interrupts
msr???? cpsr, r1
mrs r0, spsr
stmia?? r3!, {r0, sp, lr}?????????????? ; store the ABT mode Registers
?
mov???? r1, #Mode_IRQ:OR:I_Bit:OR:F_Bit ; Enter IRQ mode, no interrupts
msr???? cpsr, r1
mrs???? r0, spsr
stmia?? r3!, {r0, sp, lr}?????????????? ; store the IRQ Mode Registers
?
mov???? r1, #Mode_UND:OR:I_Bit:OR:F_Bit ; Enter UND mode, no interrupts
msr???? cpsr, r1
mrs???? r0, spsr
stmia?? r3!, {r0, sp, lr}?????????????? ; store the UND mode Registers
?
mov???? r1, #Mode_SYS:OR:I_Bit:OR:F_Bit ; Enter SYS mode, no interrupts
msr???? cpsr, r1
stmia?? r3!, {sp, lr}?????????????????? ; store the SYS mode Registers
?
mov???? r1, #Mode_SVC:OR:I_Bit:OR:F_Bit ; Back to SVC mode, no interrupts
msr???? cpsr, r1
?
;?????? 3. do Checksum on the Sleepdata
ldr???? r3, =SLEEPDATA_BASE_VIRTUAL ; get pointer to SLEEPDATA
mov???? r2, #0
ldr???? r0, =SLEEPDATA_SIZE ; get size of data structure (in words)
30
ldr???? r1, [r3], #4
and???? r1, r1, #0x1
mov???? r1, r1, LSL #31
orr???? r1, r1, r1, LSR #1
add???? r2, r2, r1
subs??? r0, r0, #1
bne???? %b30
/****************************************************************/
計算睡眠數據的checksum,保存在r2寄存器中
/****************************************************************/
ldr???? r0, =vINFORM3
str???? r2, [r0] ; Store in Power Manager Scratch pad register
/****************************************************************/
把保存在r2寄存器中的睡眠數據的checksum保存到INFORM3寄存器中,以便喚醒過程計算checksum時比較。
/****************************************************************/
?
?
;?????? 4. Interrupt Disable
ldr???? r0, =vINTBASE
mvn???? r2, #0
str???? r2, [r0, #oINTMSK]
str???? r2, [r0, #oSRCPND]
str???? r2, [r0, #oINTPND]
?
;;?????? 5. Cache Flush
[ {TRUE}
bl????? OALClearUTLB
bl????? OALFlushICache
ldr???? r0, = (DCACHE_LINES_PER_SET - 1)???
ldr???? r1, = (DCACHE_NUM_SETS - 1)???
ldr???? r2, = DCACHE_SET_INDEX_BIT???
ldr???? r3, = DCACHE_LINE_SIZE????
bl????? OALFlushDCache
]
?
;?????? 6. Setting Wakeup External Interrupt(EINT0) Mode
ldr???? r0, =vGPIOBASE
?
ldr???? r1, =0x5502
str???? r1, [r0, #oGPFCON]
/****************************************************************/
設置GPF0為EINT0,并且設置為下降沿觸發(fā),只要這里的設置準確才能正常從睡眠狀態(tài)喚醒系統(tǒng)。
/****************************************************************/
?
ldr???? r4, =vRSTCON
ldr???? r5, =0x0ff80???????????
str???? r5, [r4]
/****************************************************************/
?
/****************************************************************/
?
ldr???? r4, =vOSCSET
ldr???? r5, =0x8000???????????
str???? r5, [r4]
/****************************************************************/
?
/****************************************************************/
?
ldr???? r4, =vPWRCFG
ldr???? r5, =0x8201??????????
str???? r5, [r4]
/****************************************************************/
?
?
/****************************************************************/
?
ldr???? r4, =vPWRMODE
ldr r5, [r4]
bic r5, r5, #0xff00
bic r5, r5, #0x00ff
ldr r6, =0x2BED
orr???? r5, r5, r6??????????? ; Power Off Mode
?
str???? r5, [r4] ; Power Off !!
??? b .
/****************************************************************/
?
/****************************************************************/
?
1.4 系統(tǒng)進入休眠前必須的動作
?
在系統(tǒng)進入休眠前,正確設置外部喚醒中斷,才能夠喚醒CPU.一般來說,正確設置喚醒中斷源,有三個要點。
⑴ 把對應的GPIO設置為中斷功能
?
⑵明確外部中斷觸發(fā)條件,比如我們把這個喚醒用的中斷源所對應的IO接到一個按鍵上,希望通過按下按鍵來實現喚醒。那么就得明確,當按下這個按鍵時,IO口上的電平會發(fā)生什么樣的變化。
?
⑶ 設置EXTINTn寄存器,按照按鍵按下時IO電平的變化條件來設置。比如當按下按鍵時,IO口上的電平會發(fā)生從高到低的變化,那么我們就設置對應的EXTINTn,使得中斷觸發(fā)條件為Falling edge trigeerde,即下降沿觸發(fā)。
?
?
2. 系統(tǒng)從睡眠狀態(tài)喚醒的過程
2.1 喚醒
當按下power鍵(GPF0/EINT0端口產生下降沿),程序就從nboot開始執(zhí)行,也即從/Src/Bootloader/Stepldr/statup.s文件的入口ResetHandler開始
?
Stepldr的入口函數startup.s是由stepldr目錄下的sources文件下“EXEENTRY=StartUp”來指定的,startup.s函數的主要功能如下所示:
1)startup.s函數的入口處
STARTUPTEXT
LEAF_ENTRY StartUp ;用于指定Startup.s函數的入口點
b ResetHandler ;無條件跳轉到ResetHandler函數
b .
……………………….
b .
;-----------------------------------
; Steppingstone loader entry point.
;-----------------------------------
ResetHandler
ldr r0, =WTCON ; disable the watchdog timer.
mov r1,#0
str r1, [r0]
……………………
2) 禁止看門狗,屏蔽所有的中斷及設置中斷模式
ResetHandler
ldr r0, =WTCON ; disable the watchdog timer.
mov r1,#0
str r1, [r0]
?
ldr r0, = GPACDH
ldr r1, = 0x1AA8A
str r1, [r0]
/**********************************************************************/
GPACON和GPADAT在S3C2443中已不存在,被GPACDL和GPACDH代替,其作用如下:
GPACDL:Configuration and data register for port A low
GPACDH:Configuration and data register for port A high
配置為功能端,但不甚清楚如此配置的原因。
/**********************************************************************/
ldr r0, = GPFCON
ldr r1, = 0x5500
?
2
str r1, [r0]
ldr r0, =INTMSK ; mask all first-level interrupts.
ldr r1, =0xffffffff
str r1, [r0]
ldr r0, =INTSUBMSK ; mask all second-level interrupts.
ldr r1, =0x1fffffff
str r1, [r0]
/**********************************************************************/
屏蔽子中斷和中斷,從而在stepldr階段不能使用中斷服務功能。
/**********************************************************************/
?
ldr r0, = INTMOD
mov r1, #0x0 ; set all interrupt as IRQ
str r1, [r0]
/**********************************************************************/
設置所有的中斷為IRQ中斷。
/**********************************************************************/
3)設置時鐘頻率
ldr r0,=CLKDIV0 ; Set Clock Divider
ldr r1,[r0]
bic r1,r1,#0x37 ; clear HCLKDIV, PREDIV, PCLKDIV
bic r1,r1,#(0xf<<9) ; clear ARMCLKDIV
ldr r2,=((Startup_ARMCLKdiv<<9)+(Startup_PREdiv<<4)+(Startup_PCLKdiv<<2)+(Startup_HCLKdiv))
orr r1,r1,r2
str r1,[r0]
/**********************************************************************/
先清除PREDIV、PCLKDIV、HCLKDIV和ARMCLKDIV,在重新根據系統(tǒng)的需要來設置這幾個參數,Startup_ARMCLKdiv等這幾個參數在stepldr目錄下的option.inc下定義。
ldr r0,=LOCKCON0 ; Set lock time of MPLL. added by junon
mov r1,#0xe10 ; Fin = 12MHz - 0x800, 16.9844MHz - 0xA00
str r1,[r0]
LOCKCON0是MPLL鎖存時間的統(tǒng)計寄存器,啟用PLL之后,由這個寄存器的值來決定為ARMCLK,HCLK和PCLK服務的MPLL鎖存時間的計數值,典型情況下,這個值必須大于300us。
/**********************************************************************/
ldr r0,=LOCKCON1 ; Set lock time of EPLL. added by junon
mov r1,#0x800 ; Fin = 12MHz - 0x800, 16.9844MHz - 0xA00
str r1,[r0]
/**********************************************************************/
LOCKCON1是EPLL鎖存時間的統(tǒng)計寄存器,啟用PLL之后,由這個寄存器的值來決定為ARMCLK,HCLK和PCLK服務的MPLL鎖存時間的計數值,典型情況下,這個值必須大于150。
/**********************************************************************/
?
ldr r0,=MPLLCON ; Set MPLL
ldr r1,=((0<<24)+(Startup_Mdiv<<16)+(Startup_Pdiv<<8)+(Startup_Sdiv))
str r1,[r0]
?
?? ldr r0,=EPLLCON ; Set EPLL
ldr r1,=((0<<24)+(Startup_EMdiv<<16)+(Startup_EPdiv<<8)+(Startup_ESdiv))
str r1,[r0]
PLL的輸出頻率由MPLLCON和EPLLCON寄存器的值來決定,其值盡量根據S3C2443用戶手冊中推薦使用的表來選擇
MPLLCON相關參數的表:
?
EPLLCON相關參數的表:
?
?
?
ldr r0,=CLKSRC ; Select MPLL clock out for SYSCLK
ldr r1,[r0]
orr r1,r1,#0x50
str r1,[r0]
設置CLKSRC中的ESYSCLK選擇方式為EPLL輸出和MSYSCLK選擇方式為MPLL輸出,見下圖:
4) 設置總線的同步方式
bl MMU_SetAsyncBusMode
這個函數的代碼如下所示:
LEAF_ENTRY MMU_SetAsyncBusMode
mrc? p15, 0, r0, c1, c0, 0
orr? r0, r0, #R1_nF:OR:R1_iA
mcr? p15, 0, r0, c1, c0, 0
mov? pc, lr
?? 5) 初始化內存控制器
bl InitMEM
這個函數體如下所示:
InitMEM
ldr r0,=GPKCON
ldr r1,=0xaaaaaaaa ; set Sdata[31:16]
str r1, [r0]
/**********************************************************************/
GPKCON就是SDATACFG寄存器,這是32位SDRAM的配置寄存器,為了控制32位的SDRAM,在內存初始化之前,SDATACFG應該設置為0xAAAAAAAA
/**********************************************************************/
?
add???? r0, pc, #MEMDATA - (. + 8)
?
ldr r1,=BANKCFG ;
add r2, r0, #16 ;End address of MEMDATA
110
/**********************************************************************/
先將存儲器地址為r0的字數據讀入到寄存器r3中,然后將新地址r0+4寫入r0.
ldr r3, [r0], #4
將寄存器r3的值寫入存儲器地址為r0的寄存器,也即BANKCFG,也就是把MEMDATA標號處的第一個分配的單元數據給BANKCFG(0x48000000)賦值,然后將新地址r1+4寫入r1,這時的r1指向BANKCON1(0x48000008)
str r3, [r1], #4
比較r2和r0的值,如果相等,表示對BANKCFG、BANKCON1、BANKCON2和BANKCON3這四個寄存器的初始化已經完成,如果沒有,則跳到上面110處繼續(xù)執(zhí)行,直到對這四個寄存器始
化完成。
cmp r2, r0
bne %B110
?
先清除BANKCON1的最低兩位,再賦值01給這兩位,用于產生一個PALL命令
ldr r2,=BANKCON1
ldr r1,[r2]
bic r1,r1,#(0x3<<0)
orr r1,r1,#(0x1<<0) ; 4nd : Issue a PALL command
str r1,[r2]
對REFRESH的DRAM刷新周期賦值,這個值REFCYC=refresh period(這個和SDRAM的刷新周期有關,本系統(tǒng)使用K4S56163PF,其刷新周期為64ms,計算時是以s為單位的)*HCLK
ldr r4,=REFRESH ; 5fh : refresh cycle every 255-clock cycles
ldr r0,=0xff
str r0,[r4]
?
?
mov r0, #0x100 ; 6th : wait 2 auto - clk
120 subs r0, r0,#1;
bne %B120
?
bic r1,r1,#(0x3<<0) ; 7th : Issue a MRS command
orr r1,r1,#(0x2<<0)
str r1,[r2]
?
ldr r4,=REFRESH ; 8fh : refresh? normal
ldr r0,=REFCYC
str r0,[r4]
?
orr r1,r1,#(0x3<<0) ; 9th : Issue a EMRS command
str r1,[r2]
?
bic r1,r1,#(0x3<<0) ; 10th : Issue a Normal mode
str r1,[r2]
?
// R14也稱作子程序連接寄存器lr,當執(zhí)行BL子程序調用指令時,lr得到R15(程序計數器PC)的備份,下面這行語句可以實現返回到跳轉的地址處。
mov pc, lr
?
?
6)靜態(tài)內存控制器(staic memory controller,SMC)的初始化,這個控制器在本開發(fā)板中用于控制nor flash,而mx300沒有使用nor flash,所以應該不需要對SMC進行初始化.
bl InitSSMC
InitSSMC函數的定義如下:
InitSSMC
?
;Set SSMC Memory parameter control registers : AMD Flash
ldr r0,=SMBIDCYR0
ldr r1,=IDCY0
str r1,[r0]
?
ldr r0,=SMBWSTRDR0
ldr r1,=WSTRD0
str r1,[r0]
?
ldr r0,=SMBWSTWRR0
ldr r1,=WSTWR0
str r1,[r0]
?
ldr r0,=SMBWSTOENR0
ldr r1,=WSTOEN0
str r1,[r0]
?
ldr r0,=SMBWSTWENR0
ldr r1,=WSTWEN0
str r1,[r0]
?
ldr r0,=SMBCR0
ldr r1,=(SMBCR0_2+SMBCR0_1+SMBCR0_0)
str r1,[r0]
?
ldr r0,=SMBWSTBRDR0
ldr r1,=WSTBRD0
str r1,[r0]
?
?
ldr r0,=SMBWSTBRDR0
ldr r1,=WSTBRD0
str r1,[r0]
?
ldr r0,=SSMCCR
ldr r1,=((MemClkRatio<<1)+(SMClockEn<<0))
str r1,[r0]
?
;ldr r0,=SMBWSTRDR5
;ldr r1,=0xe
;str r1,[r0]
?
mov pc, lr
?
7) S3C2443X的系統(tǒng)控制器(system controller)有三大功能:復位管理,產生時鐘和電源管理,下面先介紹復位管理。
當給S3C2443X的系統(tǒng)上電(power-on)時,外部設備必須插入復位來初始化S3C2443X的內部狀態(tài),S3C2443X有四種復位類型,在復位時,系統(tǒng)控制器的復位控制器能夠使系統(tǒng)進入四種復位類型預先定義的狀態(tài)中,這四種復位類型是:硬件復位,看門狗復位,軟件復位和喚醒復位
I:硬件復位,當nRESET引腳插入低電平時產生硬件復位,這種類型的復位是一種uncompromised,unmaskable和complete reset,以硬件復位方式啟動時,除了RTC以外的系統(tǒng)所有單元都被初始化為可知的狀態(tài)(初始化狀態(tài))。
II:看門狗復位,看門狗計數器監(jiān)測到設備異常的狀態(tài)時就會產生看門狗復位。
III:軟件復位(software reset),當對SWRST寄存器的每一位寫1時,就產生軟件復位。
IV:喚醒復位(wakeup reset),當系統(tǒng)從sleep mode中喚醒時,就產生喚醒復位。
?
通過reset狀態(tài)寄存器來得到復位狀態(tài)。
ldr r1, =RSTSTAT
ldr r0, [r1]
如果是從sleep中喚醒,則RSTSTAT[3]=1,否認RSTSTAT[3]=0。如果是從sleep中喚醒,則指令TST運算結果為非零,影響CPSR的Z標志位,這時Z=0;如果不是從sleep中喚醒,則指令TST運算結果為零,此時Z=1。
tst r0, #0x8
如果從sleep中喚醒,則接著執(zhí)行下面的指令;如果不是(正常的啟動),則跳到下面標號為2處接著執(zhí)行。beq指令在Z標志位置位時(Z=1,表示上面的TST指令運算結果為0,從而知//道RSTSTAT[3]=0,而這表明系統(tǒng)不是從sleep中喚醒。)跳轉。
beq %F2???????????????????? ; if not wakeup from PowerOffmode Skip
?
如果是從sleep mode中喚醒,接下來深入及具體判斷是通過RTC tick,或是RTC alarm,還是EINT終端模式來從sleep mode中喚醒。
ldr r1, =WKUPSTAT
ldr r0, [r1]
判斷是否通過RTC alarm來從sleep mode中喚醒系統(tǒng)
tst r0, #(1<<1)
如果是通過RTC alarm來喚醒,則WKUPSTAT[1]=1,那么上面tst運算結果為非零,則CPSR的Z=0,那么就接著往下執(zhí)行;如果不是通過alarm來喚醒,則WKUPSTAT[1]=0,那么上面tst運算結果為零,則CPSR的Z=1,那么跳轉到下面標號6處執(zhí)行
beq %f6???????????????????? ; if not wakeup from PowerOffmode Skip
?
如果是通過RTC alarm來喚醒,則接著到此處執(zhí)行,設置RTCCON[0]=1:啟動RTC控制。
ldr? r1,=RTCCON
ldr r3,[r1]
orr r3,r3,#0x1
str r3,[r1]
?
enable RTC alarm控制的相關功能項
ldr? r1,=RTCALM
ldr r3,=0x7f
str r3,[r1]
?
設置RTC alarm秒,分,小時,日,月和年控制寄存器,以便下次喚醒所用。
ldr r1, =BCDSEC
ldr r2, =ALMSEC
ldr r3,[r1]
str r3,[r2]
?
ldr r1, =BCDMIN
ldr r2, =ALMMIN
ldr r3,[r1]
str r3,[r2]
?
ldr r1, =BCDHOUR
ldr r2, =ALMHOUR
ldr r3,[r1]
str r3,[r2]
?
ldr r1, =BCDDATE
ldr r2, =ALMDATE
ldr r3,[r1]
str r3,[r2]
?
ldr r1, =BCDMON
ldr r2, =ALMMON
ldr r3,[r1]
str r3,[r2]
?
ldr r1, =BCDYEAR
ldr r2, =ALMYEAR
ldr r3,[r1]
str r3,[r2]
?
ldr? r1,=RTCCON
ldr r3,[r1]
bic r3,r3,#0x1
str r3,[r1]
?
喚醒的復位方式啟動,但又不是通過RTC alarm喚醒,則直接跳到此處執(zhí)行;如果是通過RTC alarm喚醒,則先重新啟動RTC alarm控制及設置相應的控制寄存器再接著到標號6處執(zhí)行。
6
?
ldr r2, =0x200000 ; offset into the RAM
add r2, r2, #0x30000000 ; add physical base
mov???? pc, r2 ;? & jump to StartUp address
nop
nop
nop
b .
跳轉到 RAM中的一個地址去執(zhí)行,這個地址是0x32000000。那么熟悉2443 WINCE啟動的朋友們應該明白了,這個地址就是Bootloader把NandFlash里的數據裝載完畢后,跳轉執(zhí)行的地址。那么在這里,跳轉到0x302000000這個地址后,WINCE系統(tǒng)就會被裝載了,也就是說WINCE的操作系統(tǒng)被喚醒了。
?
2?
如果不是從sleep中喚醒,而是其他的復位方式,將接著從這里執(zhí)行。
??? ldr r1, =RSTSTAT
ldr r0, [r1]
tst指令用于判斷當前的復位方式是否時軟件復位:如果是軟件復位,則RSTSTAT[5]=1,tst指令的運行結果為非零,則CPSR的Z=0;如果不是,則RSTSTAT[5]=0,tst指令的運算結果為零,則CPSR的Z=1
tst r0, #(1<<5)
如果是軟件復位,根據上面tst指令的運算,知道CPSR的Z=0,則接著執(zhí)行下面的語句;如果不是軟件復位,則跳轉到BringUpWinCE處接著執(zhí)行
beq BringUpWinCE???????????????????? ; if not wakeup from PowerOffmode Skip
?
如果是軟件復位,從此處接著執(zhí)行
JumpToRAM
0x30200000(=0x30000000+0x200000)是NK.bin的image start地址
?
ldr r2, =0x200000 ; offset into the RAM
add r2, r2, #0x30000000 ; add physical base
直接跳轉到SDRAM的0x30200000從WINCE操作系統(tǒng)內核映像的入口處執(zhí)行,軟件復位方式只用到了stepldr,然后就直接跳轉到內核中執(zhí)行了。
mov???? pc, r2 ;? & jump to StartUp address
nop
nop
nop
b .//???????????????????????????????????????????????????????????????????????
?
如果不是軟件復位,這時應該是硬件復位(或是看門狗復位,應該也是最常用的上電啟動),緊接著此處執(zhí)行
BringUpWinCE
? [ {TRUE} ; DonGo
; Clear RAM.
;
mov? r1,#0
mov? r2,#0
mov? r3,#0
mov? r4,#0
mov? r5,#0
mov? r6,#0
mov? r7,#0
mov? r8,#0
?
ldr r0,=0x30000000?? ; Start address (physical 0x3000.0000).
ldr r9,=0x04000000?? ; 64MB of RAM.
20
stm指令用于將寄存器列表(在此r1到r8)所指示的多個寄存器中的值存入到由基址寄存器所指向的一片連續(xù)存儲器中,條件碼ia表示每次傳送后地址值(基址寄存器的值,在此的初始值為0x30000000)加,下面stmia指令的實際意義:用r1的值(0)給0x30000000指向的存儲器賦值,在此實際是對SDRAM清零,因為0x30000000到0x34000000這64MB的空間是用于SDRAM的,用r2的值給0x30000004指向的存儲器賦值,如此類推,用r8的值給0x30000028指向的存儲器賦值,這次傳送完成后,使r0=0x30000032。
stmia r0!, {r1-r8}
上面stmia指令每進行一次數據傳送,0x04000000相應減去32(4*8),用于判斷對64MB的
SDRAM清零動作是否完成
subs r9, r9, #32
如果清零完成,則接著執(zhí)行下面的語句;否則會跳到到上面標號為20處繼續(xù)對SDRAM的清零。
bne %B20
]
?
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/chinesedragon2010/archive/2010/07/21/5753720.aspx
總結
以上是生活随笔為你收集整理的WINCE6.0+S3C2443睡眠和唤醒(sleep and wake up)的实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: activesync对应的COM口
- 下一篇: 如何导出wince6.0的SDK