RK3568平台 RTC时间框架

一.RTC时间框架概述

RTC(Real Time Clock)是一种用于计时的模块,可以是再soc内部,也可以是外部模块。对于soc内部的RTC,只需要读取寄存器即可,对于外部模块的RTC,一般需要使用到I2C接口进行读取。至于如何供电,都是可以在主电源断开后使用纽扣电源辅助供电,达到设备断电仍然可以计时的效果。

对于soc内部的RTC,需要额外的晶振,而外部模块的RTC不需要。

在linux内核里,rtc是一个字符设备,内核实现了一个通用的字符设备层,提供给应用层系统调用,给底下的RTC硬件驱动层提供注册接口。每款RTC需要编写对应的硬件驱动,填写读取和设置时间的回调函数,并且注册进系统。从上到下分别是应用层、rtc通用字符设备层、rtc底层驱动层。

Linux 内核中,RTC 驱动的结构图如下所示, 可以分为三个层次:

接口层,负责向用户空间提供操作的结点以及相关接口。
• RTC Core, 为rtc 驱动提供了一套API, 完成设备和驱动的注册等。
• RTC 驱动层,负责具体的RTC 驱动实现,如设置时间、闹钟等设置寄存器的操作。

二.RTC设备驱动

申请rtc_device,RTC注册函数:

struct rtc_device *devm_rtc_device_register(struct device *dev,  
                              const char *name, 
                              const struct rtc_class_ops *ops,  
                              struct module *owner)

这个接口会自动帮你从设备树的aliases节点获取rtcx的序号,如果没有填写就自动分配一个序号。

注销rtc_device,RTC注销函数:

void devm_rtc_device_unregister(struct device *dev,  
                           struct rtc_device *rtc)

内核RTC框架提供了3中数据结构:

struct rtc_time、struct rtc_device和struct rtc_device_ops结构,其定义如下:

struct rtc_time {
    int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year/*从1900开始*/;
    int tm_wday, tm_yday, tm_isdst/*夏令时标志*/;
};
 
struct rtc_device {
    struct device dev;
    struct module *owner;
    int id; // 由内核提供给rtc设备的全局索引,/dev/rtc<id>
    char name[RTC_DEVICE_NAME_SIZE];
    const struct rtc_class_ops *ops; // 一组操作,例如 设置/读取 时间/闹钟
    struct mutex ops_lock;
    struct cdev char_dev;
    ulong flags;
 
    ulong irq_data;
    spinlock_t irq_lock;
    wait_queue_head_t irq_queue;
 
    struct rtc_task *irq_task;
    spinlock_t irq_task_lock;
    int irq_freq;
    int max_user_freq;
 
    struct work_struct irqwork;
};
 
struct rtc_class_ops {
    int (*open)(struct device *dev); // 用户在设备/dev/rtc1上调用read时的callback
    int (*release)(struct device *dev);// 用户在设备/dev/rtc1上调用close时的callback
    int (*ioctl)(struct device *dev, uint cmd, ulong arg); // 用户在设备/dev/rtc1上调用ioctl时的callback
    int (*read_time)(struct device *dev, struct rtc_time *tm); // rtc内核的回调函数
    int (*set_time)(struct device *dev, struct rtc_time *tm);
    int (*read_alarm)(struct device *dev, struct rtc_wkalrm *alarm);
    int (*set_alarm)(struct device *dev, struct rtc_wkalrm *alarm);
    int (*read_callback)(struct device *dev, int data); // 用户在设备/dev/rtc1上调用read时的callback
    int (*alarm_irq_enable)(struct device *dev, uint enabled);
};
 
// rtc模块提供了宏to_rtc_device(d)把 struct device结构转变为struct rtc_device{}结构

读取和设置时间 :

驱动程序负责提供读取和设置设备时间的函数。RTC总是以二进制编码的格式存储/恢复时间,其中每个4位表示0~9而非0~F,内核提供bcd2bin()和bin2bcd()两个转换的宏。提供辅助函数rtc_valid_tm(struct rtm_time *)用于确定struct rtc_time{}表示合法的时间。

函数使用示例:

static int foo_rtc_read_time(struct device *dev, struct rtc_time *tm) {
    struct foo_regs regs;
    int error = foo_device_read(dev, &regs, 0, sizeof(regs));
    if (error) return error;
    tm->tm_sec = bcd2bin(regs.seconds);
    tm->tm_min = bcd2bin(regs.minutes);
    tm->tm_hour = bcd2bin(regs.cent_hours);
    tm->tm_mday = bcd2bin(regs.date);
    tm->tm_wday = bcd2bin(regs.day) - 1;
    tm->tm_mon = bcd2bin(regs.month) - 1;
    tm->tm_year = bcd2bin(regs.years) + 100; // 设备的epoch是2000,加回到1900
    return rtc_valid_tm(tm);
}
 
static int foo_rtc_set_time(struct device *dev, struct rtc_time *tm) {
    struct foo_regs regs;
    regs.seconds = bin2bcd(tm->tm_sec);
    regs.minutes = bin2bcd(tm->tm_min);
    regs.cent_hours = bin2bcd(tm->tm_hour);
 
    regs.day = bin2bcd(tm->tm_wday + 1);
    regs.date = bin2bcd(tm->tm_mday);
 
    regs.month = bin2bcd(tm->tm_mon + 1);
 
    regs.cent_hours |= BQ32K_CENT;
    regs.years = bin2bcd(tm->tm_year % 100);
    return write_into_device(dev, &regs, 0, sizeof(regs));
}

三.RTC用户空间

 rtc在sys中拥有一个类,可以查看一些信息。

  • name 查看rtc型号

  • range 查看rtc支持的起始时间和结束时间

  • date 查看rtc当前日期

  • time 查看rtc当前时间

  • since_epoch 查看当前rtc时间距离epoch经历了多少秒,epoch是一个时间点1970 年 1 月 1 日凌晨零点零分零秒

  • hctosys 这个rtc是否在上电时候同步设置系统时间

  • max_user_freq 可读可写用于查看和设置RTC周期中断的最大频率,一般是1hz

  • offset 查看和设置当前的rtc校准精度的偏移值,和回调read_offset、set_offset有关,注意是ppb为单位,而且是可正可负

  • wakealarm 查看和设置闹钟时间,有的rtc会被隐藏起来这个属性,sys属性如何隐藏可以参考rtc_attr_group、rtc_attr_is_visible、rtc_does_wakealarm这三个。

在注册rtc驱动的时候,会自动在proc注册一个文件/proc/driver/rtc,此文件只可以读

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/414218.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

prometheus+grafana监控nginx的简单实现

1.编译安装NGINX 加入编译安装nginx-module-vts模块,目的是为了获取更多的监控数据(虚拟主机&#xff0c;upstream等) nginx下载 http://nginx.org/download/nginx-1.20.2.tar.gz nginx-module-vts下载 https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2…

自然语言处理: 第十三章Xinference部署

项目地址: Xorbitsai/inference 理论基础 正如同Xorbits Inference&#xff08;Xinference&#xff09;官网介绍是一个性能强大且功能全面的分布式推理框架。可用于大语言模型&#xff08;LLM&#xff09;&#xff0c;语音识别模型&#xff0c;多模态模型等各种模型的推理。通…

在PyCharm中使用Git

安装Git CMD检查Git版本 打开cmd&#xff0c;输入git version&#xff0c;检查当前下载版本 配置git的user信息 在cmd中输入 git config --global user.name "用户名"git config --global user.email "用户邮箱"输入&#xff1a;git config --list&…

Linux下性能分析的可视化图表工具

1 sar 和sadf 1.1 简介 sar命令可以记录系统下的常见活动信息&#xff0c;例如CPU使用率、网络统计数据、Block I/O数据、内存使用情况 等。 sar命令的“-o [file_name]”参数可以将系统活动数据记录到file_name文件&#xff0c;然后通过sadf来解析&#xff0c;sadf命令的“-g…

音频混音算法的实现

最近项目有用到混音算法&#xff0c;这里用比较常见的一种&#xff0c;就是简单的加和之后做一下归一化。 是参考这个博主实现的&#xff1a; 音频混音的算法实现 下面直接贴代码&#xff1a; #include <stdio.h> #include <stdlib.h> #include <math.h&…

【王道数据结构】【chapter7查找】【P285t5】

线性表中各节点的检索概率不等时&#xff0c;可用如下策略提高顺序检索的效率&#xff1b;若找到指定的结点&#xff0c;则将该结点和其前驱结点&#xff08;若存在&#xff09;交换&#xff0c;使得经常被访问的结点尽量位于表的前端。试设计在顺序结构和链式结构的线性表盘上…

计算机网络:深入探索HTTP

引言&#xff1a; HTTP&#xff0c;全称超文本传输协议&#xff08;Hypertext Transfer Protocol&#xff09;&#xff0c;是互联网上数据通信的基础。它定义了客户端&#xff08;如浏览器&#xff09;和服务器之间如何交互和传输数据。HTTP最初是为了支持Web浏览而设计的&…

Flink动态分区裁剪

1 原理 1.1 静态分区裁剪与动态分区裁剪 静态分区裁剪的原理跟谓词下推是一致的&#xff0c;只是适用的是分区表&#xff0c;通过将where条件中的分区条件下推到数据源达到减少分区扫描的目的   动态分区裁剪应用于Join场景&#xff0c;这种场景下&#xff0c;分区条件在joi…

南京师范大学计电院数据结构课设——排序算法

1 排序算法 1.1 题目要求 编程实现希尔、快速、堆排序、归并排序算法。要求首先随机产生10000个数据存入磁盘文件&#xff0c;然后读入数据文件&#xff0c;分别采用不同的排序方法进行排序并将结果存入文件中。 1.2 算法思想描述 1.2.1 随机数生成 当需要生成一系列随机数…

C#理论 —— WPF 应用程序Console 控制台应用

文章目录 1. WPF 应用程序1.1 工程创建1.2 控件1.2.1 控件的公共属性1.2.1 TextBox 文本框1.2.1 Button 按钮 *. Console 控制台应用1.1 工程创建 1. WPF 应用程序 1.1 工程创建 Visual Studio 中新建项目 - 选择WPF 应用程序&#xff1b; 1.2 控件 1.2.1 控件的公共属性 …

RunnerGo UI自动化测试脚本如何配置

RunnerGo提供从API管理到API性能再到可视化的API自动化、UI自动化测试功能模块&#xff0c;覆盖了整个产品测试周期。 RunnerGo UI自动化基于Selenium浏览器自动化方案构建&#xff0c;内嵌高度可复用的测试脚本&#xff0c;测试团队无需复杂的代码编写即可开展低代码的自动化…

Ubuntu Mysql Innodb cluster集群搭建+MaxScale负载均衡(读写分离)

Ubuntu系统版本 20.04.3 LTS (Focal Fossa) 、64位系统。 cat /etc/os-release查看Ubuntu系统是32位还是64位 uname -m如果显示“i686”,则表示安装了32位操作系统。如果显示“x86_64”,则表示安装了64位操作系统。 一、安装MySql 参考: https://blog.csdn.net/qq_3712…

高级语言期末2010级B卷

1.编写程序根据如下公式计算X的值&#xff08;精确到1e-5&#xff09;。 #include <stdio.h>int main(){int i1;double flag1.0/(2*i-1)*2.0*i/(2*i-1);double sum0;while(flag>1e-5){sumflag;i;flag1.0/(2*i-1)*2.0*i/(2*i-1);}printf("%lf",sum);return 0…

【kubernetes】关于k8s集群的资源发布方式(灰度/滚动发布)

目录 一、常见的发布方式 二、详解kubectl陈述式方式做灰度发布&#xff08;金丝雀发布&#xff09; 步骤一&#xff1a;先基于deployment控制器创建pod&#xff0c;然后发布 步骤二&#xff1a;基于命令行灰度发布 步骤三&#xff1a;测试等到版本稳定以后&#xff0c;再完…

自动驾驶消息传输机制-LCM

需要用到LCM消息通讯&#xff0c;遂研究下。 这里写目录标题 1 LCM简介2. LCM源码分析3 LCM C教程与实例3.1 安装配置及介绍3.2 创建类型定义3.3 初始化LCM3.4 发布publish一个消息3.5 订阅和接收一个消息3.6 LCM进程间通讯3.7 注意事项&#xff1f;3.7.1 当数据结构定义的是数…

unity学习(41)——创建(create)角色脚本(panel)——UserHandler(收)+CreateClick(发)——创建发包!

1.客户端的程序结构被我精简过&#xff0c;现在去MessageManager.cs中增加一个UserHandler函数&#xff0c;根据收到的包做对应的GameInfo赋值。 2.在Model文件夹下新增一个协议文件UserProtocol&#xff0c;内容很简单。 using System;public class UserProtocol {public co…

2024牛客寒假算法基础集训营1(补题)

文章目录 ABCDEFGHIJKL A n的范围很小暴力直接 O ( n 3 ) O(n^3) O(n3)直接做就行。 我还傻的统计了一下前后缀&#xff0c;不过怎么写都行这道题。 #include <bits/stdc.h> #define int long long #define rep(i,a,b) for(int i (a); i < (b); i) #define fep(i,…

图片生成 Stable Diffusion Web 安装教程

一 Stable Diffusion Web介绍 1 什么是stable diffussion web &#xff1f; Stable Diffusion Web 是一个基于 Stable Diffusion 模型开发的图形用户界面&#xff08;GUI&#xff09;应用程序&#xff0c;它允许用户通过简单的网页交互方式来利用人工智能技术进行艺术创作和图像…

2024数字中国创新大赛·数据要素赛道“能源大数据应用赛”正式上线!参赛指南请查收

近日&#xff0c;由国网福建电力承办的2024数字中国创新大赛能源大数据应用赛正式上线发布。赛事按照数字中国建设、能源革命的战略要求&#xff0c;围绕能源数据要素x、能源数字技术、能源商业模式等热点设置赛题&#xff0c;诚邀社会各界为加快建成新型电力系统出谋划策&…

LVGL 环境搭建-基于WSL

背景说明 小白刚开始接触LVGL&#xff0c;前些日子狠心花198元入手了一块堪称LVGL 入门利器~HMI-Board 开发板&#xff0c;虽然有RT-Thread 集成好的LVGL 环境&#xff0c;只需要几个步骤就能成功把lvgl 的示例运行起来&#xff0c;对于爱折腾的我来说&#xff0c;过于简单也并…