Linux内核 -- RTC 驱动的注册方式

server/2025/1/11 22:04:31/

Linux 内核中 RTC 驱动的注册方式

在 Linux 内核中,RTC(Real-Time Clock)驱动的注册可以通过多种方式实现,以下整理了常见的注册方式及其注意事项。

1. 使用 devm_rtc_device_register

这是注册 RTC 驱动的最常用方法,基于设备资源管理(devm_)机制,能够自动管理资源释放。

示例代码

#include <linux/rtc.h>static int rtc_read_time(struct device *dev, struct rtc_time *tm) {// 模拟读取时间tm->tm_sec = 30;tm->tm_min = 15;tm->tm_hour = 10;tm->tm_mday = 25;tm->tm_mon = 5;tm->tm_year = 123; // 表示 2023 年return 0;
}static int rtc_set_time(struct device *dev, struct rtc_time *tm) {// 模拟设置时间pr_info("Setting time: %d:%d:%d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);return 0;
}static const struct rtc_class_ops rtc_ops = {.read_time = rtc_read_time,.set_time = rtc_set_time,
};static int rtc_probe(struct platform_device *pdev) {struct rtc_device *rtc;rtc = devm_rtc_device_register(&pdev->dev, "rtc-name", &rtc_ops, THIS_MODULE);if (IS_ERR(rtc))return PTR_ERR(rtc);return 0;
}

适用场景

  • 驱动逻辑较简单。
  • 希望简化资源管理工作。

注意事项

  • 必须确保设备正确传递到 devm_ 机制中。
  • 如果需要手动释放资源,请使用 rtc_device_register

2. 使用 rtc_device_register

相比 devm_rtc_device_register,此方法需要手动管理资源,适用于需要更高资源控制的场景。

示例代码

#include <linux/rtc.h>static int rtc_read_time(struct device *dev, struct rtc_time *tm) {// 模拟读取时间tm->tm_sec = 30;tm->tm_min = 15;tm->tm_hour = 10;tm->tm_mday = 25;tm->tm_mon = 5;tm->tm_year = 123; // 表示 2023 年return 0;
}static int rtc_set_time(struct device *dev, struct rtc_time *tm) {// 模拟设置时间pr_info("Setting time: %d:%d:%d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);return 0;
}static const struct rtc_class_ops rtc_ops = {.read_time = rtc_read_time,.set_time = rtc_set_time,
};struct rtc_device *rtc;rtc = rtc_device_register("rtc-name", dev, &rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))return PTR_ERR(rtc);/* 在 remove 或出错路径中释放资源 */
rtc_device_unregister(rtc);

适用场景

  • 驱动需要复杂的初始化逻辑。
  • 不希望依赖 devm_ 机制。

注意事项

  • 在驱动卸载时需手动调用 rtc_device_unregister 释放资源。
  • 避免资源泄漏。

3. 通过设备树或 ACPI 自动绑定

当 RTC 设备通过设备树或 ACPI 描述时,可以自动绑定到对应的驱动。

示例设备树

rtc@10000000 {compatible = "vendor,rtc";reg = <0x10000000 0x100>;
};

示例驱动代码

static int rtc_read_time(struct device *dev, struct rtc_time *tm) {// 模拟读取时间tm->tm_sec = 30;tm->tm_min = 15;tm->tm_hour = 10;tm->tm_mday = 25;tm->tm_mon = 5;tm->tm_year = 123; // 表示 2023 年return 0;
}static int rtc_set_time(struct device *dev, struct rtc_time *tm) {// 模拟设置时间pr_info("Setting time: %d:%d:%d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);return 0;
}static const struct rtc_class_ops rtc_ops = {.read_time = rtc_read_time,.set_time = rtc_set_time,
};static int rtc_probe(struct platform_device *pdev) {struct rtc_device *rtc;rtc = devm_rtc_device_register(&pdev->dev, "rtc-name", &rtc_ops, THIS_MODULE);if (IS_ERR(rtc))return PTR_ERR(rtc);return 0;
}

适用场景

  • 嵌入式系统中常见。
  • RTC 资源通过设备树或 ACPI 描述。

注意事项

  • 确保 compatible 字段与驱动匹配。
  • 驱动需正确处理资源获取和释放。

4. 使用 rtc_class

适用于创建自定义 RTC 类设备的场景。

示例代码

#include <linux/rtc.h>
#include <linux/device.h>struct class *rtc_class;
struct device *rtc_dev;rtc_class = class_create(THIS_MODULE, "rtc");
if (IS_ERR(rtc_class))return PTR_ERR(rtc_class);rtc_dev = device_create(rtc_class, NULL, MKDEV(0, 0), NULL, "rtc0");
if (IS_ERR(rtc_dev)) {class_destroy(rtc_class);return PTR_ERR(rtc_dev);
}/* 在退出时清理资源 */
device_destroy(rtc_class, MKDEV(0, 0));
class_destroy(rtc_class);

适用场景

  • 自定义 RTC 类设备。
  • 需要特殊行为的 RTC 设备。

注意事项

  • 必须手动管理资源,避免资源泄漏。
  • 需要显式调用 class_destroydevice_destroy

注意事项

  1. 选择合适的注册方式

    • 简单驱动可用 devm_rtc_device_register
    • 需要手动控制资源时选择 rtc_device_register
    • 测试或模拟设备时使用设备树或 ACPI 自动绑定。
  2. 设备树支持:确保设备树描述与驱动匹配。

  3. 资源管理

    • 使用 devm_ 接口时资源自动管理。
    • 手动注册时注意清理资源。
  4. 兼容性

    • 检查硬件是否支持 RTC。
    • 根据具体硬件接口(I2C、SPI、平台设备)选择正确的实现方式。
  5. 功能扩展:可根据需求增加闹钟功能、中断支持等。


http://www.ppmy.cn/server/157588.html

相关文章

将光源视角的深度贴图应用于摄像机视角的渲染

将光源视角的深度贴图应用于摄像机视角的渲染是阴影映射&#xff08;Shadow Mapping&#xff09;技术的核心步骤之一。这个过程涉及到将摄像机视角下的片段坐标转换到光源视角下&#xff0c;并使用深度贴图来判断这些片段是否处于阴影中。 1. 生成光源视角的深度贴图 首先&…

景芯SOC设计实战

终身辅导、一对一辅导&#xff0c;手把手教您完成SoC全流程设计&#xff0c;从入门到进阶&#xff0c;带您掌握SoC芯片架构、算法、设计、验证、DFT、后端及低功耗全流程&#xff01;直播视频不定期升级&#xff01;让您快速超越同龄人&#xff01; 景芯团队主打文档服务器实战…

Go语言中的接收器(Receiver)详解

在 Go 语言中&#xff0c;接收器&#xff08;Receiver&#xff09; 是指在方法声明中与方法绑定的对象。它是 Go 语言实现面向对象编程&#xff08;OOP&#xff09;特性的核心之一。接收器的作用是将方法绑定到某个类型的实例&#xff08;值或者指针&#xff09;&#xff0c;让…

多租户架构是什么?

多租户架构&#xff08;Multi-Tenant Architecture&#xff09;是一种软件架构模型&#xff0c;在这种架构下&#xff0c;一个应用程序可以同时为多个不同的“租户”提供服务&#xff0c;每个租户的数据和设置是隔离的&#xff0c;但都共享同一份软件和硬件资源。每个租户可以视…

《操作系统真象还原》第十二章(一) —— 系统调用

本章节所有代码托管在miniOS 章节任务介绍 任务简介 上一节&#xff0c;我们实现了用户进程的创建&#xff0c;至此&#xff0c;我们成功将操作系统的使用权给用户进行了开放&#xff0c;用户至此可以创建进程然后实现自己的功能&#xff0c;但用户实现的功能最终还是要在操…

macOS安装nvm

新建一个文件夹&#xff0c;使用git将nvm给clone下来 git clone https://github.com/nvm-sh/nvm.git 使用vim编辑~/.bash_profile文件&#xff08;没有就新建&#xff09;添加以下代码 export NVM_DIR"$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] &&…

解决Docker冲突问题

错误&#xff1a;docker-ce-cli conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 错误&#xff1a;docker-ce conflicts with 2:docker-1.13.1-210.git7d71120.el7.centos.x86_64 您可以尝试添加 --skip-broken 选项来解决该问题 您可以尝试执行&#xff1a;…

模式识别-Ch2-高斯下判别函数

高斯密度下的判别函数 高斯分布 在给定均值和方差的所有分布中&#xff0c;正态分布的熵最大根据Central Limit Theorem(中心极限定理)&#xff0c;大量独立随机变量之和趋近正态分布实际环境中&#xff0c;很多类别的特征分布趋近正态分布 多元正态分布&#xff1a; x [ x …