通用模块(5)——RTC模块
参考链接:
https://blog.csdn.net/bb807777/article/details/80447747https://blog.csdn.net/u011290127/article/details/95401602
rtc架构
kernel-3.4.39/include/linux/rtc.h
struct rtc_class_ops {int (*open)(struct device *);void (*release)(struct device *);int (*ioctl)(struct device *, unsigned int, unsigned long);int (*read_time)(struct device *, struct rtc_time *);int (*set_time)(struct device *, struct rtc_time *);int (*read_alarm)(struct device *, struct rtc_wkalrm *);int (*set_alarm)(struct device *, struct rtc_wkalrm *);int (*proc)(struct device *, struct seq_file *);int (*set_mmss)(struct device *, unsigned long secs);int (*read_callback)(struct device *, int data);int (*alarm_irq_enable)(struct device *, unsigned int enabled);
};struct rtc_device
{struct device dev;struct module *owner;int id;char name[RTC_DEVICE_NAME_SIZE];const struct rtc_class_ops *ops;struct mutex ops_lock;struct cdev char_dev;unsigned long flags;unsigned long irq_data;spinlock_t irq_lock;wait_queue_head_t irq_queue;struct fasync_struct *async_queue;struct rtc_task *irq_task;spinlock_t irq_task_lock;int irq_freq;int max_user_freq;struct timerqueue_head timerqueue;struct rtc_timer aie_timer;struct rtc_timer uie_rtctimer;struct hrtimer pie_timer; /* sub second exp, so needs hrtimer */int pie_enabled;struct work_struct irqwork;/* Some hardware can't support UIE mode */int uie_unsupported;#ifdef CONFIG_RTC_INTF_DEV_UIE_EMULstruct work_struct uie_task;struct timer_list uie_timer;/* Those fields are protected by rtc->irq_lock */unsigned int oldsecs;unsigned int uie_irq_active:1;unsigned int stop_uie_polling:1;unsigned int uie_task_active:1;unsigned int uie_timer_active:1;
#endif
};
#define to_rtc_device(d) container_of(d, struct rtc_device, dev)
使用dump_stack()打印出Android设置rtc时间后,rtc内核阶段相应接口函数的调用逻辑:
log信息:
[ 73.081000] [] (unwind_backtrace+0x0/0x134) from [] (rx8010_set_time+0x1c/0x1ec)
[ 73.091000] [] (rx8010_set_time+0x1c/0x1ec) from [] (rtc_set_time+0x64/0xc4)
[ 73.100000] [] (rtc_set_time+0x64/0xc4) from [] (alarm_ioctl+0x2b4/0x618)
[ 73.109000] [] (alarm_ioctl+0x2b4/0x618) from [] (do_vfs_ioctl+0x3f8/0x5ac)
[ 73.118000] [] (do_vfs_ioctl+0x3f8/0x5ac) from [] (sys_ioctl+0x6c/0x7c)
[ 73.127000] [] (sys_ioctl+0x6c/0x7c) from [] (ret_fast_syscall+0x0/0x30)
内核驱动程序
kernel-3.4.39/drivers/rtc/rtc-rx8010.c
static struct rtc_class_ops rx8010_rtc_ops = {.read_time = rx8010_get_time,.set_time = rx8010_set_time,.read_alarm = rx8010_read_alarm,.set_alarm = rx8010_set_alarm,.alarm_irq_enable = rx8010_alarm_irq_enable,
};
kernel-3.4.39/drivers/rtc/interface.c
int rtc_read_time(struct rtc_device *rtc, struct rtc_time *tm)
{int err;err = mutex_lock_interruptible(&rtc->ops_lock);if (err)return err;err = __rtc_read_time(rtc, tm);mutex_unlock(&rtc->ops_lock);return err;
}
EXPORT_SYMBOL_GPL(rtc_read_time);int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
{int err;err = rtc_valid_tm(tm);if (err != 0)return err;err = mutex_lock_interruptible(&rtc->ops_lock);if (err)return err;if (!rtc->ops)err = -ENODEV;else if (rtc->ops->set_time)err = rtc->ops->set_time(rtc->dev.parent, tm);else if (rtc->ops->set_mmss) {unsigned long secs;err = rtc_tm_to_time(tm, &secs);if (err == 0)err = rtc->ops->set_mmss(rtc->dev.parent, secs);} elseerr = -EINVAL;mutex_unlock(&rtc->ops_lock);/* A timer might have just expired */schedule_work(&rtc->irqwork);return err;
}
EXPORT_SYMBOL_GPL(rtc_set_time);EXPORT_SYMBOL_GPL(rtc_read_alarm);
EXPORT_SYMBOL_GPL(rtc_set_alarm);
EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
linux/kernel/kernel-3.4.39/drivers/staging/android/alarm-dev.c
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{case ANDROID_ALARM_SET_RTC:if (copy_from_user(&new_rtc_time, (void __user *)arg,sizeof(new_rtc_time))) {rv = -EFAULT;goto err1;}rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);rtc_dev = alarmtimer_get_rtcdev();rv = do_settimeofday(&new_rtc_time);if (rv < 0)goto err1;if (rtc_dev)rv = rtc_set_time(rtc_dev, &new_rtc_tm);spin_lock_irqsave(&alarm_slock, flags);alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;wake_up(&alarm_wait_queue);spin_unlock_irqrestore(&alarm_slock, flags);if (rv < 0)goto err1;break;
Android层jni
frameworks/base/services/core/jni/com_android_server_AlarmManagerService.cpp
class AlarmImpl
{
public:AlarmImpl(int *fds, size_t n_fds);virtual ~AlarmImpl();virtual int set(int type, struct timespec *ts) = 0;virtual int setTime(struct timeval *tv) = 0;virtual int waitForAlarm() = 0;protected:int *fds;size_t n_fds;
};static jint android_server_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
{AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);struct timeval tv;int ret;if (millis <= 0 || millis / 1000LL >= INT_MAX) {return -1;}tv.tv_sec = (time_t) (millis / 1000LL);tv.tv_usec = (suseconds_t) ((millis % 1000LL) * 1000LL);ALOGD("Setting time of day to sec=%d\n", (int) tv.tv_sec);ret = impl->setTime(&tv);if(ret < 0) {ALOGW("Unable to set rtc to %ld: %s\n", tv.tv_sec, strerror(errno));ret = -1;}return ret;
}static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
{struct timezone tz;tz.tz_minuteswest = minswest;tz.tz_dsttime = 0;int result = settimeofday(NULL, &tz);if (result < 0) {ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));return -1;} else {ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);}return 0;
}static JNINativeMethod sMethods[] = {/* name, signature, funcPtr */{"init", "()J", (void*)android_server_AlarmManagerService_init},{"close", "(J)V", (void*)android_server_AlarmManagerService_close},{"set", "(JIJJ)V", (void*)android_server_AlarmManagerService_set},{"waitForAlarm", "(J)I", (void*)android_server_AlarmManagerService_waitForAlarm},{"setKernelTime", "(JJ)I", (void*)android_server_AlarmManagerService_setKernelTime},{"setKernelTimezone", "(JI)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
};int register_android_server_AlarmManagerService(JNIEnv* env)
{return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",sMethods, NELEM(sMethods));
}
framework层
frameworks/base/services/java/com/android/server/AlarmManagerService.java
frameworks/base/core/java/android/app/AlarmManager.java下面的是直接提供给app层的API接口,它是AlarmManagerService.java的一个封装。
相关内容
操作指令
hwclock –r 显示硬件时钟与日期
hwclock –s 将系统时钟调整为与目前的硬件时钟一致。
hwclock –w 将硬件时钟调整为与目前的系统时钟一致
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
