新手提问,关于4418开发板休眠疑惑

2019-03-26 12:22发布

本帖最后由 msmmbl 于 2017-9-30 12:48 编辑

起源:
我想DIY做一个触摸屏,显示天气、门禁摄像头,挂在家里的墙上。曾在网上征求已经,(相关帖子:https://www.v2ex.com/t/387944)最后打算自己DIY。作为一个网络工程师,略懂一些C、C++,平时工作用的都是java、php。于是买了一块friendlyarm nanopi2,和触摸屏(http://wiki.friendlyarm.com/wiki/index.php/NanoPi_2/zh),选择它是体积小、带wifi、带触摸屏、能运行安卓(后面写UI方便)。

改造:
因为是一个信息显示屏,我不希望他是常亮的,因此首先需要解决的是系统的休眠和唤醒,后面可以加一个人体检测模块,在有人靠近的时候自动唤醒。

写官方提供的Android 5.1.1固件到SD卡,开机,开始测试:
1. 按下板子上的power按键,屏幕熄灭,说明安卓系统正常休眠。
2. 过了一会儿,我去摸了下CPU芯片,还是热热的,说明CPU没有进入休眠状态。

接上串口线,输入
cat /sys/power/wake_lock
返回
taken_from_init_nanopi2_rc

说明有一个taken_from_init_nanopi2_rc的wake_lock,使得内核不能进入休眠。

查看官方github代码,https://github.com/friendlyarm/a ... d340835a56579913f92,在init_nanopi.rc脚本中,有这么一句话:

HACK, suspend is broken. remove me when it's fixed
write /sys/power/wake_lock taken_from_init_nanopi2_rc


嗯,看来官方发现不能休眠,于是加了一个锁,干脆就不让系统休眠。

由于看是2015年提交的代码,现在是2017年了,说不定现在官方已经解决了吧,一方面我给代码的作者发了封邮件,另一方面我询问的客服。
客服说:我们公司所有的板子,都无法正常休眠,具体是什么原因,我们不方便说。好吧……

不过我收到了代码作者的邮件回复,说明遇到了问题是:系统休眠后无法唤醒。

不管这样,我还是先试着能不能解决这个问题。先把这个锁解开
echo "taken_from_init_nanopi2_rc" > /sys/power/wake_unlock

这个时候,内核开始进入休眠过程,不过很快退出了,报了一个错误,当时忘了截图,大意是触摸屏休眠函数调用返回-1。
嗯,看了下源代码,休眠的时候,要往I2C中写入4个字节,然而驱动写I2C部分的代码似乎写的不对,只写了2个字节。于是改了下,重新编译内核,再次测试。

再次测试的结果是,在休眠到最后一部,有一个event1由让休眠退出了。查了一些,event1属于触摸屏设备。想着触摸屏的驱动问题后面再说,实在不行再网上再找一个,先不管了。于是在内核编译去掉了对触摸屏的支持,重新编译后,再次测试。

这次似乎可以了。
  1. PM: suspend entry 2017-09-29 01:11:40.085606501 UTC
  2. [  108.620000] PM: Syncing filesystems ... done.
  3. [  108.632000] PM: Preparing system for mem sleep
  4. [  108.640000] Freezing user space processes ... (elapsed 0.040 seconds) done.
  5. [  108.688000] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
  6. [  108.696000] PM: Entering mem sleep
  7. [  108.700000] calling  rfkill2+ [url=home.php?mod=space&uid=775551]@[/url] 418, parent: mmc1:0001:2
  8. [  108.708000] call rfkill2+ returned 0 after 1 usecs
  9. [  108.712000] calling  rfkill1+ @ 418, parent: phy0
  10. [  108.716000] call rfkill1+ returned 0 after 0 usecs
  11. [  108.720000] calling  phy0+ @ 418, parent: mmc1:0001:2
  12. [  108.728000] call phy0+ returned 0 after 3 usecs
  13. ......
  14. [  110.504000] calling  uart-pl011.1+ @ 83, parent: none
  15. [  110.504000] calling  uart-pl011.0+ @ 55, parent: none
  16. [  110.504000] call uart-pl011.1+ returned 0 after 3 usecs
  17. [  110.552000] uart-pl011.0: ttyAMA0: Unable to drain transmitter
  18. [  110.552000] call uart-pl011.0+ returned 0 after 45918 usecs
  19. [  110.568000] call reg-dummy+ returned 0 after 0 usecs
  20. [  110.572000] calling  ram_console+ @ 418, parent: platform
  21. [  110.576000] call ram_console+ returned 0 after 0 usecs
  22. [  110.584000] PM: suspend of devices complete after 1236.879 msecs
  23. [  110.588000] PM: late suspend of devices complete after 0.300 msecs
  24. [  110.596000] PM: noirq suspend of devices complete after 0.463 msecs
  25. [  110.604000] Disabling non-boot CPUs ...
  26. [  110.612000] PM: Calling vic_suspend+0x0/0xd0
  27. [  110.612000] suspend_one_vic: suspending vic at f0002000
  28. [  110.612000] suspend_one_vic: suspending vic at f0003000
  29. [  110.612000] PM: Calling timekeeping_suspend+0x0/0x124
  30. [  110.612000] PM: Calling suspend_time_syscore_suspend+0x0/0x18
  31. [  110.612000] PM: Calling sched_clock_suspend+0x0/0x2c
  32. [  110.612000] PM: Calling fw_suspend+0x0/0x18
  33. [  110.612000] PM: Calling cpufreq_bp_suspend+0x0/0xa4
  34. [  110.612000] PM: Calling cpu_pm_suspend+0x0/0x18
  35. suspend_enter enter
  36. suspend machine...
复制代码

OK,指示灯熄灭,CPU过了一会也凉了,然后我就发现悲剧了,按下POWPE再也无法唤醒系统了,什么反应都没有。我成功复现了作者邮件中的问题。

---------------------------------------------------------------------------------------------
作为一个只当了一周的临时的、业余嵌入爱好工程师,现在完全没有了方向。但是也有几个疑问。
log的最后是suspend machine,看了下代码,这个log来自内核https://github.com/friendlyarm/l ... m/mach-s5p4418/pm.c,代码是
  1. static int __powerdown(unsigned long arg)
  2. {
  3.         void (*power_down)(ulong, ulong) =
  4.                         (void (*)(ulong, ulong))((ulong)do_suspend + 0x220);
  5.         int ret;

  6.         ret = suspend_machine();
  7.         if (0 == ret)
  8.                 pm_suspend_data_restore(NULL);
  9.         FLUSH_CACHE();
  10.         if (0 > ret)
  11.                 return ret;        /* wake up */

  12.         if(do_suspend == NULL) {
  13.                 lldebugout("Fail, inavalid suspend callee ");
  14.                 return 0;
  15.         }

  16.         suspend_cpu_enter();
  17.         
  18.         lldebugout("suspend machine... ");

  19.         END_FLUSH_CACHE();
  20.         power_down(IO_ADDRESS(PHY_BASEADDR_ALIVE), IO_ADDRESS(PHY_BASEADDR_DREX));

  21.         while (1);
  22. }
复制代码

我觉得代码最后是停在了END_FLUSH_CACHE();这一行。那如果系统唤醒了,代码是接着从哪里运行的?我猜有两种,搜了一下资料没有确认。

(1)系统唤醒了从下面的power_down(IO_ADDRESS(PHY_BASEADDR_ALIVE), IO_ADDRESS(PHY_BASEADDR_DREX));运行
从上面可以看到        void (*power_down)(ulong, ulong) =  (void (*)(ulong, ulong))((ulong)do_suspend + 0x220);
而do_suspend的定义我查了下      do_suspend = __arm_ioremap_exec(0xffff0000, 0x10000, 0);
0xffff0000我查了下三星的datasheet,是sram的起始地址,所以看上去它是在执行sram中的某个函数。难道是在uboot中的某个函数?
我猜是https://github.com/friendlyarm/u ... iap/s5p4418/start.S中的某个函数,可否请教下这个应该怎么看。

(2)系统唤醒了直接从uboot开始执行代码。
我看了一些文章,uboot中会有一些地方去判断系统是wake还是reset中启动的,但是我这个似乎没有找到。

另外,我在另一个论坛看到了一个产品(http://bbs.9tripod.com/forum.php?mod=viewthread&tid=33060),官方声称是可以休眠的。我下载了他们的源代码代码,比对了start.S文件,和上面的pm.c文件,发现完全一样。

由于现在进入mem休眠模式后,按下电源按键没有任何反应,完全没有头绪接下来刚怎么查找问题。希望坛子里的朋友能发表下意见,给一些方向,哪怕一点点都可以。在此谢谢。

此帖出自Linux与安卓论坛
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。