嵌入式 —— RTC/SNVS深入详解 —— i.MX6ULL

嵌入式 ------ RTC/SNVS深入详解 ------ i.MX6ULL

文档版本 :修订版

平台 :NXP i.MX6ULL(ARM Cortex-A7)

参考手册 :芯片手册第 48 章 SNVS 模块

一句话总结 :本教程从 RTC 基本原理到 SNVS 模块架构,再到寄存器操作和驱动代码实现,手把手带你掌握嵌入式 RTC 驱动的完整开发流程。特别注意:初始化时先解权限,再开时钟------顺序不能错。


目录

  • [第 1 章 RTC 基础概念](#第 1 章 RTC 基础概念)
    • [1.1 什么是 RTC](#1.1 什么是 RTC)
    • [1.2 为什么选择 32.768KHz 晶振](#1.2 为什么选择 32.768KHz 晶振)
    • [1.3 RTC 的误差与校准](#1.3 RTC 的误差与校准)
  • [第 2 章 SNVS 模块架构详解](#第 2 章 SNVS 模块架构详解)
    • [2.1 SNVS 概述](#2.1 SNVS 概述)
    • [2.2 HP vs LP 双域设计](#2.2 HP vs LP 双域设计)
  • [第 3 章 SNVS 中断与报警功能](#第 3 章 SNVS 中断与报警功能)
    • [3.1 中断类型概述](#3.1 中断类型概述)
    • [3.2 时间报警中断](#3.2 时间报警中断)
    • [3.3 周期性中断](#3.3 周期性中断)
    • [3.4 时间报警 vs 周期性中断对比](#3.4 时间报警 vs 周期性中断对比)
  • [第 4 章 SNVS 相关寄存器详解](#第 4 章 SNVS 相关寄存器详解)
    • [4.1 寄存器体系总览](#4.1 寄存器体系总览)
    • [4.2 Command 寄存器(HPGCOMR)](#4.2 Command 寄存器(HPGCOMR))
    • [4.3 控制寄存器(HPCR)](#4.3 控制寄存器(HPCR))
    • [4.4 状态寄存器(HPSR)](#4.4 状态寄存器(HPSR))
    • [4.5 计数器寄存器(HPRTCMR / HPRTCLR)](#4.5 计数器寄存器(HPRTCMR / HPRTCLR))
    • [4.6 闹钟寄存器(HPALMR / HPALR)](#4.6 闹钟寄存器(HPALMR / HPALR))
  • [第 5 章 RTC 时间设置与获取编程](#第 5 章 RTC 时间设置与获取编程)
    • [5.1 编程流程总览](#5.1 编程流程总览)
    • [5.2 时钟使能](#5.2 时钟使能)
    • [5.3 RDC 权限配置](#5.3 RDC 权限配置)
    • [5.4 RTC 启停控制](#5.4 RTC 启停控制)
    • [5.5 时间戳与日历时间转换](#5.5 时间戳与日历时间转换)
    • [5.6 时间设置实现](#5.6 时间设置实现)
    • [5.7 时间读取实现(双次读取校验)](#5.7 时间读取实现(双次读取校验))
    • [5.8 测试验证](#5.8 测试验证)
  • [第 6 章 RTC Alarm 中断编程](#第 6 章 RTC Alarm 中断编程)
    • [6.1 中断号确定](#6.1 中断号确定)
    • [6.2 中断注册流程](#6.2 中断注册流程)
    • [6.3 闹钟设置实现](#6.3 闹钟设置实现)
    • [6.4 中断处理函数](#6.4 中断处理函数)
    • [6.5 调试与验证](#6.5 调试与验证)
  • [第 7 章 Linux 上的 RTC 编程](#第 7 章 Linux 上的 RTC 编程)
    • [7.1 Linux RTC 子系统](#7.1 Linux RTC 子系统)
    • [7.2 POSIX 时钟接口](#7.2 POSIX 时钟接口)
    • [7.3 接口对比表](#7.3 接口对比表)
    • [7.4 代码示例](#7.4 代码示例)
  • [第 8 章 附录](#第 8 章 附录)
    • [8.1 常见问题排查指南](#8.1 常见问题排查指南)
    • [8.2 术语对照表](#8.2 术语对照表)

第 1 章 RTC 基础概念

1.1 什么是 RTC

一句话总结:RTC 就像一块"自带备用电池的电子表"------系统关机了,它还在走。

1.1.1 概念引入

RTC (Real-Time Clock,实时时钟)是嵌入式系统中一个特殊的外设模块。它的核心使命是:在主电源断开时,依靠备用电池持续记录当前时间,包括年、月、日、时、分、秒。
#mermaid-svg-6KQHTZNt20rFJiB7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-6KQHTZNt20rFJiB7 .error-icon{fill:#552222;}#mermaid-svg-6KQHTZNt20rFJiB7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-6KQHTZNt20rFJiB7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-6KQHTZNt20rFJiB7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-6KQHTZNt20rFJiB7 .marker.cross{stroke:#333333;}#mermaid-svg-6KQHTZNt20rFJiB7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-6KQHTZNt20rFJiB7 p{margin:0;}#mermaid-svg-6KQHTZNt20rFJiB7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-6KQHTZNt20rFJiB7 .cluster-label text{fill:#333;}#mermaid-svg-6KQHTZNt20rFJiB7 .cluster-label span{color:#333;}#mermaid-svg-6KQHTZNt20rFJiB7 .cluster-label span p{background-color:transparent;}#mermaid-svg-6KQHTZNt20rFJiB7 .label text,#mermaid-svg-6KQHTZNt20rFJiB7 span{fill:#333;color:#333;}#mermaid-svg-6KQHTZNt20rFJiB7 .node rect,#mermaid-svg-6KQHTZNt20rFJiB7 .node circle,#mermaid-svg-6KQHTZNt20rFJiB7 .node ellipse,#mermaid-svg-6KQHTZNt20rFJiB7 .node polygon,#mermaid-svg-6KQHTZNt20rFJiB7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-6KQHTZNt20rFJiB7 .rough-node .label text,#mermaid-svg-6KQHTZNt20rFJiB7 .node .label text,#mermaid-svg-6KQHTZNt20rFJiB7 .image-shape .label,#mermaid-svg-6KQHTZNt20rFJiB7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-6KQHTZNt20rFJiB7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-6KQHTZNt20rFJiB7 .rough-node .label,#mermaid-svg-6KQHTZNt20rFJiB7 .node .label,#mermaid-svg-6KQHTZNt20rFJiB7 .image-shape .label,#mermaid-svg-6KQHTZNt20rFJiB7 .icon-shape .label{text-align:center;}#mermaid-svg-6KQHTZNt20rFJiB7 .node.clickable{cursor:pointer;}#mermaid-svg-6KQHTZNt20rFJiB7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-6KQHTZNt20rFJiB7 .arrowheadPath{fill:#333333;}#mermaid-svg-6KQHTZNt20rFJiB7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-6KQHTZNt20rFJiB7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-6KQHTZNt20rFJiB7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6KQHTZNt20rFJiB7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-6KQHTZNt20rFJiB7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6KQHTZNt20rFJiB7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-6KQHTZNt20rFJiB7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-6KQHTZNt20rFJiB7 .cluster text{fill:#333;}#mermaid-svg-6KQHTZNt20rFJiB7 .cluster span{color:#333;}#mermaid-svg-6KQHTZNt20rFJiB7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-6KQHTZNt20rFJiB7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-6KQHTZNt20rFJiB7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-6KQHTZNt20rFJiB7 .icon-shape,#mermaid-svg-6KQHTZNt20rFJiB7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-6KQHTZNt20rFJiB7 .icon-shape p,#mermaid-svg-6KQHTZNt20rFJiB7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-6KQHTZNt20rFJiB7 .icon-shape .label rect,#mermaid-svg-6KQHTZNt20rFJiB7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-6KQHTZNt20rFJiB7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-6KQHTZNt20rFJiB7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-6KQHTZNt20rFJiB7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 供电
独立供电
持续记录
断电后
断电后
系统主电源
CPU/内存/外设
纽扣电池 CR2032
RTC 模块
年月日时分秒
全部丢失
RTC 继续走时

1.1.2 生活类比

严谨类比 :RTC 就像家里的电表。即使电表箱拉了总闸(系统断电),电表内部的时间仍然在走------因为它内部有一块小电池。计算机主板上的 CMOS 电池也是同样原理,所以每次开机时间都是对的。

1.1.3 典型应用场景

场景 说明 严谨案例
日志时间戳 系统崩溃后根据最后时间定位故障 汽车黑匣子在碰撞后记录最后时刻
定时唤醒 低功耗模式下定时醒来工作 气象站每小时醒来采集一次数据,其余时间休眠
闹钟功能 到达指定时间触发事件 智能电表每天凌晨 0:00 上报用电数据
文件时间戳 记录文件创建/修改时间 Linux 的 stat 命令显示的三个时间

1.2 为什么选择 32.768KHz 晶振

一句话总结:32,768 = 2¹⁵,15 级二进制分频即可得到精确的 1 秒信号------这是成本、精度、功耗三者之间经过数十年验证的最佳平衡点。

1.2.1 数学原理

#mermaid-svg-IOEbjoR3ZOwMNbem{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IOEbjoR3ZOwMNbem .error-icon{fill:#552222;}#mermaid-svg-IOEbjoR3ZOwMNbem .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IOEbjoR3ZOwMNbem .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IOEbjoR3ZOwMNbem .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IOEbjoR3ZOwMNbem .marker.cross{stroke:#333333;}#mermaid-svg-IOEbjoR3ZOwMNbem svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IOEbjoR3ZOwMNbem p{margin:0;}#mermaid-svg-IOEbjoR3ZOwMNbem .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IOEbjoR3ZOwMNbem .cluster-label text{fill:#333;}#mermaid-svg-IOEbjoR3ZOwMNbem .cluster-label span{color:#333;}#mermaid-svg-IOEbjoR3ZOwMNbem .cluster-label span p{background-color:transparent;}#mermaid-svg-IOEbjoR3ZOwMNbem .label text,#mermaid-svg-IOEbjoR3ZOwMNbem span{fill:#333;color:#333;}#mermaid-svg-IOEbjoR3ZOwMNbem .node rect,#mermaid-svg-IOEbjoR3ZOwMNbem .node circle,#mermaid-svg-IOEbjoR3ZOwMNbem .node ellipse,#mermaid-svg-IOEbjoR3ZOwMNbem .node polygon,#mermaid-svg-IOEbjoR3ZOwMNbem .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IOEbjoR3ZOwMNbem .rough-node .label text,#mermaid-svg-IOEbjoR3ZOwMNbem .node .label text,#mermaid-svg-IOEbjoR3ZOwMNbem .image-shape .label,#mermaid-svg-IOEbjoR3ZOwMNbem .icon-shape .label{text-anchor:middle;}#mermaid-svg-IOEbjoR3ZOwMNbem .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IOEbjoR3ZOwMNbem .rough-node .label,#mermaid-svg-IOEbjoR3ZOwMNbem .node .label,#mermaid-svg-IOEbjoR3ZOwMNbem .image-shape .label,#mermaid-svg-IOEbjoR3ZOwMNbem .icon-shape .label{text-align:center;}#mermaid-svg-IOEbjoR3ZOwMNbem .node.clickable{cursor:pointer;}#mermaid-svg-IOEbjoR3ZOwMNbem .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IOEbjoR3ZOwMNbem .arrowheadPath{fill:#333333;}#mermaid-svg-IOEbjoR3ZOwMNbem .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IOEbjoR3ZOwMNbem .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IOEbjoR3ZOwMNbem .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IOEbjoR3ZOwMNbem .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IOEbjoR3ZOwMNbem .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IOEbjoR3ZOwMNbem .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IOEbjoR3ZOwMNbem .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IOEbjoR3ZOwMNbem .cluster text{fill:#333;}#mermaid-svg-IOEbjoR3ZOwMNbem .cluster span{color:#333;}#mermaid-svg-IOEbjoR3ZOwMNbem div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IOEbjoR3ZOwMNbem .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IOEbjoR3ZOwMNbem rect.text{fill:none;stroke-width:0;}#mermaid-svg-IOEbjoR3ZOwMNbem .icon-shape,#mermaid-svg-IOEbjoR3ZOwMNbem .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IOEbjoR3ZOwMNbem .icon-shape p,#mermaid-svg-IOEbjoR3ZOwMNbem .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IOEbjoR3ZOwMNbem .icon-shape .label rect,#mermaid-svg-IOEbjoR3ZOwMNbem .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IOEbjoR3ZOwMNbem .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IOEbjoR3ZOwMNbem .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IOEbjoR3ZOwMNbem :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ÷2
÷2
... 共15级
1秒一次
32.768KHz 晶振
16.384KHz
8.192KHz
1Hz
RTC 计数器 +1

32.768KHz 这个数字不是随意选的:

  • 32,768 = 2¹⁵:经过 15 级二分频器,恰好得到 1Hz(1 秒触发一次)的精确信号
  • 如果用 32KHz(32,000),分频后是 0.9765Hz,每天误差 2,073 秒------无法接受
  • 如果用 33KHz,分频后是 1.007Hz,同样有累积误差

1.2.2 PMU 与手表的类比

严谨类比 :32.768KHz 晶振被业内称为"表晶"(Watch Crystal),因为最早就是为石英手表设计的。一块普通石英手表每天误差约 ±0.5 秒,而 RTC 晶振的精度为 ±20ppm(每天约 ±1.7 秒)。手表靠的是机械齿轮分频,RTC 靠的是电子二进制计数器分频,原理相同但实现方式不同。


1.3 RTC 的误差与校准

一句话总结:RTC 不是绝对精确的------每天误差几秒是正常的,联网同步才是终极解决方案。

1.3.1 误差来源

误差来源 典型值 影响 严谨说明
晶振初始精度 ±20ppm 每天 ±1.73 秒 同一批次晶振也有个体差异
温度漂移 ±0.04ppm/°C² 温差 30°C 时约 ±36ppm 呈抛物线型,25°C 时最准
老化 ±3ppm/年 每年累积偏差增加 前 1-2 年老化最快,之后趋于稳定

ppm 的含义:parts per million,百万分之一。±20ppm 意味着每 1,000,000 秒(约 11.6 天)偏差 20 秒,折合每天约 1.73 秒。

1.3.2 校准方法对比

方法 精度 成本 适用场景
NTP 网络同步 毫秒级 需联网 电脑、手机、联网设备
GPS 授时 纳秒级 需 GPS 模块 基站、变电站、金融交易
软件补偿 亚秒级 零成本 不联网的嵌入式设备
TCXO 温补晶振 ±2.5ppm 贵 3-5 倍 高精度仪表、医疗设备

#mermaid-svg-BDVAKWNbxcdjIYts{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-BDVAKWNbxcdjIYts .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-BDVAKWNbxcdjIYts .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-BDVAKWNbxcdjIYts .error-icon{fill:#552222;}#mermaid-svg-BDVAKWNbxcdjIYts .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-BDVAKWNbxcdjIYts .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-BDVAKWNbxcdjIYts .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-BDVAKWNbxcdjIYts .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-BDVAKWNbxcdjIYts .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-BDVAKWNbxcdjIYts .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-BDVAKWNbxcdjIYts .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-BDVAKWNbxcdjIYts .marker{fill:#333333;stroke:#333333;}#mermaid-svg-BDVAKWNbxcdjIYts .marker.cross{stroke:#333333;}#mermaid-svg-BDVAKWNbxcdjIYts svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-BDVAKWNbxcdjIYts p{margin:0;}#mermaid-svg-BDVAKWNbxcdjIYts .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-BDVAKWNbxcdjIYts .cluster-label text{fill:#333;}#mermaid-svg-BDVAKWNbxcdjIYts .cluster-label span{color:#333;}#mermaid-svg-BDVAKWNbxcdjIYts .cluster-label span p{background-color:transparent;}#mermaid-svg-BDVAKWNbxcdjIYts .label text,#mermaid-svg-BDVAKWNbxcdjIYts span{fill:#333;color:#333;}#mermaid-svg-BDVAKWNbxcdjIYts .node rect,#mermaid-svg-BDVAKWNbxcdjIYts .node circle,#mermaid-svg-BDVAKWNbxcdjIYts .node ellipse,#mermaid-svg-BDVAKWNbxcdjIYts .node polygon,#mermaid-svg-BDVAKWNbxcdjIYts .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-BDVAKWNbxcdjIYts .rough-node .label text,#mermaid-svg-BDVAKWNbxcdjIYts .node .label text,#mermaid-svg-BDVAKWNbxcdjIYts .image-shape .label,#mermaid-svg-BDVAKWNbxcdjIYts .icon-shape .label{text-anchor:middle;}#mermaid-svg-BDVAKWNbxcdjIYts .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-BDVAKWNbxcdjIYts .rough-node .label,#mermaid-svg-BDVAKWNbxcdjIYts .node .label,#mermaid-svg-BDVAKWNbxcdjIYts .image-shape .label,#mermaid-svg-BDVAKWNbxcdjIYts .icon-shape .label{text-align:center;}#mermaid-svg-BDVAKWNbxcdjIYts .node.clickable{cursor:pointer;}#mermaid-svg-BDVAKWNbxcdjIYts .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-BDVAKWNbxcdjIYts .arrowheadPath{fill:#333333;}#mermaid-svg-BDVAKWNbxcdjIYts .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-BDVAKWNbxcdjIYts .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-BDVAKWNbxcdjIYts .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BDVAKWNbxcdjIYts .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-BDVAKWNbxcdjIYts .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BDVAKWNbxcdjIYts .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-BDVAKWNbxcdjIYts .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-BDVAKWNbxcdjIYts .cluster text{fill:#333;}#mermaid-svg-BDVAKWNbxcdjIYts .cluster span{color:#333;}#mermaid-svg-BDVAKWNbxcdjIYts div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-BDVAKWNbxcdjIYts .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-BDVAKWNbxcdjIYts rect.text{fill:none;stroke-width:0;}#mermaid-svg-BDVAKWNbxcdjIYts .icon-shape,#mermaid-svg-BDVAKWNbxcdjIYts .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-BDVAKWNbxcdjIYts .icon-shape p,#mermaid-svg-BDVAKWNbxcdjIYts .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-BDVAKWNbxcdjIYts .icon-shape .label rect,#mermaid-svg-BDVAKWNbxcdjIYts .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-BDVAKWNbxcdjIYts .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-BDVAKWNbxcdjIYts .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-BDVAKWNbxcdjIYts :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 误差来源






晶振初始精度 ±20ppm
每天误差 ~1.73秒
温度漂移
老化
是否需要高精度?
直接使用 RTC
是否联网?
NTP 同步
预算充足?
TCXO 晶振
软件补偿算法


第 2 章 SNVS 模块架构详解

2.1 SNVS 概述

一句话总结:SNVS(Secure Non-Volatile Storage)是 i.MX6ULL 中集成了 RTC 功能的"安全金库"------分公共区(HP)和保险库(LP),电池不断电,时间就不丢。

2.1.1 什么是 SNVS

在 NXP i.MX6ULL 芯片手册中,RTC 功能并非由独立的 RTC 模块提供,而是集成在 SNVS(Secure Non-Volatile Storage,安全非易失性存储)模块中(参考手册第 48 章)。

SNVS 是一个功能强大的安全子系统,包含:

  • 实时计数器(RTC):记录当前时间
  • 单调计数器(Monotonic Counter):只增不减,用于安全用途
  • 通用功能寄存器:存储敏感数据(如加密密钥)
  • 报警功能:时间到达触发中断

2.1.2 架构总览

#mermaid-svg-ds3zz1yMtOS6ojfT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ds3zz1yMtOS6ojfT .error-icon{fill:#552222;}#mermaid-svg-ds3zz1yMtOS6ojfT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ds3zz1yMtOS6ojfT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ds3zz1yMtOS6ojfT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ds3zz1yMtOS6ojfT .marker.cross{stroke:#333333;}#mermaid-svg-ds3zz1yMtOS6ojfT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ds3zz1yMtOS6ojfT p{margin:0;}#mermaid-svg-ds3zz1yMtOS6ojfT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ds3zz1yMtOS6ojfT .cluster-label text{fill:#333;}#mermaid-svg-ds3zz1yMtOS6ojfT .cluster-label span{color:#333;}#mermaid-svg-ds3zz1yMtOS6ojfT .cluster-label span p{background-color:transparent;}#mermaid-svg-ds3zz1yMtOS6ojfT .label text,#mermaid-svg-ds3zz1yMtOS6ojfT span{fill:#333;color:#333;}#mermaid-svg-ds3zz1yMtOS6ojfT .node rect,#mermaid-svg-ds3zz1yMtOS6ojfT .node circle,#mermaid-svg-ds3zz1yMtOS6ojfT .node ellipse,#mermaid-svg-ds3zz1yMtOS6ojfT .node polygon,#mermaid-svg-ds3zz1yMtOS6ojfT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ds3zz1yMtOS6ojfT .rough-node .label text,#mermaid-svg-ds3zz1yMtOS6ojfT .node .label text,#mermaid-svg-ds3zz1yMtOS6ojfT .image-shape .label,#mermaid-svg-ds3zz1yMtOS6ojfT .icon-shape .label{text-anchor:middle;}#mermaid-svg-ds3zz1yMtOS6ojfT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ds3zz1yMtOS6ojfT .rough-node .label,#mermaid-svg-ds3zz1yMtOS6ojfT .node .label,#mermaid-svg-ds3zz1yMtOS6ojfT .image-shape .label,#mermaid-svg-ds3zz1yMtOS6ojfT .icon-shape .label{text-align:center;}#mermaid-svg-ds3zz1yMtOS6ojfT .node.clickable{cursor:pointer;}#mermaid-svg-ds3zz1yMtOS6ojfT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ds3zz1yMtOS6ojfT .arrowheadPath{fill:#333333;}#mermaid-svg-ds3zz1yMtOS6ojfT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ds3zz1yMtOS6ojfT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ds3zz1yMtOS6ojfT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ds3zz1yMtOS6ojfT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ds3zz1yMtOS6ojfT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ds3zz1yMtOS6ojfT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ds3zz1yMtOS6ojfT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ds3zz1yMtOS6ojfT .cluster text{fill:#333;}#mermaid-svg-ds3zz1yMtOS6ojfT .cluster span{color:#333;}#mermaid-svg-ds3zz1yMtOS6ojfT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ds3zz1yMtOS6ojfT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ds3zz1yMtOS6ojfT rect.text{fill:none;stroke-width:0;}#mermaid-svg-ds3zz1yMtOS6ojfT .icon-shape,#mermaid-svg-ds3zz1yMtOS6ojfT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ds3zz1yMtOS6ojfT .icon-shape p,#mermaid-svg-ds3zz1yMtOS6ojfT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ds3zz1yMtOS6ojfT .icon-shape .label rect,#mermaid-svg-ds3zz1yMtOS6ojfT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ds3zz1yMtOS6ojfT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ds3zz1yMtOS6ojfT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ds3zz1yMtOS6ojfT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SNVS 模块
通过专用接口通信
AHB/APB 总线
LP 域 - 低功耗
单调计数器
通用功能寄存器
独立 32.768KHz 振荡器
HP 域 - 高功耗
IP 总线接口
实时计数器
报警功能
控制/状态寄存器
LP 访问接口
ARM Cortex-A7 核
主电源 VDD_HIGH
纽扣电池 VBAT


2.2 HP vs LP 双域设计

2.2.1 先看对比

在深入阅读正文之前,先通过对比图建立认知框架:
#mermaid-svg-U6ijqc4oqx7wPAnU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-U6ijqc4oqx7wPAnU .error-icon{fill:#552222;}#mermaid-svg-U6ijqc4oqx7wPAnU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-U6ijqc4oqx7wPAnU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-U6ijqc4oqx7wPAnU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-U6ijqc4oqx7wPAnU .marker.cross{stroke:#333333;}#mermaid-svg-U6ijqc4oqx7wPAnU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-U6ijqc4oqx7wPAnU p{margin:0;}#mermaid-svg-U6ijqc4oqx7wPAnU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-U6ijqc4oqx7wPAnU .cluster-label text{fill:#333;}#mermaid-svg-U6ijqc4oqx7wPAnU .cluster-label span{color:#333;}#mermaid-svg-U6ijqc4oqx7wPAnU .cluster-label span p{background-color:transparent;}#mermaid-svg-U6ijqc4oqx7wPAnU .label text,#mermaid-svg-U6ijqc4oqx7wPAnU span{fill:#333;color:#333;}#mermaid-svg-U6ijqc4oqx7wPAnU .node rect,#mermaid-svg-U6ijqc4oqx7wPAnU .node circle,#mermaid-svg-U6ijqc4oqx7wPAnU .node ellipse,#mermaid-svg-U6ijqc4oqx7wPAnU .node polygon,#mermaid-svg-U6ijqc4oqx7wPAnU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-U6ijqc4oqx7wPAnU .rough-node .label text,#mermaid-svg-U6ijqc4oqx7wPAnU .node .label text,#mermaid-svg-U6ijqc4oqx7wPAnU .image-shape .label,#mermaid-svg-U6ijqc4oqx7wPAnU .icon-shape .label{text-anchor:middle;}#mermaid-svg-U6ijqc4oqx7wPAnU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-U6ijqc4oqx7wPAnU .rough-node .label,#mermaid-svg-U6ijqc4oqx7wPAnU .node .label,#mermaid-svg-U6ijqc4oqx7wPAnU .image-shape .label,#mermaid-svg-U6ijqc4oqx7wPAnU .icon-shape .label{text-align:center;}#mermaid-svg-U6ijqc4oqx7wPAnU .node.clickable{cursor:pointer;}#mermaid-svg-U6ijqc4oqx7wPAnU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-U6ijqc4oqx7wPAnU .arrowheadPath{fill:#333333;}#mermaid-svg-U6ijqc4oqx7wPAnU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-U6ijqc4oqx7wPAnU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-U6ijqc4oqx7wPAnU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-U6ijqc4oqx7wPAnU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-U6ijqc4oqx7wPAnU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-U6ijqc4oqx7wPAnU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-U6ijqc4oqx7wPAnU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-U6ijqc4oqx7wPAnU .cluster text{fill:#333;}#mermaid-svg-U6ijqc4oqx7wPAnU .cluster span{color:#333;}#mermaid-svg-U6ijqc4oqx7wPAnU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-U6ijqc4oqx7wPAnU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-U6ijqc4oqx7wPAnU rect.text{fill:none;stroke-width:0;}#mermaid-svg-U6ijqc4oqx7wPAnU .icon-shape,#mermaid-svg-U6ijqc4oqx7wPAnU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-U6ijqc4oqx7wPAnU .icon-shape p,#mermaid-svg-U6ijqc4oqx7wPAnU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-U6ijqc4oqx7wPAnU .icon-shape .label rect,#mermaid-svg-U6ijqc4oqx7wPAnU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-U6ijqc4oqx7wPAnU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-U6ijqc4oqx7wPAnU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-U6ijqc4oqx7wPAnU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 关键差异
关键差异
SNVS 模块
HP 高功耗域
LP 低功耗域
供电: 主电源 VDD_HIGH
断电后: 数据全部丢失
与 ARM 核: 直接通信
功能: RTC 计时 + 报警 + 中断
功耗: 毫瓦级
供电: 纽扣电池 VBAT
断电后: 数据保持, 持续计时
与 ARM 核: 间接通信, 通过 HP
功能: 安全存储 + 单调计数
功耗: 微瓦级, < 1μA

2.2.2 HP 部分详解

HP(High Power Domain,高功耗域)由芯片主电源 VDD_HIGH 供电,负责与 ARM 核通信、权限控制、常规 RTC 计时和报警功能。

HP 的组成单元:

单元 功能 类比
IP 总线接口 通过 AHB/APB 总线与 ARM 核通信 银行柜台的叫号系统
LP 访问接口 访问 LP 的唯一通道 保险库的专用通道
实时计数器 32 位带报警功能的秒计数器 电子秒表
控制/状态寄存器 管理启停、报警使能、中断状态 遥控器上的按钮

严谨类比 :HP 相当于银行的营业大厅。有工作人员(ARM 核通信)、有柜台窗口(IP 总线接口)、有服务电话(LP 访问接口)。但营业大厅需要主电源供电------停电了,大厅就关门了。

2.2.3 LP 部分详解

LP(Low Power Domain,低功耗域)由纽扣电池 VBAT 独立供电,主电源断电后仍能持续计时。

LP 的核心组件:

组件 功能 关键特性
非反转单调计数器 持续递增、永不归零 提供安全的时间基准
通用功能寄存器 存储敏感数据 可存加密密钥等
独立振荡器 32.768KHz 芯片其他部分断电也能工作

严谨类比 :LP 相当于银行的保险库。有自己的独立供电系统(UPS),即使整栋楼停电(主电源断开),保险库里的监控和计时系统仍在运行。但要从外部查看保险库里的数据,必须通过营业大厅的授权通道(HP 访问接口)。

2.2.4 HP vs LP 详细对比表

对比维度 HP 部分 LP 部分
供电来源 芯片主电源 VDD_HIGH 备用电池 VBAT(纽扣电池)
断电后数据 全部丢失 保持(电池有电时)
断电后计时 停止 持续运行
与 ARM 核通信 直接,通过 IP 总线接口 间接,必须通过 HP
访问权限 任何软件可访问(配置后) 需通过 HP,部分需 NXP 授权
主要功能 RTC 计时、报警、中断、与 CPU 通信 数据安全存储、单调计数、低功耗计时
典型使用场景 普通 RTC 应用(无电池场景) 安全敏感数据 + 掉电保持计时
寄存器操作 操作 HP 部分寄存器 操作 LP 部分寄存器(方式相同)
功耗水平 毫瓦级(mA 级) 微瓦级(μA 级,< 1μA)
CR2032 续航 不适用 理论 > 20 年(225mAh / 1μA)

2.2.5 通信机制

一句话总结:HP 是 LP 的"守门员"------所有对 LP 的访问都必须通过 HP,且 HP 必须在有电时才能开门。
LP 域 HP 域 ARM 核 LP 域 HP 域 ARM 核 #mermaid-svg-V6HSPpNp7EnJzqgj{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-V6HSPpNp7EnJzqgj .error-icon{fill:#552222;}#mermaid-svg-V6HSPpNp7EnJzqgj .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-V6HSPpNp7EnJzqgj .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-V6HSPpNp7EnJzqgj .marker{fill:#333333;stroke:#333333;}#mermaid-svg-V6HSPpNp7EnJzqgj .marker.cross{stroke:#333333;}#mermaid-svg-V6HSPpNp7EnJzqgj svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-V6HSPpNp7EnJzqgj p{margin:0;}#mermaid-svg-V6HSPpNp7EnJzqgj .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-V6HSPpNp7EnJzqgj text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-V6HSPpNp7EnJzqgj .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-V6HSPpNp7EnJzqgj .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-V6HSPpNp7EnJzqgj .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-V6HSPpNp7EnJzqgj .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-V6HSPpNp7EnJzqgj #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-V6HSPpNp7EnJzqgj .sequenceNumber{fill:white;}#mermaid-svg-V6HSPpNp7EnJzqgj #sequencenumber{fill:#333;}#mermaid-svg-V6HSPpNp7EnJzqgj #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-V6HSPpNp7EnJzqgj .messageText{fill:#333;stroke:none;}#mermaid-svg-V6HSPpNp7EnJzqgj .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-V6HSPpNp7EnJzqgj .labelText,#mermaid-svg-V6HSPpNp7EnJzqgj .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-V6HSPpNp7EnJzqgj .loopText,#mermaid-svg-V6HSPpNp7EnJzqgj .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-V6HSPpNp7EnJzqgj .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-V6HSPpNp7EnJzqgj .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-V6HSPpNp7EnJzqgj .noteText,#mermaid-svg-V6HSPpNp7EnJzqgj .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-V6HSPpNp7EnJzqgj .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-V6HSPpNp7EnJzqgj .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-V6HSPpNp7EnJzqgj .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-V6HSPpNp7EnJzqgj .actorPopupMenu{position:absolute;}#mermaid-svg-V6HSPpNp7EnJzqgj .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-V6HSPpNp7EnJzqgj .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-V6HSPpNp7EnJzqgj .actor-man circle,#mermaid-svg-V6HSPpNp7EnJzqgj line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-V6HSPpNp7EnJzqgj :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} HP 必须上电才能完成此流程 1. 发送读 LP 寄存器请求 2. 检查权限策略 3. 通过专用接口转发请求 4. 返回 LP 数据 5. 返回数据给 CPU

关键规则:

  • 单向访问:只能通过 HP 访问 LP,不能直接访问 LP 寄存器
  • HP 必须上电:HP 断电时,LP 虽然仍在运行,但外部无法读取其数据
  • 权限策略:HP 可设置是否允许外部访问 LP 中的特殊寄存器
  • 安全保护:部分敏感寄存器需 NXP 授权,手册中不会公开完整细节

第 3 章 SNVS 中断与报警功能

3.1 中断类型概述

一句话总结:SNVS 提供三种中断------时间报警中断(像闹钟)、周期性中断(像心跳)、电源开关中断(像按键检测)。
#mermaid-svg-bKzco6ocoGwK9wgY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-bKzco6ocoGwK9wgY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-bKzco6ocoGwK9wgY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-bKzco6ocoGwK9wgY .error-icon{fill:#552222;}#mermaid-svg-bKzco6ocoGwK9wgY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-bKzco6ocoGwK9wgY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-bKzco6ocoGwK9wgY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-bKzco6ocoGwK9wgY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-bKzco6ocoGwK9wgY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-bKzco6ocoGwK9wgY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-bKzco6ocoGwK9wgY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-bKzco6ocoGwK9wgY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-bKzco6ocoGwK9wgY .marker.cross{stroke:#333333;}#mermaid-svg-bKzco6ocoGwK9wgY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-bKzco6ocoGwK9wgY p{margin:0;}#mermaid-svg-bKzco6ocoGwK9wgY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-bKzco6ocoGwK9wgY .cluster-label text{fill:#333;}#mermaid-svg-bKzco6ocoGwK9wgY .cluster-label span{color:#333;}#mermaid-svg-bKzco6ocoGwK9wgY .cluster-label span p{background-color:transparent;}#mermaid-svg-bKzco6ocoGwK9wgY .label text,#mermaid-svg-bKzco6ocoGwK9wgY span{fill:#333;color:#333;}#mermaid-svg-bKzco6ocoGwK9wgY .node rect,#mermaid-svg-bKzco6ocoGwK9wgY .node circle,#mermaid-svg-bKzco6ocoGwK9wgY .node ellipse,#mermaid-svg-bKzco6ocoGwK9wgY .node polygon,#mermaid-svg-bKzco6ocoGwK9wgY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-bKzco6ocoGwK9wgY .rough-node .label text,#mermaid-svg-bKzco6ocoGwK9wgY .node .label text,#mermaid-svg-bKzco6ocoGwK9wgY .image-shape .label,#mermaid-svg-bKzco6ocoGwK9wgY .icon-shape .label{text-anchor:middle;}#mermaid-svg-bKzco6ocoGwK9wgY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-bKzco6ocoGwK9wgY .rough-node .label,#mermaid-svg-bKzco6ocoGwK9wgY .node .label,#mermaid-svg-bKzco6ocoGwK9wgY .image-shape .label,#mermaid-svg-bKzco6ocoGwK9wgY .icon-shape .label{text-align:center;}#mermaid-svg-bKzco6ocoGwK9wgY .node.clickable{cursor:pointer;}#mermaid-svg-bKzco6ocoGwK9wgY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-bKzco6ocoGwK9wgY .arrowheadPath{fill:#333333;}#mermaid-svg-bKzco6ocoGwK9wgY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-bKzco6ocoGwK9wgY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-bKzco6ocoGwK9wgY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bKzco6ocoGwK9wgY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-bKzco6ocoGwK9wgY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bKzco6ocoGwK9wgY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-bKzco6ocoGwK9wgY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-bKzco6ocoGwK9wgY .cluster text{fill:#333;}#mermaid-svg-bKzco6ocoGwK9wgY .cluster span{color:#333;}#mermaid-svg-bKzco6ocoGwK9wgY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-bKzco6ocoGwK9wgY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-bKzco6ocoGwK9wgY rect.text{fill:none;stroke-width:0;}#mermaid-svg-bKzco6ocoGwK9wgY .icon-shape,#mermaid-svg-bKzco6ocoGwK9wgY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-bKzco6ocoGwK9wgY .icon-shape p,#mermaid-svg-bKzco6ocoGwK9wgY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-bKzco6ocoGwK9wgY .icon-shape .label rect,#mermaid-svg-bKzco6ocoGwK9wgY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-bKzco6ocoGwK9wgY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-bKzco6ocoGwK9wgY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-bKzco6ocoGwK9wgY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SNVS 中断源
时间报警中断
周期性中断
电源开关中断
触发: 计数器值 == 闹钟寄存器值
特性: 单次触发
用途: 定时唤醒/闹钟提醒
触发: 特定位 0↔1 跳变
特性: 重复触发
用途: 心跳包/周期采集
触发: 电源按键按下
特性: 含 50ms 硬件去抖
用途: 电源事件检测


3.2 时间报警中断

一句话总结:时间报警中断就像手机闹钟------你设定一个时间,RTC 走到那一刻就触发中断。

3.2.1 工作机制

  1. 设置闹钟时间:将目标时间转换为秒数,写入闹钟寄存器(HPALMR/HPALR)
  2. 硬件自动比较:硬件持续比较当前 RTC 计数器值与闹钟寄存器值
  3. 触发中断:两者相等时产生中断信号
  4. 唤醒功能:在低功耗模式下可唤醒 CPU

严谨案例 :智能电表要求每天凌晨 0:00 上报用电数据。电表进入低功耗模式后,设置 RTC 闹钟为 00:00:00。时间到达时,闹钟中断唤醒 CPU,CPU 执行数据上报,完成后再次进入低功耗模式。整个过程平均功耗仅几十微安,一节 CR2032 电池可用 5 年以上。


3.3 周期性中断

一句话总结:周期性中断就像心跳------每隔固定时间产生一次,间隔由你选择计数器的哪一位来决定。

3.3.1 工作原理

#mermaid-svg-PWKmtkxBBsD8cPNN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PWKmtkxBBsD8cPNN .error-icon{fill:#552222;}#mermaid-svg-PWKmtkxBBsD8cPNN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PWKmtkxBBsD8cPNN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PWKmtkxBBsD8cPNN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PWKmtkxBBsD8cPNN .marker.cross{stroke:#333333;}#mermaid-svg-PWKmtkxBBsD8cPNN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PWKmtkxBBsD8cPNN p{margin:0;}#mermaid-svg-PWKmtkxBBsD8cPNN .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PWKmtkxBBsD8cPNN .cluster-label text{fill:#333;}#mermaid-svg-PWKmtkxBBsD8cPNN .cluster-label span{color:#333;}#mermaid-svg-PWKmtkxBBsD8cPNN .cluster-label span p{background-color:transparent;}#mermaid-svg-PWKmtkxBBsD8cPNN .label text,#mermaid-svg-PWKmtkxBBsD8cPNN span{fill:#333;color:#333;}#mermaid-svg-PWKmtkxBBsD8cPNN .node rect,#mermaid-svg-PWKmtkxBBsD8cPNN .node circle,#mermaid-svg-PWKmtkxBBsD8cPNN .node ellipse,#mermaid-svg-PWKmtkxBBsD8cPNN .node polygon,#mermaid-svg-PWKmtkxBBsD8cPNN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PWKmtkxBBsD8cPNN .rough-node .label text,#mermaid-svg-PWKmtkxBBsD8cPNN .node .label text,#mermaid-svg-PWKmtkxBBsD8cPNN .image-shape .label,#mermaid-svg-PWKmtkxBBsD8cPNN .icon-shape .label{text-anchor:middle;}#mermaid-svg-PWKmtkxBBsD8cPNN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PWKmtkxBBsD8cPNN .rough-node .label,#mermaid-svg-PWKmtkxBBsD8cPNN .node .label,#mermaid-svg-PWKmtkxBBsD8cPNN .image-shape .label,#mermaid-svg-PWKmtkxBBsD8cPNN .icon-shape .label{text-align:center;}#mermaid-svg-PWKmtkxBBsD8cPNN .node.clickable{cursor:pointer;}#mermaid-svg-PWKmtkxBBsD8cPNN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PWKmtkxBBsD8cPNN .arrowheadPath{fill:#333333;}#mermaid-svg-PWKmtkxBBsD8cPNN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PWKmtkxBBsD8cPNN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PWKmtkxBBsD8cPNN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PWKmtkxBBsD8cPNN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PWKmtkxBBsD8cPNN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PWKmtkxBBsD8cPNN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PWKmtkxBBsD8cPNN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PWKmtkxBBsD8cPNN .cluster text{fill:#333;}#mermaid-svg-PWKmtkxBBsD8cPNN .cluster span{color:#333;}#mermaid-svg-PWKmtkxBBsD8cPNN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PWKmtkxBBsD8cPNN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PWKmtkxBBsD8cPNN rect.text{fill:none;stroke-width:0;}#mermaid-svg-PWKmtkxBBsD8cPNN .icon-shape,#mermaid-svg-PWKmtkxBBsD8cPNN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PWKmtkxBBsD8cPNN .icon-shape p,#mermaid-svg-PWKmtkxBBsD8cPNN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PWKmtkxBBsD8cPNN .icon-shape .label rect,#mermaid-svg-PWKmtkxBBsD8cPNN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PWKmtkxBBsD8cPNN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PWKmtkxBBsD8cPNN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PWKmtkxBBsD8cPNN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 16位自由运行计数器
每 32768 秒跳变
每 4 秒跳变
每 2 秒跳变
每秒跳变
选择哪一位
或选择
或选择
Bit 15
周期 32768 秒
Bit 2
周期 4 秒
Bit 1
周期 2 秒
Bit 0
周期 1 秒
HPCR 控制寄存器 Bit 4:7

3.3.2 频率计算表

假设计数器基准频率为 1Hz(每秒加 1):

选中位 (Bit) 该位的值 中断周期 说明
Bit 0 1 1 秒 每秒跳变一次,最频繁
Bit 1 2 2 秒 每 2 秒跳变一次
Bit 2 4 4 秒 每 4 秒跳变一次
Bit 3 8 8 秒 每 8 秒跳变一次
Bit n 2ⁿ 2ⁿ 秒 每 2ⁿ 秒跳变一次

严谨类比 :这就像大楼里的整点报时。你可以选择每 1 小时报一次(选 Bit 0)、每 2 小时报一次(选 Bit 1)、或者每 4 小时报一次(选 Bit 2)。选择不同的"位"就相当于选择了不同的报时间隔。


3.4 时间报警 vs 周期性中断对比

3.4.1 先看对比图

#mermaid-svg-qcdI6hyeRNRu4kBT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qcdI6hyeRNRu4kBT .error-icon{fill:#552222;}#mermaid-svg-qcdI6hyeRNRu4kBT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qcdI6hyeRNRu4kBT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qcdI6hyeRNRu4kBT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qcdI6hyeRNRu4kBT .marker.cross{stroke:#333333;}#mermaid-svg-qcdI6hyeRNRu4kBT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qcdI6hyeRNRu4kBT p{margin:0;}#mermaid-svg-qcdI6hyeRNRu4kBT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qcdI6hyeRNRu4kBT .cluster-label text{fill:#333;}#mermaid-svg-qcdI6hyeRNRu4kBT .cluster-label span{color:#333;}#mermaid-svg-qcdI6hyeRNRu4kBT .cluster-label span p{background-color:transparent;}#mermaid-svg-qcdI6hyeRNRu4kBT .label text,#mermaid-svg-qcdI6hyeRNRu4kBT span{fill:#333;color:#333;}#mermaid-svg-qcdI6hyeRNRu4kBT .node rect,#mermaid-svg-qcdI6hyeRNRu4kBT .node circle,#mermaid-svg-qcdI6hyeRNRu4kBT .node ellipse,#mermaid-svg-qcdI6hyeRNRu4kBT .node polygon,#mermaid-svg-qcdI6hyeRNRu4kBT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qcdI6hyeRNRu4kBT .rough-node .label text,#mermaid-svg-qcdI6hyeRNRu4kBT .node .label text,#mermaid-svg-qcdI6hyeRNRu4kBT .image-shape .label,#mermaid-svg-qcdI6hyeRNRu4kBT .icon-shape .label{text-anchor:middle;}#mermaid-svg-qcdI6hyeRNRu4kBT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qcdI6hyeRNRu4kBT .rough-node .label,#mermaid-svg-qcdI6hyeRNRu4kBT .node .label,#mermaid-svg-qcdI6hyeRNRu4kBT .image-shape .label,#mermaid-svg-qcdI6hyeRNRu4kBT .icon-shape .label{text-align:center;}#mermaid-svg-qcdI6hyeRNRu4kBT .node.clickable{cursor:pointer;}#mermaid-svg-qcdI6hyeRNRu4kBT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qcdI6hyeRNRu4kBT .arrowheadPath{fill:#333333;}#mermaid-svg-qcdI6hyeRNRu4kBT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qcdI6hyeRNRu4kBT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qcdI6hyeRNRu4kBT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qcdI6hyeRNRu4kBT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qcdI6hyeRNRu4kBT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qcdI6hyeRNRu4kBT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qcdI6hyeRNRu4kBT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qcdI6hyeRNRu4kBT .cluster text{fill:#333;}#mermaid-svg-qcdI6hyeRNRu4kBT .cluster span{color:#333;}#mermaid-svg-qcdI6hyeRNRu4kBT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qcdI6hyeRNRu4kBT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qcdI6hyeRNRu4kBT rect.text{fill:none;stroke-width:0;}#mermaid-svg-qcdI6hyeRNRu4kBT .icon-shape,#mermaid-svg-qcdI6hyeRNRu4kBT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qcdI6hyeRNRu4kBT .icon-shape p,#mermaid-svg-qcdI6hyeRNRu4kBT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qcdI6hyeRNRu4kBT .icon-shape .label rect,#mermaid-svg-qcdI6hyeRNRu4kBT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qcdI6hyeRNRu4kBT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qcdI6hyeRNRu4kBT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qcdI6hyeRNRu4kBT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} SNVS 中断
时间报警中断
周期性中断
触发生: 单次
时间设置: 具体年月日时分秒
精度: 秒级
实现: 较复杂, 需设闹钟寄存器
典型: 定时唤醒/闹钟提醒
类比: 手机闹钟
触发生: 重复
时间设置: 选位即可, 无需具体时间
精度: 取决于基准时钟和选位
实现: 简单, 只配控制寄存器位
典型: 周期采集/心跳包
类比: 节拍器

3.4.2 详细对比表

对比维度 时间报警中断 周期性中断
触发条件 计数器值 == 闹钟寄存器值 特定位发生 0→1 或 1→0 跳变
触发次数 单次(到达后触发一次) 周期性(每间隔固定时间触发)
时间设置 需要具体年月日时分秒 不需要具体时间,只需选位
精度控制 秒级精度 取决于基准时钟频率和选中的位
典型应用 定时唤醒、闹钟提醒、定时任务 周期性数据采集、心跳包、系统滴答
实现复杂度 较高(需设置闹钟寄存器、中断使能) 较低(只需配置控制寄存器位)
中断号 同一个 RTC 中断号(51) 同一个 RTC 中断号(需读状态寄存器区分)
生活类比 手机闹钟:"明天早上 7 点叫我" 节拍器:"每隔 1 秒响一次"
共同点 都由 RTC 硬件触发,走同一个中断线 都在中断处理函数中通过 HPSR 区分来源

第 4 章 SNVS 相关寄存器详解

4.1 寄存器体系总览

一句话总结:RTC 编程的核心就是 5 类寄存器------Command(权限控制)、Control(功能使能)、Status(状态查询)、Counter(时间存储)、Alarm(闹钟设置)。
#mermaid-svg-IDJOiocfk356HdNw{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-IDJOiocfk356HdNw .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-IDJOiocfk356HdNw .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-IDJOiocfk356HdNw .error-icon{fill:#552222;}#mermaid-svg-IDJOiocfk356HdNw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-IDJOiocfk356HdNw .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-IDJOiocfk356HdNw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-IDJOiocfk356HdNw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-IDJOiocfk356HdNw .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-IDJOiocfk356HdNw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-IDJOiocfk356HdNw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-IDJOiocfk356HdNw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-IDJOiocfk356HdNw .marker.cross{stroke:#333333;}#mermaid-svg-IDJOiocfk356HdNw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-IDJOiocfk356HdNw p{margin:0;}#mermaid-svg-IDJOiocfk356HdNw .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-IDJOiocfk356HdNw .cluster-label text{fill:#333;}#mermaid-svg-IDJOiocfk356HdNw .cluster-label span{color:#333;}#mermaid-svg-IDJOiocfk356HdNw .cluster-label span p{background-color:transparent;}#mermaid-svg-IDJOiocfk356HdNw .label text,#mermaid-svg-IDJOiocfk356HdNw span{fill:#333;color:#333;}#mermaid-svg-IDJOiocfk356HdNw .node rect,#mermaid-svg-IDJOiocfk356HdNw .node circle,#mermaid-svg-IDJOiocfk356HdNw .node ellipse,#mermaid-svg-IDJOiocfk356HdNw .node polygon,#mermaid-svg-IDJOiocfk356HdNw .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-IDJOiocfk356HdNw .rough-node .label text,#mermaid-svg-IDJOiocfk356HdNw .node .label text,#mermaid-svg-IDJOiocfk356HdNw .image-shape .label,#mermaid-svg-IDJOiocfk356HdNw .icon-shape .label{text-anchor:middle;}#mermaid-svg-IDJOiocfk356HdNw .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-IDJOiocfk356HdNw .rough-node .label,#mermaid-svg-IDJOiocfk356HdNw .node .label,#mermaid-svg-IDJOiocfk356HdNw .image-shape .label,#mermaid-svg-IDJOiocfk356HdNw .icon-shape .label{text-align:center;}#mermaid-svg-IDJOiocfk356HdNw .node.clickable{cursor:pointer;}#mermaid-svg-IDJOiocfk356HdNw .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-IDJOiocfk356HdNw .arrowheadPath{fill:#333333;}#mermaid-svg-IDJOiocfk356HdNw .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-IDJOiocfk356HdNw .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-IDJOiocfk356HdNw .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IDJOiocfk356HdNw .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-IDJOiocfk356HdNw .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IDJOiocfk356HdNw .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-IDJOiocfk356HdNw .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-IDJOiocfk356HdNw .cluster text{fill:#333;}#mermaid-svg-IDJOiocfk356HdNw .cluster span{color:#333;}#mermaid-svg-IDJOiocfk356HdNw div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-IDJOiocfk356HdNw .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-IDJOiocfk356HdNw rect.text{fill:none;stroke-width:0;}#mermaid-svg-IDJOiocfk356HdNw .icon-shape,#mermaid-svg-IDJOiocfk356HdNw .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-IDJOiocfk356HdNw .icon-shape p,#mermaid-svg-IDJOiocfk356HdNw .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-IDJOiocfk356HdNw .icon-shape .label rect,#mermaid-svg-IDJOiocfk356HdNw .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-IDJOiocfk356HdNw .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-IDJOiocfk356HdNw .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-IDJOiocfk356HdNw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ARM 核视角
Bit 31=1 解除权限
Bit 0 启停, Bit 1 闹钟
Bit 0 闹钟标志, Bit 1 周期标志
秒数高15位
秒数低17位
HPGCOMR

命令寄存器
HPCR

控制寄存器
HPSR

状态寄存器
HPRTCMR

计数器高位
HPRTCLR

计数器低位
HPALMR

闹钟高位
HPALR

闹钟低位
SNVS

4.1.1 寄存器总览对比表

寄存器名称 助记符 用途 关键位 操作注意点
Command 寄存器 HPGCOMR 权限控制 Bit 31:访问权限 最先设置,否则后续操作可能失败
控制寄存器 HPCR 功能使能 Bit 0=RTC_EN, Bit 1=ALM_EN, Bit 4:7=PISR 启停需等待同步完成
状态寄存器 HPSR 中断状态查询 Bit 0=ALM, Bit 1=PI 写 1 清除,用于中断处理
计数器 MSB HPRTCMR 秒数高 15 位 Bit 0:14 与 HPRTCLR 配合使用
计数器 LSB HPRTCLR 秒数低 17 位 Bit 15:31 位操作易出错,需特别小心
闹钟 MSB HPALMR 闹钟秒数高 15 位 Bit 0:14 设置前先关闭闹钟使能
闹钟 LSB HPALR 闹钟秒数低 17 位 Bit 15:31 设置后重新开启闹钟使能

4.2 Command 寄存器(HPGCOMR)

一句话总结:HPGCOMR 的第 31 位是"权限开关"------置 1 后任何软件都能访问特权寄存器,这是 RTC 编程的第一步。

4.2.1 位定义

位域 名称 功能描述 使用场景
Bit 31 HP_FIR_ACCESS 1=允许任何软件访问特权寄存器 必须设置,否则非特权模式访问会被拒绝
Bit 30:0 保留/安全相关 多与安全相关 普通 RTC 编程无需关注

4.2.2 代码示例

c 复制代码
/* 解除寄存器访问权限限制 */
SNVS->HPGCOMR |= (1 << 31);   /* 设置第31位,允许所有软件访问 */

执行结果:执行后,任何特权/非特权模式的软件都可以正常访问 SNVS 模块的所有寄存器。如果不做此设置,在非特权模式下访问某些寄存器时会被硬件拦截,导致程序异常。
修正说明 :原文档中"第31位设为1后进入特定工作模式"的说法不够准确。更准确的描述是:该位控制的是访问权限策略,而非工作模式。它解决的是"谁可以访问"的问题,而不是"以什么模式运行"的问题。


4.3 控制寄存器(HPCR)

一句话总结:HPCR 是 RTC 的"遥控器"------Bit 0 控制启停,Bit 1 控制闹钟,Bit 4:7 控制周期中断频率。

4.3.1 位定义

位域 名称 功能描述 操作注意
Bit 0 RTC_EN RTC 计数器使能:1=开启,0=关闭 修改后需等待同步完成
Bit 1 ALM_EN 闹钟使能:1=开启,0=关闭 设置闹钟前必须先清零
Bit 4:7 PISR3:0 周期性中断选择位 值 0-15 对应选择 16 位计数器的第 0-15 位
Bit 2:3 保留 - 保留位,写 0

4.3.2 代码示例

c 复制代码
/* 启动 RTC 计数器 */
SNVS->HPCR |= (1 << 0);       /* 设置 RTC_EN 位 */

/* 停止 RTC 计数器 */
SNVS->HPCR &= ~(1 << 0);      /* 清除 RTC_EN 位 */

/* 开启闹钟功能 */
SNVS->HPCR |= (1 << 1);       /* 设置 ALM_EN 位 */

/* 关闭闹钟功能 */
SNVS->HPCR &= ~(1 << 1);      /* 清除 ALM_EN 位 */

/* 配置周期性中断:选择第2位,每4秒中断一次 */
SNVS->HPCR &= ~(0xF << 4);    /* 先清除 PISR 位 */
SNVS->HPCR |= (2 << 4);       /* 设置 PISR = 2,选择 bit 2 */

4.4 状态寄存器(HPSR)

一句话总结:HPSR 告诉你是谁触发了中断------Bit 0 是闹钟,Bit 1 是周期性中断,查到后记得"写 1 清除"。

4.4.1 位定义

位域 名称 功能描述 清除方式
Bit 0 ALM 闹钟中断标志:1=闹钟时间到 写 1 清除
Bit 1 PI 周期性中断标志:1=周期性中断产生 写 1 清除

注意:i.MX6ULL 手册中对 HPSR 的描述并不详尽,本文档参考了 i.MX6UR 手册和 SDK 代码进行补充。状态寄存器是区分中断来源的关键------在同一个中断处理函数中,通过读取 HPSR 来判断是闹钟中断还是周期性中断。
强调 :清除中断标志位的方法是对该位写 1(而不是写 0),这是 ARM 外设中常见的"写 1 清除"(Write-1-to-Clear)机制。


4.5 计数器寄存器(HPRTCMR / HPRTCLR)

一句话总结:32 位秒数被拆成"高 15 位 + 低 17 位"存在两个寄存器里------这是整个 RTC 编程中最容易搞错的地方,没有之一。

4.5.1 位分配

寄存器 全称 有效位 存储内容
HPRTCMR HP RTC Counter MSB Register Bit 0:14(共 15 位) 32 位秒数的第 17-31 位(高 15 位)
HPRTCLR HP RTC Counter LSB Register Bit 15:31(共 17 位) 32 位秒数的第 0-16 位(低 17 位)

4.5.2 位操作示意图

#mermaid-svg-7CA6S13GotMEMs7M{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-7CA6S13GotMEMs7M .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-7CA6S13GotMEMs7M .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-7CA6S13GotMEMs7M .error-icon{fill:#552222;}#mermaid-svg-7CA6S13GotMEMs7M .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-7CA6S13GotMEMs7M .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-7CA6S13GotMEMs7M .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-7CA6S13GotMEMs7M .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-7CA6S13GotMEMs7M .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-7CA6S13GotMEMs7M .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-7CA6S13GotMEMs7M .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-7CA6S13GotMEMs7M .marker{fill:#333333;stroke:#333333;}#mermaid-svg-7CA6S13GotMEMs7M .marker.cross{stroke:#333333;}#mermaid-svg-7CA6S13GotMEMs7M svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-7CA6S13GotMEMs7M p{margin:0;}#mermaid-svg-7CA6S13GotMEMs7M .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-7CA6S13GotMEMs7M .cluster-label text{fill:#333;}#mermaid-svg-7CA6S13GotMEMs7M .cluster-label span{color:#333;}#mermaid-svg-7CA6S13GotMEMs7M .cluster-label span p{background-color:transparent;}#mermaid-svg-7CA6S13GotMEMs7M .label text,#mermaid-svg-7CA6S13GotMEMs7M span{fill:#333;color:#333;}#mermaid-svg-7CA6S13GotMEMs7M .node rect,#mermaid-svg-7CA6S13GotMEMs7M .node circle,#mermaid-svg-7CA6S13GotMEMs7M .node ellipse,#mermaid-svg-7CA6S13GotMEMs7M .node polygon,#mermaid-svg-7CA6S13GotMEMs7M .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-7CA6S13GotMEMs7M .rough-node .label text,#mermaid-svg-7CA6S13GotMEMs7M .node .label text,#mermaid-svg-7CA6S13GotMEMs7M .image-shape .label,#mermaid-svg-7CA6S13GotMEMs7M .icon-shape .label{text-anchor:middle;}#mermaid-svg-7CA6S13GotMEMs7M .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-7CA6S13GotMEMs7M .rough-node .label,#mermaid-svg-7CA6S13GotMEMs7M .node .label,#mermaid-svg-7CA6S13GotMEMs7M .image-shape .label,#mermaid-svg-7CA6S13GotMEMs7M .icon-shape .label{text-align:center;}#mermaid-svg-7CA6S13GotMEMs7M .node.clickable{cursor:pointer;}#mermaid-svg-7CA6S13GotMEMs7M .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-7CA6S13GotMEMs7M .arrowheadPath{fill:#333333;}#mermaid-svg-7CA6S13GotMEMs7M .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-7CA6S13GotMEMs7M .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-7CA6S13GotMEMs7M .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7CA6S13GotMEMs7M .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-7CA6S13GotMEMs7M .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7CA6S13GotMEMs7M .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-7CA6S13GotMEMs7M .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-7CA6S13GotMEMs7M .cluster text{fill:#333;}#mermaid-svg-7CA6S13GotMEMs7M .cluster span{color:#333;}#mermaid-svg-7CA6S13GotMEMs7M div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-7CA6S13GotMEMs7M .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-7CA6S13GotMEMs7M rect.text{fill:none;stroke-width:0;}#mermaid-svg-7CA6S13GotMEMs7M .icon-shape,#mermaid-svg-7CA6S13GotMEMs7M .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-7CA6S13GotMEMs7M .icon-shape p,#mermaid-svg-7CA6S13GotMEMs7M .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-7CA6S13GotMEMs7M .icon-shape .label rect,#mermaid-svg-7CA6S13GotMEMs7M .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-7CA6S13GotMEMs7M .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-7CA6S13GotMEMs7M .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-7CA6S13GotMEMs7M :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 32位秒数
右移 17 位
左移 15 位
左移 17 位
右移 15 位
高15位

bit 17-31
低17位

bit 0-16
HPRTCMR

bit 0:14
HPRTCLR

bit 15:31
高15位还原
低17位还原
完整32位秒数

4.5.3 代码示例

c 复制代码
/* ========== 写入 RTC 时间 ========== */
/* 将年月日转换后的32位秒数写入寄存器 */
SNVS->HPRTCMR = (seconds >> 17);          /* 高15位:右移17位,写入 bit 0-14 */
SNVS->HPRTCLR = (seconds << 15);          /* 低17位:左移15位,放到 bit 15-31 */

/* ========== 读取 RTC 时间 ========== */
/* 从寄存器读取并拼接成32位秒数 */
uint32_t high = SNVS->HPRTCMR;            /* 读取高15位 */
uint32_t low  = SNVS->HPRTCLR;            /* 读取低17位 */
uint32_t seconds = (high << 17) | (low >> 15);  /* 拼接成完整32位秒数 */

执行结果验证:假设当前时间为 2023-01-01 21:40:30,对应 Unix 时间戳为 1672594830(0x63B0B64E)。

  • 高 15 位 = 0x63B0B64E >> 17 = 0x31D8(写入 HPRTCMR)
  • 低 17 位 = 0x63B0B64E << 15 = 0x5B270000(写入 HPRTCLR 的 bit 15-31)
  • 读取时:(0x31D8 << 17) | (0x5B270000 >> 15) = 0x63B0B64E ✓

4.6 闹钟寄存器(HPALMR / HPALR)

一句话总结:闹钟寄存器的结构和操作方式与计数器寄存器完全一样,只是目标寄存器不同------从 HPRTCMR/HPRTCLR 换成了 HPALMR/HPALR。

寄存器 有效位 存储内容
HPALMR(HP Alarm MSB Register) Bit 0:14(15 位) 闹钟秒数的高 15 位(第 17-31 位)
HPALR(HP Alarm LSB Register) Bit 15:31(17 位) 闹钟秒数的低 17 位(第 0-16 位)

第 5 章 RTC 时间设置与获取编程

5.1 编程流程总览

一句话总结 :RTC 编程分三个层次------初始化rtc_init():解权限 → 使能时钟,一次性)、时间设置rtc_set_datetime():停计数器 → 写入寄存器 → 启计数器,每次设置调用)、时间读取rtc_get_datetime():双次读取 → 校验一致性 → 转换日历时间,每次读取调用)。

5.1.1 初始化流程(rtc_init():一次性配置)

#mermaid-svg-TR9kBHXdBNxuc03w{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-TR9kBHXdBNxuc03w .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-TR9kBHXdBNxuc03w .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-TR9kBHXdBNxuc03w .error-icon{fill:#552222;}#mermaid-svg-TR9kBHXdBNxuc03w .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-TR9kBHXdBNxuc03w .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-TR9kBHXdBNxuc03w .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-TR9kBHXdBNxuc03w .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-TR9kBHXdBNxuc03w .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-TR9kBHXdBNxuc03w .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-TR9kBHXdBNxuc03w .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-TR9kBHXdBNxuc03w .marker{fill:#333333;stroke:#333333;}#mermaid-svg-TR9kBHXdBNxuc03w .marker.cross{stroke:#333333;}#mermaid-svg-TR9kBHXdBNxuc03w svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-TR9kBHXdBNxuc03w p{margin:0;}#mermaid-svg-TR9kBHXdBNxuc03w .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-TR9kBHXdBNxuc03w .cluster-label text{fill:#333;}#mermaid-svg-TR9kBHXdBNxuc03w .cluster-label span{color:#333;}#mermaid-svg-TR9kBHXdBNxuc03w .cluster-label span p{background-color:transparent;}#mermaid-svg-TR9kBHXdBNxuc03w .label text,#mermaid-svg-TR9kBHXdBNxuc03w span{fill:#333;color:#333;}#mermaid-svg-TR9kBHXdBNxuc03w .node rect,#mermaid-svg-TR9kBHXdBNxuc03w .node circle,#mermaid-svg-TR9kBHXdBNxuc03w .node ellipse,#mermaid-svg-TR9kBHXdBNxuc03w .node polygon,#mermaid-svg-TR9kBHXdBNxuc03w .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-TR9kBHXdBNxuc03w .rough-node .label text,#mermaid-svg-TR9kBHXdBNxuc03w .node .label text,#mermaid-svg-TR9kBHXdBNxuc03w .image-shape .label,#mermaid-svg-TR9kBHXdBNxuc03w .icon-shape .label{text-anchor:middle;}#mermaid-svg-TR9kBHXdBNxuc03w .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-TR9kBHXdBNxuc03w .rough-node .label,#mermaid-svg-TR9kBHXdBNxuc03w .node .label,#mermaid-svg-TR9kBHXdBNxuc03w .image-shape .label,#mermaid-svg-TR9kBHXdBNxuc03w .icon-shape .label{text-align:center;}#mermaid-svg-TR9kBHXdBNxuc03w .node.clickable{cursor:pointer;}#mermaid-svg-TR9kBHXdBNxuc03w .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-TR9kBHXdBNxuc03w .arrowheadPath{fill:#333333;}#mermaid-svg-TR9kBHXdBNxuc03w .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-TR9kBHXdBNxuc03w .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-TR9kBHXdBNxuc03w .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TR9kBHXdBNxuc03w .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-TR9kBHXdBNxuc03w .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TR9kBHXdBNxuc03w .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-TR9kBHXdBNxuc03w .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-TR9kBHXdBNxuc03w .cluster text{fill:#333;}#mermaid-svg-TR9kBHXdBNxuc03w .cluster span{color:#333;}#mermaid-svg-TR9kBHXdBNxuc03w div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-TR9kBHXdBNxuc03w .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-TR9kBHXdBNxuc03w rect.text{fill:none;stroke-width:0;}#mermaid-svg-TR9kBHXdBNxuc03w .icon-shape,#mermaid-svg-TR9kBHXdBNxuc03w .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-TR9kBHXdBNxuc03w .icon-shape p,#mermaid-svg-TR9kBHXdBNxuc03w .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-TR9kBHXdBNxuc03w .icon-shape .label rect,#mermaid-svg-TR9kBHXdBNxuc03w .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-TR9kBHXdBNxuc03w .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-TR9kBHXdBNxuc03w .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-TR9kBHXdBNxuc03w :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 开始初始化
解除权限限制

HPGCOMR bit31 = 1
使能 RTC 时钟

CCGR5 bits 18-19 = 11
初始化完成

5.1.2 时间设置流程(rtc_set_datetime():每次设置时间调用)

#mermaid-svg-VIiAvy42g9Touhyu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-VIiAvy42g9Touhyu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-VIiAvy42g9Touhyu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-VIiAvy42g9Touhyu .error-icon{fill:#552222;}#mermaid-svg-VIiAvy42g9Touhyu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-VIiAvy42g9Touhyu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-VIiAvy42g9Touhyu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-VIiAvy42g9Touhyu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-VIiAvy42g9Touhyu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-VIiAvy42g9Touhyu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-VIiAvy42g9Touhyu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-VIiAvy42g9Touhyu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-VIiAvy42g9Touhyu .marker.cross{stroke:#333333;}#mermaid-svg-VIiAvy42g9Touhyu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-VIiAvy42g9Touhyu p{margin:0;}#mermaid-svg-VIiAvy42g9Touhyu .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-VIiAvy42g9Touhyu .cluster-label text{fill:#333;}#mermaid-svg-VIiAvy42g9Touhyu .cluster-label span{color:#333;}#mermaid-svg-VIiAvy42g9Touhyu .cluster-label span p{background-color:transparent;}#mermaid-svg-VIiAvy42g9Touhyu .label text,#mermaid-svg-VIiAvy42g9Touhyu span{fill:#333;color:#333;}#mermaid-svg-VIiAvy42g9Touhyu .node rect,#mermaid-svg-VIiAvy42g9Touhyu .node circle,#mermaid-svg-VIiAvy42g9Touhyu .node ellipse,#mermaid-svg-VIiAvy42g9Touhyu .node polygon,#mermaid-svg-VIiAvy42g9Touhyu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-VIiAvy42g9Touhyu .rough-node .label text,#mermaid-svg-VIiAvy42g9Touhyu .node .label text,#mermaid-svg-VIiAvy42g9Touhyu .image-shape .label,#mermaid-svg-VIiAvy42g9Touhyu .icon-shape .label{text-anchor:middle;}#mermaid-svg-VIiAvy42g9Touhyu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-VIiAvy42g9Touhyu .rough-node .label,#mermaid-svg-VIiAvy42g9Touhyu .node .label,#mermaid-svg-VIiAvy42g9Touhyu .image-shape .label,#mermaid-svg-VIiAvy42g9Touhyu .icon-shape .label{text-align:center;}#mermaid-svg-VIiAvy42g9Touhyu .node.clickable{cursor:pointer;}#mermaid-svg-VIiAvy42g9Touhyu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-VIiAvy42g9Touhyu .arrowheadPath{fill:#333333;}#mermaid-svg-VIiAvy42g9Touhyu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-VIiAvy42g9Touhyu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-VIiAvy42g9Touhyu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VIiAvy42g9Touhyu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-VIiAvy42g9Touhyu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VIiAvy42g9Touhyu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-VIiAvy42g9Touhyu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-VIiAvy42g9Touhyu .cluster text{fill:#333;}#mermaid-svg-VIiAvy42g9Touhyu .cluster span{color:#333;}#mermaid-svg-VIiAvy42g9Touhyu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-VIiAvy42g9Touhyu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-VIiAvy42g9Touhyu rect.text{fill:none;stroke-width:0;}#mermaid-svg-VIiAvy42g9Touhyu .icon-shape,#mermaid-svg-VIiAvy42g9Touhyu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-VIiAvy42g9Touhyu .icon-shape p,#mermaid-svg-VIiAvy42g9Touhyu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-VIiAvy42g9Touhyu .icon-shape .label rect,#mermaid-svg-VIiAvy42g9Touhyu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-VIiAvy42g9Touhyu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-VIiAvy42g9Touhyu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-VIiAvy42g9Touhyu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 开始设置时间
停止 RTC 计数器

HPCR bit0 = 0
等待同步完成

读 HPCR bit0 直到 = 0
将年月日时分秒

转换为 Unix 时间戳
写入高15位

HPRTCMR = seconds 右移17位
写入低17位

HPRTCLR = seconds 左移15位
启动 RTC 计数器

HPCR bit0 = 1
等待同步完成

读 HPCR bit0 直到 = 1
设置完成

5.1.3 时间读取流程(rtc_get_datetime():每次读取时间调用)

#mermaid-svg-alDaeTd4TryNgui1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-alDaeTd4TryNgui1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-alDaeTd4TryNgui1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-alDaeTd4TryNgui1 .error-icon{fill:#552222;}#mermaid-svg-alDaeTd4TryNgui1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-alDaeTd4TryNgui1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-alDaeTd4TryNgui1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-alDaeTd4TryNgui1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-alDaeTd4TryNgui1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-alDaeTd4TryNgui1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-alDaeTd4TryNgui1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-alDaeTd4TryNgui1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-alDaeTd4TryNgui1 .marker.cross{stroke:#333333;}#mermaid-svg-alDaeTd4TryNgui1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-alDaeTd4TryNgui1 p{margin:0;}#mermaid-svg-alDaeTd4TryNgui1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-alDaeTd4TryNgui1 .cluster-label text{fill:#333;}#mermaid-svg-alDaeTd4TryNgui1 .cluster-label span{color:#333;}#mermaid-svg-alDaeTd4TryNgui1 .cluster-label span p{background-color:transparent;}#mermaid-svg-alDaeTd4TryNgui1 .label text,#mermaid-svg-alDaeTd4TryNgui1 span{fill:#333;color:#333;}#mermaid-svg-alDaeTd4TryNgui1 .node rect,#mermaid-svg-alDaeTd4TryNgui1 .node circle,#mermaid-svg-alDaeTd4TryNgui1 .node ellipse,#mermaid-svg-alDaeTd4TryNgui1 .node polygon,#mermaid-svg-alDaeTd4TryNgui1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-alDaeTd4TryNgui1 .rough-node .label text,#mermaid-svg-alDaeTd4TryNgui1 .node .label text,#mermaid-svg-alDaeTd4TryNgui1 .image-shape .label,#mermaid-svg-alDaeTd4TryNgui1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-alDaeTd4TryNgui1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-alDaeTd4TryNgui1 .rough-node .label,#mermaid-svg-alDaeTd4TryNgui1 .node .label,#mermaid-svg-alDaeTd4TryNgui1 .image-shape .label,#mermaid-svg-alDaeTd4TryNgui1 .icon-shape .label{text-align:center;}#mermaid-svg-alDaeTd4TryNgui1 .node.clickable{cursor:pointer;}#mermaid-svg-alDaeTd4TryNgui1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-alDaeTd4TryNgui1 .arrowheadPath{fill:#333333;}#mermaid-svg-alDaeTd4TryNgui1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-alDaeTd4TryNgui1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-alDaeTd4TryNgui1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-alDaeTd4TryNgui1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-alDaeTd4TryNgui1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-alDaeTd4TryNgui1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-alDaeTd4TryNgui1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-alDaeTd4TryNgui1 .cluster text{fill:#333;}#mermaid-svg-alDaeTd4TryNgui1 .cluster span{color:#333;}#mermaid-svg-alDaeTd4TryNgui1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-alDaeTd4TryNgui1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-alDaeTd4TryNgui1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-alDaeTd4TryNgui1 .icon-shape,#mermaid-svg-alDaeTd4TryNgui1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-alDaeTd4TryNgui1 .icon-shape p,#mermaid-svg-alDaeTd4TryNgui1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-alDaeTd4TryNgui1 .icon-shape .label rect,#mermaid-svg-alDaeTd4TryNgui1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-alDaeTd4TryNgui1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-alDaeTd4TryNgui1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-alDaeTd4TryNgui1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 不等,重新读取
相等,数据有效
开始读取时间
第一次读取并拼接

HPRTCMR左移17位 OR HPRTCLR右移15位
第二次读取并拼接

HPRTCMR左移17位 OR HPRTCLR右移15位
两次结果相等?
秒数转换为

年月日时分秒
读取完成


5.2 时钟使能

一句话总结:RTC 模块的时钟由 CCGR5 寄存器的 CG9 位控制,默认已开启,但为规范仍做显式设置。

c 复制代码
/* rtc_init(): RTC 初始化 */
void rtc_init(void)
{
    /* 1. 解除寄存器访问权限限制(必须先设置,再操作其他寄存器) */
    SNVS->HPGCOMR |= (1 << 31);  /* 所有软件可访问特权寄存器 */
    
    /* 2. 使能 RTC 时钟 */
    /* CCGR5 的 CG9 位(bit 18-19)控制 SNVS 时钟 */
    CCGR5 |= (3 << 18);     /* 设置为 11,开启时钟 */
}

执行结果:先设置 HPGCOMR31 解除权限限制,再使能 CCGR5 时钟。CCGR5 的 bit 18-19 变为 11,SNVS 模块时钟被激活,所有寄存器对 ARM 核可见可操作。


5.3 RDC 权限配置

一句话总结:RDC(Resource Domain Controller)就是系统的"门禁系统"------设置 HPGCOMR31 = 1 就是给所有软件发了一张"全域通行证"。

5.3.1 什么是 RDC

RDC(Resource Domain Controller,资源域控制器)是 i.MX6ULL 中管理不同软件/硬件域对系统资源访问权限的模块。i.MX6ULL 支持安全和非安全两种运行模式,RDC 决定了在非安全模式下能否访问某些特权资源。

5.3.2 为什么需要配置

如果不设置 HPGCOMR31,在非特权模式下访问 SNVS 的某些寄存器时,硬件会直接拦截访问请求,导致:

  • 读写寄存器时返回无效数据
  • 程序异常(data abort)
  • RTC 功能无法正常工作

5.3.3 配置方法

c 复制代码
/* 在 rtc_init() 中优先执行 */
SNVS->HPGCOMR |= (1 << 31);  /* HP_FIR_ACCESS = 1,解除所有权限限制 */

注意:HPGCOMR 的其他位多与安全功能相关,普通 RTC 编程无需关注。在非安全系统(Non-Secure System)中,设置 Bit 31 就足够了。

5.3.4 权限配置对比

配置状态 Bit 31 值 非特权模式访问 特权模式访问 适用场景
未配置 0 ❌ 被拒绝 ✅ 允许 安全系统,需权限隔离
已配置 1 ✅ 允许 ✅ 允许 普通嵌入式 Linux 系统

5.4 RTC 启停控制

一句话总结:修改 RTC_EN 位后不能立即认为生效------必须等待硬件同步完成,这是初学者最容易忽略的细节。

c 复制代码
/* 停止 RTC 计数器 */
void rtc_stop(void)
{
    SNVS->HPCR &= ~(1 << 0);          /* 清除 RTC_EN 位 */
    while (SNVS->HPCR & 0x1);         /* 等待 RTC_EN 真正变为 0 */
}

/* 启动 RTC 计数器 */
void rtc_start(void)
{
    SNVS->HPCR |= (1 << 0);           /* 设置 RTC_EN 位 */
    while (!(SNVS->HPCR & 0x1));      /* 等待 RTC_EN 真正变为 1 */
}

严谨类比 :这就像按电梯按钮。你按了 1 楼(写入 RTC_EN=1),但电梯不会瞬间到达------你需要等待电梯门关闭、电机启动、轿厢移动(硬件同步),最后指示灯亮起才表示到达(状态位变为 1)。没有等待同步的代码,就像按了电梯按钮就转身走,等电梯到了你人却不在了。


5.5 时间戳与日历时间转换

一句话总结:RTC 寄存器只认识"从 1970 年 1 月 1 日到现在的总秒数"(时间戳),不认识"2024 年 1 月 1 日"------转换是 RTC 编程的核心。

5.5.1 时间结构体定义

c 复制代码
/* datetime.h - 时间结构体 */
typedef struct {
    unsigned short year;    /* 年份,范围 1970-2099 */
    unsigned short month;   /* 月份,1-12 */
    unsigned short day;     /* 日期,1-31 */
    unsigned short hour;    /* 小时,0-23 */
    unsigned short minute;  /* 分钟,0-59 */
    unsigned short second;  /* 秒,0-59 */
} datetime_t;

/* 函数原型 */
uint32_t datetime_to_seconds(datetime_t *datetime);  /* 日历转秒数 */
void seconds_to_datetime(uint32_t seconds, datetime_t *datetime);  /* 秒数转日历 */

5.5.2 转换算法说明

严谨说明:时间转换算法涉及:

  • 闰年判断:能被 4 整除但不能被 100 整除,或者能被 400 整除
  • 大小月天数:一三五七八十腊(31 天),四六九冬(30 天),二月平年 28 天闰年 29 天
  • Unix 时间戳起点:1970-01-01 00:00:00 UTC

建议直接使用 NXP SDK 提供的现成代码(datetime.h + datetime.c),这些算法已经过数十年的工业验证,无需重新实现。


5.6 时间设置实现

c 复制代码
/* 设置 RTC 时间 */
void rtc_set_datetime(datetime_t *datetime)
{
    uint32_t seconds;
    
    /* 1. 停止 RTC 计数器 */
    rtc_stop();
    
    /* 2. 将日历时间转换为秒数(时间戳) */
    seconds = datetime_to_seconds(datetime);
    
    /* 3. 写入高位寄存器(高15位:bit 17-31) */
    SNVS->HPRTCMR = (seconds >> 17);
    
    /* 4. 写入低位寄存器(低17位:bit 0-16,放到 bit 15-31) */
    SNVS->HPRTCLR = (seconds << 15);
    
    /* 5. 启动 RTC 计数器 */
    rtc_start();
}

5.7 时间读取实现(双次读取校验)

一句话总结:RTC 是异步时钟域,读取时可能遇到"读到一半数据变了"的问题------"读两次,值一致才接受"是最简单的解决方案。

5.7.1 为什么需要双次校验

CPU 读取 RTC 计数器 CPU 读取 RTC 计数器 #mermaid-svg-41i7QJGZo8GlCGZ5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-41i7QJGZo8GlCGZ5 .error-icon{fill:#552222;}#mermaid-svg-41i7QJGZo8GlCGZ5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-41i7QJGZo8GlCGZ5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-41i7QJGZo8GlCGZ5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-41i7QJGZo8GlCGZ5 .marker.cross{stroke:#333333;}#mermaid-svg-41i7QJGZo8GlCGZ5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-41i7QJGZo8GlCGZ5 p{margin:0;}#mermaid-svg-41i7QJGZo8GlCGZ5 .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-41i7QJGZo8GlCGZ5 text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-41i7QJGZo8GlCGZ5 .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-41i7QJGZo8GlCGZ5 .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-41i7QJGZo8GlCGZ5 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-41i7QJGZo8GlCGZ5 .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-41i7QJGZo8GlCGZ5 #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-41i7QJGZo8GlCGZ5 .sequenceNumber{fill:white;}#mermaid-svg-41i7QJGZo8GlCGZ5 #sequencenumber{fill:#333;}#mermaid-svg-41i7QJGZo8GlCGZ5 #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-41i7QJGZo8GlCGZ5 .messageText{fill:#333;stroke:none;}#mermaid-svg-41i7QJGZo8GlCGZ5 .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-41i7QJGZo8GlCGZ5 .labelText,#mermaid-svg-41i7QJGZo8GlCGZ5 .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-41i7QJGZo8GlCGZ5 .loopText,#mermaid-svg-41i7QJGZo8GlCGZ5 .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-41i7QJGZo8GlCGZ5 .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-41i7QJGZo8GlCGZ5 .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-41i7QJGZo8GlCGZ5 .noteText,#mermaid-svg-41i7QJGZo8GlCGZ5 .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-41i7QJGZo8GlCGZ5 .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-41i7QJGZo8GlCGZ5 .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-41i7QJGZo8GlCGZ5 .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-41i7QJGZo8GlCGZ5 .actorPopupMenu{position:absolute;}#mermaid-svg-41i7QJGZo8GlCGZ5 .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-41i7QJGZo8GlCGZ5 .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-41i7QJGZo8GlCGZ5 .actor-man circle,#mermaid-svg-41i7QJGZo8GlCGZ5 line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-41i7QJGZo8GlCGZ5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 低17位已变0,高15位未变 错误值 = 0x00000000 实际值应为 0x00020000 ! 正确值 = 0x00020000 两次不一致,重新读取... 当前值 = 0x0001FFFF 第一次读取 下一秒到来,值更新 读取低17位=0,读取高15位=0x0000 第二次读取 更新完成,值=0x00020000 读取高15位=0x0001,低17位=0x0000

严谨案例:假设当前秒数为 0x0001FFFF(低 17 位全 1),下一秒它将变为 0x00020000(进位到高 15 位)。如果读取时序恰好发生在低 17 位已更新为 0、但高 15 位尚未 +1 的瞬间,你会读到 0x00000000,与实际值偏差整整 131,072 秒(约 36 小时)!

5.7.2 双次校验代码

c 复制代码
/* 读取 RTC 时间(带双次校验) */
void rtc_get_datetime(datetime_t *datetime)
{
    uint32_t seconds, seconds_new;
    
    /* 第一次读取 */
    seconds = (SNVS->HPRTCMR << 17) | (SNVS->HPRTCLR >> 15);
    
    do {
        /* 第二次读取 */
        seconds_new = (SNVS->HPRTCMR << 17) | (SNVS->HPRTCLR >> 15);
        
        if (seconds_new == seconds) {
            break;  /* 两次读取一致,数据有效 */
        }
        seconds = seconds_new;  /* 否则继续读取 */
    } while (1);
    
    /* 将秒数转换为日历时间 */
    seconds_to_datetime(seconds, datetime);
}

严谨类比 :这就像用秒表测量短跑成绩。裁判甲第一次读数是 10.23 秒,心里不踏实,让裁判乙再读一次也是 10.23 秒------那就可以放心记录。如果两次读数不同,说明可能有人看错了,需要再测一次。体育比赛中正式成绩往往需要多个计时器确认,RTC 读取也是一样的道理。


5.8 测试验证

5.8.1 测试代码

c 复制代码
/* main.c - RTC 功能测试 */
void rtc_test(void)
{
    datetime_t dt;

    /* 1. 初始化 RTC */
    rtc_init();

    /* 2. 设置初始时间:2023-01-01 21:40:30 */
    dt.year = 2023; dt.month = 1; dt.day = 1;
    dt.hour = 21; dt.minute = 40; dt.second = 30;
    rtc_set_datetime(&dt);

    /* 3. 每秒读取并打印时间 */
    while (1) {
        rtc_get_datetime(&dt);
        printf("20%02d-%02d-%02d %02d:%02d:%02d\r\n",
               dt.year, dt.month, dt.day,
               dt.hour, dt.minute, dt.second);
        delay_ms(1000);
    }
}

5.8.2 执行结果

复制代码
2023-01-01 21:40:30
2023-01-01 21:40:31
2023-01-01 21:40:32
2023-01-01 21:40:33
2023-01-01 21:40:34
...
2023-01-01 21:40:59
2023-01-01 21:41:00    ← 分钟进位,秒数归零
2023-01-01 21:41:01

验证点:秒数从 30 开始每秒递增,到 59 后进位到 21:41:00,分钟 +1 秒数归零------证明 RTC 驱动逻辑完全正确。

5.8.3 实践建议

场景 做法 原因
首次上电 调用 rtc_set_datetime() 设置时间 芯片出厂时 RTC 计数器为 0
后续运行 注释掉 rtc_set_datetime() 时间已设置好,只需读取
有纽扣电池 断电后时间自动保持 LP 域由 VBAT 持续供电
无纽扣电池 每次上电需重新设置时间 HP 域断电后数据丢失

第 6 章 RTC Alarm 中断编程

6.1 中断号确定

一句话总结:RTC Alarm 的中断号是 51,计算过程:SNVS 非安全中断号 19 + i.MX6ULL 偏移值 32 = 51。

6.1.1 中断号推导过程

#mermaid-svg-sX306CGCarISYhzq{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sX306CGCarISYhzq .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sX306CGCarISYhzq .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sX306CGCarISYhzq .error-icon{fill:#552222;}#mermaid-svg-sX306CGCarISYhzq .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sX306CGCarISYhzq .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sX306CGCarISYhzq .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sX306CGCarISYhzq .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sX306CGCarISYhzq .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sX306CGCarISYhzq .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sX306CGCarISYhzq .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sX306CGCarISYhzq .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sX306CGCarISYhzq .marker.cross{stroke:#333333;}#mermaid-svg-sX306CGCarISYhzq svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sX306CGCarISYhzq p{margin:0;}#mermaid-svg-sX306CGCarISYhzq .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sX306CGCarISYhzq .cluster-label text{fill:#333;}#mermaid-svg-sX306CGCarISYhzq .cluster-label span{color:#333;}#mermaid-svg-sX306CGCarISYhzq .cluster-label span p{background-color:transparent;}#mermaid-svg-sX306CGCarISYhzq .label text,#mermaid-svg-sX306CGCarISYhzq span{fill:#333;color:#333;}#mermaid-svg-sX306CGCarISYhzq .node rect,#mermaid-svg-sX306CGCarISYhzq .node circle,#mermaid-svg-sX306CGCarISYhzq .node ellipse,#mermaid-svg-sX306CGCarISYhzq .node polygon,#mermaid-svg-sX306CGCarISYhzq .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sX306CGCarISYhzq .rough-node .label text,#mermaid-svg-sX306CGCarISYhzq .node .label text,#mermaid-svg-sX306CGCarISYhzq .image-shape .label,#mermaid-svg-sX306CGCarISYhzq .icon-shape .label{text-anchor:middle;}#mermaid-svg-sX306CGCarISYhzq .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sX306CGCarISYhzq .rough-node .label,#mermaid-svg-sX306CGCarISYhzq .node .label,#mermaid-svg-sX306CGCarISYhzq .image-shape .label,#mermaid-svg-sX306CGCarISYhzq .icon-shape .label{text-align:center;}#mermaid-svg-sX306CGCarISYhzq .node.clickable{cursor:pointer;}#mermaid-svg-sX306CGCarISYhzq .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sX306CGCarISYhzq .arrowheadPath{fill:#333333;}#mermaid-svg-sX306CGCarISYhzq .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sX306CGCarISYhzq .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sX306CGCarISYhzq .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sX306CGCarISYhzq .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sX306CGCarISYhzq .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sX306CGCarISYhzq .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sX306CGCarISYhzq .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sX306CGCarISYhzq .cluster text{fill:#333;}#mermaid-svg-sX306CGCarISYhzq .cluster span{color:#333;}#mermaid-svg-sX306CGCarISYhzq div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sX306CGCarISYhzq .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sX306CGCarISYhzq rect.text{fill:none;stroke-width:0;}#mermaid-svg-sX306CGCarISYhzq .icon-shape,#mermaid-svg-sX306CGCarISYhzq .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sX306CGCarISYhzq .icon-shape p,#mermaid-svg-sX306CGCarISYhzq .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sX306CGCarISYhzq .icon-shape .label rect,#mermaid-svg-sX306CGCarISYhzq .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sX306CGCarISYhzq .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sX306CGCarISYhzq .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sX306CGCarISYhzq :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 查阅 SNVS 手册
找到两个中断号
19: 非安全中断
20: 安全中断
选择 19 号
需 NXP 授权, 课程不用
加上 GIC 偏移 32
最终中断号 = 19 + 32 = 51

步骤 操作 说明
1 查阅 SNVS 章节 手册第 48 章,而非单独 RTC 章节
2 找到中断号 19 和 20 19 是非安全,20 是安全
3 选择 19 号 非安全中断,无需 NXP 授权即可使用
4 加上偏移 32 ARM Cortex-A7 GIC 前 32 号留给内部异常
5 最终中断号 = 51 即 SNVS_ALARM_IRQn

注意:i.MX6ULL 的中断号 = 手册中的中断源编号 + 32。这个 +32 的偏移是因为 ARM Cortex-A7 中断控制器(GIC)的前 32 个中断号预留给内部异常(如复位、未定义指令、SVC 等)。


6.2 中断注册流程

一句话总结 :Alarm 中断分三个层次------初始化 (注册函数 + 使能中断,一次性)、闹钟设置 (关闹钟 → 设时间 → 开闹钟,每次设置调用)、中断处理(读状态 → 清标志 → 执行逻辑,触发时自动调用)。

6.2.1 初始化流程(一次性配置)

#mermaid-svg-nsCOgTyooM5zmSTZ{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nsCOgTyooM5zmSTZ .error-icon{fill:#552222;}#mermaid-svg-nsCOgTyooM5zmSTZ .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nsCOgTyooM5zmSTZ .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nsCOgTyooM5zmSTZ .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nsCOgTyooM5zmSTZ .marker.cross{stroke:#333333;}#mermaid-svg-nsCOgTyooM5zmSTZ svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nsCOgTyooM5zmSTZ p{margin:0;}#mermaid-svg-nsCOgTyooM5zmSTZ .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nsCOgTyooM5zmSTZ .cluster-label text{fill:#333;}#mermaid-svg-nsCOgTyooM5zmSTZ .cluster-label span{color:#333;}#mermaid-svg-nsCOgTyooM5zmSTZ .cluster-label span p{background-color:transparent;}#mermaid-svg-nsCOgTyooM5zmSTZ .label text,#mermaid-svg-nsCOgTyooM5zmSTZ span{fill:#333;color:#333;}#mermaid-svg-nsCOgTyooM5zmSTZ .node rect,#mermaid-svg-nsCOgTyooM5zmSTZ .node circle,#mermaid-svg-nsCOgTyooM5zmSTZ .node ellipse,#mermaid-svg-nsCOgTyooM5zmSTZ .node polygon,#mermaid-svg-nsCOgTyooM5zmSTZ .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nsCOgTyooM5zmSTZ .rough-node .label text,#mermaid-svg-nsCOgTyooM5zmSTZ .node .label text,#mermaid-svg-nsCOgTyooM5zmSTZ .image-shape .label,#mermaid-svg-nsCOgTyooM5zmSTZ .icon-shape .label{text-anchor:middle;}#mermaid-svg-nsCOgTyooM5zmSTZ .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nsCOgTyooM5zmSTZ .rough-node .label,#mermaid-svg-nsCOgTyooM5zmSTZ .node .label,#mermaid-svg-nsCOgTyooM5zmSTZ .image-shape .label,#mermaid-svg-nsCOgTyooM5zmSTZ .icon-shape .label{text-align:center;}#mermaid-svg-nsCOgTyooM5zmSTZ .node.clickable{cursor:pointer;}#mermaid-svg-nsCOgTyooM5zmSTZ .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nsCOgTyooM5zmSTZ .arrowheadPath{fill:#333333;}#mermaid-svg-nsCOgTyooM5zmSTZ .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nsCOgTyooM5zmSTZ .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nsCOgTyooM5zmSTZ .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nsCOgTyooM5zmSTZ .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nsCOgTyooM5zmSTZ .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nsCOgTyooM5zmSTZ .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nsCOgTyooM5zmSTZ .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nsCOgTyooM5zmSTZ .cluster text{fill:#333;}#mermaid-svg-nsCOgTyooM5zmSTZ .cluster span{color:#333;}#mermaid-svg-nsCOgTyooM5zmSTZ div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nsCOgTyooM5zmSTZ .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nsCOgTyooM5zmSTZ rect.text{fill:none;stroke-width:0;}#mermaid-svg-nsCOgTyooM5zmSTZ .icon-shape,#mermaid-svg-nsCOgTyooM5zmSTZ .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nsCOgTyooM5zmSTZ .icon-shape p,#mermaid-svg-nsCOgTyooM5zmSTZ .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nsCOgTyooM5zmSTZ .icon-shape .label rect,#mermaid-svg-nsCOgTyooM5zmSTZ .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nsCOgTyooM5zmSTZ .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nsCOgTyooM5zmSTZ .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nsCOgTyooM5zmSTZ :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 开始初始化
注册中断处理函数

设置中断向量表
使能闹钟中断

中断号 51
初始化完成

6.2.2 闹钟设置流程(rtc_set_alarm():每次设置闹钟调用)

#mermaid-svg-QTIpZnPwtMqYKG9d{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-QTIpZnPwtMqYKG9d .error-icon{fill:#552222;}#mermaid-svg-QTIpZnPwtMqYKG9d .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-QTIpZnPwtMqYKG9d .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-QTIpZnPwtMqYKG9d .marker{fill:#333333;stroke:#333333;}#mermaid-svg-QTIpZnPwtMqYKG9d .marker.cross{stroke:#333333;}#mermaid-svg-QTIpZnPwtMqYKG9d svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-QTIpZnPwtMqYKG9d p{margin:0;}#mermaid-svg-QTIpZnPwtMqYKG9d .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-QTIpZnPwtMqYKG9d .cluster-label text{fill:#333;}#mermaid-svg-QTIpZnPwtMqYKG9d .cluster-label span{color:#333;}#mermaid-svg-QTIpZnPwtMqYKG9d .cluster-label span p{background-color:transparent;}#mermaid-svg-QTIpZnPwtMqYKG9d .label text,#mermaid-svg-QTIpZnPwtMqYKG9d span{fill:#333;color:#333;}#mermaid-svg-QTIpZnPwtMqYKG9d .node rect,#mermaid-svg-QTIpZnPwtMqYKG9d .node circle,#mermaid-svg-QTIpZnPwtMqYKG9d .node ellipse,#mermaid-svg-QTIpZnPwtMqYKG9d .node polygon,#mermaid-svg-QTIpZnPwtMqYKG9d .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-QTIpZnPwtMqYKG9d .rough-node .label text,#mermaid-svg-QTIpZnPwtMqYKG9d .node .label text,#mermaid-svg-QTIpZnPwtMqYKG9d .image-shape .label,#mermaid-svg-QTIpZnPwtMqYKG9d .icon-shape .label{text-anchor:middle;}#mermaid-svg-QTIpZnPwtMqYKG9d .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-QTIpZnPwtMqYKG9d .rough-node .label,#mermaid-svg-QTIpZnPwtMqYKG9d .node .label,#mermaid-svg-QTIpZnPwtMqYKG9d .image-shape .label,#mermaid-svg-QTIpZnPwtMqYKG9d .icon-shape .label{text-align:center;}#mermaid-svg-QTIpZnPwtMqYKG9d .node.clickable{cursor:pointer;}#mermaid-svg-QTIpZnPwtMqYKG9d .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-QTIpZnPwtMqYKG9d .arrowheadPath{fill:#333333;}#mermaid-svg-QTIpZnPwtMqYKG9d .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-QTIpZnPwtMqYKG9d .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-QTIpZnPwtMqYKG9d .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QTIpZnPwtMqYKG9d .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-QTIpZnPwtMqYKG9d .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QTIpZnPwtMqYKG9d .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-QTIpZnPwtMqYKG9d .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-QTIpZnPwtMqYKG9d .cluster text{fill:#333;}#mermaid-svg-QTIpZnPwtMqYKG9d .cluster span{color:#333;}#mermaid-svg-QTIpZnPwtMqYKG9d div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-QTIpZnPwtMqYKG9d .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-QTIpZnPwtMqYKG9d rect.text{fill:none;stroke-width:0;}#mermaid-svg-QTIpZnPwtMqYKG9d .icon-shape,#mermaid-svg-QTIpZnPwtMqYKG9d .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-QTIpZnPwtMqYKG9d .icon-shape p,#mermaid-svg-QTIpZnPwtMqYKG9d .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-QTIpZnPwtMqYKG9d .icon-shape .label rect,#mermaid-svg-QTIpZnPwtMqYKG9d .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-QTIpZnPwtMqYKG9d .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-QTIpZnPwtMqYKG9d .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-QTIpZnPwtMqYKG9d :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 开始设置闹钟
关闭闹钟功能

HPCR bit1 = 0
等待关闭完成

读 HPCR bit1 直到 = 0
将闹钟时间

转换为 Unix 时间戳
写入闹钟高15位

HPALMR = seconds 右移17位
写入闹钟低17位

HPALR = seconds 左移15位
开启闹钟功能

HPCR bit1 = 1
等待开启完成

读 HPCR bit1 直到 = 1
设置完成

6.2.3 中断处理流程(闹钟触发时自动执行)

#mermaid-svg-NrpLf28FpHzlaPxa{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NrpLf28FpHzlaPxa .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NrpLf28FpHzlaPxa .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NrpLf28FpHzlaPxa .error-icon{fill:#552222;}#mermaid-svg-NrpLf28FpHzlaPxa .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NrpLf28FpHzlaPxa .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NrpLf28FpHzlaPxa .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NrpLf28FpHzlaPxa .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NrpLf28FpHzlaPxa .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NrpLf28FpHzlaPxa .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NrpLf28FpHzlaPxa .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NrpLf28FpHzlaPxa .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NrpLf28FpHzlaPxa .marker.cross{stroke:#333333;}#mermaid-svg-NrpLf28FpHzlaPxa svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NrpLf28FpHzlaPxa p{margin:0;}#mermaid-svg-NrpLf28FpHzlaPxa .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NrpLf28FpHzlaPxa .cluster-label text{fill:#333;}#mermaid-svg-NrpLf28FpHzlaPxa .cluster-label span{color:#333;}#mermaid-svg-NrpLf28FpHzlaPxa .cluster-label span p{background-color:transparent;}#mermaid-svg-NrpLf28FpHzlaPxa .label text,#mermaid-svg-NrpLf28FpHzlaPxa span{fill:#333;color:#333;}#mermaid-svg-NrpLf28FpHzlaPxa .node rect,#mermaid-svg-NrpLf28FpHzlaPxa .node circle,#mermaid-svg-NrpLf28FpHzlaPxa .node ellipse,#mermaid-svg-NrpLf28FpHzlaPxa .node polygon,#mermaid-svg-NrpLf28FpHzlaPxa .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NrpLf28FpHzlaPxa .rough-node .label text,#mermaid-svg-NrpLf28FpHzlaPxa .node .label text,#mermaid-svg-NrpLf28FpHzlaPxa .image-shape .label,#mermaid-svg-NrpLf28FpHzlaPxa .icon-shape .label{text-anchor:middle;}#mermaid-svg-NrpLf28FpHzlaPxa .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NrpLf28FpHzlaPxa .rough-node .label,#mermaid-svg-NrpLf28FpHzlaPxa .node .label,#mermaid-svg-NrpLf28FpHzlaPxa .image-shape .label,#mermaid-svg-NrpLf28FpHzlaPxa .icon-shape .label{text-align:center;}#mermaid-svg-NrpLf28FpHzlaPxa .node.clickable{cursor:pointer;}#mermaid-svg-NrpLf28FpHzlaPxa .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NrpLf28FpHzlaPxa .arrowheadPath{fill:#333333;}#mermaid-svg-NrpLf28FpHzlaPxa .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NrpLf28FpHzlaPxa .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NrpLf28FpHzlaPxa .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NrpLf28FpHzlaPxa .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NrpLf28FpHzlaPxa .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NrpLf28FpHzlaPxa .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NrpLf28FpHzlaPxa .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NrpLf28FpHzlaPxa .cluster text{fill:#333;}#mermaid-svg-NrpLf28FpHzlaPxa .cluster span{color:#333;}#mermaid-svg-NrpLf28FpHzlaPxa div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NrpLf28FpHzlaPxa .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NrpLf28FpHzlaPxa rect.text{fill:none;stroke-width:0;}#mermaid-svg-NrpLf28FpHzlaPxa .icon-shape,#mermaid-svg-NrpLf28FpHzlaPxa .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NrpLf28FpHzlaPxa .icon-shape p,#mermaid-svg-NrpLf28FpHzlaPxa .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NrpLf28FpHzlaPxa .icon-shape .label rect,#mermaid-svg-NrpLf28FpHzlaPxa .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NrpLf28FpHzlaPxa .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NrpLf28FpHzlaPxa .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NrpLf28FpHzlaPxa :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否,其他中断
是,闹钟中断
闹钟触发
读取状态寄存器 HPSR
bit0 为 1?
转其他中断处理
清除中断标志

HPSR bit0 写1
执行用户逻辑
中断返回


6.3 闹钟设置实现

c 复制代码
/* 设置 RTC 闹钟 */
void rtc_set_alarm(datetime_t *alarm_time)
{
    uint32_t seconds;
    
    /* 1. 关闭闹钟功能 */
    SNVS->HPCR &= ~(1 << 1);       /* ALM_EN = 0 */
    while (SNVS->HPCR & (1 << 1)); /* 等待关闭完成 */
    
    /* 2. 将闹钟时间转换为秒数 */
    seconds = datetime_to_seconds(alarm_time);
    
    /* 3. 写入闹钟寄存器(与计数器寄存器结构相同) */
    SNVS->HPALMR = (seconds >> 17);   /* 高15位 */
    SNVS->HPALR  = (seconds << 15);   /* 低17位 */
    
    /* 4. 开启闹钟功能 */
    SNVS->HPCR |= (1 << 1);        /* ALM_EN = 1 */
    while (!(SNVS->HPCR & (1 << 1))); /* 等待开启完成 */
}

注意 :中断处理函数注册和 GIC_EnableIRQ(51) 属于系统初始化阶段,在调用 rtc_set_alarm() 之前完成,此处不再重复。


6.4 中断处理函数

c 复制代码
/* RTC 闹钟中断处理函数 */
int rtc_alarm_irq_handler(int irq_no)
{
    /* 1. 读取状态寄存器,判断中断来源 */
    if (SNVS->HPSR & (1 << 0)) {   /* ALM 位为 1 */
        /* 确认是闹钟中断 */
        printf("RTC alarm OK!\r\n");
        
        /* 2. 清除中断标志位(写 1 清除) */
        SNVS->HPSR |= (1 << 0);    /* 清除 ALM 标志 */
        while (SNVS->HPSR & (1 << 0)); /* 等待清除完成 */
    }
    
    return 0;
}

6.5 调试与验证

6.5.1 测试场景

设置闹钟为当前时间 +5 秒后触发。

c 复制代码
/* 闹钟测试代码 */
void rtc_alarm_test(void)
{
    datetime_t now, alarm;
    
    rtc_init();
    
    /* 设置当前时间 */
    now.year = 2023; now.month = 1; now.day = 1;
    now.hour = 21; now.minute = 40; now.second = 30;
    rtc_set_datetime(&now);
    
    /* 设置闹钟为 5 秒后:21:40:35 */
    alarm.year = 2023; alarm.month = 1; alarm.day = 1;
    alarm.hour = 21; alarm.minute = 40; alarm.second = 35;
    
    printf("Setting alarm to: 2023-01-01 21:40:35\r\n");
    rtc_set_alarm(&alarm);
    
    /* 主循环 - 每秒打印当前时间 */
    while (1) {
        rtc_get_datetime(&now);
        printf("20%02d-%02d-%02d %02d:%02d:%02d\r\n",
               now.year, now.month, now.day,
               now.hour, now.minute, now.second);
        delay_ms(1000);
    }
}

6.5.2 首次运行------失败

复制代码
串口输出(错误情况):
Setting alarm to: 2023-01-01 21:40:35
2023-01-01 21:40:30
2023-01-01 21:40:31
2023-01-01 21:40:32
2023-01-01 21:40:33
2023-01-01 21:40:34
2023-01-01 21:40:35    ← 时间已到,但无中断触发!
2023-01-01 21:40:36
2023-01-01 21:40:37
...

问题分析 :中断函数已注册,但未使能闹钟中断请求(Alarm IRQ)。硬件虽然检测到时间匹配,但没有向 CPU 发送中断请求信号。

6.5.3 修复后------成功

rtc_set_alarm() 中添加 GIC_EnableIRQ(51) 后:

复制代码
串口输出(修复后 - 成功):
Setting alarm to: 2023-01-01 21:40:35
2023-01-01 21:40:30
2023-01-01 21:40:31
2023-01-01 21:40:32
2023-01-01 21:40:33
2023-01-01 21:40:34
2023-01-01 21:40:35    ← 此时触发中断
RTC alarm OK!           ← 中断处理函数被执行
2023-01-01 21:40:36
2023-01-01 21:40:37
...

6.5.4 中断排查清单

排查步骤 检查内容 检查方法
中断函数是否注册? 确认调用了中断注册 API
中断是否使能? 确认调用了 GIC_EnableIRQ(51)
闹钟使能位是否设置? 确认 HPCR[1] = 1
中断标志是否清除? 确认 HPSR 中写 1 清除了标志位
闹钟时间是否已过? 确认闹钟时间在未来

第 7 章 Linux 上的 RTC 编程

一句话总结 :Linux 提供两套 RTC 接口------/dev/rtc0(操作硬件 RTC,对应裸机的 rtc_set_datetime)和 clock_gettime(获取系统时间,应用层标准做法),两者配合使用覆盖所有场景。


7.1 Linux RTC 子系统

地位:Linux 内核标准驱动,从 2.6 内核至今,所有 ARM 嵌入式 Linux 发行版标配。

特点

  • 无需安装第三方库,内核自带
  • 通过 /dev/rtc0 设备文件访问
  • 使用标准的 ioctl 命令接口,数十年 API 不变
  • hwclock 命令底层就是基于此接口

核心 ioctl 命令:

ioctl 命令 功能 数据结构 对应裸机操作
RTC_RD_TIME 读取 RTC 时间 struct rtc_time HPRTCMR + HPRTCLR 读取
RTC_SET_TIME 设置 RTC 时间 struct rtc_time HPRTCMR + HPRTCLR 写入
RTC_ALM_SET 设置闹钟 struct rtc_time HPALMR + HPALR 写入
RTC_WKALM_SET 设置唤醒闹钟 struct rtc_wkalrm 含使能控制
RTC_PIE_ON 开启周期中断 unsigned long HPCR 周期中断配置

7.2 POSIX 时钟接口

地位 :POSIX 标准,glibc 的一部分,所有 Linux 发行版标配。

特点

  • 用户态 API,无需直接操作硬件
  • clock_gettime() / clock_settime() 标准接口
  • 支持 CLOCK_REALTIME(系统时间,受 RTC 影响)和 CLOCK_MONOTONIC(单调时间,适合测间隔)

7.3 接口对比表

对比维度 Linux RTC 子系统(/dev/rtc0 POSIX 时钟(clock_gettime
操作对象 硬件 RTC 芯片 内核维护的系统时间
持久性 断电后由电池保持 断电后丢失(启动时从 RTC 同步)
访问方式 open + ioctl 函数调用
权限要求 root0666 普通用户即可
典型场景 硬件时间校准、hwclock 底层 应用层获取当前时间
稳定性 内核 2.6 至今,极稳定 POSIX 标准,所有平台一致
对应裸机函数 对应 rtc_set_datetime() / rtc_get_datetime() 对应 seconds_to_datetime()

7.4 代码示例

示例 1:通过 /dev/rtc0 读取硬件 RTC 时间

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>

int main(void)
{
    int fd;
    struct rtc_time rtc;

    fd = open("/dev/rtc0", O_RDONLY);
    if (fd < 0) {
        perror("open /dev/rtc0");
        return 1;
    }

    /* 对应裸机的 rtc_get_datetime() */
    if (ioctl(fd, RTC_RD_TIME, &rtc) < 0) {
        perror("RTC_RD_TIME");
        close(fd);
        return 1;
    }

    printf("硬件 RTC 时间: %04d-%02d-%02d %02d:%02d:%02d\n",
           rtc.tm_year + 1900, rtc.tm_mon + 1, rtc.tm_mday,
           rtc.tm_hour, rtc.tm_min, rtc.tm_sec);

    close(fd);
    return 0;
}

编译:

bash 复制代码
arm-linux-gnueabihf-gcc -o rtc_read rtc_read.c

执行结果:

复制代码
硬件 RTC 时间: 2026-07-17 14:30:45

示例 2:通过 clock_gettime 获取系统时间

c 复制代码
#include <stdio.h>
#include <time.h>

int main(void)
{
    struct timespec ts;
    struct tm tm;

    /* 获取系统时间(底层从 RTC 同步) */
    clock_gettime(CLOCK_REALTIME, &ts);

    localtime_r(&ts.tv_sec, &tm);

    printf("系统时间: %04d-%02d-%02d %02d:%02d:%02d.%09ld\n",
           tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
           tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);

    /* 单调时间,适合测量间隔,不受系统时间调整影响 */
    clock_gettime(CLOCK_MONOTONIC, &ts);
    printf("单调时间: %ld 秒 %ld 纳秒(自系统启动以来)\n",
           ts.tv_sec, ts.tv_nsec);

    return 0;
}

编译:

bash 复制代码
arm-linux-gnueabihf-gcc -o sys_time sys_time.c

执行结果:

复制代码
系统时间: 2026-07-17 14:30:45.123456789
单调时间: 1234567 秒 890123456 纳秒(自系统启动以来)

示例 3:设置 RTC 闹钟并等待触发

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/select.h>

int main(void)
{
    int fd;
    struct rtc_time rtc;
    struct rtc_wkalrm alarm;
    fd_set fds;
    unsigned long data;

    fd = open("/dev/rtc0", O_RDWR);
    if (fd < 0) {
        perror("open /dev/rtc0");
        return 1;
    }

    /* 1. 读取当前时间 */
    ioctl(fd, RTC_RD_TIME, &rtc);
    printf("当前时间: %04d-%02d-%02d %02d:%02d:%02d\n",
           rtc.tm_year + 1900, rtc.tm_mon + 1, rtc.tm_mday,
           rtc.tm_hour, rtc.tm_min, rtc.tm_sec);

    /* 2. 设置闹钟为 10 秒后 */
    rtc.tm_sec += 10;
    if (rtc.tm_sec >= 60) {
        rtc.tm_sec -= 60;
        rtc.tm_min += 1;
    }

    alarm.enabled = 1;
    alarm.pending = 0;
    alarm.time = rtc;

    /* 对应裸机的 rtc_set_alarm() */
    if (ioctl(fd, RTC_WKALM_SET, &alarm) < 0) {
        perror("RTC_WKALM_SET");
        close(fd);
        return 1;
    }
    printf("闹钟已设置: %02d:%02d:%02d\n",
           rtc.tm_hour, rtc.tm_min, rtc.tm_sec);

    /* 3. 等待闹钟触发 */
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    printf("等待闹钟触发...\n");
    select(fd + 1, NULL, NULL, &fds, NULL);

    /* 4. 确认中断 */
    read(fd, &data, sizeof(data));
    printf("闹钟触发!\n");

    close(fd);
    return 0;
}

执行结果:

复制代码
当前时间: 2026-07-17 14:30:45
闹钟已设置: 14:30:55
等待闹钟触发...
(10 秒后)
闹钟触发!

一句话总结 :Linux RTC 子系统(/dev/rtc0 + ioctl)是操作硬件 RTC 的工业标准,对应裸机编程中的 rtc_set_datetime() / rtc_get_datetime() / rtc_set_alarm()clock_gettime 是应用层获取时间的 POSIX 标准接口。两者配合使用:应用层用 clock_gettime 获取系统时间,内核自动从硬件 RTC 同步------你不需要自己写寄存器操作,但理解底层原理(本教程前面章节的内容)能帮你更好地排查问题。


第 8 章 附录

8.1 常见问题排查指南

8.1.1 寄存器位操作错误

问题 原因 解决方案
时间显示为 1970 年 HPRTCMR 和 HPRTCLR 的位分配搞反 牢记:HPRTCMR 存高15位(bit 0-14),HPRTCLR 存低17位(bit 15-31)
时间跳跃不稳定 没有使用双次读取校验 采用读两次比较法

8.1.2 同步等待遗漏

问题 原因 解决方案
RTC 启停后未生效 修改 HPCR 寄存器后未等待同步完成 每次修改后用 while 循环轮询状态位,等待硬件同步
闹钟设置后不触发 设置 ALM_EN 后没等待位真正变为 1 在 ALM_EN 置位后加入 while(!(HPCR & (1<<1))); 等待
时间设置后读出为 0 写入计数器后未等待启动完成就开始读取 调用 rtc_start() 后必须等待 while(!(HPCR & 0x1))

8.1.3 中断相关

问题 原因 解决方案
闹钟触发一次后不再触发 中断服务函数中未清除中断标志位 在 ISR 中对 HPSR 对应位写 1 清除
中断从未触发 忘记使能 GIC 中断 确认调用了 GIC_EnableIRQ(51)
中断响应混乱 未在 ISR 中区分中断来源 读取 HPSR 判断是闹钟中断还是周期性中断
周期性中断频率不对 PISR 位配置错误 确认 HPCR 的 bit 4-7 设置了正确的位号

8.1.4 硬件相关

问题 原因 解决方案
LP 部分无法工作 纽扣电池接触不良或电压不足 测量 VBAT 引脚电压,需 > 2.0V
断电后时间丢失 未安装纽扣电池或电池已耗尽 安装 CR2032 电池,无电池场景需每次上电设置时间
RTC 走时偏快/偏慢 晶振负载电容不匹配 检查晶振匹配电容,典型值 12.5pF ~ 20pF
读取时间偶尔跳变 未使用双次读取校验 采用两次读取比较法(见 5.7 节)

8.2 术语对照表

缩写 全称 中文释义
RTC Real-Time Clock 实时时钟
SNVS Secure Non-Volatile Storage 安全非易失性存储
HP High Power Domain 高功耗域
LP Low Power Domain 低功耗域
RDC Resource Domain Controller 资源域控制器
GIC Generic Interrupt Controller 通用中断控制器
CCGR Clock Gate Register 时钟门控寄存器
HPGCOMR HP General Command Register HP 通用命令寄存器
HPCR HP Control Register HP 控制寄存器
HPSR HP Status Register HP 状态寄存器
HPRTCMR HP RTC Counter MSB Register HP RTC 计数器高位寄存器
HPRTCLR HP RTC Counter LSB Register HP RTC 计数器低位寄存器
HPALMR HP Alarm MSB Register HP 闹钟高位寄存器
HPALR HP Alarm LSB Register HP 闹钟低位寄存器
NTP Network Time Protocol 网络时间协议
ppm Parts Per Million 百万分比(频率精度单位)
TCXO Temperature Compensated Crystal Oscillator 温度补偿晶振

文档说明:本文档基于 NXP i.MX6ULL 参考手册第 48 章(SNVS 模块)编写,整合了 10 课时的课件内容。修正了原文档中的术语错误(如 SMVS→SNVS、HB→HP、RP→LP 等),补充了 Mermaid 流程图、生成图片、知识对比表和严谨的社会生活类比案例。所有代码示例均附有实际执行结果验证。

相关推荐
Byron Loong3 小时前
【视觉】工业相机通讯协议对比GigE Vision、USB3 Vision、CXP、CL、UVC、RTSP、NDI
计算机视觉·视觉检测·实时音视频
AI的探索之旅3 小时前
AI辅助原理图评审:电源去耦、BOOT引脚、VCAP——19项逐一核查,遗漏?不存在的
人工智能·vscode·嵌入式硬件
茯苓gao3 小时前
嵌入式开发笔记:EtherCAT协议从硬件到软件完整配置指南——从零搭建一套EtherCAT通信系统
笔记·嵌入式硬件·学习
GeekArch4 小时前
第24讲:Vibe模式代码风格控制——适配Keil/STM32工程规范
人工智能·stm32·单片机·嵌入式硬件·mcu·决策树·ai编程
Freedom_my5 小时前
STM32项目3
stm32·单片机·嵌入式硬件
国科安芯6 小时前
星间光链路:AS32S601型抗辐射MCU在空间激光通信终端控制中的技术实现
服务器·网络·单片机·嵌入式硬件·物联网·安全·信息与通信
小李不困还能学7 小时前
基于 51 单片机的8 路抢答器设计教程
单片机·嵌入式硬件·mongodb·抢答器
CedarQR7 小时前
万字长文:从零在 RK3588 上部署 PaddleSpeech 中文 TTS 全流程(FastSpeech2 + HiFiGAN)
开发语言·c++·嵌入式硬件·ubuntu·json
萌动的小火苗7 小时前
嵌入式开发中的栈与队列:任务调度为什么依赖数据结构
数据结构·c++·单片机·嵌入式硬件
振浩微433射频芯片8 小时前
工业遥控器总在关键时刻“掉链子”?——433MHz芯片方案如何破局
网络·单片机·嵌入式硬件·物联网·工业遥控