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

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.1SetSystemPowerState()

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

SetSystemPowerState(NULL,POWER_STATE_ON,POWER_FORCE);

下图是这个函数的定义

3.1.3.2Powermanager的相关调用

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

⑴FileSystemPowerFunction():

⑵PowerOffSystem()

⑶Sleep()

3.1.3.3内核的相关调用

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

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

3.1.3.4OEMPowerOff()函数

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

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

⑴BSPPowerOff()函数

à pRTCPort->RTCCON=0x0;

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

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

设置ADC的工作模式为standbymode,在睡眠状态下,触摸屏不需要工作,所以设置为standymode,见下图:

àpIOPort->MISCCR|=(1<<12);//USBport=suspend

设置USBport为挂起模式,降低在睡眠时的功耗。

àpCLKPWR->USB_PHYPWR|=(0xf<<0);

见下图:

àpCLKPWR->PWRCFG&=~(1<<4);

关闭对usb物理端口的供电。

àpCLKPWR->USB_CLKCON&=~(1<<31);

见下图

àpCLKPWR->INFORM0=0x2BED;

这个寄存器可用于在进入睡眠前保留一些重要或者特别目的的数据,以便唤醒过程或唤醒后可以使用。

à关闭背光灯和LCD

⑵savesystemregisters

…………………………………..

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_ENTRYOALCPUPowerOff

;1.PushSVCstateontoourstack

stmdbsp!,{r4-r12}

stmdbsp!,{lr}

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

我们知道R13常用作堆栈指针(sp),用于保存当前堆栈地址。SVC:表示处理器模式为管理模式。Stm指令是多寄存器存储指令,在此表示把r4r129个寄存器中的值存储到基址寄存器(sp)所指示的一片连续存储器中,stm后面的db表示每次传送前地址值减;!表示数据加载与存储完毕之后,将最后的地址写入基址寄存器,如不使用!,则基址寄存器的内容不改变。假设sp=0x90020,stmdbsp!,{r4-r12}的操作如下:

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

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

第三步:0x9004c-4=0x90048

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

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

最后一步:就是sp=0x90030

lr:R14寄存器也称为子程序连接器(SubroutineLinkRegister)或连接寄存器LR

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

;2.SaveMMU&CPURegistertoRAM

ldrr3,=SLEEPDATA_BASE_VIRTUAL;baseofSleepmodestorage

ldrr2,=Awake_address;storeVirtualreturnaddress

strr2,[r3],#4

mrcp15,0,r2,c1,c0,0;loadr2withMMUControl

ldrr0,=MMU_CTL_MASK;maskofftheundefinedbits

bicr2,r2,r0

strr2,[r3],#4;storeMMUControldata

mrcp15,0,r2,c2,c0,0;loadr2withTTBaddress.

ldrr0,=MMU_TTB_MASK;maskofftheundefinedbits

bicr2,r2,r0

strr2,[r3],#4;storeTTBaddress

mrcp15,0,r2,c3,c0,0;loadr2withdomainaccesscontrol.

strr2,[r3],#4;storedomainaccesscontrol

strsp,[r3],#4;storeSVCstackpointer

mrsr2,spsr

strr2,[r3],#4;storeSVCstatusregister

movr1,#Mode_FIQ:OR:I_Bit:OR:F_Bit;EnterFIQmode,nointerrupts

msrcpsr,r1

mrsr2,spsr

stmiar3!,{r2,r8-r12,sp,lr};storetheFIQmoderegisters

movr1,#Mode_ABT:OR:I_Bit:OR:F_Bit;EnterABTmode,nointerrupts

msrcpsr,r1

mrs r0,spsr

stmiar3!,{r0,sp,lr};storetheABTmodeRegisters

movr1,#Mode_IRQ:OR:I_Bit:OR:F_Bit;EnterIRQmode,nointerrupts

msrcpsr,r1

mrsr0,spsr

stmiar3!,{r0,sp,lr};storetheIRQModeRegisters

movr1,#Mode_UND:OR:I_Bit:OR:F_Bit;EnterUNDmode,nointerrupts

msrcpsr,r1

mrsr0,spsr

stmiar3!,{r0,sp,lr};storetheUNDmodeRegisters

movr1,#Mode_SYS:OR:I_Bit:OR:F_Bit;EnterSYSmode,nointerrupts

msrcpsr,r1

stmiar3!,{sp,lr};storetheSYSmodeRegisters

movr1,#Mode_SVC:OR:I_Bit:OR:F_Bit;BacktoSVCmode,nointerrupts

msrcpsr,r1

;3.doChecksumontheSleepdata

ldrr3,=SLEEPDATA_BASE_VIRTUAL ;getpointertoSLEEPDATA

movr2,#0

ldrr0,=SLEEPDATA_SIZE ;getsizeofdatastructure(inwords)

30

ldrr1,[r3],#4

andr1,r1,#0x1

movr1,r1,LSL#31

orrr1,r1,r1,LSR#1

addr2,r2,r1

subsr0,r0,#1

bne%b30

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

计算睡眠数据的checksum,保存在r2寄存器中

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

ldrr0,=vINFORM3

strr2,[r0] ;StoreinPowerManagerScratchpadregister

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

把保存在r2寄存器中的睡眠数据的checksum保存到INFORM3寄存器中,以便唤醒过程计算checksum时比较。

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

;4.InterruptDisable

ldrr0,=vINTBASE

mvnr2,#0

strr2,[r0,#oINTMSK]

strr2,[r0,#oSRCPND]

strr2,[r0,#oINTPND]

;;5.CacheFlush

[{TRUE}

blOALClearUTLB

blOALFlushICache

ldrr0,=(DCACHE_LINES_PER_SET-1)

ldrr1,=(DCACHE_NUM_SETS-1)

ldrr2,=DCACHE_SET_INDEX_BIT

ldrr3,=DCACHE_LINE_SIZE

blOALFlushDCache

]

;6.SettingWakeupExternalInterrupt(EINT0)Mode

ldrr0,=vGPIOBASE

ldrr1,=0x5502

strr1,[r0,#oGPFCON]

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

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

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

ldrr4,=vRSTCON

ldrr5,=0x0ff80

strr5,[r4]

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

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

ldrr4,=vOSCSET

ldrr5,=0x8000

strr5,[r4]

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

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

ldrr4,=vPWRCFG

ldrr5,=0x8201

strr5,[r4]

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

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

ldrr4,=vPWRMODE

ldr r5,[r4]

bic r5,r5,#0xff00

bic r5,r5,#0x00ff

ldr r6,=0x2BED

orrr5,r5,r6;PowerOffMode

strr5,[r4] ;PowerOff!!

b.

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

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

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

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

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

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

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

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_ENTRYStartUp;用于指定Startup.s函数的入口点

bResetHandler;无条件跳转到ResetHandler函数

b.

……………………….

b.

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

;Steppingstoneloaderentrypoint.

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

ResetHandler

ldrr0,=WTCON;disablethewatchdogtimer.

movr1,#0

strr1,[r0]

……………………

2)禁止看门狗,屏蔽所有的中断及设置中断模式

ResetHandler

ldrr0,=WTCON;disablethewatchdogtimer.

movr1,#0

strr1,[r0]

ldrr0,=GPACDH

ldrr1,=0x1AA8A

strr1,[r0]

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

GPACON和GPADAT在S3C2443中已不存在,被GPACDL和GPACDH代替,其作用如下:

GPACDL:ConfigurationanddataregisterforportAlow

GPACDH:ConfigurationanddataregisterforportAhigh

配置为功能端,但不甚清楚如此配置的原因。

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

ldrr0,=GPFCON

ldrr1,=0x5500

2

strr1,[r0]

ldrr0,=INTMSK;maskallfirst-levelinterrupts.

ldrr1,=0xffffffff

strr1,[r0]

ldrr0,=INTSUBMSK;maskallsecond-levelinterrupts.

ldrr1,=0x1fffffff

strr1,[r0]

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

屏蔽子中断和中断,从而在stepldr阶段不能使用中断服务功能。

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

ldrr0,=INTMOD

movr1,#0x0;setallinterruptasIRQ

strr1,[r0]

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

设置所有的中断为IRQ中断。

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

3)设置时钟频率

ldrr0,=CLKDIV0;SetClockDivider

ldrr1,[r0]

bicr1,r1,#0x37;clearHCLKDIV,PREDIV,PCLKDIV

bicr1,r1,#(0xf<<9);clearARMCLKDIV

ldrr2,=((Startup_ARMCLKdiv<<9)+(Startup_PREdiv<<4)+(Startup_PCLKdiv<<2)+(Startup_HCLKdiv))

orrr1,r1,r2

strr1,[r0]

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

先清除PREDIV、PCLKDIV、HCLKDIV和ARMCLKDIV,在重新根据系统的需要来设置这几个参数,Startup_ARMCLKdiv等这几个参数在stepldr目录下的option.inc下定义。

ldrr0,=LOCKCON0;SetlocktimeofMPLL.addedbyjunon

movr1,#0xe10;Fin=12MHz-0x800,16.9844MHz-0xA00

strr1,[r0]

LOCKCON0是MPLL锁存时间的统计寄存器,启用PLL之后,由这个寄存器的值来决定为ARMCLK,HCLK和PCLK服务的MPLL锁存时间的计数值,典型情况下,这个值必须大于300us。

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

ldrr0,=LOCKCON1;SetlocktimeofEPLL.addedbyjunon

movr1,#0x800;Fin=12MHz-0x800,16.9844MHz-0xA00

strr1,[r0]

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

LOCKCON1是EPLL锁存时间的统计寄存器,启用PLL之后,由这个寄存器的值来决定为ARMCLK,HCLK和PCLK服务的MPLL锁存时间的计数值,典型情况下,这个值必须大于150。

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

ldr r0,=MPLLCON ; SetMPLL

ldr r1,=((0<<24)+(Startup_Mdiv<<16)+(Startup_Pdiv<<8)+(Startup_Sdiv))

str r1,[r0]

ldr r0,=EPLLCON ; SetEPLL

ldr r1,=((0<<24)+(Startup_EMdiv<<16)+(Startup_EPdiv<<8)+(Startup_ESdiv))

str r1,[r0]

PLL的输出频率由MPLLCON和EPLLCON寄存器的值来决定,其值尽量根据S3C2443用户手册中推荐使用的表来选择

MPLLCON相关参数的表:

EPLLCON相关参数的表:

ldr r0,=CLKSRC ; SelectMPLLclockoutforSYSCLK

ldr r1,[r0]

orr r1,r1,#0x50

str r1,[r0]

设置CLKSRC中的ESYSCLK选择方式为EPLL输出和MSYSCLK选择方式为MPLL输出,见下图:

4)设置总线的同步方式

bl MMU_SetAsyncBusMode

这个函数的代码如下所示:

LEAF_ENTRYMMU_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 ;setSdata[31:16]

str r1,[r0]

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

GPKCON就是SDATACFG寄存器,这是32位SDRAM的配置寄存器,为了控制32位的SDRAM,在内存初始化之前,SDATACFG应该设置为0xAAAAAAAA

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

addr0,pc,#MEMDATA-(.+8)

ldr r1,=BANKCFG ;

add r2,r0,#16 ;EndaddressofMEMDATA

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 : IssueaPALLcommand

str r1,[r2]

对REFRESH的DRAM刷新周期赋值,这个值REFCYC=refreshperiod(这个和SDRAM的刷新周期有关,本系统使用K4S56163PF,其刷新周期为64ms,计算时是以s为单位的)*HCLK

ldr r4,=REFRESH ; 5fh:refreshcycleevery255-clockcycles

ldr r0,=0xff

str r0,[r4]

mov r0,#0x100 ; 6th:wait2auto-clk

120 subs r0,r0,#1;

bne %B120

bic r1,r1,#(0x3<<0) ; 7th : IssueaMRScommand

orr r1,r1,#(0x2<<0)

str r1,[r2]

ldr r4,=REFRESH ; 8fh:refreshnormal

ldr r0,=REFCYC

str r0,[r4]

orr r1,r1,#(0x3<<0) ; 9th : IssueaEMRScommand

str r1,[r2]

bic r1,r1,#(0x3<<0) ; 10th : IssueaNormalmode

str r1,[r2]

// R14也称作子程序连接寄存器lr,当执行BL子程序调用指令时,lr得到R15(程序计数器PC)的备份,下面这行语句可以实现返回到跳转的地址处。

mov pc,lr

6)静态内存控制器(staicmemorycontroller,SMC)的初始化,这个控制器在本开发板中用于控制norflash,而mx300没有使用norflash,所以应该不需要对SMC进行初始化.

bl InitSSMC

InitSSMC函数的定义如下:

InitSSMC

;SetSSMCMemoryparametercontrolregisters:AMDFlash

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]

movpc,lr

7)S3C2443X的系统控制器(systemcontroller)有三大功能:复位管理,产生时钟和电源管理,下面先介绍复位管理。

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

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

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

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

IV:唤醒复位(wakeupreset),当系统从sleepmode中唤醒时,就产生唤醒复位。

通过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;ifnotwakeupfromPowerOffmodeSkip

如果是从sleepmode中唤醒,接下来深入及具体判断是通过RTCtick,或是RTCalarm,还是EINT终端模式来从sleepmode中唤醒。

ldr r1,=WKUPSTAT

ldr r0,[r1]

判断是否通过RTCalarm来从sleepmode中唤醒系统

tst r0,#(1<<1)

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

beq %f6;ifnotwakeupfromPowerOffmodeSkip

如果是通过RTCalarm来唤醒,则接着到此处执行,设置RTCCON[0]=1:启动RTC控制。

ldr r1,=RTCCON

ldr r3,[r1]

orr r3,r3,#0x1

str r3,[r1]

enableRTCalarm控制的相关功能项

ldr r1,=RTCALM

ldr r3,=0x7f

str r3,[r1]

设置RTCalarm秒,分,小时,日,月和年控制寄存器,以便下次唤醒所用。

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]

唤醒的复位方式启动,但又不是通过RTCalarm唤醒,则直接跳到此处执行;如果是通过RTCalarm唤醒,则先重新启动RTCalarm控制及设置相应的控制寄存器再接着到标号6处执行。

6

ldr r2,=0x200000 ;offsetintotheRAM

add r2,r2,#0x30000000 ;addphysicalbase

movpc,r2 ;&jumptoStartUpaddress

nop

nop

nop

b.

跳转到RAM中的一个地址去执行,这个地址是0x32000000。那么熟悉2443WINCE启动的朋友们应该明白了,这个地址就是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;ifnotwakeupfromPowerOffmodeSkip

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

JumpToRAM

0x30200000(=0x30000000+0x200000)是NK.bin的imagestart地址

ldr r2,=0x200000 ;offsetintotheRAM

add r2,r2,#0x30000000 ;addphysicalbase

直接跳转到SDRAM的0x30200000从WINCE操作系统内核映像的入口处执行,软件复位方式只用到了stepldr,然后就直接跳转到内核中执行了。

movpc,r2 ;&jumptoStartUpaddress

nop

nop

nop

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

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

BringUpWinCE

[{TRUE} ;DonGo

;ClearRAM.

;

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;Startaddress(physical0x3000.0000).

ldr r9,=0x04000000;64MBofRAM.

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


vGPIOBASEEQU0xb1600000;Port A control
oGPFCONEQU0x50 ;Port F control
oGPFDATEQU 0x54
oGPGCONEQU 0x60
oGPGDATEQU 0x64
oGSTATUS3EQU0xb8 ;Saved data0(32-bit) before entering POWER_OFF mode
oGSTATUS4EQU0xbc ;Saved data0(32-bit) before entering POWER_OFF mode
vINTBASEEQU0xb0a00000;Interrupt request status
oSRCPNDEQU0x00 ;Interrupt request status
oINTMSKEQU0x08 ;Interrupt mask control
oINTPNDEQU0x10 ;Interrupt request status

vMISCCREQU0xb1600080;Miscellaneous control
vCLKCONEQU0xb0c0000c;Clock generator control
vCLKDIVNEQU0xb0c00014 ;Clock divider control
vCAMDIVNEQU0xb0c00018;Camera clock divider
vREFRESHEQU0xb0800024;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 EQU0xA0028000; keep in sync w/ config.bib
SLEEPDATA_BASE_PHYSICAL EQU0x30028000

SleepState_Data_StartEQU (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}
ldrr0, =WTCON ; disable the watchdog timer.
ldrr1, =0x0
strr1, [r0]

ldrr0, =INTMSK ; mask all first-level interrupts.
ldrr1, =0xffffffff
strr1, [r0]

ldrr0, =INTSUBMSK ; mask all second-level interrupts.
ldrr1, =0x7fff
strr1, [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.
ldrr0, =LOCKTIME
ldrr1, =0xffffff
strr1, [r0]

ldr r0, = UPLLCON
ldr r1, = ((56 << 12) + (2 << 4) + 2)
str r1, [r0]

nop
nop
nop
nop
nop
nop
nop

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

mov r0, #0x2000
1
subs r0, r0, #1
bne %B1
]

movr0, #0
movr1, #0x32000000
movr2, #0x20000
90
strr0, [r1]
addr1, r1, #4
subsr2, 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
mrsr0, 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
;;;addr2, 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]

;ldrr1, =0x30
;strr1, [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
blOALClearUTLB
blOALFlushICache
ldr r0, = (DCACHE_LINES_PER_SET - 1)
ldr r1, = (DCACHE_NUM_SETS - 1)
ldr r2, = DCACHE_SET_INDEX_BIT
ldr r3, = DCACHE_LINE_SIZE
blOALFlushDCache

; 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
ldrr0, [r0]
ldr r0, =vCLKCON
ldrr0, [r0]

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

ldr r2, =vMISCCR
ldrr3, [r2]
orrr3, r3, #(3<<17) ; Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
;orrr3, r3, #(7<<17) ; Make sure that SCLK0:SCLK->0, SCLK1:SCLK->0, SCKE=L during boot-up
bicr3, r3, #(7<<20)
orrr3, 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.
;
;;;ldrr6, =0x92000000; make address to 0x9200 0020
;;;addr6, 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
strr3, [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
ldrr1, [r0]
bicr1, r1, #(0x3<<8)
orrr1, r1, #(0x0<<8); 1:3:6
str r1, [r0]
mov pc, lr

LEAF_ENTRY CLKDIV166
ldr r0, = vCAMDIVN
ldrr1, [r0]
bicr1, r1, #(0x3<<8)
orrr1, 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
ldrr3, [r2]
bicr3, r3, #(0x3<<8)
orrr3, r3, #(0x0<<8); 1:4:8
str r1, [r0]
str r3, [r2]
mov pc, lr

LEAF_ENTRY CLKDIV188
ldr r0, = vCAMDIVN
ldrr1, [r0]
bicr1, r1, #(0x3<<8)
orrr1, 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
ldrr0, = vCAMDIVN
ldrr1, [r0]
orrr1, r1, #(0x1<<12); DVS_EN bit = 1(FCLK = HCLK)
strr1, [r0]
movpc, lr

LEAF_ENTRY DVS_OFF
ldrr0, = vCAMDIVN
ldrr1, [r0]
bicr1, r1, #(0x1<<12); DVS_EN bit = 0(FCLK = MPLL clock)
strr1, [r0]
movpc, 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 GPJ7GPJ6 GPJ5GPJ4 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 11 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值