实现wince6 休眠 唤醒 流程和分析

来源:互联网 发布:ann神经网络 python 编辑:程序博客网 时间:2024/05/01 15:23

 

 

 1. 保证 在\oal\oallib 文件下 有 startup.s   如图

 
 
在 oal\oallib 文件中的source 中 startup 要保证是
    ARM_SOURCES=\
           startup.s
  
startup.s 的内容见本文 最下部分     oallib\startup.s 和 bootloader\startup.s 中的是不一样的
 

 2. 保证 在C:\WINCE600\PLATFORM\SMDK2440A\SRC\OAL\OALLIB 文件夹下 有 power.c   

     此文件中 主要实现 几个 休眠和 唤醒需要的几个函数
   
     BSPPowerOff()
     功能:遍历参与驱动中有电源管理的驱动 然后关闭驱动电源 主要是 USB 和 LCD
     BSPPowerOn()
    功能:打开驱动电源 初始化串口和时钟
     ConfigStopGPIO() 配置休眠时 I/O 低功耗模式
     InitTimer()
     
     具体看文末
 
3. 休眠和唤醒的 流程 和分析
 
 

3.1. 系统进入睡眠状态的过程

3.1.1 硬件相关电路

我们的产品使用GPF0/EINT0作为系统进入睡眠和从睡眠中唤醒的唤醒源,如下图所示:

EINT0作为唤醒源,而EINT0S3C2443datasheet中相关描述如下:

那么我们就需要知道触发这个中断(EINT0)的电平变化情况,是低电平触发?或是高电平触发?或是下降沿触发?或是上升沿触发?或是上升沿和下降沿触发?上面的设计是:在未按下按键(S5)时,EINT0是低电平,当按下按键时,EINT0是高电平,我们以松开按键时作为触发条件,也即下降沿时触发,初始化代码如下所示

3.1.2 系统进入睡眠的方式

WINCE6.0有三种方式让系统进入睡眠的状态,如下所示:

我们系统是采用第三种方式使系统进入睡眠状态的,

3.1.3 系统进入睡眠状态的调用流程

3.1.3.1 SetSystemPowerState()

power按键驱动的IST中,当我们按下power键,在松开按键时,会调用SetSystemPowerState()函数,如下:

SetSystemPowerState( NULL, POWER_STATE_ON, POWER_FORCE );

下图是这个函数的定义

3.1.3.2 Power manager的相关调用

OEM调用了SetSystemPowerState()函数,就转入power manager的工作流,执行下面的动作:

⑴ FileSystemPowerFunction()

⑵ PowerOffSystem()

⑶ Sleep()

3.1.3.3 内核的相关调用

Power manager的以上调用之后,接下来转入内核的调用流程,执行以下操作

其中power off GWES和文件系统进程是内核的工作,下面重点介绍OEMPowerOff()函数,这个函数在\Src\Common\Power\off.c下定义,这个函数体所实现的内容就对应到S3C2243 CPU的相关部分了,下图是系统进入睡眠状态之前的工作:

3.1.3.4 OEMPowerOff()函数

根据OEMPowerOff函数的流程图来说明这个函数体的功能。

下面分别介绍这个函数体主体部分:

⑴BSPPowerOff()函数

à pRTCPort->RTCCON=0x0;

这句主要目的就是在系统进入睡眠之前,禁止RTC控制使能,预防在系统进入睡眠状态后意外修改RTC寄存器的值,CPU的相关描述如下

à pADCPort->ADCCON|=(1<<2);

设置ADC的工作模式为standby mode,在睡眠状态下,触摸屏不需要工作,所以设置为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口一般设置为输入,已减少系统在睡眠时的功耗。

⑷ 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指令是多寄存器存储指令,在此表示把r4r129个寄存器中的值存储到基址寄存器(sp)所指示的一片连续存储器中,stm后面的db表示每次传送前地址值减;!表示数据加载与存储完毕之后,将最后的地址写入基址寄存器,如不使用!,则基址寄存器的内容不改变。假设sp=0x90020stmdb   sp!, {r4-r12}的操作如下:

第一步:在存储前,0x90050的值减4(对于ARM指令是4,对Thumb指令是2),也即为0x9004c

第二步:把寄存器r12的值存储到0x9004c指向的存储区域。

第三步:0x9004c-4=0x90048

第四步:把寄存器r11的值存储到0x90048指向的存储区域。

……………………………………

最后一步:就是sp=0x90030

lrR14寄存器也称为子程序连接器(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]

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

设置GPF0EINT0,并且设置为下降沿触发,只要这里的设置准确才能正常从睡眠状态唤醒系统。

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

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 .

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

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

3.1.4 系统进入休眠前必须的动作

在系统进入休眠前,正确设置外部唤醒中断,才能够唤醒CPU.一般来说,正确设置唤醒中断源,有三个要点。 

⑴ 把对应的GPIO设置为中断功能 

⑵明确外部中断触发条件,比如我们把这个唤醒用的中断源所对应的IO接到一个按键上,希望通过按下按键来实现唤醒。那么就得明确,当按下这个按键时,IO口上的电平会发生什么样的变化。

⑶ 设置EXTINTn寄存器,按照按键按下时IO电平的变化条件来设置。比如当按下按键时,IO口上的电平会发生从高到低的变化,那么我们就设置对应的EXTINTn,使得中断触发条件为Falling edge trigeerde,即下降沿触发。 

3.2. 系统从睡眠状态唤醒的过程

3.2.1 唤醒

当按下power(GPF0/EINT0端口产生下降沿),程序就从nboot开始执行,也即从\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 

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,在重新根据系统的需要来设置这几个参数,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锁存时间的统计寄存器,启用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锁存时间的统计寄存器,启用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处继续执行,直到对这四个寄存器始

化完成。

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的刷新周期有关,本系统使用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,当执行BL子程序调用指令时,lr得到R15(程序计数器PC)的备份,下面这行语句可以实现返回到跳转的地址处。

mov pc, lr

6)静态内存控制器(staic memory controller,SMC)的初始化,这个控制器在本开发板中用于控制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的系统控制器(system controller)有三大功能:复位管理,产生时钟和电源管理,下面先介绍复位管理。

当给S3C2443X的系统上电(power-on)时,外部设备必须插入复位来初始化S3C2443X的内部状态,S3C2443X有四种复位类型,在复位时,系统控制器的复位控制器能够使系统进入四种复位类型预先定义的状态中,这四种复位类型是:硬件复位,看门狗复位,软件复位和唤醒复位

I:硬件复位,当nRESET引脚插入低电平时产生硬件复位,这种类型的复位是一种uncompromised,unmaskable和complete reset,以硬件复位方式启动时,除了RTC以外的系统所有单元都被初始化为可知的状态(初始化状态)。

II:看门狗复位,看门狗计数器监测到设备异常的状态时就会产生看门狗复位。

III:软件复位(software reset),当对SWRST寄存器的每一位写1时,就产生软件复位。

IV:唤醒复位(wakeup reset),当系统从sleep mode中唤醒时,就产生唤醒复位。

通过reset状态寄存器来得到复位状态。

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中唤醒,则接着执行下面的指令;如果不是(正常的启动),则跳到下面标号为2处接着执行。beq指令在Z标志位置位时(Z=1,表示上面的TST指令运算结果为0,从而知//道RSTSTAT[3]=0,而这表明系统不是从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中唤醒系统

tst r0, #(1<<1)

如果是通过RTC alarm来唤醒,则WKUPSTAT[1]=1,那么上面tst运算结果为非零,则CPSR的Z=0,那么就接着往下执行;如果不是通过alarm来唤醒,则WKUPSTAT[1]=0,那么上面tst运算结果为零,则CPSR的Z=1,那么跳转到下面标号6处执行

beq %f6                     ; if not wakeup from PowerOffmode Skip

如果是通过RTC alarm来唤醒,则接着到此处执行,设置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唤醒,则直接跳到此处执行;如果是通过RTC alarm唤醒,则先重新启动RTC alarm控制及设置相应的控制寄存器再接着到标号6处执行。

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中的一个地址去执行,这个地址是0x32000000。那么熟悉2443 WINCE启动的朋友们应该明白了,这个地址就是Bootloader把NandFlash里的数据装载完毕后,跳转执行的地址。那么在这里,跳转到0x302000000这个地址后,WINCE系统就会被装载了,也就是说WINCE的操作系统被唤醒了。

2  

如果不是从sleep中唤醒,而是其他的复位方式,将接着从这里执行。

    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,则接着执行下面的语句;如果不是软件复位,则跳转到BringUpWinCE处接着执行

beq BringUpWinCE                     ; if not wakeup from PowerOffmode Skip

如果是软件复位,从此处接着执行

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操作系统内核映像的入口处执行,软件复位方式只用到了stepldr,然后就直接跳转到内核中执行了。

mov     pc, r2 ;  & jump to StartUp address

nop

nop

nop

b .//???????????????????????????????????????????????????????????????????????

如果不是软件复位,这时应该是硬件复位(或是看门狗复位,应该也是最常用的上电启动),紧接着此处执行

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)所指示的多个寄存器中的值存入到由基址寄存器所指向的一片连续存储器中,条件码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 

如果清零完成,则接着执行下面的语句;否则会跳到到上面标号为20处继续对SDRAM的清零。

bne %B20

]

 
========================================================================================
startup.s  文件内容

;
;  Copyright (c) Microsoft Corporation.  All rights reserved.
;
;
;  Use of this source code is subject to the terms of the Microsoft end-user
;  license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
;  If you did not accept the terms of the EULA, you are not authorized to use
;  this source code. For a copy of the EULA, please see the LICENSE.RTF on your
;  install media.
;
;------------------------------------------------------------------------------
;
;   File:  startup.s
;
;   Kernel startup routine for Samsung SMDK2440A board. Hardware is
;   initialized in boot loader - so there isn''t much code at all.
;
;------------------------------------------------------------------------------

        INCLUDE kxarm.h
  INCLUDE s3c2440a.inc

  IMPORT  OALClearUTLB
  IMPORT  OALFlushICache
  IMPORT  OALFlushDCache


vGPIOBASE EQU 0xb1600000 ;Port A control
oGPFCON  EQU 0x50            ;Port F control
oGPFDAT  EQU 0x54
oGPGCON  EQU 0x60
oGPGDAT  EQU 0x64
oGSTATUS3 EQU 0xb8            ;Saved data0(32-bit) before entering POWER_OFF mode
oGSTATUS4 EQU 0xbc            ;Saved data0(32-bit) before entering POWER_OFF mode
vINTBASE EQU 0xb0a00000 ;Interrupt request status
oSRCPND  EQU 0x00         ;Interrupt request status
oINTMSK  EQU 0x08         ;Interrupt mask control
oINTPND  EQU 0x10         ;Interrupt request status

vMISCCR  EQU 0xb1600080 ;Miscellaneous control
vCLKCON  EQU 0xb0c0000c ;Clock generator control
vCLKDIVN EQU 0xb0c00014  ;Clock divider control
vCAMDIVN EQU 0xb0c00018 ;Camera clock divider
vREFRESH EQU 0xb0800024 ;DRAM/SDRAM refresh


; Data Cache Characteristics.
;
DCACHE_LINES_PER_SET_BITS       EQU     6
DCACHE_LINES_PER_SET            EQU     64
DCACHE_NUM_SETS                 EQU     8
DCACHE_SET_INDEX_BIT            EQU     (32 - DCACHE_LINES_PER_SET_BITS)
DCACHE_LINE_SIZE                EQU     32

 

SLEEPDATA_BASE_VIRTUAL          EQU 0xA0028000  ; keep in sync w/ config.bib
SLEEPDATA_BASE_PHYSICAL         EQU 0x30028000

SleepState_Data_Start  EQU     (0)

SleepState_WakeAddr      EQU     (SleepState_Data_Start      )
SleepState_MMUCTL           EQU     (SleepState_WakeAddr    + WORD_SIZE )
SleepState_MMUTTB        EQU     (SleepState_MMUCTL   + WORD_SIZE )
SleepState_MMUDOMAIN     EQU     (SleepState_MMUTTB   + WORD_SIZE )
SleepState_SVC_SP        EQU     (SleepState_MMUDOMAIN   + WORD_SIZE )
SleepState_SVC_SPSR      EQU     (SleepState_SVC_SP   + WORD_SIZE )
SleepState_FIQ_SPSR      EQU     (SleepState_SVC_SPSR    + WORD_SIZE )
SleepState_FIQ_R8        EQU     (SleepState_FIQ_SPSR    + WORD_SIZE )
SleepState_FIQ_R9        EQU     (SleepState_FIQ_R8   + WORD_SIZE )
SleepState_FIQ_R10       EQU     (SleepState_FIQ_R9   + WORD_SIZE )
SleepState_FIQ_R11       EQU     (SleepState_FIQ_R10  + WORD_SIZE )
SleepState_FIQ_R12       EQU     (SleepState_FIQ_R11  + WORD_SIZE )
SleepState_FIQ_SP        EQU     (SleepState_FIQ_R12  + WORD_SIZE )
SleepState_FIQ_LR        EQU     (SleepState_FIQ_SP   + WORD_SIZE )
SleepState_ABT_SPSR      EQU     (SleepState_FIQ_LR   + WORD_SIZE )
SleepState_ABT_SP        EQU     (SleepState_ABT_SPSR    + WORD_SIZE )
SleepState_ABT_LR        EQU     (SleepState_ABT_SP   + WORD_SIZE )
SleepState_IRQ_SPSR      EQU     (SleepState_ABT_LR   + WORD_SIZE )
SleepState_IRQ_SP        EQU     (SleepState_IRQ_SPSR    + WORD_SIZE )
SleepState_IRQ_LR        EQU     (SleepState_IRQ_SP   + WORD_SIZE )
SleepState_UND_SPSR      EQU     (SleepState_IRQ_LR   + WORD_SIZE )
SleepState_UND_SP        EQU     (SleepState_UND_SPSR    + WORD_SIZE )
SleepState_UND_LR        EQU     (SleepState_UND_SP   + WORD_SIZE )
SleepState_SYS_SP        EQU     (SleepState_UND_LR   + WORD_SIZE )
SleepState_SYS_LR        EQU     (SleepState_SYS_SP   + WORD_SIZE )

SleepState_Data_End      EQU     (SleepState_SYS_LR + WORD_SIZE )

SLEEPDATA_SIZE       EQU     ((SleepState_Data_End - SleepState_Data_Start) / 4)

        IMPORT  KernelStart
       
        ;TEXTAREA
        STARTUPTEXT
        LEAF_ENTRY StartUp
       
        ; Compute the OEMAddressTable''s physical address and
        ; load it into r0. KernelStart expects r0 to contain
        ; the physical address of this table. The MMU isn''t
        ; turned on until well into KernelStart. 

   [ {TRUE}
    ldr r0, =WTCON       ; disable the watchdog timer.
    ldr r1, =0x0        
    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, =0x7fff
    str r1, [r0]

    ; CLKDIVN
    ldr r0,=CLKDIVN
    ldr r1,=0x5     ; 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]

    ; MMU_SetAsyncBusMode FCLK:HCLK= 1:2
    ands r1, r1, #0x0e
    beq %F5
    mrc p15,0,r0,c1,c0,0
    orr r0,r0,#R1_nF:OR:R1_iA
    mcr p15,0,r0,c1,c0,0
5
   
 ; TODO: to reduce PLL lock time, adjust the LOCKTIME register.
    ldr r0, =LOCKTIME
    ldr r1, =0xffffff
    str r1, [r0]
   
 ldr     r0, = UPLLCON
 ldr     r1, = ((56 << 12) + (2 << 4) + 2) 
 str     r1, [r0]
 
 nop
 nop
 nop
 nop
 nop
 nop
 nop

 ldr  r0, = MPLLCON
 ldr     r1, = ((92 << 12) + (1 << 4) + 1)
 str  r1, [r0]

 mov     r0, #0x2000

 subs    r0, r0, #1
 bne     %B1 
      ]

 mov  r0, #0
 mov  r1, #0x32000000
 mov  r2, #0x20000
90
 str  r0, [r1]
 add  r1, r1, #4
 subs r2, r2, #4
 bne  %B90
 


        add     r0, pc, #g_oalAddressTable - (. + 8)
        bl      KernelStart
  
        INCLUDE oemaddrtab_cfg.inc


       
        ENTRY_END

  LTORG

 


 LEAF_ENTRY OALCPUPowerOff1

;       1. Push SVC state onto our stack
 stmdb   sp!, {r4-r12}                  
 stmdb   sp!, {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
 ldr     r2, =0x0
 ldr     r0, =(SLEEPDATA_SIZE-1)  ; get size of data structure (in words)
30
 ldr     r1, [r3], #4
 and     r1, r1, #0x1
 mov     r1, r1, ROR #31
 add     r2, r2, r1
 subs    r0, r0, #1
 bne     %b30

 ldr     r0, =vGPIOBASE
 ;;;add  r2, r2, #1    ; test checksum of the Sleep data error
 str     r2, [r0, #oGSTATUS3]  ; Store in Power Manager Scratch pad register

 ldr     r0, =vGPIOBASE
; ldr     r1, =0x550a
    ldr     r1, =0x0a
 str     r1, [r0, #oGPFCON]
 
; ldr  r1, =0x30
; str  r1, [r0, #oGPFDAT] 

;       4. Interrupt Disable
    ldr     r0, =vINTBASE
    mvn     r2, #0
 str     r2, [r0, #oINTMSK]
 str     r2, [r0, #oSRCPND]
 str     r2, [r0, #oINTPND]

;;       5. Cache Flush
 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,1,2) Mode
 ldr     r0, =vGPIOBASE

; ldr     r1, =0x550a
 ldr     r1, =0xaaaa
 str     r1, [r0, #oGPFCON]

; ldr     r1, =0x55550100
 ldr     r1, =0x00000000
 str     r1, [r0, #oGPGCON]

;       7. Go to Power-Off Mode
 ldr  r0, =vMISCCR   ; hit the TLB
 ldr  r0, [r0]
 ldr  r0, =vCLKCON
 ldr  r0, [r0]

 ldr     r0, =vREFRESH  
 ldr     r1, [r0]  ; r1=rREFRESH 
 orr     r1, r1, #(1 << 22)

 ldr  r2, =vMISCCR
 ldr  r3, [r2]
 orr  r3, r3, #(3<<17)        ; Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
; orr  r3, r3, #(7<<17)        ; Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
 bic  r3, r3, #(7<<20)
 orr  r3, r3, #(6<<20)

 ldr     r4, =vCLKCON
 ldr     r5, =0x1ffff8            ; Power Off Mode

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Sometimes it is not working in cache mode. So I modify to jump to ROM area.
;
;;; ldr  r6, =0x92000000  ; make address to 0x9200 0020
;;; add  r6, r6, #0x20  ;
;;; mov     pc, r6    ; jump to Power off code in ROM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

 b       SelfRefreshAndPowerOff

 ALIGN   32                      ; for I-Cache Line(32Byte, 8 Word)

SelfRefreshAndPowerOff  ; run with Instruction Cache''s code
 str     r1, [r0]  ; Enable SDRAM self-refresh
 str  r3, [r2]  ; MISCCR Setting
 str     r5, [r4]  ; Power Off !!
 b       .

 LTORG

; This point is called from EBOOT''s startup code(MMU is enabled)
;       in this routine, left information(REGs, INTMSK, INTSUBMSK ...)

Awake_address

;       1. Recover CPU Registers

 ldr     r3, =SLEEPDATA_BASE_VIRTUAL  ; Sleep mode information data structure
 add     r2, r3, #SleepState_FIQ_SPSR
 mov     r1, #Mode_FIQ:OR:I_Bit:OR:F_Bit  ; Enter FIQ mode, no interrupts - also FIQ
 msr     cpsr, r1
 ldr     r0,  [r2], #4
 msr     spsr, r0
 ldr     r8,  [r2], #4
 ldr     r9,  [r2], #4
 ldr     r10, [r2], #4
 ldr     r11, [r2], #4
 ldr     r12, [r2], #4
 ldr     sp,  [r2], #4
 ldr     lr,  [r2], #4

 mov     r1, #Mode_ABT:OR:I_Bit   ; Enter ABT mode, no interrupts
 msr     cpsr, r1
 ldr     r0, [r2], #4
 msr     spsr, r0
 ldr     sp, [r2], #4
 ldr     lr, [r2], #4

 mov     r1, #Mode_IRQ:OR:I_Bit   ; Enter IRQ mode, no interrupts
 msr     cpsr, r1
 ldr     r0, [r2], #4
 msr     spsr, r0
 ldr     sp, [r2], #4
 ldr     lr, [r2], #4

 mov     r1, #Mode_UND:OR:I_Bit   ; Enter UND mode, no interrupts
 msr     cpsr, r1
 ldr     r0, [r2], #4
 msr     spsr, r0
 ldr     sp, [r2], #4
 ldr     lr, [r2], #4

 mov     r1, #Mode_SYS:OR:I_Bit   ; Enter SYS mode, no interrupts
 msr     cpsr, r1
 ldr     sp, [r2], #4
 ldr     lr, [r2]

 mov     r1, #Mode_SVC:OR:I_Bit     ; Enter SVC mode, no interrupts - FIQ is available
 msr     cpsr, r1
 ldr     r0, [r3, #SleepState_SVC_SPSR]
 msr     spsr, r0

;       2. Recover Last mode's REG's, & go back to caller of OALCPUPowerOff()

 ldr     sp, [r3, #SleepState_SVC_SP]
 ldr     lr, [sp], #4
 ldmia   sp!, {r4-r12}
 mov     pc, lr                          ; and now back to our sponsors


        ENTRY_END

;------------------------------------------------------------------------------
; Clock Division Change funtion for DVS on S3C2440A.
;------------------------------------------------------------------------------

 LEAF_ENTRY CLKDIV124
 ldr     r0, = vCLKDIVN
 ldr     r1, = 0x3  ; 0x3 = 1:2:4
 str     r1, [r0]
 mov     pc, lr

 LEAF_ENTRY CLKDIV144
 ldr     r0, = vCLKDIVN
 ldr     r1, = 0x4  ; 0x4 = 1:4:4
 str     r1, [r0]
 mov     pc, lr

 LEAF_ENTRY CLKDIV136
 ldr     r0, = vCLKDIVN
 ldr     r1, = 0x7   ; 1:6:12
 str     r1, [r0]
 ldr     r0, = vCAMDIVN
 ldr  r1, [r0]
 bic  r1, r1, #(0x3<<8)
 orr  r1, r1, #(0x0<<8) ; 1:3:6
 str     r1, [r0] 
 mov     pc, lr

 LEAF_ENTRY CLKDIV166
 ldr     r0, = vCAMDIVN
 ldr  r1, [r0]
 bic  r1, r1, #(0x3<<8)
 orr  r1, r1, #(0x1<<8) ; 1:6:12
 str     r1, [r0]
 ldr     r0, = vCLKDIVN
 ldr     r1, = 0x6   ; 1:6:6
 str     r1, [r0] 
 mov     pc, lr

 LEAF_ENTRY CLKDIV148
 ldr     r0, = vCLKDIVN
 ldr     r1, = 0x5   ; 1:8:16
 ldr     r2, = vCAMDIVN
 ldr  r3, [r2]
 bic  r3, r3, #(0x3<<8)
 orr  r3, r3, #(0x0<<8) ; 1:4:8
 str     r1, [r0]
 str     r3, [r2]
 mov     pc, lr

 LEAF_ENTRY CLKDIV188
 ldr     r0, = vCAMDIVN
 ldr  r1, [r0]
 bic  r1, r1, #(0x3<<8)
 orr  r1, r1, #(0x2<<8) ; 1:8:16
 ldr     r2, = vCLKDIVN
 ldr     r3, = 0x4   ; 1:8:8
 str     r1, [r0]
 str     r3, [r2]
 mov     pc, lr

 LEAF_ENTRY DVS_ON 
 ldr  r0, = vCAMDIVN
 ldr  r1, [r0]
 orr  r1, r1, #(0x1<<12) ; DVS_EN bit = 1(FCLK = HCLK)
 str  r1, [r0]
 mov  pc, lr

 LEAF_ENTRY DVS_OFF
 ldr  r0, = vCAMDIVN
 ldr  r1, [r0]
 bic  r1, r1, #(0x1<<12) ; DVS_EN bit = 0(FCLK = MPLL clock)
 str  r1, [r0]
 mov  pc, lr
 
        END

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


 

======================================================================
power.c 内容

//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
//      THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//      ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//      THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//      PARTICULAR PURPOSE.
// 
// -----------------------------------------------------------------------------
#include <windows.h>
#include <bsp.h>

#define Clear_FrameBuffer 0xA0100000

void InitTimer(void);
void ConfigStopGPIO(void);
void TurnOffBackLight(void);

VOID BSPPowerOff()
{

    volatile S3C2440A_IOPORT_REG *pIOPort = (S3C2440A_IOPORT_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);
    volatile S3C2440A_ADC_REG *pADCPort = (S3C2440A_ADC_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_ADC, FALSE);
    volatile S3C2440A_RTC_REG *pRTCPort = (S3C2440A_RTC_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_RTC, FALSE);
    volatile S3C2440A_LCD_REG *pLCDPort = (S3C2440A_LCD_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_LCD, FALSE);
 
 ULONG *FrameBufferPtr = (ULONG *)Clear_FrameBuffer;
 ULONG FrameBufferCount;
 //RETAILMSG(1,(TEXT("BSPPowerOff\r\n"))); 
    pRTCPort->RTCCON=0x0;   // R/W disable, 1/32768, Normal(merge), No reset
    pADCPort->ADCCON|=(1<<2);  // ADC StanbyMode

    pIOPort->MISCCR|=(1<<12); //USB port0 = suspend
    pIOPort->MISCCR|=(1<<13); //USB port1 = suspend

    pIOPort->MISCCR|=(1<<2); //Previous state at STOP(?) mode (???)

    //D[31:0] pull-up off. The data bus will not be float by the external bus holder.
    //If the pull-up resitsers are turned on,
    //there will be the leakage current through the pull-up resister
    pIOPort->MISCCR=pIOPort->MISCCR|(3<<0);

 // In the evaluation board, Even though in sleep mode, the devices are all supplied the power.
 pIOPort->MSLCON = (0<<11)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0);
 pIOPort->DSC0 = (1<<31)|(3<<8)|(3<<0);
 pIOPort->DSC1 = (3<<28)|(3<<26)|(3<24)|(3<<22)|(3<<20)|(3<<18);

 // Clear frame buffer & wait until framebuffer refresh
 for (FrameBufferCount = 0 ; FrameBufferCount < 480*800/2 ; FrameBufferCount++)
  *FrameBufferPtr++ = 0;//0xffffffff;
 pLCDPort->LCDSRCPND = 0x2;
 while((pLCDPort->LCDSRCPND & 0x2) == 0);
 pLCDPort->LCDSRCPND = 0x2;
 while((pLCDPort->LCDSRCPND & 0x2) == 0);
 pLCDPort->LCDSRCPND = 0x2;
 while((pLCDPort->LCDSRCPND & 0x2) == 0);
 pLCDPort->LCDSRCPND = 0x2;


 //TurnOffBackLight();
    /* LCD Controller Disable               */
   // CLRPORT32(&pIOPort->GPGDAT, 1 << 4);
}

void ConfigStopGPIO(void)
{
    volatile S3C2440A_IOPORT_REG *pIOPort = (S3C2440A_IOPORT_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);

    // Check point
    // 1) NC pin: input pull-up on
    // 2) If input is driver externally: input pull-up off
    // 3) If a connected component draws some current: output low.
    // 4) If a connected component draws no current: output high.
   
    //chip # = 5

    //CAUTION:Follow the configuration order for setting the ports.
    // 1) setting value(GPnDAT)
    // 2) setting control register  (GPnCON)
    // 3) configure pull-up resistor(GPnUP) 

    //32bit data bus configuration 
    //*** PORT A GROUP
    //Ports  : GPA22 GPA21  GPA20 GPA19 GPA18 GPA17 GPA16 GPA15 GPA14 GPA13 GPA12 
    //Signal : nFCE nRSTOUT nFRE  nFWE  ALE   CLE   nGCS5 nGCS4 nGCS3 nGCS2 nGCS1
    //Binary : 1     1      1,    1     1     1     1,    1     1     1     1,
    //POFF   : 1     0      1,    1     0     0     1,    1     1     1     1,
    //-------------------------------------------------------------------------------------------
    //Ports  : GPA11  GPA10  GPA9   GPA8   GPA7   GPA6   GPA5   GPA4   GPA3   GPA2   GPA1   GPA0
    //Signal : ADDR26 ADDR25 ADDR24 ADDR23 ADDR22 ADDR21 ADDR20 ADDR19 ADDR18 ADDR17 ADDR16 ADDR0
    //Binary : 1      1      1      1,     1      1      1      1,     1      1      1      1        
    //POFF   : 0      0      0      0,     0      0      0      0,     0      0      0      0
    pIOPort->GPACON = 0x7fffff;

    //**** PORT B GROUP
    //Ports  : GPB10   GPB9    GPB8    GPB7    GPB6    GPB5     GPB4    GPB3   GPB2   GPB1       GPB0
    //Signal : nXDREQ0 nXDACK0 nXDREQ1 nXDACK1 nSS_KBD nDIS_OFF L3CLOCK L3DATA L3MODE nIrDATXDEN Keyboard
    //Setting: INPUT   OUTPUT  INPUT   OUTPUT  INPUT   OUT      OUT     OUT    OUT    INPUT      INPUT
    //Binary : 00,     01      00,     01      00,     01       01,     01     01,    00         00 
    //PU_OFF :  0       1       0,      1      1(ext)  1(*)     1,      1      1      1(ext)     1(ext)          
    //*:nDIS_OFF:4.7K external pull-down resistor                                
//  pIOPort->GPBDAT=  0x0|(0<<9)|(1<<7)|(0<<5)|(1<<4)|(1<<3)|(1<<2);   // SHLIM 040116
 pIOPort->GPBDAT=  0x0|(1<<9)|(1<<7)|(0<<5)|(1<<4)|(1<<3)|(1<<2);   // SHLIM 040116
 pIOPort->GPBCON = 0x044550; 
    pIOPort->GPBUP  = (0x2ff)&(~(0x1<<1));   //0x2fd->2ff, 3uA is reduced. Why?
 
 pIOPort->GPBCON &=~(0x3<<18);
 pIOPort->GPBCON |= (0x1<<18);
 pIOPort->GPBUP  &= ~(0x1<<9);   //控制电源
 pIOPort->GPBDAT |= (0x1<<9);

 pIOPort->GPBUP  &= ~(0x1<<1);   //控制电源
 pIOPort->GPBCON &= ~(0x3<<2);
 pIOPort->GPBCON |= (0x1<<2);
 pIOPort->GPBDAT &= ~(0x1<<1); 
 
    //*** PORT C GROUP
    //Ports  : GPC15 GPC14 GPC13 GPC12 GPC11 GPC10 GPC9 GPC8 GPC7  GPC6   GPC5   GPC4 GPC3 GPC2  GPC1 GPC0
    //Signal : VD7   VD6   VD5   VD4   VD3   VD2   VD1  VD0 LCDVF2 LCDVF1 LCDVF0 VM VFRAME VLINE VCLK LEND 
    //Setting: IN    IN    IN    IN    IN    IN    IN   IN   OUT   OUT    OUT    IN   IN   IN    IN   IN
    //Binary : 00    00,   00    00,   00    00,   00   00,  01    01,    01     00,  00   00,   00   00
    //PU_OFF :  0     0     0     0,    0     0     0    0,   1     1      1      0,   0    0     0    0
    pIOPort->GPCDAT = 0x0;
    pIOPort->GPCCON = 0x00005400;  //0x00000000; 
    pIOPort->GPCUP  = 0x00e0;      //0x0000;    

 pIOPort->GPCUP  &= ~(0x1<<6);     //关灯 方便调试的 以后需要删除 long
 pIOPort->GPCCON &= ~(0x3<<12); 
 pIOPort->GPCCON |= (0x1<<12); 
 pIOPort->GPCDAT |= (0x1<<6);   
 
 //LCDVFn is connected the analog circuit in LCD. So, this signal should be output L.
   
    //*** PORT D GROUP
    //Ports  : GPD15 GPD14 GPD13 GPD12 GPD11 GPD10 GPD9 GPD8 GPD7 GPD6 GPD5 GPD4 GPD3 GPD2 GPD1 GPD0
    //Signal : VD23  VD22  VD21  VD20  VD19  VD18  VD17 VD16 VD15 VD14 VD13 VD12 VD11 VD10 VD9  VD8
    //Setting: IN    IN    IN    IN    IN    IN    IN   IN   IN   IN   IN   IN   IN   IN   IN   IN
    //Binary : 00    00,   00    00,   00    00,   00   00,  00   00,  00   00,  00   00,  00   00
    //PU_OFF :  0     0     0     0,    0     0     0    0,   0    0    0    0,   0    0    0    0
    pIOPort->GPDDAT=  0x0;
    pIOPort->GPDCON = 0x0; 
    pIOPort->GPDUP  = 0x0;   

    //*** PORT E GROUP
    //Ports  : GPE15  GPE14  GPE13   GPE12    GPE11    GPE10   GPE9    GPE8    GPE7    GPE6  GPE5  GPE4 
    //Signal : IICSDA IICSCL SPICLK0 SPIMOSI0 SPIMISO0 SDDATA3 SDDATA2 SDDATA1 SDDATA0 SDCMD SDCLK I2SSDO
    //Setting: IN     IN     IN      IN       IN       IN      IN      IN      IN      IN    IN    OUT
    //Binary : 00     00,    00      00,      00       00,     00      00,     00      00,   00    01,    
    //PU_OFF :  1-ext  1-ext  0       0,       0        0       0       0,      0       0     0     1,
    //------------------------------------------------------------------------------------------------
    //Ports  : GPE3   GPE2  GPE1    GPE0   
    //Signal : I2SSDI CDCLK I2SSCLK I2SLRCK    
    //Setting: IN     OUT   OUT     OUT
    //Binary : 00     01,   01      01
    //PU_OFF :  1-ext  1     1       1
    pIOPort->GPEDAT = 0x0|(1<<4)|(1<<2)|(1<<1)|(1<<0);
    pIOPort->GPECON = 0x00000115; 
    pIOPort->GPEUP  = 0xc01f;    

    //*** PORT F GROUP
    //Ports  : GPF7   GPF6   GPF5   GPF4   GPF3        GPF2  GPF1   GPF0
    //Signal : nLED_8 nLED_4 nLED_2 nLED_1 nIRQ_PCMCIA EINT2 KBDINT EINT0
    //Setting: Output Output Output Output IN          IN    IN     EINT0
    //Binary : 01     01,    01     01,    00          00,   00     10
    //PU_OFF :  1      1      1      1,     0-ext       1-ext 1-ext  1-ext
    pIOPort->GPFDAT = 0x0  |(0xf<<4);
    pIOPort->GPFCON = 0x5502;
    pIOPort->GPFUP  = 0xf7;  

 pIOPort->GPFCON &= ~(0x3<<8) ;   //设置GPF4 为 EINT4
 pIOPort->GPFCON |= (0x2<<8) ;   //设置GPF4 为 EINT4
                        
    //*** PORT G GROUP
    //Ports  : GPG15 GPG14 GPG13 GPG12 GPG11  GPG10    GPG9     GPG8     GPG7      GPG6   
    //Signal : nYPON YMON  nXPON XMON  EINT19 DMAMODE1 DMAMODE0 DMASTART KBDSPICLK KBDSPIMOSI
    //Setting: OUT   OUT   OUT   OUT   OUT    OUT      OUT      OUT      OUT       OUT
    //Binary : 01    01,   01    01,   01-dbg 01,      01       01,      01        01
    //PU_OFF :  1     1     1     1,    1-ext  1        1        1,       1         1
    //---------------------------------------------------------------------------------------
    //Ports  : GPG5       GPG4      GPG3   GPG2    GPG1    GPG0   
    //Signal : KBDSPIMISO LCD_PWREN EINT11 nSS_SPI IRQ_LAN IRQ_PCMCIA
    //Setting: IN         IN        EINT11 IN      IN      IN
    //Binary : 00         00,       10     00,     00      00
    //PU_OFF :  0-ext      0,        1-ext  0       0       0
#if 0
    pIOPort->GPGDAT = 0x0 |(1<<11)|(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<9)|(1<<8)|(1<<7)|(1<<6) ;
    pIOPort->GPGCON = 0x55455080;   //GPG11=OUT  //for debug
    pIOPort->GPGUP  = 0xfbc8;   
#else // Modified for 2440
 pIOPort->GPGDAT = 0;
 pIOPort->GPGCON = 0x00000000;
 pIOPort->GPGUP = 0x0;
#endif

    //*** PORT H GROUP
    //Ports  : GPH10   GPH9    GPH8 GPH7  GPH6  GPH5 GPH4 GPH3 GPH2 GPH1  GPH0
    //Signal : CLKOUT1 CLKOUT0 UCLK nCTS1 nRTS1 RXD1 TXD1 RXD0 TXD0 nRTS0 nCTS0
    //Setting: IN      IN      IN   IN    IN    IN   OUT  RXD0 TXD0 OUT   IN
    //Binary : 00,     00      00,  00    00,   00   01,  10   10,  01    00
    //PU_OFF :  0       0       0,   1-ext 1-ext 1-ext 1, 1-ext 1    1     1-ext

    pIOPort->GPHDAT = 0x0|(1<<6)|(1<<1)|(1<<4);   
    pIOPort->GPHCON = 0x0001a4;      //0x0011a4->0x0001a4 reduces 12uA why -> MAX3232C may sink 12uA.
    pIOPort->GPHUP  = 0x0ff;    // The pull up function is disabled GPH[10:0]

 pIOPort->GPBUP  &= ~(0x1<<10);   //控制电源
 pIOPort->GPHCON &= ~(0x3<<20);
 pIOPort->GPHCON |= (0x1<<20);
 pIOPort->GPHDAT &= ~(0x1<<10); //为0 wifi sleep 

 //PORT J GROUP
 //Ports :  GPJ12    GPJ11     GPJ10   GPJ9  GPJ8      GPJ7 GPJ6  GPJ5 GPJ4  GPJ3  GPJ2  GPJ1  GPJ0
 //Signal : CAMRESET CAMCLKOUT CAMHREF CAMVS CAMPCLKIN CAMD7 CAMD6 CAMD5 CAMD4 CAMD3 CAMD2 CAMD1 CAMD0
 //Setting: Out      Out       Out     Out   Out       Out   Out   Out   Out   Out   Out   Out   Out
 //Binary : 01     01        01      01    01        01    01    01    01    01    01    01    01
 //PU_OFF : 0     0     1       1     1         1     1     1  1   1     1     1     1
 //---------------------------------------------------------------------------------------
 
 pIOPort->GPJCON = 0x02aaaaaa;
 pIOPort->GPJUP  = 0x1fff;    // The pull up function is disabled GPH[10:0]
   
    //External interrupt will be falling edge triggered.
//    pIOPort->rEXTINT0 = 0x22222222;    // EINT[7:0]
    pIOPort->EXTINT0 = 0x22222224;    // EINT[7:0]   // charlie. button glich
    pIOPort->EXTINT1 = 0x22222222;    // EINT[15:8]
    pIOPort->EXTINT2 = 0x22222022;    // EINT[23:16]
}


VOID BSPPowerOn()
{
    volatile S3C2440A_IOPORT_REG *pIOPort = (S3C2440A_IOPORT_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);
    volatile S3C2440A_LCD_REG *pLCD = (S3C2440A_LCD_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_LCD, FALSE);

 OEMInitDebugSerial();
 
 InitTimer();

    pIOPort->EXTINT0 = 0x22222222;    // EINT[7:0]
    pIOPort->EXTINT1 = 0x22222222;    // EINT[15:8]                           
    pIOPort->EXTINT2 = 0x22222222;    // EINT[23:16]

 pIOPort->GSTATUS2 = pIOPort->GSTATUS2;

    pIOPort->MISCCR &= ~(1<<12); //USB port0 = normal mode
    pIOPort->MISCCR &= ~(1<<13); //USB port1 = normal mode

 pLCD->LCDCON1 &= ~(0x1);
 lcd_spi_init();
 pLCD->LCDCON1 |= (0x1);

 // LCD Controller Enable

 //SETPORT32(&pIOPort->GPGDAT, 1 << 4);


 

}

//------------------------------------------------------------------------------
//
//  Function:  InitClock
//
//  This function is now considered obsolete. It is called by kernel after OAL
//  returns from OEMPowerOff. All its function should be moved to OEMPowerOff.
//
// This function is defined on \common\src\common\other\clock.c
//
VOID InitTimer()
{
 volatile S3C2440A_PWM_REG *g_pPWMRegs = (S3C2440A_PWM_REG*)OALPAtoUA(S3C2440A_BASE_REG_PA_PWM);
    UINT32 tcon;

 RETAILMSG(1,(TEXT("InitClock\r\n")));

     // Hardware Setup
    g_pPWMRegs = (S3C2440A_PWM_REG*)OALPAtoUA(S3C2440A_BASE_REG_PA_PWM);

    OUTREG32(&g_pPWMRegs->TCFG0, INREG32(&g_pPWMRegs->TCFG0) & ~0x0000FF00);
    OUTREG32(&g_pPWMRegs->TCFG0, INREG32(&g_pPWMRegs->TCFG0) | (25-1) <<8);  // charlie, Timer4 scale value
    OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) & ~(0xF << 16));
    OUTREG32(&g_pPWMRegs->TCFG1, INREG32(&g_pPWMRegs->TCFG1) | (0 << 16)); // charlie, Timer4 Division
    OUTREG32(&g_pPWMRegs->TCNTB4, g_oalTimer.countsPerSysTick);

    // Start timer in auto reload mode
    tcon = INREG32(&g_pPWMRegs->TCON) & ~(0x0F << 20);
    OUTREG32(&g_pPWMRegs->TCON, tcon | (0x2 << 20) );
    OUTREG32(&g_pPWMRegs->TCON, tcon | (0x5 << 20) );
}

//------------------------------------------------------------------------------

//==========================================
// add by long
//==========================================
void TurnOffBackLight(void)
{
 volatile S3C2440A_IOPORT_REG *pIOPort = (S3C2440A_IOPORT_REG*)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);
 pIOPort->GPBCON &= (~0x3);
 pIOPort->GPBCON |=   0x01;
 pIOPort->GPBUP |= 0x01;
 pIOPort->GPCDAT &= ~0x1;
}

原创粉丝点击