rt-thread rtc设备驱动开发

基于pico rtc设备驱动开发

      • I/O设备框架
      • RTC设备
      • 功能配置——启用Soft RTC
      • 功能配置——启用NTP时间自动同步
      • 功能配置——启用硬件RTC

RT-Thread 的 RTC (实时时钟)设备为操作系统的时间系统提供了基础服务。应用层对于 RTC 设备一般不存在直接调用的 API ,使用者中间接通过设备的 control 接口完成交互。

I/O设备框架

​ I/O 设备模型框架,如下图所示,它位于硬件和应用程序之间,共分为 I/O 设备管理层、设备驱动框架层、设备驱动层。
在这里插入图片描述
​ I/O 设备管理层实现了对设备驱动程序的封装。应用程序通过 I/O 设备管理接口获得正确的设备驱动,然后通过这个设备驱动与底层 I/O 硬件设备进行数据(或控制)交互。应用层通过该层提供的标准接口访问底层设备,只需关注功能,无需考虑底层的变更,从而降低了代码的耦合性、复杂性,提高了系统的可靠性。
在这里插入图片描述
​ 设备驱动框架层是对同类硬件设备驱动的抽象,为I/O设备管理层提供功能实现调用接口。

​ 设备驱动层是一组驱使硬件设备工作的程序,实现访问硬件设备的功能。

​ 从源码层面解释各层之间的联系,如下图所示。图中,横向表示分层,纵向表示各类的继承派生关系。从下到上不断抽象、屏蔽下层差异,体现了面向对象的抽象的思想。上层为基类,下层为派生类。派生类各自实现父类提供的统一接口。这样,驱动层的不同厂商的相同硬件模块可创建各自的派生类对象,然后对接到框架层同一的基类接口,从而形成多对一的面向抽象的关系。同理,从设备驱动框架层到IO设备管理接口层,又是上层对下层的一次抽象。

​ 在RT-Thread中,I/O设备管理层和驱动设备框架层已完成封装,若新增设备驱动到I/O设备框架时,一般只需要结合硬件设备提供的SDK对设备驱动层进行驱动开发。
在这里插入图片描述
详细可参考:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/device

RTC设备

​ 在开启 RTC 设备框架以及 RTC 驱动之后,用户可以 #include <sys/time.h> 用来引用标准的时间操作函数,对软件或硬件RTC设备进行访问和操作。如:

​ 设置日期:rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day)

​ 设置时间:rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)

​ 获取当前时间:time_t time(time_t *t)

功能配置——启用Soft RTC

​ 在rt-thread 源码下的pico设备目录下(如rt-thread-master/bsp/raspberry-pico/),构建dist项目框架。source ~/.env/env.sh 将env工具引入该路径,启动工具,在 menuconfig 中可以启用使用软件模拟 RTC 的功能。
在这里插入图片描述
​ scons编译构建后,将生成的rtthread-pico.uf2文件拷贝至pico设备(RPI-RP2 disk)中。通过串口连接访问设备。在Finsh命令行,执行date命令,查看效果如下图。实际验证中,Soft RTC的时间比实际要快很多,精度不高。
在这里插入图片描述
ps: C语言项目的裁剪配置本质上通过条件编译和宏的展开进行的。RT-Thread借助Kconfig机制实现该功能。Env在根目录下执行menuconfig命令后会递归解析各级Kconfig文件,然后提供如下配置界面,完成相应的配置后并保存,根目录下会存在一份.config文件保存当前选择的配置项,并将.config文件转为RT-Thread的系统配置文件rtconfig.h。详细内容可参考:https://bbs.elecfans.com/jishu_2279148_1_1.html

功能配置——启用NTP时间自动同步

​ 若 RT-Thread 已接入互联网,可启用 NTP 时间自动同步功能,定期同步本地时间。

​ 首先在 menuconfig 中按照如下选项开启 NTP 功能:
在这里插入图片描述
​ 开启 NTP 后 RTC 的自动同步功能将会自动开启,还可以设置同步周期和首次同步的延时时间:
在这里插入图片描述
​ 生成执行执行文件,在Finsh命令行,输入 date 即可查看当前当地时区时间,大致效果如下:
在这里插入图片描述

功能配置——启用硬件RTC

查看PICO RP2040设备现有驱动。查看UART和GPIO的驱动源码所在路径,后续将在该路径下添加RTC驱动相关的源码。
在这里插入图片描述
​ 硬件RTC驱动源码开发,参考现有的UART及GPIO的驱动源码,了解其结构及逻辑调用关系。参考PICO RP2040设备SDK下的…/pico-sdk/src/rp2_common/hardware_rtc下的RTC源码,了解当前PICO 设备下所能与硬件操作相关的函数实现。参考/rt-thread/components/drivers/rtc/下的RTC的设备驱动框架源码,了解RTC设备类封装的函数及相关接口体。综上,针对某一操作,传递至设备框架层的函数能够有效调用驱动层的函数,驱动层的函数调用设备SDK衍生出的函数,进而实现对硬件的操作。
在这里插入图片描述
​ 参考看门狗设备使用时序图,RTC设备驱动核心代码如下:

​ 创建RTC设备:
在这里插入图片描述
​ 根据设备框架层rtc.h下的结构体,创建设备驱动层drv_rtc.c下的_rtc_ops对象。
在这里插入图片描述
​ 接下来,依次实现RTC设备初始化函数(pico_rtc_init)、设置时间函数(pico_rtc_set_secs)、获取时间函数(pico_rtc_get_secs),使得RTC具备硬件访问能力。

​ RTC设备驱动程序根据RTC设备模型定义,创建出具备硬件访问能力的RTC设备实例后,将RTC设备通过 rt_hw_rtc_register() 接口注册到RTC设备驱动框架中。
在这里插入图片描述
​ 硬件RTC验证:
在这里插入图片描述
​ ps:设备驱动开发中所涉及到的其他源文件或头文件,可在当前项目下的libraries中的SConscript进行添加。

rtc_driver.c:

#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <stdio.h>
#include <time.h>
#include <string.h>#include "board.h"
#include "drv_rtc.h"
#include <sys/time.h>#include "pico.h"
#include "hardware/rtc.h"
#include "hardware/irq.h"
#include "hardware/resets.h"
#include "hardware/clocks.h"struct rtc_device_object
{rt_rtc_dev_t  rtc_dev;
#ifdef RT_USING_ALARMstruct rt_rtc_wkalarm   wkalarm;
#endif
};static struct rtc_device_object rtc_device;bool rtc_running(void) {return (rtc_hw->ctrl & RTC_CTRL_RTC_ACTIVE_BITS);
}static bool valid_datetime(datetime_t *t) {// Valid ranges taken from RTC doc. Note when setting an RTC alarm// these values are allowed to be -1 to say "don't match this value"if (!(t->year >= 0 && t->year <= 4095)) return false;if (!(t->month >= 1 && t->month <= 12)) return false;if (!(t->day >= 1 && t->day <= 31)) return false;if (!(t->hour >= 0 && t->hour <= 23)) return false;if (!(t->min >= 0 && t->min <= 59)) return false;if (!(t->sec >= 0 && t->sec <= 59)) return false;return true;
}time_t datetime2sec(int year, int mon, int day, int hour, int min, int sec)
{struct tm tt;memset(&tt, 0, sizeof(tt));tt.tm_year = year;tt.tm_mon = mon;tt.tm_mday = day;tt.tm_hour = hour;tt.tm_min = min;tt.tm_sec = sec;return mktime(&tt);
}static rt_err_t pico_rtc_init(void){// Get clk_rtc freq and make sure it is runninguint rtc_freq = clock_get_hz(clk_rtc);assert(rtc_freq != 0);// Take rtc out of reset now that we know clk_rtc is runningreset_block(RESETS_RESET_RTC_BITS);unreset_block_wait(RESETS_RESET_RTC_BITS);// Set up the 1 second divider.// If rtc_freq is 400 then clkdiv_m1 should be 399rtc_freq -= 1;// Check the freq is not too big to divideassert(rtc_freq <= RTC_CLKDIV_M1_BITS);// Write divide valuertc_hw->clkdiv_m1 = rtc_freq;return RT_EOK; 
}bool rtc_get_datetime(datetime_t *t) {// Make sure RTC is runningif (!rtc_running()) {return false;}// Note: RTC_0 should be read before RTC_1uint32_t rtc_0 = rtc_hw->rtc_0;uint32_t rtc_1 = rtc_hw->rtc_1;t->dotw  = (int8_t) ((rtc_0 & RTC_RTC_0_DOTW_BITS ) >> RTC_RTC_0_DOTW_LSB);t->hour  = (int8_t) ((rtc_0 & RTC_RTC_0_HOUR_BITS ) >> RTC_RTC_0_HOUR_LSB);t->min   = (int8_t) ((rtc_0 & RTC_RTC_0_MIN_BITS  ) >> RTC_RTC_0_MIN_LSB);t->sec   = (int8_t) ((rtc_0 & RTC_RTC_0_SEC_BITS  ) >> RTC_RTC_0_SEC_LSB);t->year  = (int16_t) ((rtc_1 & RTC_RTC_1_YEAR_BITS ) >> RTC_RTC_1_YEAR_LSB);t->month = (int8_t) ((rtc_1 & RTC_RTC_1_MONTH_BITS) >> RTC_RTC_1_MONTH_LSB);t->day   = (int8_t) ((rtc_1 & RTC_RTC_1_DAY_BITS  ) >> RTC_RTC_1_DAY_LSB);return true;
}static rt_err_t pico_rtc_get_secs(time_t *sec)
{struct timeval tv;datetime_t t;rtc_get_datetime(&t);tv.tv_sec = datetime2sec(t.year,t.month,t.day,t.hour,t.min,t.sec);*(time_t *) sec = tv.tv_sec;return RT_EOK;
}bool rtc_set_datetime(datetime_t *t) {if (!valid_datetime(t)) {return false;}// Disable RTCrtc_hw->ctrl = 0;// Wait while it is still activewhile (rtc_running()) {tight_loop_contents();}// Write to setup registersrtc_hw->setup_0 = (((uint32_t)t->year)  << RTC_SETUP_0_YEAR_LSB ) |(((uint32_t)t->month) << RTC_SETUP_0_MONTH_LSB) |(((uint32_t)t->day)   << RTC_SETUP_0_DAY_LSB);rtc_hw->setup_1 = (((uint32_t)t->dotw)  << RTC_SETUP_1_DOTW_LSB) |(((uint32_t)t->hour)  << RTC_SETUP_1_HOUR_LSB) |(((uint32_t)t->min)   << RTC_SETUP_1_MIN_LSB)  |(((uint32_t)t->sec)   << RTC_SETUP_1_SEC_LSB);// Load setup values into rtc clock domainrtc_hw->ctrl = RTC_CTRL_LOAD_BITS;// Enable RTC and wait for it to be runningrtc_hw->ctrl = RTC_CTRL_RTC_ENABLE_BITS;while (!rtc_running()) {tight_loop_contents();}return true;
}static rt_err_t pico_rtc_set_secs(time_t *sec)
{datetime_t t;struct tm *local;local = localtime(sec);t.year = local->tm_year;t.month = local->tm_mon;t.day = local->tm_mday;t.hour = local->tm_hour;t.min = local->tm_min;t.sec = local->tm_sec;rtc_set_datetime(&t);return RT_EOK;
}const static struct rt_rtc_ops _rtc_ops =
{pico_rtc_init,pico_rtc_get_secs,pico_rtc_set_secs,RT_NULL,RT_NULL,RT_NULL,RT_NULL,
};int rt_hw_rtc_init(void)
{rt_err_t ret = RT_EOK;rtc_device.rtc_dev.ops = &_rtc_ops;ret = rt_hw_rtc_register(&rtc_device.rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);if(ret != RT_EOK){return ret;}
#ifdef RT_USING_ALARMrt_rtc_alarm_init();
#endif
}
INIT_DEVICE_EXPORT(rt_hw_rtc_init);

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于ZYNQ阵列涡流检测系统硬件设计(一)

为实现阵列涡流检测系统总体功能&#xff0c;需研制一套多通道信号采集硬件系统&#xff0c;以搭配 软件编程实现分时激励和分时采集。基于以上要求&#xff0c;本章介绍了阵列涡流检测系统的硬 件模块设计。 3.1 阵列涡流检测系统总体设计 阵列涡流检测系统需要利用 DA …

分布式软件架构——传输链路

传输链路 链路指无源的点到点的物理连接。链路是计算机网络中的一个重要概念&#xff0c;它指的是连接两个网络设备的物理或逻辑路径。简单来说&#xff0c;链路就是电信号或数据在网络中传输的路径。在计算机网络中&#xff0c;链路可以分为物理链路和逻辑链路两种。物理链路…

【UI自动化测试】appium+python+unittest+HTMLRunner

进阶Python接口自动化测试必备教程&#xff08;2023全网最详细&#xff09; 简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以python文件模式执行脚本生成测试报告 下载与安装 下载需要自…

举例说明基于线性回归的单层神经网络网络(以梯度下降算法来求解权重的过程)...

我们将通过一个简单的例子来说明基于线性回归的单层神经网络&#xff0c;以及如何使用梯度下降算法来求解权重。 假设我们有以下数据集&#xff0c;表示学生的学习时间&#xff08;小时&#xff09;与他们的考试分数&#xff1a; 学习时间&#xff08;X&#xff09;&#xff1a…

线程池学习(五)线程工厂、线程池工厂

Executors 定义的Executor, ExecutorService, ScheduledExecutorService, ThreadFactory和Callable类的工厂和实用程序方法&#xff0c;我们称为线程池工厂。ThreadFactory 为定制化创建新线程的对象,我们称为线程工厂 前面几期的学习中&#xff0c;我已经初步会使用线程池了&…

MySQL内置函数

内置函数从实现的功能角度可以分为数值函数、字符串函数、日期和时间函数、流程控制函数、加密与解密函数&#xff0c;获取MySQL信息函数、聚合函数等。 1.数值函数 来源&#xff1a; 版权声明&#xff1a;本文为CSDN博主「清风拂来水波不兴」的原创文章&#xff0c;遵循CC 4…

Ceph简介及部署

Ceph Ceph一、存储基础1、单机存储设备2、Ceph 简介3、Ceph 优势5、Ceph 架构6、Ceph 核心组件7、OSD 存储后端8、Ceph 数据的存储过程9、Ceph 版本发行生命周期10、Ceph 集群部署 二、部署ceph-deploy Ceph 集群前环境配置1、关闭 selinux 与防火墙2、根据规划设置主机名3、配…

数据中心水浸事件,该如何找回安全?

数据中心是现代企业和组织中不可或缺的基础设施&#xff0c;承载着大量的敏感数据和关键业务运作。然而&#xff0c;水浸事件可能成为数据中心的巨大威胁&#xff0c;可能导致设备故障、数据丢失以及业务中断&#xff0c;给组织带来严重的损失和风险。 因此&#xff0c;为了保护…

gd32f103vbt6 串口OTA升级3-linux端的部分

一. 简介 本文主要是对linux端升级单片机程序的功能部分做一些介绍&#xff0c;包括一些软件流程。 二.硬件部分 2.1 rk3399cpugd32f103 2.2 连接方式&#xff1a;串口&#xff08;115200&#xff0c;8N1&#xff09;或者iic&#xff08;本文没有介绍iic&#xff09; 三、其…

WebRTC不同方案对比

1.功能上会有一些出入&#xff0c;尤其是国内的metaRTC版本迭代很快&#xff0c; 2.后续的ffmpeg也在进行支持webrtc特性&#xff0c;obs新的版本好像已经支持了webrtc&#xff0c; 3.对于webrtc部分缺少的信令部分的标准化也有了对应的标准whip和whep协议 所以&#xff0c;如…

一道SQL题

有个搞数仓的朋友不知道从哪儿弄了个题。。。 做了做体验了一下。。。 记录记录。 分析 要保证每天都要做新题 5天必须都做题&#xff0c;不然GG 最后一天必须做新题&#xff0c;如果最后一天做新题了&#xff0c;前面那几天没做新题&#xff0c;做的是老题 最后一天&#…

QT:问题、解决与原因

在这里记录一些自己遇到的在QT开发上面的小问题和tips 目录 QComboBox 设置qss样式不生效qt按钮设置点击释放效果实现效果 QComboBox 设置qss样式不生效 我设置的样式是&#xff1a; box->setStyleSheet("QComboBox {""border: none;""padding:…

支付宝支付上线准备工作(商家自研接入)

商家自研流程 1.创建应用 登录支付宝开放平台创建 网页/移动应用 说明&#xff1a;生成的应用唯一标识 APPID 可用于调用开放产品接口。 2.配置应用 2.1 应用详情 2.2 产品绑定 2.3 开发设置 在开发 > 开发设置 中配置应用信息。 2.3.1 接口加密方式 按操作步骤进行…

抖音seo源码部署/开源不加密可二开/抖音seo优化开发方案

一、前言 抖音是目前国内非常流行的短视频平台之一&#xff0c;用户数量庞大&#xff0c;更是吸引了许多企业和个人在上面开设账号&#xff0c;通过发布内容来进行流量变现。但是&#xff0c;在一个账号发布内容的同时&#xff0c;管理员又需要同时关注多个账号&#xff0c;对账…

mysql中的行格式之compact格式分析

mysql中的行格式之compact格式分析 mysql行格式 所谓行格式&#xff0c;就是指mysql一行数据的存储格式。 InnoDB 储存引擎支持有四种行储存格式&#xff1a;Compact、Redundant、Dynamic 和 Compressed。 Redundant是很古老的行格式了&#xff0c;因为占用空间最多&#x…

基于深度学习的高精度道路瑕疵检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度道路瑕疵&#xff08;裂纹&#xff08;Crack&#xff09;、检查井&#xff08;Manhole&#xff09;、网&#xff08;Net&#xff09;、裂纹块&#xff08;Patch-Crack&#xff09;、网块&#xff08;Patch-Net&#xff09;、坑洼块&#x…

【C++】模板进阶—非类型模板参数、模板特化及模板的分离编译

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f681; 个人主页&#xff1a;不 良 &#x1f525; 系列专栏&#xff1a;&#x1f6f8;C &#x1f6f9;Linux &#x1f4d5; 学习格言&#xff1a;博观而约取&#xff0…

什么是云应用程序?

应用程序优先的云服务的日益普及导致应用程序与云服务的融合程度比以前更深。应用程序和云之间的运行时边界正在从虚拟机转移到容器和函数。集成边界正在从仅访问数据库和消息代理转向应用程序的机械部分混合并在云中运行的边界。在这个最终架构中&#xff0c;应用程序是“云绑…

pwm呼吸灯

文章目录 一、呼吸灯二、代码实现三、引脚分配 一、呼吸灯 呼吸灯是指灯光在微电脑的控制之下完成由亮到暗的逐渐变化&#xff0c;使用开发板上的四个led灯实现1s间隔的呼吸灯。 二、代码实现 c module pwm_led( input clk ,input rst_n ,output reg [3:0] led ); …

photoshop制作法线和凹凸贴图

做个选区 Ctrlj 法线贴图 生成凹凸贴图