1. 具体实现步骤①在./common文件夹下新建cmd_suspend.c,并在此文件中添加如下内容+#include
+#include
+#include
+#include
+#include
+
+extern void s3c2440_cpu_suspend(void); //调用外部函数,调用下面用汇编写的函数
+
+static void delay(volatile int d)
+{
+ while(d--);
+}
+
+int do_suspend (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{+//查询2440芯片手册第七章就可以得出2440的工作模式设置:现在我们主要设置休眠模式,根据数据手册设置相关寄存器即可+ /* 休眠: */
+
+ /* 1. 配置GPIO: 比如想维持LED亮或灭, 用于唤醒CPU的引脚要设为中断功能 */
+ /* 对于NAND启动: 要设置EINT23,22,21为输入引脚 */ S3c24x0.h文件中有引脚的宏定义
+ rGPGCON &= ~((3<<30) | (3<<28) | (3<<26));
+
+ /* JZ2440只有S2/S3/S4可用作唤醒源,设置它们对应的GPIO用于中断模式 */
+ rGPFCON &= ~((3<<0) | (3<<4));
+ rGPFCON |= ((2<<0) | (2<<4));
+
+ rGPGCON &= ~(3<<6);
+ rGPGCON |= (2<<6);
+
+ /* 2. 设置INTMSK屏蔽所有中断: 在sleep模式下,这些引脚只是用于唤醒系统,当CPU正常运行时可以重新设置INTMSK让这些引脚用于中断功能 */
+ rINTMSK = ~0;
+
+ /* 3. 配置唤醒源 */
+ rEXTINT0 |= (6<<0) | (6<<8); /* EINT0,2双边沿触发 */
+ rEXTINT1 |= (6<<12); /* EINT11双边沿触发 */
+
+ /* 4. 设置MISCCR[13:12]=11b, 使得USB模块进入休眠 */
+ rMISCCR |= (3<<12);
+
+ /* 5. 在GSTATUS[4:3]保存某值, 它们可以在系统被唤醒时使用 */
+ //rGSTATUS3 = ; /* 唤醒时首先执行的函数的地址 */
+ //rGSTATUS4 = ; /* */
+
+ /* 6. 设置 MISCCR[1:0] 使能数据总线的上拉电阻 */
+ rMISCCR &= ~(3);
+
+ /* 7. 清除 LCDCON1.ENVID 以停止LCD */
+ rLCDCON1 &= ~1;
+
+ /* 8~12使用汇编来实现,参考内核源码:
+ * archarmmach-s3c2410sleep.S
+ */
+ //新建u-boot-1.1.6/cpu/arm920t/suspend.S文件+suspend.s文件内容如下:+#define S3C2440_REFRESH_SELF (1<<22)
+#define S3C2440_MISCCR_SDSLEEP (7<<17)
+#define S3C2440_CLKCON_POWER (1<<3)
+
+#define GSTATUS2 (0x560000B4)
+#define GSTATUS3 (0x560000B8)
+#define GSTATUS4 (0x560000BC)
+
+#define REFRESH (0x48000024)
+#define MISCCR (0x56000080)
+#define CLKCON (0x4C00000C)
+
+.globl s3c2440_cpu_suspend //全局函数
+ @@ prepare cpu to sleep
+s3c2440_cpu_suspend:
+ stmdb sp!, { r4-r12,lr }
+
+ /* GSTATUS3中存放唤醒时要执行的函数 */
+ ldr r0, =s3c2440_do_resume
+ ldr r1, =GSTATUS3
+ str r0, [r1]
+
+ ldr r1, =GSTATUS4
+ str sp, [r1]
+
+ ldr r4, =REFRESH
+ ldr r5, =MISCCR
+ ldr r6, =CLKCON
+ ldr r7, [ r4 ] @ get REFRESH
+ ldr r8, [ r5 ] @ get MISCCR
+ ldr r9, [ r6 ] @ get CLKCON
+
+ orr r7, r7, #S3C2440_REFRESH_SELF @ SDRAM sleep command
+ orr r8, r8, #S3C2440_MISCCR_SDSLEEP @ SDRAM power-down signals
+ orr r9, r9, #S3C2440_CLKCON_POWER @ power down command
+
+ teq pc, #0 @ first as a trial-run to load cache
+ bl s3c2440_do_sleep
+ teq r0, r0 @ now do it for real
+ b s3c2440_do_sleep @
+
+ @@ align next bit of code to cache line
+ .align 5
+s3c2440_do_sleep:
+ streq r7, [ r4 ] @ SDRAM sleep command
+ streq r8, [ r5 ] @ SDRAM power-down config
+ streq r9, [ r6 ] @ CPU sleep
+1: beq 1b
+ mov pc, r14
+
+s3c2440_do_resume:
+ /* 返回到do_suspend函数 */
+ ldr r1, =GSTATUS4
+ ldr sp, [r1]
+
+ ldmia sp!, { r4-r12,pc }
+ /* 8. 读这2个寄存器: rREFRESH and rCLKCON, 以便填充TLB
+ * 如果不使用MMU的话,这个目的可以忽略
+ */
+
+ /* 9. 设置 REFRESH[22]=1b,让SDRAM进入self-refresh mode */
+
+ /* 10. 等待SDRAM成功进入self-refresh mode */
+
+ /* 11.设置 MISCCR[19:17]=111b以保护SDRAM信号(SCLK0,SCLK1 and SCKE) */
+
+ /* 12. 设置CLKCON的SLEEP位让系统进入sleep mode */
+ printf("suspend ...");
+ delay(1000000);
+ s3c2440_cpu_suspend(); /* 执行到这里就不会返回,直到CPU被唤醒 */
+ ++++ //修改cpuarm920tstart.s文件,唤醒的时候类似于nREST pin,所以修改start.s文件,实现唤醒功能
+ /* 恢复运行: 重新初始化硬件 */
+ serial_init();
+ printf("wake up
");
+
+
+ return 0;
+}
+
+
+U_BOOT_CMD(
+ suspend, 1, 0, do_suspend, //1表示只要一个参数
+ "suspend - suspend the board
",
+ " - suspend the board"
+);②在./common/Makefile中添加:COBJS-y += cmd_led.oSOBJS = suspend.o③在Linux环境下,重新编译u-boot,得到u-boot.bin,并下载到自己的开发板中测试,输入help就会发现led命令