|
[技术分享]Firefly-rk3288定时开机实现!
发表于 2016-7-11 17:39:25
浏览:63322
|
回复:24
打印
只看该作者
[复制链接]
楼主
本帖最后由 Livvol 于 2016-7-13 17:47 编辑
如题,先上实现效果:
我板子上跑的是ubuntu 14.04系统。
查看下RTC硬件时钟的时间,如果与当前系统时间不符,那么将系统时间同步到RTC硬件时钟即可:- firefly@firefly:~$ sudo hwclock -r
- Mon 11 Jul 2016 07:42:39 AM UTC -0.432840 seconds
- firefly@firefly:~$ sudo hwclock -w
复制代码
给硬件时钟写入定时开机时间:
- sudo ./on_off 2016.07.11.08.00.00
复制代码 on_off 是一个简单的C程序,负责从节点/dev/alarm 给硬件时钟写入定时开机时间。
可以查看一下内核打印信息,看一下开机时间是否已经写进去:
- firefly@firefly:~$ dmesg
- [ 364.964700] hym8563_rtc_set_alarm:diff_sec= 1007s , use alarm
- [ 364.967412] alarm_release: clear alarm, pending 0
复制代码 如果出现上面信息,就说明开机时间已经顺利写进去,关机,然后静静等待,到时间后系统会自动启动,完美~。
接下来讲下实现方法,主要修改内核的两个个文件即可。ubuntu14.04 使用的内核版本跟Android 4.4的内核版本基本一致,可以利用我们的Android 4.4 SDK的内核来进行修改和编译。
首先需要修改:
kernel/drivers/rtc/rtc-HYM8563.c
@@ -25,6 +25,7 @@
#include "rtc-HYM8563.h"
#include <linux/of_gpio.h>
#include <linux/irqdomain.h>
+#include <linux/kernel.h>
#define RTC_SPEED 200 * 1000
struct hym8563 {
@@ -36,6 +37,7 @@ struct hym8563 {
struct wake_lock wake_lock;
};
static struct i2c_client *gClient = NULL;
+static struct hym8563 *g_hym8563 = NULL;
static int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
{
@@ -543,6 +546,7 @@ static int hym8563_probe(struct i2c_client *client, const struct i2c_device_id
int rc = 0;
u8 reg = 0;
struct hym8563 *hym8563;
+ struct rtc_wkalrm alarm;
struct rtc_device *rtc = NULL;
struct rtc_time tm_read, tm = {
.tm_wday = 6,
@@ -609,7 +613,8 @@ static int hym8563_probe(struct i2c_client *client, const struct i2c_device_id
goto exit;
}
hym8563->rtc = rtc;
+ g_hym8563 = hym8563;
+ hym8563_rtc_read_alarm(&gClient->dev,&alarm);
return 0;
exit:
@@ -629,7 +634,7 @@ static int hym8563_remove(struct i2c_client *client)
}
-void hym8563_shutdown(struct i2c_client * client)
+/*void hym8563_shutdown(struct i2c_client * client)
{ u8 regs[2];
int ret;
//disable clkout
@@ -637,6 +642,28 @@ void hym8563_shutdown(struct i2c_client * client)
ret=hym8563_i2c_set_regs(client, RTC_CLKOUT, regs, 1);
if(ret<0)
printk("rtc shutdown is error\n");
+}*/
+static void hym8563_shutdown(struct i2c_client * client)
+{
+ struct device *pdev = &client->dev;
+ struct rtc_wkalrm alarm;
+ struct rtc_device *rtc_dev = g_hym8563->rtc;
+ u8 regs[4];
+
+ rtc_read_alarm(rtc_dev,&alarm);
+
+ if(alarm.enabled == 1){
+ printk("%s this in shutdowm,the alarm.enabled = 1 \n",__func__);
+ }
+ hym8563_i2c_read_regs(client,RTC_CTL2,regs,1);
+ regs[0] |= AIE;
+ hym8563_i2c_set_regs(client, RTC_CTL2,regs,1);
+ hym8563_i2c_read_regs(client,RTC_CTL2,regs,1);
+
+ regs[0] |=TIE;
+ hym8563_i2c_set_regs(client,RTC_CTL2,regs,1);
+ hym8563_i2c_read_regs(client,RTC_CTL2,regs,1);
+
}
@@ -661,16 +688,19 @@ struct i2c_driver hym8563_driver = {
.probe = hym8563_probe,
.remove = hym8563_remove,
//.shutdown=hym8563_shutdown,
+ .shutdown=hym8563_shutdown,
.id_table = hym8563_id,
};
接下来修改:
kernel/drivers/staging/android/alarm-dev.c
@@ -110,18 +110,35 @@ static void alarm_clear(enum android_alarm_type alarm_type)
}
static void alarm_set(enum android_alarm_type alarm_type,
struct timespec *ts)
{
uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;
+ struct rtc_time time;
+ struct rtc_device *rtc_dev;
+ struct rtc_wkalrm alarm;
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d set %ld.%09ld\n",
alarm_type, ts->tv_sec, ts->tv_nsec);
alarm_enabled |= alarm_type_mask;
devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
spin_unlock_irqrestore(&alarm_slock, flags);
+ if(alarm_type == 4){
+ rtc_time_to_tm(ts->tv_sec,&time);
+ rtc_dev = alarmtimer_get_rtcdev();
+ alarm.time.tm_year = time.tm_year;
+ alarm.time.tm_mon = time.tm_mon;
+ alarm.time.tm_mday = time.tm_mday;
+ alarm.time.tm_wday = time.tm_wday;
+ alarm.time.tm_hour = time.tm_hour;
+ alarm.time.tm_min = time.tm_min;
+ alarm.time.tm_sec = time.tm_sec;
+ alarm.enabled = 1;
+ rtc_set_alarm(rtc_dev,&alarm);
+ }
}
static int alarm_wait(void)
以上是我从整理好的patch里面搬下来的,有点乱。大家改的时候耐心点,别看错:P~以上两个文件修改完后,编译好内核,并烧到板子上即可。
修改好的这两个文件我已上传,见附件。
然后,就可以写个简单的C程序,来验证下修改是否有效啦。
以下为代码的部分内容,其余大家可以自行发挥编辑,我就不贴上来了:
- #define type_4 1074291010
- fd = open("/dev/alarm", O_RDWR);
- if(fd < 0) {
- printf("Unable to open alarm driver: %s\n", strerror(errno));
- return -1;
- }
- ts.ts_sec = (int)timep;
- ts.ts_nsec =0;
- res = ioctl(fd,type_4,&ts);
- if(res < 0) {
- printf("Unable to set rtc to %ld: %s\n", ts.ts_sec, strerror(errno));
- close(fd);
- return 0;
- }
复制代码以上为Firefly-rk3288定时开机的基本实现!:victory:,如有不妥的地方,欢迎大家来吐槽:lol。
有定时开机就有定时关机,至于定时关机,比较简单的思路是写个程序循环判定设置的时间是否与当前时间相等,相等就调用系统指令poweroff关机即可。大家可以试试~
|
|