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 初始化步骤
- 初始化 SNVS_SRTC:首先需要初始化 SNVS_LP 中的 SRTC 模块。
- 设置 RTC 时间:在第一次使用 RTC 时,需要设置初始时间。
- 使能 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_HPCOMR | 0x020CC000 | NPSWA_EN(31) | 非特权软件访问控制位 |
SNVS_LPCR | 0x020CC038 | SRTC_ENV(0) | SRTC 使能位 |
SNVS_LPSRTCMR | 0x020CC03C | bit14:0 | SRTC 计数器高 15 位 |
SNVS_LPSRTCLR | 0x020CC040 | bit31:15 | SRTC 计数器低 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
相关链接: