嵌入式 ------ 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 工作机制
- 设置闹钟时间:将目标时间转换为秒数,写入闹钟寄存器(HPALMR/HPALR)
- 硬件自动比较:硬件持续比较当前 RTC 计数器值与闹钟寄存器值
- 触发中断:两者相等时产生中断信号
- 唤醒功能:在低功耗模式下可唤醒 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 |
函数调用 |
| 权限要求 | 需 root 或 0666 |
普通用户即可 |
| 典型场景 | 硬件时间校准、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 流程图、生成图片、知识对比表和严谨的社会生活类比案例。所有代码示例均附有实际执行结果验证。