本帖最后由 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属于触摸屏设备。想着触摸屏的驱动问题后面再说,实在不行再网上再找一个,先不管了。于是在内核编译去掉了对触摸屏的支持,重新编译后,再次测试。
这次似乎可以了。
- PM: suspend entry 2017-09-29 01:11:40.085606501 UTC
- [ 108.620000] PM: Syncing filesystems ... done.
- [ 108.632000] PM: Preparing system for mem sleep
- [ 108.640000] Freezing user space processes ... (elapsed 0.040 seconds) done.
- [ 108.688000] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
- [ 108.696000] PM: Entering mem sleep
- [ 108.700000] calling rfkill2+ [url=home.php?mod=space&uid=775551]@[/url] 418, parent: mmc1:0001:2
- [ 108.708000] call rfkill2+ returned 0 after 1 usecs
- [ 108.712000] calling rfkill1+ @ 418, parent: phy0
- [ 108.716000] call rfkill1+ returned 0 after 0 usecs
- [ 108.720000] calling phy0+ @ 418, parent: mmc1:0001:2
- [ 108.728000] call phy0+ returned 0 after 3 usecs
- ......
- [ 110.504000] calling uart-pl011.1+ @ 83, parent: none
- [ 110.504000] calling uart-pl011.0+ @ 55, parent: none
- [ 110.504000] call uart-pl011.1+ returned 0 after 3 usecs
- [ 110.552000] uart-pl011.0: ttyAMA0: Unable to drain transmitter
- [ 110.552000] call uart-pl011.0+ returned 0 after 45918 usecs
- [ 110.568000] call reg-dummy+ returned 0 after 0 usecs
- [ 110.572000] calling ram_console+ @ 418, parent: platform
- [ 110.576000] call ram_console+ returned 0 after 0 usecs
- [ 110.584000] PM: suspend of devices complete after 1236.879 msecs
- [ 110.588000] PM: late suspend of devices complete after 0.300 msecs
- [ 110.596000] PM: noirq suspend of devices complete after 0.463 msecs
- [ 110.604000] Disabling non-boot CPUs ...
- [ 110.612000] PM: Calling vic_suspend+0x0/0xd0
- [ 110.612000] suspend_one_vic: suspending vic at f0002000
- [ 110.612000] suspend_one_vic: suspending vic at f0003000
- [ 110.612000] PM: Calling timekeeping_suspend+0x0/0x124
- [ 110.612000] PM: Calling suspend_time_syscore_suspend+0x0/0x18
- [ 110.612000] PM: Calling sched_clock_suspend+0x0/0x2c
- [ 110.612000] PM: Calling fw_suspend+0x0/0x18
- [ 110.612000] PM: Calling cpufreq_bp_suspend+0x0/0xa4
- [ 110.612000] PM: Calling cpu_pm_suspend+0x0/0x18
- suspend_enter enter
- suspend machine...
复制代码
OK,指示灯熄灭,CPU过了一会也凉了,然后我就发现悲剧了,按下POWPE再也无法唤醒系统了,什么反应都没有。我成功复现了作者邮件中的问题。
---------------------------------------------------------------------------------------------
作为一个只当了一周的临时的、业余嵌入爱好工程师,现在完全没有了方向。但是也有几个疑问。
log的最后是suspend machine,看了下代码,这个log来自内核
https://github.com/friendlyarm/l ... m/mach-s5p4418/pm.c,代码是
- static int __powerdown(unsigned long arg)
- {
- void (*power_down)(ulong, ulong) =
- (void (*)(ulong, ulong))((ulong)do_suspend + 0x220);
- int ret;
- ret = suspend_machine();
- if (0 == ret)
- pm_suspend_data_restore(NULL);
- FLUSH_CACHE();
- if (0 > ret)
- return ret; /* wake up */
- if(do_suspend == NULL) {
- lldebugout("Fail, inavalid suspend callee
");
- return 0;
- }
- suspend_cpu_enter();
-
- lldebugout("suspend machine...
");
- END_FLUSH_CACHE();
- power_down(IO_ADDRESS(PHY_BASEADDR_ALIVE), IO_ADDRESS(PHY_BASEADDR_DREX));
- while (1);
- }
复制代码
我觉得代码最后是停在了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与安卓论坛
一周热门 更多>