1. 概述

在嵌入式系统中,实时时钟(RTC)是一个非常重要的外设模块,用于提供精确的时间信息。STM32 系列微控制器中的 RTC 模块大家可能已经非常熟悉,它通常需要一个 32.768KHz 的晶振来提供时钟源。而在 I.MX6U 系列处理器中,RTC 模块并不直接称为“RTC”,而是集成在 SNVS(Secure Non-Volatile Storage,安全非易失性存储)模块中。本文将详细介绍 I.MX6U 中的 SNVS RTC 模块,并讲解如何对其进行初始化和使用。

2. SNVS 模块简介

SNVS 模块是 I.MX6U 系列处理器中的一个低功耗外设模块,主要用于提供安全的非易失性存储功能。SNVS 模块包含以下几个主要部分:

  • 安全的实时计数器(SRTC):用于提供实时时钟功能。
  • 单调计数器(Monotonic Counter):用于计数,通常用于安全相关的应用。
  • 通用寄存器:用于存储一些配置信息和状态。

SNVS 模块分为两个子模块:SNVS_HP(高功耗域)和 SNVS_LP(低功耗域)。这两个子模块的电源来源如下:

  • SNVS_LP:由专用的 always-powered-on 电源域供电,系统主电源和备用电源都可以为其供电。
  • SNVS_HP:由系统主电源供电。

在系统主电源掉电后,SNVS_LP 会继续由纽扣电池供电,从而保证实时时钟的持续运行。

3. SNVS RTC 模块的工作原理

SNVS 模块中的 RTC 功能由 SRTC(Secure Real-Time Clock)提供。SRTC 本质上是一个定时器,只要给它提供 32.768KHz 的时钟源,它就会持续运行。SRTC 的计数器值保存在两个寄存器中:

  • SNVS_LPSRTCMR:保存计数器的高 15 位。
  • SNVS_LPSRTCLR:保存计数器的低 17 位。

通过读取这两个寄存器的值,可以获取当前的秒数,从而计算出当前的时间和日期。

3.1 寄存器说明

3.1.1 SNVS_HPCOMR 寄存器

  • NPSWA_EN (bit31):非特权软件访问控制位。如果非特权软件要访问 SNVS 模块,此位必须设置为 1。

3.1.2 SNVS_LPCR 寄存器

  • SRTC_ENV (bit0):SRTC 使能位。将此位设置为 1 可以启用 SRTC 计数器。

3.1.3 SNVS_LPSRTCMR 和 SNVS_LPSRTCLR 寄存器

  • SNVS_LPSRTCMR:保存 SRTC 计数器的高 15 位。
  • SNVS_LPSRTCLR:保存 SRTC 计数器的低 17 位。

注意:根据 NXP 官方的《I.MX6UL 参考手册》,SNVS_LPSRTCMR 和 SNVS_LPSRTCLR 寄存器的描述可能存在错误。实际使用中,SRTC 计数器是 32 位的,而不是 47 位。具体来说:

  • SNVS_LPSRTCMR 的 bit14:0 是 SRTC 计数器的高 15 位。
  • SNVS_LPSRTCLR 的 bit31:bit15 是 SRTC 计数器的低 17 位。

4. SNVS RTC 模块的初始化与配置

4.1 初始化步骤

  1. 初始化 SNVS_SRTC:首先需要初始化 SNVS_LP 中的 SRTC 模块。
  2. 设置 RTC 时间:在第一次使用 RTC 时,需要设置初始时间。
  3. 使能 RTC:配置好 RTC 并设置初始时间后,使能 RTC。

4.2 代码示例

以下是一个简单的 SNVS RTC 初始化与配置的代码示例:

#include <stdint.h>

// 定义 SNVS 相关寄存器地址
#define SNVS_HPCOMR   (*((volatile uint32_t *)0x020CC000))
#define SNVS_LPCR     (*((volatile uint32_t *)0x020CC038))
#define SNVS_LPSRTCMR (*((volatile uint32_t *)0x020CC03C))
#define SNVS_LPSRTCLR (*((volatile uint32_t *)0x020CC040))

// 初始化 SNVS RTC
void SNVS_RTC_Init(void) {
    // 使能非特权软件访问
    SNVS_HPCOMR |= (1 << 31);

    // 关闭 SRTC
    SNVS_LPCR &= ~(1 << 0);

    // 设置初始时间(例如:2023年1月1日 00:00:00)
    uint32_t initial_time = 1672531200; // 2023-01-01 00:00:00 的 Unix 时间戳
    SNVS_LPSRTCMR = (initial_time >> 17) & 0x7FFF; // 设置高15位
    SNVS_LPSRTCLR = (initial_time << 15) & 0xFFFF8000; // 设置低17位

    // 使能 SRTC
    SNVS_LPCR |= (1 << 0);
}

// 获取当前时间
uint32_t SNVS_RTC_GetTime(void) {
    uint32_t high = SNVS_LPSRTCMR & 0x7FFF;
    uint32_t low = (SNVS_LPSRTCLR >> 15) & 0x1FFFF;
    return (high << 17) | low;
}

4.3 寄存器配置表

寄存器名称地址位域描述
SNVS_HPCOMR0x020CC000NPSWA_EN(31)非特权软件访问控制位
SNVS_LPCR0x020CC038SRTC_ENV(0)SRTC 使能位
SNVS_LPSRTCMR0x020CC03Cbit14:0SRTC 计数器高 15 位
SNVS_LPSRTCLR0x020CC040bit31:15SRTC 计数器低 17 位

5. 硬件原理分析

在 I.MX6U-ALPHA 开发板上,SNVS 模块的电源由纽扣电池提供,确保在主电源掉电后 RTC 仍能正常运行。开发板上的 32.768KHz 晶振为 SRTC 提供时钟源。

5.1 电源结构图

  • VDD_HIGH_IN:系统主电源,供给 SNVS_HP 和 SNVS_LP。
  • VDD_SNVS_IN:纽扣电池电源,仅供给 SNVS_LP,确保在主电源掉电后 SNVS_LP 继续运行。

6. 总结

本文详细介绍了 I.MX6U 系列处理器中的 SNVS RTC 模块,包括其工作原理、寄存器配置以及初始化步骤。通过本文的讲解,读者可以掌握如何在 I.MX6U 平台上使用 SNVS RTC 模块来实现实时时钟功能。在实际开发中,需要注意 NXP 官方手册中关于寄存器的描述可能存在错误,建议参考 SDK 包和 Linux 内核中的相关驱动代码进行开发。


参考资料

  • 《I.MX6UL 参考手册》
  • NXP SDK 包中的 fsl_snvs_hp.c
  • Linux 内核中的 rtc-snvs.c

相关链接