RTC 设备驱动

更新时间:
2024-01-10
下载文档

RTC 设备驱动

实时时钟(RTC)的主要功能是在系统掉电的情况下,利用备用电源使时钟继续运行,保证不会丢失时间信息。现以 S3C2440 芯片为例,介绍其内部 RTC 原理及驱动实现。

硬件原理

S3C2440 内部集成了 RTC 模块。其内部的寄存器 BCDSEC,BCDMIN,BCDHOUR,BCDDAY,BCDDATE,BCDMON 和 BCDYEAR 分别存储了当前的秒,分,小时,星期,日,月和年,表示时间的数值都是 BCD 码。这些寄存器的内容可读可写,并且只有在寄存器 RTCCON 的第 0 位为 1 时才能进行读写操作。为了防止误操作,当不进行读写时,要把该位清零。当读取这些寄存器时,用户能够获取当前的时间;当写入这些寄存器时,用户能够设置当前的时间。另外需要注意的是,因为有所谓的“一秒误差”,因此当读取到的秒为 0 时,需要重新再读取一遍这些寄存器的内容,才能保证时间的正确。

寄存器配置

现介绍 RTC 驱动编写中常用的寄存器。

  • RTCCON 控制寄存器

用于选择时钟,使能/禁能 RTC 控制。在对存储时间信息的寄存器进行读写前,需要将该寄存器第 0 位置 1,读写结束后需要将该寄存器的第 0 位清零。

  • BCDSEC

存储 RTC 时间当前秒信息,用 BCD 码表示。[6:4]取值范围 :0 至 5,[3:0]取值范围 :0 至 9。

  • BCDMIN

存储 RTC 时间当前分信息,用 BCD 码表示。[6:4]取值范围 :0 至 5,[3:0]取值范围 :0 至 9。

  • BCDHOUR

存储 RTC 时间当前时信息,用 BCD 码表示。[5:4]取值范围 :0 至 2,[3:0]取值范围 :0 至 9。

  • BCDDAY

存储 RTC 时间当前星期信息,用 BCD 码表示。[2:0]取值范围 :1 至 7。

  • BCDDATE

存储 RTC 时间当前日信息,用 BCD 码表示。[5:4]取值范围 :0 至 3,[3:0]取值范围 :0 至 9。

  • BCDMON

存储 RTC 时间当前月信息,用 BCD 码表示。[4]取值范围 :0 至 1,[3:0]取值范围 :0 至 9。

  • BCDYEAR

存储 RTC 时间当前年信息,用 BCD 码表示。[7:0]取值范围 :00 至 99。

驱动实现

现以 SylixOS 中 mini2440 的 BSP 为例,介绍该芯片中 RTC 驱动的具体实现。

RTC 设备控制块

首先封装 RTC 设备控制块,其具体结构如下:

#include <SylixOS.h>
typedef struct {
    LW_DEV_HDR              RTCDEV_devhdr;              /*  设备头                  */
    PLW_RTC_FUNCS           RTCDEV_prtcfuncs;           /*  操作函数集               */
} LW_RTC_DEV;
  • RTCDEV_devhdr :RTC 设备头。
  • RTCDEV_prtcfuncs :RTC硬件接口函数。

其中RTC设备头结构参照“字符设备的创建及管理”小节,RTC 硬件接口函数结构如下:

#include <SylixOS.h>
typedef struct {
    VOIDFUNCPTR               RTC_pfuncInit;             /*  初始化 RTC                  */
    FUNCPTR                   RTC_pfuncSet;              /*  设置硬件 RTC 时间            */
    FUNCPTR                   RTC_pfuncGet;              /*  读取硬件 RTC 时间            */
    FUNCPTR                   RTC_pfuncIoctl;            /*  更多复杂的 RTC 控制          */
                                                         /*  例如设置唤醒闹铃中断等等       */
} LW_RTC_FUNCS;
  • RTC_pfuncInit :RTC 初始化。
  • RTC_pfuncSet :RTC 时间设置。
  • RTC_pfuncGet :RTC 时间获取。
  • RTC_pfuncIoctl :RTC 其他 I/O 控制。

RTC 设备接口函数获取

RTCDEV_prtcfuncs 接口函数由驱动中 rtcGetFuncs 函数获取。其调用关系如下:

PLW_RTC_FUNCS   rtcGetFuncs (VOID)
{
    static LW_RTC_FUNCS    rtcfuncs = {LW_NULL, 
                                       __rtcSetTime, 
                                       __rtcGetTime,
                                       LW_NULL};
    return  (&rtcfuncs);
}

可见,RTC 的硬件操作函数主要实现了 RTC 的时间设置和时间获取函数。

__rtcSetTime :RTC 时间设置

#include <SylixOS.h>
static int  __rtcSetTime (PLW_RTC_FUNCS  prtcfuncs, time_t  *ptimeNow);

函数 __rtcSetTime 原型分析:

  • 此函数成功返回 ERROR_NONE
  • 参数 prtcfuncs 是 RTC 硬件接口函数。
  • 参数 ptimeNow 是当前时间,参数类型 time_t 是 long long 类型。

__rtcSetTime :RTC时间设置

#include <SylixOS.h>
static int  __rtcGetTime (PLW_RTC_FUNCS  prtcfuncs, time_t  *ptimeNow);

函数 __ rtcGetTime 原型分析:

  • 此函数成功返回 ERROR_NONE ,输出当前 RTC 时间。
  • 参数 prtcfuncs 是 RTC 硬件接口函数。
  • 参数 ptimeNow 是当前时间,参数类型 time_t 是 long long 类型。

RTC 设备驱动安装

调用 API_RtcDrvInstall 函数安装 RTC 设备驱动程序,其详细描述如下:

#include <SylixOS.h>
INT  API_RtcDrvInstall (VOID);

函数 API_RtcDrvInstall 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR

该函数中主要调用 API_IosDrvInstall 安装RTC的 Open、Close、Ioctl 操作函数,调用如下:

_G_iRtcDrvNum = iosDrvInstall(__rtcOpen, 
                              (FUNCPTR)LW_NULL, 
                              __rtcOpen,
                              __rtcClose,
                              LW_NULL,
                              LW_NULL,
                              __rtcIoctl);

__rtcOpen :打开 RTC 设备,打开操作主要是将 RTC 设备打开次数加 1。

#include <SylixOS.h>
static LONG  __rtcOpen (PLW_RTC_DEV         prtcdev, 
                        PCHAR               pcName, 
                        INT                 iFlags, 
                        INT                 iMode);

函数 __rtcOpen 原型分析:

  • 此函数成功返回 RTC 设备结构体。
  • 参数 prtcdev 是 RTC 设备结构体。
  • 参数 pcName 是设备名。
  • 参数 iFlags 是打开方式。
  • 参数 iMode 是打开方法。

__rtcClose :关闭RTC设备,关闭操作主要是将 RTC 设备打开次数减 1。

#include <SylixOS.h>
static LONG  __rtcClose (PLW_RTC_DEV    prtcdev);

函数 __rtcClose 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
  • 参数 prtcdev 是RTC设备结构体。

__rtcIoctl :控制RTC设备,主要是设置 RTC 时间和获取 RTC 时间。

#include <SylixOS.h>
static INT  __rtcIoctl (PLW_RTC_DEV   prtcdev, INT  iCmd, PVOID  pvArg);

函数 __rtcIoctl 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
  • 参数 prtcdev 是 RTC 设备结构体。
  • 参数 iCmd 是控制命令。
  • 参数 pvArg 是控制参数。

注意:
rtcIoctl 函数最终调用的就是 RTC 硬件接口函数中的 rtcSetTime 和 __rtcGetTime 函数来设置 RTC 时间和获取 RTC 时间。

RTC 设备创建和管理

调用 API_RtcDevCreate 创建 RTC 设备并将设备加入设备链表进行管理。其函数原型如下:

#include <SylixOS.h>
INT  API_RtcDevCreate (PLW_RTC_FUNCS   prtcfuncs);

函数 API_RtcDevCreate 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
  • 参数 prtcfuncs 是 RTC 操作函数集。

RTC 时间同步

RTC 设备创建完成并安装完设备驱动程序后,即可调用 API_RtcToSys 内核函数获取 RTC 当前时间,并将获取到的时间同步到系统时间。其函数原型如下:

#include <SylixOS.h>
INT  API_RtcToSys (VOID);

函数 API_RtcToSys 原型分析:

  • 此函数成功返回 ERROR_NONE ,失败返回 PX_ERROR
文档内容是否对您有所帮助?
有帮助
没帮助