嵌入式系统中降低CPU功耗的实现方法转让专利

申请号 : CN200810201121.7

文献号 : CN101727171B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 彭世峰

申请人 : 上海摩波彼克半导体有限公司

摘要 :

本发明涉及一种嵌入式系统中降低CPU功耗的实现方法,将CPU由运行态进入停止态包括关闭CPU中断、将CPU现场恢复运行代码拷贝到存储模块、将CPU现场运行状态信息保存到存储模块并进行调整、关闭CPU进入停止状态,将CPU由停止态进入运行态包括对CPU重新供电和提供稳定时钟信号、CPU执行现场恢复运行代码从存储模块中读取CPU现场运行状态信息、将复位运行代码拷贝到存储模块、打开CPU中断。采用该种嵌入式系统中降低CPU功耗的实现方法,通过片上系统进行特别设计加上系统软件的配合,实现了在系统忙时打开CPU,系统空闲时彻底关闭CPU的效果,使得系统的平均功耗进一步降低,而且实现过程简单快捷,工作性能稳定可靠,适用范围较为广泛。

权利要求 :

1.一种嵌入式系统中降低CPU功耗的实现方法,所述的嵌入式系统包括片上系统、CPU、存储模块和电源模块,其特征在于,所述的方法包括将CPU由运行态进入停止态的处理操作和将CPU由停止态进入运行态的处理操作,所述的将CPU由运行态进入停止态的处理操作包括以下步骤:(A1)片上系统在系统没有程序需要执行的时候将CPU的中断关闭;

(A2)片上系统将CPU现场恢复运行代码拷贝到存储模块中的以CPU上电首先执行的地址为起始地址的存储区中;

(A3)片上系统将当前的CPU现场运行状态信息保存到存储模块中;

(A4)片上系统对存储模块中保存的CPU现场运行状态信息进行调整操作,具体为:将PC指针的值指向CPU所执行的指令的下一条指令;

(A5)片上系统驱动电源系统将CPU关闭进入停止状态;

所述的将CPU由停止态进入运行态的处理操作包括以下步骤:(B1)片上系统在系统中断到来的时候驱动电源系统对CPU重新提供电源;

(B2)片上系统对CPU重新提供稳定时钟信号;

(B3)CPU执行所述的CPU现场恢复运行代码,从存储模块中读取所述的CPU现场运行状态信息;

(B4)片上系统将复位运行代码拷贝到存储模块中的以CPU上电首先执行的地址为起始地址的存储区中;

(B5)片上系统将CPU的中断打开。

2.根据权利要求1所述的嵌入式系统中降低CPU功耗的实现方法,其特征在于,所述的将CPU的中断关闭,具体为:片上系统通过对CPU的状态寄存器的设置关闭CPU的中断;

所述的将CPU的中断打开,具体为:

片上系统通过对CPU的状态寄存器的设置打开CPU的中断。

3.根据权利要求1所述的嵌入式系统中降低CPU功耗的实现方法,其特征在于,所述的CPU上电首先执行的地址为0x00地址。

4.根据权利要求1所述的嵌入式系统中降低CPU功耗的实现方法,其特征在于,所述的CPU现场运行状态信息包括存储器管理单元的状态值、高速缓存的状态值和CPU中所有寄存器的状态值。

5.根据权利要求1所述的嵌入式系统中降低CPU功耗的实现方法,其特征在于,所述的将CPU关闭进入停止状态,具体为:片上系统通过配置硬件寄存器相应的状态值关闭CPU。

说明书 :

嵌入式系统中降低CPU功耗的实现方法

技术领域

[0001] 本发明涉及嵌入式系统领域,特别涉及嵌入式系统功耗控制技术领域,具体是指一种嵌入式系统中降低CPU功耗的实现方法。

背景技术

[0002] 嵌入式系统尤其是消费类电子系统对功耗有严格的要求,随着能源的日益紧张,以前不重视功耗的个人计算机系统现在也逐渐考虑功耗了。
[0003] 通常的嵌入式系统中一旦系统起来后CPU一直供电,在大多数系统中程序执行占比较小的时间,大多数时间系统处在空闲状态,而空闲状态下CPU仍然在运行,CPU的功耗占片上系统(SOC,System on Chip)上功耗比较大的部分,而片上系统一般就是在单个芯片上集成了CPU、UART,USB等多个模块。为了降低SOC的功耗,在现有技术中,普遍的实现方法是当系统空闲时把CPU频率降低或者停止CPU的执行,这两种方式虽然可以大大降低系统功耗,但前两种方式系统仍然在给CPU供电,CPU虽然不执行指令了,但本身还是要消耗部分电流的。
[0004] 一般来说,嵌入式系统都是由中断驱动的,当外部中断发生时SOC需要把中断信号送给CPU,在早期的设计方案中,系统启动起来后CPU一直处于运行态,这样一旦中断到来,SOC马上就把中断送给CPU,而CPU很快响应中断(假设中断没有被CPU自己锁定),但这种方案的弊端是CPU一直处在运行态,系统平均功耗很大(这里的平均功耗是在一段较长的时间内系统平均耗电量);后来人们对这种方案做了改进,当系统有一段时间空闲时,让CPU进入休眠态,这样当中断到来时SOC只需要给CPU提供稳定的时钟(Clock),CPU就被唤醒了,然后CPU响应中断,这种方案因为CPU不是处在运行态就处在休眠态,永远到不了停止态,虽然相对前一种方法功耗降低了很多,但CPU功耗还是较高,同时为了能够适应当今对嵌入式设备电源功耗管理的更高要求,也有必要对CPU功耗进一步降低。

发明内容

[0005] 本发明的目的是克服了上述现有技术中的缺点,提供一种能够有效降低嵌入式系统的平均功耗、过程简单快捷、工作性能稳定可靠、适用范围较为广泛的嵌入式系统中降低CPU功耗的实现方法。
[0006] 为了实现上述的目的,本发明的嵌入式系统中降低CPU功耗的实现方法如下:
[0007] 该嵌入式系统中降低CPU功耗的实现方法,所述的嵌入式系统包括片上系统、CPU、存储模块(Memory)和电源模块,其主要特点是,所述的方法包括将CPU由运行态进入停止态的处理操作和将CPU由停止态进入运行态的处理操作,所述的将CPU由运行态进入停止态的处理操作包括以下步骤:
[0008] (A1)片上系统在系统没有程序需要执行的时候将CPU的中断关闭;
[0009] (A2)片上系统将CPU现场恢复运行代码拷贝到存储模块中的以CPU上电首先执行的地址为起始地址的存储区中;
[0010] (A3)片上系统将当前的CPU现场运行状态信息保存到存储模块中;
[0011] (A4)片上系统对存储模块中保存的CPU现场运行状态信息进行调整操作;
[0012] (A5)片上系统驱动电源系统将CPU关闭进入停止状态;
[0013] 所述的将CPU由停止态进入运行态的处理操作包括以下步骤:
[0014] (B1)片上系统在系统中断到来的时候驱动电源系统对CPU重新提供电源;
[0015] (B2)片上系统对CPU重新提供稳定时钟信号;
[0016] (B3)CPU执行所述的CPU现场恢复运行代码,从存储模块中读取所述的CPU现场运行状态信息;
[0017] (B4)片上系统将复位运行代码拷贝到存储模块中的以CPU上电首先执行的地址为起始地址的存储区中;
[0018] (B5)片上系统将CPU的中断打开。
[0019] 该嵌入式系统中降低CPU功耗的实现方法中的将CPU的中断关闭,具体为:
[0020] 片上系统通过对CPU的状态寄存器的设置关闭CPU的中断。
[0021] 该嵌入式系统中降低CPU功耗的实现方法中的将CPU的中断打开,具体为:
[0022] 片上系统通过对CPU的状态寄存器的设置打开CPU的中断。
[0023] 该嵌入式系统中降低CPU功耗的实现方法中的CPU上电首先执行的地址为0x00地址。
[0024] 该嵌入式系统中降低CPU功耗的实现方法中的CPU现场运行状态信息包括存储器管理单元(MMU,Memory Management Unit)的状态值、高速缓存(Cache)的状态值和CPU中所有寄存器的状态值。
[0025] 该嵌入式系统中降低CPU功耗的实现方法中的对存储模块中保存的CPU现场运行状态信息进行调整操作,具体为:
[0026] 将PC指针的值指向CPU所执行的指令的下一条指令。
[0027] 该嵌入式系统中降低CPU功耗的实现方法中的将CPU关闭进入停止状态,具体为:
[0028] 片上系统通过配置硬件寄存器相应的状态值关闭CPU。
[0029] 采用了该发明的嵌入式系统中降低CPU功耗的实现方法,由于通过对片上系统进行特别设计加上系统软件的配合,当系统空闲时(即没有程序需要执行)通过硬件配置把CPU推入停止态,中断来时如果CPU处于运行态,SOC直接把中断送给CPU,如果中断来时CPU处在停止态,SOC首先给CPU供电,然后给CPU提供时钟信号,从而CPU就被唤醒了,紧接着系统软件对CPU做相应配置和场景恢复,然后CPU响应中断,从而不再需要CPU始终处于运行态,程序变成了一个单独的主体,当需要运行的时候程序把自己拿到CPU上去执行,执行完后关闭CPU,实现了在系统忙时打开CPU,系统空闲时彻底关闭CPU的效果,使得系统的平均功耗进一步降低,而且实现过程简单快捷,工作性能稳定可靠,适用范围较为广泛。

附图说明

[0030] 图1为本发明的嵌入式系统中的片上系统结构示意图。
[0031] 图2为本发明的嵌入式系统中降低CPU功耗的实现方法的将CPU由运行态进入停止态的处理操作流程图。
[0032] 图3为本发明的嵌入式系统中降低CPU功耗的实现方法的将CPU由停止态进入运行态的处理操作流程图。
[0033] 图4为本发明的嵌入式系统中降低CPU功耗的实现方法中CPU状态迁移示意图。

具体实施方式

[0034] 为了能够更清楚地理解本发明的技术内容,特举以下实施例详细说明。
[0035] 首先定义CPU在系统运行中处于的三种状态,运行态、停止态、休眠态。
[0036] (1)运行态——表示CPU目前有供电,能正常的执行指令,当然这时候肯定有稳定的Clock提供给CPU,相对其他两种状态这时候CPU功耗最大。
[0037] (2)停止态——CPU完全被断电了,既没有Clock又没有供电,相对其他两种状态这时候CPU功耗最小,这时候CPU断电前的场景全部丢失,重新启动后需要对以前的场景进行恢复。
[0038] (3)休眠态——SOC还在给CPU供电,但没有给CPU送Clock。这种状态下的CPU功耗比运行态下的CPU功耗小,比停止态下CPU功耗大,但这时候CPU停止Clock前的场景继续保存,一旦有Clock,CPU在原来的场景上继续执行。
[0039] 请参阅图1至图4所示,该嵌入式系统中降低CPU功耗的实现方法,所述的嵌入式系统包括片上系统、CPU、存储模块和电源模块,其中,所述的方法包括将CPU由运行态进入停止态的处理操作和将CPU由停止态进入运行态的处理操作,所述的将CPU由运行态进入停止态的处理操作包括以下步骤:
[0040] (A1)片上系统在系统没有程序需要执行的时候将CPU的中断关闭,具体为:
[0041] 片上系统通过对CPU的状态寄存器的设置关闭CPU的中断;
[0042] 也可以采用其它任何与CPU所匹配的相应方式;
[0043] (A2)片上系统将CPU现场恢复运行代码拷贝到存储模块中的以CPU上电首先执行的地址为起始地址的存储区中;该CPU上电首先执行的地址可以为0x00地址,也可以根据所具体使用的CPU芯片所规定的其它任何地址;
[0044] (A3)片上系统将当前的CPU现场运行状态信息保存到存储模块中;该CPU现场运行状态信息包括存储器管理单元的状态值、高速缓存的状态值和CPU中所有寄存器的状态值,还可以包括其它任何需要存储的信息;
[0045] (A4)片上系统对存储模块中保存的CPU现场运行状态信息进行调整操作,具体为:
[0046] 将PC指针的值指向CPU所执行的指令的下一条指令;
[0047] (A5)片上系统驱动电源系统将CPU关闭进入停止状态,具体为:
[0048] 片上系统通过配置硬件寄存器相应的状态值关闭CPU;
[0049] 也可以采用其它任何与CPU所匹配的相应方式;
[0050] 所述的将CPU由停止态进入运行态的处理操作包括以下步骤:
[0051] (B1)片上系统在系统中断到来的时候驱动电源系统对CPU重新提供电源;
[0052] (B2)片上系统对CPU重新提供稳定时钟信号;
[0053] (B3)CPU执行所述的CPU现场恢复运行代码,从存储模块中读取所述的CPU现场运行状态信息;
[0054] (B4)片上系统将复位运行代码拷贝到存储模块中的以CPU上电首先执行的地址为起始地址的存储区中;
[0055] (B5)片上系统将CPU的中断打开,具体为:
[0056] 片上系统通过对CPU的状态寄存器的设置打开CPU的中断。
[0057] 也可以采用其它任何与CPU所匹配的相应方式;
[0058] 在实际使用当中,本发明的方法的基本思想是当系统空闲时,即没有程序需要执行时,通过一些硬件配置把CPU推入停止态,中断来时如果CPU处于运行态(CPU在运行的过程中也有可能来中断),SOC直接把中断送给CPU,如果中断来时CPU处在停止态,SOC首先给CPU供电,然后给CPU提供Clock,这样CPU就被唤醒了,紧接着系统软件对CPU做相应配置和场景恢复,然后CPU响应中断,因为CPU断电后再起来一般中断是被关闭的,MMU、Cache也是被关闭的,一旦断电后再唤醒需要软件做些配置,恢复上次进入停止态之前的CPU现场(例如中断是否关闭,MMU是否启动,Cache是否启动,各个寄存器的值等)。这样,在本设计中程序不再需要CPU始终处于运行态,程序变成了一个单独的主体,当需要运行的时候程序把自己拿到CPU上去执行,执行完后关闭CPU。在进一步的设计中CPU就可以变成一个共享资源,多个应用程序可以申请CPU,一旦申请到CPU就把自己拿到CPU上去执行,执行完后交出CPU的控制权,以便其他应用程序可以使用CPU。当全部应用程序都不使用CPU时通过系统配置关闭CPU。
[0059] 要实现该方案,需要SOC和系统软件的双重支持。
[0060] 1、SOC硬件的支持——基于以上基本思想,本发明首先需要SOC做相应的以下支持:
[0061] (1)SOC要能够提供关闭CPU的机制,注意在这里只是关闭CPU,关闭CPU不能影响其他外围模块的状态,例如Memory,因为程序是依赖于Memory存在的,如果关闭CPU同时也关闭了Memory,如果用断电易失性Memory,下次CPU起来后程序状态将不可恢复,CPU断电后其他模块如DMA、USB、RF、UART等的状态还要继续保持。
[0062] (2)在中断到来时SOC需要做判断,如果CPU处在停止态,那么首先需要给CPU提供电源,然后给CPU提供稳定的Clock,让CPU进入运行态。上面只是提供了基本的设计思想,并没有涉及具体的硬件实现,具体实现因SOC不同可以不同,但需要实现本专利的低功耗方案,必须提供上述两项支持。
[0063] 2、系统软件的支持——基于以上基本思想和SOC硬件的支持,本发明给出了系统软件的设计流程。这里假设CPU每次上电后从0x00地址开始执行。当所有程序都不需要执行,也就是系统进入空闲状态了,这时候我们就可以开始让CPU进入停止模式,这里给出让CPU进入停止模式和唤醒CPU要做的工作。
[0064] 首先是由运行态进入停止态:
[0065] (1)关闭中断,关闭中断的方法因CPU的不同而不同,在ARM芯片上可以通过把状态寄存器的第6和第7位置为1而关闭中断,而对于其它类型的CPU可以参考相关CPU的指令手册以进行相应的配置,这些都属于本领域技术人员的公知常识。
[0066] (2)把现场恢复的代码拷贝到0x00为起始地址的内存中,因为每次上电都是从0x00地址开始执行,系统复位(reset)后应该执行复位代码(reset code),当系统进入停止态再唤醒需要执行的是现场恢复code,而不是reset code,第一次系统上电属于reset,
0x00地址上装的是reset code,进入停止状态前应该把0x00地址上的code替换成现场恢复code。
[0067] (3)保存当前CPU现场到Memory(包括MMU、Cache、所有寄存器的状态)。
[0068] (4)调整Memory中保存的CPU现场的某些值,例如pc指针的值,让pc指针的值指向下一条指令,这样现场恢复后CPU就跳过关闭CPU的指令,从关闭CPU指令的下一条指令开始执行。
[0069] (5)关闭CPU让CPU进入停止状态,通过写特定的硬件寄存器而关闭CPU,具体的关闭方法因硬件实现的不同而不同,在实现上需要参考相关的硬件手册,这些都属于本领域技术人员的公知常识。
[0070] 至此CPU已经进入停止态,系统处在低功耗模式下,如果有中断来CPU会被唤醒。
[0071] 接下来是由停止态进入运行态,当中断来时CPU被SOC唤醒,从0x00地址开始执行现场恢复代码,以下是现场恢复的工作过程:
[0072] (1)从Memory中恢复CPU现场。现场恢复后CPU开始执行让CPU进入停止状态的下一条指令。
[0073] (2)把reset code copy到0x00为起始地址的Memory中。
[0074] (3)打开中断,这个因CPU的不同而不同,ARM上把状态寄存器的6,7两位清零便可打开中断,其他CPU请参考相关的指令文档。
[0075] 至此CPU完全恢复了进入停止状态前的场景,开始响应中断。
[0076] 下面给出一个CPU是ARM926EJS芯片的SOC的软件设计的实际例子。
[0077] 假设:0x01000000是一个32位寄存器地址,把这个寄存器写成0x0000000A,SOC就会把ARM926EJS芯片关掉,ARM926EJS芯片进入停止状态前的场景保存在0x00010000为起始地址,长度为32个32bit的Memory中,原始的reset code保存在0x00020000为起始地址,长度为32个32bit的Memory中,原始的wakeup code保存在0x00300000为起始地址长度为32个32bit的Memory中,断电后ARM926EJS芯片从0x00000000地址开始执行,在这里我们用arm汇编实现ARM926EJS芯片进入停止状态的场景保存和ARM926EJS芯片被唤醒后的场景恢复工作。
[0078] 将ARM926EJS芯片进入停止态:
[0079] (1)锁定中断,在此过程中不能响应中断。
[0080] (2)保存r4、r5、r6、r6、r7、r8、r9、r10、r11、r12、lr到当前栈。保存svc模式的cpsr到当前栈。
[0081] (3)拷贝现场恢复代码(wakeupcode)到0x00地址。
[0082] (4)R0赋值为0x00010000+256,此处将以栈的形式从高往低增长保存数据。
[0083] (5)保存当前sp指针到R0所指的位置。
[0084] (6)切换到fiq模式,以递减栈的形式保存fiq模式的r8、r9、r10、r11、r12、r13、lr、Spsr到r0所指的Memory。
[0085] (7)切换到irp模式以递减栈的形式保存irp模式的r13、r14、spsr、到r0所指的Memory。
[0086] (8)切换到undefine模式,以递减栈的形式保存undefine模式的r13、r14、spsr到r0所指的Memory。
[0087] (9)切换到abort模式,以递减栈的形式保存abort模式的r13、lr、spsr到r0所指的Memory中。
[0088] (10)切换到user模式,以递减栈的形式保存user模式的r13、lr、spsr到r0所指的Memory中。
[0089] (11)切换到svc模式,以递减栈的形式保存协处理器cp15的c1、c2、c3、c5、c6、c7、c13到r0所指的Memory中。
[0090] (12)RestoreCpuContext标号的值以递减栈的形式保存在r0所指的Memory中,把r0的值保存在0x00010000处,下次CPU被唤醒后wake up code将取出r0,并以r0作为栈地址恢复CPU的场景。RestoreCpuContext是程序中的一个标号,具体见以下源代码。
[0091] (13)通过配置外部寄存器让CPU进入停止态(stop mode)。
[0092] 实现以上步骤的具体的源代码如下:
[0093] .globl PushCpuToStopMode
[0094] PushCpuToStopMode
[0095]   ;lock interrupt
[0096] MRS r0,CPSR
[0097] ORR r0,r0,#0x000000C0
[0098] MSR CPSR_cxsf,r0
[0099] ;save CPU context to current stack,current mode must be svc mode[0100] STMDB sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}[0101] ;store svc mode cpsr
[0102] MRS r1,cpsr
[0103] STMDB sp!,{r1}
[0104] ;copy wake up code to 0x0000 address,
[0105] ;wakeup code size is 32words(one word is 32 bit);
[0106] ;original wakeup code is stored from address 0x00030000[0107] LDR r9,=0x00030000
[0108] LDR r8, =0x0
[0109] LDMIA r9!,{r0-r7}
[0110] STMIA r8!,{r0-r7}
[0111] LDMIA r9!,{r0-r7}
[0112] STMIA r8!,{r0-r7}
[0113] LDMIA r9!,{r0-r7}
[0114] STMIA r8!,{r0-r7}
[0115] LDMIA r9!,{r0-r7}
[0116] STMIA r8!,{r0-r7}
[0117] ;before push CPU to stop mode,CPU context
[0118] ;is stored to Memory 0x00010000,length is 256bytes;
[0119] LDR r0,=0x00010000
[0120] ADD r0,r0,#256
[0121] ;store svc sp
[0122] STMDB r0!,{sp}
[0123] ;change to fiq mode
[0124] MRS r1,CPSR
[0125] BIC r1,r1,#0x1F
[0126] ORR r2,r1,#0x11
[0127] MSR CPSR_cxsf,r2
[0128] ;store fiq mode r8-r14
[0129] STMDB r0!,{r8,r9,r10,r11,r12,r13,lr}
[0130] ;store fiq mode spsr
[0131] MRS r1,spsr
[0132] STMDB r0!,{r1}
[0133] ;change to irq mode
[0134] MRS r1,CPSR
[0135] BIC r1,r1,#0x1F
[0136] ORR r2,r1,#0x12
[0137] MSR CPSR_cxsf,r2
[0138] ;store irq mode r13,r14
[0139] STMDB r0!,{r13,lr}
[0140] ;store irq mode spsr
[0141] MRS r1,spsr
[0142] STMDB r0!,{r1}
[0143] ;change to undfine mode
[0144] MRS r1,CPSR
[0145] BIC r1,r1,#0x1F
[0146] ORR r2,r1,#0x1B
[0147] MSR CPSR_cxsf,r2
[0148] ;store undfine mode r13,r14
[0149] STMDB r0!,{r13,lr}
[0150] ;store undfine mode spsr
[0151] MRS r1,spsr
[0152] STMDB r0!,{r1}
[0153] ;change toabort mode
[0154] MRS r1,CPSR
[0155] BIC r1,r1,#0x1F
[0156] ORR r2,r1,#0x17
[0157] MSR CPSR_cxsf,r2
[0158] ;store abort mode r13,r14
[0159] STMDB r0!,{r13,lr}
[0160] ;store abort modespsr
[0161] MRS r1,spsr
[0162] STMDB r0!,{r1}
[0163] ;change to user mode
[0164] MRS r1,CPSR
[0165] BIC r1,r1,#0x1F
[0166] ORR r2,r1,#0x10
[0167] MSR CPSR_cxsf,r2
[0168] ;store user mode r13,r14
[0169] STMDB r0!,{r13,lr}
[0170] ;change to svc mode
[0171] MRS r1,CPSR
[0172] BIC r1,r1,#0x1F
[0173] ORR r2,r1,#0x13
[0174] MSR CPSR_cxsf,r2
[0175] ;save cp15 register.c1,c2,c3,c5,c6,c7,c13
[0176] MRC p15,0,r1,c1,c0,0
[0177] MRC p15,0,r2,c2,c0,0
[0178] MRC p15,0,r3,c3,c0,0
[0179] MRC p15,0,r4,c5,c0,0
[0180] MRC p15,0,r5,c6,c0,0
[0181] MRC p15,0,r6,c7,c0,0
[0182] MRC p15,0,r7,c13,c0,0
[0183] STMDB r0!,{r1,r2,r3,r4,r5,r6,r7}
[0184] LDR r1,=RestoreCpuContext
[0185] STMDB r0!,{r1}
[0186] ;save r0 value to address 0x00010000;
[0187] LDR r1,=0x00010000;
[0188] STR r0,[r1];
[0189] ;we have already saved all CPU context
[0190] ;follow we could push ARM926EJS to stop state
[0191] LDR r1,=0x0000000A
[0192] LDR r0,=0x01000000
[0193] STR r1,[r0]
[0194] NOP
[0195] NOP
[0196] NOP
[0197] NOP
[0198] NOP
[0199] NOP
[0200] NOP
[0201] ;here ARM926EJS have been closed.
[0202] ;after next CPU next wake,wakepu code will jump to here.[0203] ;here ARM926EJS under SVC mode
[0204] RestoreCpuContext
[0205] LDR r1,=0x00010000
[0206] LDR r0,[r1]
[0207] LDMIA r0!,{r1};this is not used,only up stack.
[0208] ;restore cp15 register c1,c2,c3,c5,c6,c7,c13
[0209] LDMIA r0!,{r1,r2,r3,r4,r5,r6,r7};
[0210] MCR p15,0,r1,c1,c0,0
[0211] MCR p15,0,r2,c2,c0,0
[0212] MCR p15,0,r3,c3,c0,0
[0213] MCR p15,0,r4,c5,c0,0
[0214] MCR p15,0,r5,c6,c0,0
[0215] MCR p15,0,r6,c7,c0,0
[0216] MCR p15,0,r7,c13,c0,0
[0217] ;change to user mode
[0218] MRS r1,CPSR
[0219] BIC r1,r1,#0x1F
[0220] ORR r2,r1,#0x10
[0221] MSR CPSR_cxsf,r2
[0222] ;restore user mode r13,r14
[0223] LDMIA r0!,{r13,lr};
[0224] ;change to abort mode
[0225] MRS r1,CPSR
[0226] BIC r1,r1,#0x1F
[0227] ORR r2,r1,#0x17
[0228] MSR CPSR_cxsf,r2
[0229] ;restore abort mode spsr
[0230] LDMIA r0!,{r3};
[0231] MSR SPSR,r3
[0232] ;restore abort mode r13,r14
[0233] LDMIA r0!,{r3,lr};
[0234] ;change to undfine mode
[0235] MRS r1,CPSR
[0236] BIC r1,r1,#0x1F
[0237] ORR r2,r1,#0x1B
[0238] MSR CPSR_cxsf,r2
[0239] ;restore undefine mode spsr
[0240] LDMIA r0!,{r3};
[0241] MSR SPSR,r3
[0242] ;restore undefine mode r13,r14
[0243] LDMIA r0!,{r3,lr};
[0244] ;change to irq mode
[0245] MRS r1,CPSR
[0246] BIC r1,r1,#0x1F
[0247] ORR r2,r1,#0x12
[0248] MSR CPSR_cxsf,r2
[0249] ;restore irq mode spsr
[0250] LDMIA r0!,{r3};
[0251] MSR SPSR,r3
[0252] ;restore irq moder13,r14
[0253] LDMIA r0!,{r3,lr};
[0254] ;change to fiq mode
[0255] MRS r1,CPSR
[0256] BIC r1,r1,#0x1F
[0257] ORR r2,r1,#0x11
[0258] MSR CPSR_cxsf,r2
[0259] ;restore fiq mode spsr
[0260] LDMIA r0!,{r3};
[0261] MSR SPSR,r3
[0262] ;restore fiq mode r8-r14
[0263] LDMIA r0!,{r8,r9,r10,r11,r12,r13,lr}
[0264] ;change to svc mode
[0265] MRS r1,CPSR
[0266] BIC r1,r1,#0x1F
[0267] ORR r2,r1,#0x13
[0268] MSR CPSR_cxsf,r2
[0269] ;resotre svc mode sp
[0270] LDMIA r0!,{sp}
[0271] ;copy reset code to 0x0000 address,
[0272] ;reset code size is 32words(one word is 32 bit);
[0273] ;original reset code is stored from address 0x00020000[0274] LDR r9,=0x00020000
[0275] LDR r8,=0x0
[0276] LDMIA r9!,{r0-r7}
[0277] STMIA r8!,{r0-r7}
[0278] LDMIA r9!,{r0-r7}
[0279] STMIA r8!,{r0-r7}
[0280] LDMIA r9!,{r0-r7}
[0281] STMIA r8!,{r0-r7}
[0282] LDMIA r9!,{r0-r7}
[0283] STMIA r8!,{r0-r7}
[0284] LDMIA sp!,{r3}
[0285] BIC r3,r3,#0x000000C0;free arm926ejs interrupt[0286] MSR SPSR,r3;restore svc mode spsr
[0287] LDMIA sp !,{r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}^;this insturction
[0288] retore all svc context,include cpsr
[0289] ;from this point code start response interrupt
[0290] 将ARM926EJS芯片进入运行态:
[0291] (1)取出0x00010000处保存的值到r0。
[0292] (2)以递增栈的形式从r0所指的Memory中取出一个word值,然后跳转到此地址(这个地址就是进入Stop mode前保存的RestoreCpuContext的值)。
[0293] (3)以递增栈的形式从r0所指的Memory中取值到r1、r2、r3、r4、r5、r6、r7用r1~r7的值恢复协处理器cp15的c1、c2、c3、c5、c6、c7、c13。
[0294] (4)切换到user模式,从r0所指的栈中以递增栈的形式恢复r13、lr。
[0295] (5)切换到abort模式,从r0所指的栈中以递增的形式恢复spsr、r13、lr。
[0296] (6)切换到undefine模式,从r0所指的栈中以递增栈的形式恢复spsr、r13、lr。
[0297] (7)切换到irq模式,从r0所指的栈中以递增栈的形式恢复spsr、r13、lr。
[0298] (8)切换到fiq模式,从r0所指的栈中以递增栈的形式恢复spsr、r8、r9、r10、r11、r12、r13、lr。
[0299] (9)切换到svc模式,从r0所指的栈中取出svc模式的sp指针值并赋给sp指针。
[0300] (10)恢复0x00地址处的复位代码(reset code),即把reset code copy到0x00地址的内存中。
[0301] (11)从sp所指的栈中取出svc模式进入停止模式前的cpsr,并开中断,把cpsr的值赋给spsr。
[0302] (12)以sp为栈指针,以递增栈的形式恢复r4、r5、r6、r7、r8、r9、r10、r11、r12、pc、cpsr。
[0303] 实现以上步骤的具体的源代码如下:
[0304] .globl WakeUpCpu
[0305] WakeUpCpu
[0306] LDR r1,=0x00010000
[0307] LDR r0,[r1]
[0308] LDMIA r0!,{r1};load RestoreCpuContext value to R1;
[0309] BX r1;jump to r1;
[0310] 采用了上述的嵌入式系统中降低CPU功耗的实现方法,由于通过对片上系统进行特别设计加上系统软件的配合,当系统空闲时(即没有程序需要执行)通过硬件配置把CPU推入停止态,中断来时如果CPU处于运行态,SOC直接把中断送给CPU,如果中断来时CPU处在停止态,SOC首先给CPU供电,然后给CPU提供时钟信号,从而CPU就被唤醒了,紧接着系统软件对CPU做相应配置和场景恢复,然后CPU响应中断,从而不再需要CPU始终处于运行态,程序变成了一个单独的主体,当需要运行的时候程序把自己拿到CPU上去执行,执行完后关闭CPU,实现了在系统忙时打开CPU,系统空闲时彻底关闭CPU的效果,使得系统的平均功耗进一步降低,而且实现过程简单快捷,工作性能稳定可靠,适用范围较为广泛。
[0311] 在此说明书中,本发明已参照其特定的实施例作了描述。但是,很显然仍可以作出各种修改和变换而不背离本发明的精神和范围。因此,说明书和附图应被认为是说明性的而非限制性的。