日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

WINCE6.0+S3C2443睡眠和唤醒(sleep and wake up)的实现

發(fā)布時間:2025/4/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。