U-boot添加电源管理命令

2019-07-13 23:00发布

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命令