mini2440电源管理 suspend实现遇到的一些问题

来源:互联网 发布:敏捷地产 知乎 编辑:程序博客网 时间:2024/05/01 04:18

内核:linux-3.4.99

bootloade:u-boot-2012-04-01

开发板:mini2440

参考:韦东山第三期视频,电源管理


边看视频边写代码边做实验,由于没有用韦老师视频中提供的现成的bootloade,image 等等,没想到一个suspend实现,把我折腾了很久,过程很曲折,但好在在各种调试中,我也学到了很多。


1.在开发板启动后 命令行键入“echo mem > /sys/power/state"没有反应?

键入之后,系统一点反应也没有 ,尝试"cat mem > /sys/power/state“后也为空。PM根本就没起来,难道PM没初始化,查看mach-smdk2440.c文件中的代码,原来我之前在学习移植linux内核代码的时候,没有PM的概念,就把PM相关的初始化代码给注释掉了(s3c_pm_init();)还原后,重新编译。cat查看就能看到支持mem suspend了。


2.使用“echo mem > /sys/power/state"进入suspend需注册唤醒源,在key驱动中的reques_irq之后,用irq_set_irq_wake函数注册,之后调用“echo mem > /sys/power/state",此时系统进入休眠。随之,问题3又来了。


3系统进入休眠后,由于我的开发板的uImage,filesystem 都是通过NFS挂载的,此时网络就中断了,明明视频上韦老师的网络还是连着的?

还是查看源码,韦老师的DM9000源码是自己重新改过的,我的dm9000用的是内核自带的源码。阅读后发现,内核自带的源码有suspend,resume函数:

static const struct dev_pm_ops dm9000_drv_pm_ops = {
.suspend = dm9000_drv_suspend,
.resume = dm9000_drv_resume,
};

当系统进入休眠后,dpm_suspended_list会调用dm9000的suspend函数,此时网络就进入了休眠,于是就断开了。当

//.pm = &dm9000_drv_pm_ops,

后,在使系统进入休眠,此时网络就不断了。问题应该就解决了吧,其实是噩梦的开始,接下来的问题,我花了两周才搞定。

4.“echo mem > /sys/power/state"后系统确实进入了休眠,但按下按键,系统重启了,这是怎么回事?

先插讲一句,当系统被唤醒时,会从u-boot开始运行,通过判断GSTATUS2寄存器的状态来区分是reset和sleep启动,需要在u-boot的start.S中添加相关的处理代码:

#if 1
ldr r0, =S3C_GSTATUS2
ldr r1,[r0]
tst r1,#(1<<1)
// bne wake_up
beq notpower


 wake_up:
        str r1, [r0]
ldr r0, =S3C_MISCCR
ldr r1,[r0]
bic r1,r1,#(7<<17)
str r1, [r0]

bl cpu_init_crit

mov r0,#1000
1:      subs r0,r0,#1
cmp r0,#0
bne 1b


#if 1
ldr r0,=S3C_GSTATUS3
ldr r1,[r0]
mov pc,r1 
#else
        ldr r1,=0x3001fd40
mov pc,r1
//0x3001fd40
#endif
 


#endif
notpower:

用了点灯,串口打印,各种方法,得出的结论是:从GSTATUS2可以看出是sleep模式启动,但GSTATUS3存的不是程序休眠前的PC地址,被清零了。可以确定的是系统休眠后,GSTAUS3保存的是PC地址:


之后线索就断了,后来偶尔在网上看到一篇文章,说是:进入睡眠后,GPIO唤醒总是导致系统重新启动,其实这是因为没有设置CPU的运行模式,而这运行模式是通过设置GPG13,GPG14,GPG15来进行的。想到之前我用自己写的简单的bootloade是可以唤醒系统的,u-boot就不行,难道GPG13,14,15在哪边被改掉了?

查看u-boot相关代码后,果真发现了问题,在smdk2440.c的board_early_init_f()函数中有:

writel(0xFF95FFBA, &gpio->gpgcon);
writel(0x0000FFFF, &gpio->gpgup);

显然是把那几个IO给配置错了,看了原理图,GPIOG在启动时也没用到啥,干脆把这两句注释掉,使其保持IO Input状态。试了下,系统能被唤醒了。


5.唤醒后,还有网卡还有问题,会出现:

WARNING: at net/sched/sch_generic.c:256 dev_watchdog+0x260/0x280()
NETDEV WATCHDOG: eth0 (dm9000): transmit queue 0 timed out
Modules linked in: key(O)
[<c001aad0>] (unwind_backtrace+0x0/0xf8) from [<c002556c>] (warn_slowpath_common+0x48/0x60)
[<c002556c>] (warn_slowpath_common+0x48/0x60) from [<c0025618>] (warn_slowpath_fmt+0x30/0x40)
[<c0025618>] (warn_slowpath_fmt+0x30/0x40) from [<c0301f4c>] (dev_watchdog+0x260/0x280)
[<c0301f4c>] (dev_watchdog+0x260/0x280) from [<c002fe14>] (run_timer_softirq+0x10c/0x244)
[<c002fe14>] (run_timer_softirq+0x10c/0x244) from [<c002aebc>] (__do_softirq+0x88/0x148)
[<c002aebc>] (__do_softirq+0x88/0x148) from [<c002b0e0>] (irq_exit+0x48/0x54)
[<c002b0e0>] (irq_exit+0x48/0x54) from [<c0016220>] (handle_IRQ+0x34/0x84)
[<c0016220>] (handle_IRQ+0x34/0x84) from [<c0014f24>] (__irq_svc+0x24/0x98)
[<c0014f24>] (__irq_svc+0x24/0x98) from [<c0016438>] (default_idle+0x28/0x44)
[<c0016438>] (default_idle+0x28/0x44) from [<c0016a0c>] (cpu_idle+0x94/0xbc)
[<c0016a0c>] (cpu_idle+0x94/0xbc) from [<c0524864>] (start_kernel+0x258/0x2ec)
---[ end trace a27c0aae2dc12ad9 ]---
------------[ cut here ]------------
WARNING: at kernel/mutex.c:198 __mutex_lock_slowpath+0x20c/0x21c()
Modules linked in: key(O)
[<c001aad0>] (unwind_backtrace+0x0/0xf8) from [<c002556c>] (warn_slowpath_common+0x48/0x60)
[<c002556c>] (warn_slowpath_common+0x48/0x60) from [<c00255a0>] (warn_slowpath_null+0x1c/0x24)
[<c00255a0>] (warn_slowpath_null+0x1c/0x24) from [<c03cab94>] (__mutex_lock_slowpath+0x20c/0x21c)
[<c03cab94>] (__mutex_lock_slowpath+0x20c/0x21c) from [<c03cabb0>] (mutex_lock+0xc/0x24)
[<c03cabb0>] (mutex_lock+0xc/0x24) from [<c01fbcb8>] (dm9000_phy_write+0x20/0xf8)
[<c01fbcb8>] (dm9000_phy_write+0x20/0xf8) from [<c01fbe30>] (dm9000_init_dm9000+0xa0/0x1c8)
[<c01fbe30>] (dm9000_init_dm9000+0xa0/0x1c8) from [<c01fbfd4>] (dm9000_timeout+0x7c/0x104)
[<c01fbfd4>] (dm9000_timeout+0x7c/0x104) from [<c0301f14>] (dev_watchdog+0x228/0x280)
[<c0301f14>] (dev_watchdog+0x228/0x280) from [<c002fe14>] (run_timer_softirq+0x10c/0x244)
[<c002fe14>] (run_timer_softirq+0x10c/0x244) from [<c002aebc>] (__do_softirq+0x88/0x148)
[<c002aebc>] (__do_softirq+0x88/0x148) from [<c002b0e0>] (irq_exit+0x48/0x54)
[<c002b0e0>] (irq_exit+0x48/0x54) from [<c0016220>] (handle_IRQ+0x34/0x84)
[<c0016220>] (handle_IRQ+0x34/0x84) from [<c0014f24>] (__irq_svc+0x24/0x98)
[<c0014f24>] (__irq_svc+0x24/0x98) from [<c0016438>] (default_idle+0x28/0x44)
[<c0016438>] (default_idle+0x28/0x44) from [<c0016a0c>] (cpu_idle+0x94/0xbc)
[<c0016a0c>] (cpu_idle+0x94/0xbc) from [<c0524864>] (start_kernel+0x258/0x2ec)
---[ end trace a27c0aae2dc12ada ]---
BUG: scheduling while atomic: swapper/0/0x00000100
Modules linked in: key(O)

这个问题我暂时还没解决方法,暂且用韦老师提供的DM9000驱动,替换下吧,错误是没有了。那个问题,还得等我慢慢看了代码找出原因,或许,哪天网上,也正好能看出点端倪。



0 0
原创粉丝点击