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

2019-07-13 23:02发布

内核: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)
[] (unwind_backtrace+0x0/0xf8) from [] (warn_slowpath_common+0x48/0x60)
[] (warn_slowpath_common+0x48/0x60) from [] (warn_slowpath_fmt+0x30/0x40)
[] (warn_slowpath_fmt+0x30/0x40) from [] (dev_watchdog+0x260/0x280)
[] (dev_watchdog+0x260/0x280) from [] (run_timer_softirq+0x10c/0x244)
[] (run_timer_softirq+0x10c/0x244) from [] (__do_softirq+0x88/0x148)
[] (__do_softirq+0x88/0x148) from [] (irq_exit+0x48/0x54)
[] (irq_exit+0x48/0x54) from [] (handle_IRQ+0x34/0x84)
[] (handle_IRQ+0x34/0x84) from [] (__irq_svc+0x24/0x98)
[] (__irq_svc+0x24/0x98) from [] (default_idle+0x28/0x44)
[] (default_idle+0x28/0x44) from [] (cpu_idle+0x94/0xbc)
[] (cpu_idle+0x94/0xbc) from [] (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)
[] (unwind_backtrace+0x0/0xf8) from [] (warn_slowpath_common+0x48/0x60)
[] (warn_slowpath_common+0x48/0x60) from [] (warn_slowpath_null+0x1c/0x24)
[] (warn_slowpath_null+0x1c/0x24) from [] (__mutex_lock_slowpath+0x20c/0x21c)
[] (__mutex_lock_slowpath+0x20c/0x21c) from [] (mutex_lock+0xc/0x24)
[] (mutex_lock+0xc/0x24) from [] (dm9000_phy_write+0x20/0xf8)
[] (dm9000_phy_write+0x20/0xf8) from [] (dm9000_init_dm9000+0xa0/0x1c8)
[] (dm9000_init_dm9000+0xa0/0x1c8) from [] (dm9000_timeout+0x7c/0x104)
[] (dm9000_timeout+0x7c/0x104) from [] (dev_watchdog+0x228/0x280)
[] (dev_watchdog+0x228/0x280) from [] (run_timer_softirq+0x10c/0x244)
[] (run_timer_softirq+0x10c/0x244) from [] (__do_softirq+0x88/0x148)
[] (__do_softirq+0x88/0x148) from [] (irq_exit+0x48/0x54)
[] (irq_exit+0x48/0x54) from [] (handle_IRQ+0x34/0x84)
[] (handle_IRQ+0x34/0x84) from [] (__irq_svc+0x24/0x98)
[] (__irq_svc+0x24/0x98) from [] (default_idle+0x28/0x44)
[] (default_idle+0x28/0x44) from [] (cpu_idle+0x94/0xbc)
[] (cpu_idle+0x94/0xbc) from [] (start_kernel+0x258/0x2ec)
---[ end trace a27c0aae2dc12ada ]---
BUG: scheduling while atomic: swapper/0/0x00000100
Modules linked in: key(O)
这个问题我暂时还没解决方法,暂且用韦老师提供的DM9000驱动,替换下吧,错误是没有了。那个问题,还得等我慢慢看了代码找出原因,或许,哪天网上,也正好能看出点端倪。