橙子随记

V1

2022/06/15阅读:30主题:自定义主题1

嵌入式开发中的几个时间概念(建议收藏)

<<< 左右滑动见更多 >>>

我生待明日,万事成蹉跎。—— 明·钱福《明日歌》

1 前言

在嵌入式系统中(包括大部分电子设备:手机、平板、手环、手表等等),时间的概念非常重要。如打印log时的时间戳、定时关机、心跳上报、日历功能、闹钟等等。上述这些功能都需要一个相对精确的时间系统。

经常涉及的与时间相关的术语包括:硬件时钟系统时钟网络时钟时区修改和同步。日常生活和工作中可能接触到的时区概念包括:UTCGMTCSTDST。在网络时间中可能接触到的概念又有:NTPSNTPNITZ。本文将会对上述涉及到的概念进行系统的整理和探讨。

2 了解概念

下面对几个概念进行集中陈述。

2.1 时区

时区[1] 是指地球上的不同区域使用同一个时间定义。以前,人们通过观察太阳的位置(时角)决定时间,这就使得不同经度的地方的时间有所不同(地方时)。1863年,首次使用时区的概念。通过设立一个区域的标准时间部分地解决了这个问题。

时区划分规则:将全球按经线从东到西划分为24个时区,其中东、西各12个时区,每个时区跨越经度15°,0区和12区跨越东西各7.5°。规定相邻区域的时间相差1小时,这样24个时区刚好是24小时,地球自转一圈。如下图是全球时区的划分明细。常见的时区概念包括:GMTUTCCSTDST时区

  • GMT(Greenwich Mean Time)指格林尼治标准时间,它是第一个世界时。GMT 12:00就是指格林尼治天文台当地的正午12:00,而GMT+8 12:00,则是指东八区的北京当地时间的12:00。格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治时)的时间。由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能和实际的太阳时相差16分钟。
  • UTC(Coordinated Universal Time)是指协调世界时,又称世界标准时间。它是以原子时为基础,由于现在世界上最精确的原子钟50亿年才会误差1秒,所以UTC时间标准非常精确。每隔几年协调世界时组织都会给世界时+1秒,让基于原子钟的世界时和基于天文学(人类感知)的格林尼治标准时间(GMT)相差不至于太大。UTC是现在世界使用的标准时间,UTC与GMT时间基本相同。
  • CST(China Standard Time)指中国标准时间。GMT + 8 = UTC + 8 = CST
  • DST(Daylight Saving Time)夏令时,又称:“日光节约时制”。是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。全世界有近110个国家每年要实行夏令时。中国现在已经不再使用夏令时。

2.2 时钟

常见的几个时钟概念包括:硬件时钟系统时钟网络时钟

  • 硬件时钟。在嵌入式领域也就是RTC时钟(Real Time Clock)。大多采用精度较高的晶振作为时钟源。在主电源掉电时,还可以工作,需要外加电池供电。通常把集成于芯片内部的 RTC 称为片内 RTC,在芯片外扩展的 RTC 称为外部 RTC。
  • 系统时钟。指软件系统的时钟。在linux和一些rtos中,启动时会去读取硬件时钟(RTC),之后则独立运行。独立运行的好处对于普通用户意义不大,但对于linux网络管理员却有很大的用处。例如,要将一个很大的网络中(跨越若干时区)的服务器同步,假如位于美国纽约的linux服务器和北京的Linux服务器,其中一台服务器无须改变硬件时钟而只需临时设置一个系统时间,如要将北京服务器上的系统时间设置为纽约时间,两台服务器完成文件的同步后,再与原来的硬件时钟同步一下即可。这样系统时钟和硬件时钟就提供了更为灵活的操作。

  • 网络时钟。网络时钟的时间源来自于专业授时的服务器(SNTP、NTP)。实现方案是在网络上指定若干时钟源服务器,为用户提供授时服务,并且这些服务器之间能够相互比较校正,以提高准确度。在移动蜂窝网络中,基站也可以通过无线网络向移动设备提供本地日期和时间、时区、夏时制偏移。网络时钟的精度一般都很高,可以达到毫秒级,可以用来对嵌入式设备进行时间同步。

2.3 时间同步

时间同步对嵌入式设备很重要,一些功能业务甚至依赖于时间信息来完成。如自注册DM业务,需要周期性的向运营商服务器上报信息,这些信息上报都是以天或者是月为周期,不可能靠软件timer来实现。和此类似的功能都需要以标准时间为基准,以此完成条件的触发。下面来探讨时间同步的话题。

2.3.1 SNTP

SNTP是简单网络时间协议(Simple Network Time protocol)的简称,它是目前Internet网上实现时间同步的一种重要工程化方法。SNTPNTP改编而来,SNTP其实是NTP的子集,只是NTP可以 分发和授时,而SNTP只有授时没有分发,也就是说你只能从SNTP获取时间,其他的什么都做不了,SNTP简化了NTP的全部流程,这样节约成本,但只能同步一个时间源。SNTP协议采用客户端/服务器的工作方式。SNTP服务器通过接收GPS信号或自带的原子钟作为系统的时间基准。SNTP客户端(嵌入式设备)能够通过定期访问SNTP服务器获得准确的时间信息,用于调整客户端自身所在系统的时间,达到同步时间的目的。在linux系统中一般有现成的SNTP客户端可以安装使用,在其他的嵌入式平台上需要移植或自主开发。一些可用的SNTP服务器汇总如下(亲测可以ping通):

  • 国家授时中心 NTP 服务器:ntp.ntsc.ac.cn
  • 阿里云公共 NTP 服务器:time.pool.aliyun.com
  • 腾讯云公共 NTP 服务器:time1.cloud.tencent.com
  • 教育网(高校自建)服务器:ntp.sjtu.edu.cn

2.3.2 NITZ

NITZ(Network Identity and Time Zone)是一种通过无线网络向移动设备提供本地日期和时间、时区、夏时制偏移,以及网络提供商身份信息的机制,这通常用于无线蜂窝网络设备(手机、通信模组)的自动更新系统时间。对于其他网络时间协议,NITZ的质量和执行力度都相对较弱。有些运营商根本就不支持,例如在国内,本地测试(广东)发现,中国移动和中国电信是支持NITZ的,中国联通就根本不支持。再者,与SNTP相比,SNTP授时能使时间分辨率达到毫秒级,NITZ则“对于时间只能精确到数分钟”。但NITZ不用连上互联网,能驻上无线蜂窝网络就行,而SNTP必须连接互联网。

3 应用

3.1 linux中时间命令

linux命令中的date命令是用来设置和查询系统时间的,而hwclock命令是用来设置和读写RTC时间(硬件时间)。有一点需要注意,linux的时间系统是由「新纪元时间」Epoch开始计算起,单位为秒,Epoch则是指定为1970年1月1日0点0分0秒,格林威治时间(GMT)。date +%s命令可以读取从1970年1月1日0点0分0秒开始到当前的秒数。

  • 读取当前秒数(以1970年1月1日0点0分0秒为计算起点);
book@zhang.c:~$ date +%s
1653752545

  • 读系统时间:date
book@zhang.c:~$ date
Sat May 28 22:41:26 CST 2022
  • 设置系统时间:date -s "20220501 12:00:00"date -s命令设置时间只会影响系统时间,不会设置RTC时间,如果需要把当前系统时间同步设置到RTC中,需要额外调用hwclock命令;
book@zhang.c:~$ date -s "20220501 12:00:00"
Sun May  1 12:00:00 CST 2022
  • 有关rtc时间的操作,主要是hwclock命令使用;
#读取并打印当前的rtc时间
hwclock -r
#读取RTC时间并设置到系统时间中去
hwclock -s 
#把当前的系统时间设置到RTC中
hwclock -w     
#完整的设置RTC的时间可执行如下命令
date -s "20220501 12:00:00"
hwclock -w
  • date命令格式化的显示时间,可以看如下的Command这一列。
        Format/result           |       Command              |          Output
--------------------------------+----------------------------+------------------------------
YYYY-MM-DD                      | date -I                    | $(date -I)
YYYY-MM-DD_hh:mm:ss             | date +%F_%T                | $(date +%F_%T)
YYYYMMDD_hhmmss                 | date +%Y%m%d_%H%M%S        | $(date +%Y%m%d_%H%M%S)
YYYYMMDD_hhmmss (UTC version)   | date --utc +%Y%m%d_%H%M%SZ | $(date --utc +%Y%m%d_%H%M%SZ)
YYYYMMDD_hhmmss (with local TZ) | date +%Y%m%d_%H%M%S%Z      | $(date +%Y%m%d_%H%M%S%Z)
YYYYMMSShhmmss                  | date +%Y%m%d%H%M%S         | $(date +%Y%m%d%H%M%S)
YYYYMMSShhmmssnnnnnnnnn         | date +%Y%m%d%H%M%S%N       | $(date +%Y%m%d%H%M%S%N)
YYMMDD_hhmmss                   | date +%y%m%d_%H%M%S        | $(date +%y%m%d_%H%M%S)
Seconds since UNIX epoch:       | date +%s                   | $(date +%s)
Nanoseconds only:               | date +%N                   | $(date +%N)
Nanoseconds since UNIX epoch:   | date +%s%N                 | $(date +%s%N)
ISO8601 UTC timestamp           | date --utc +%FT%TZ         | $(date --utc +%FT%TZ)
ISO8601 UTC timestamp + ms      | date --utc +%FT%T.%3NZ     | $(date --utc +%FT%T.%3NZ)
ISO8601 Local TZ timestamp      | date +%FT%T%Z              | $(date +%FT%T%Z)
YYYY-MM-DD (Short day)          | date +%F\(%a\)             | $(date +%F\(%a\))
YYYY-MM-DD (Long day)           | date +%F\(%A\)             | $(date +%F\(%A\))

3.2 SNTP和NITZ

在手机(包括Android和功能机)和模组产品中,SNTPNITZ两种同步系统时间的策略一般都会用到。默认使用的是NITZ来获取网络时间,但是需要有运营商的支持才能使用(中国联通就不支持),而有些设备产品只支持WIFI等无线网络,而不支持移动网络,此时就需要采用SNTP方式来获取网络时间进行同步了。SNTP协议时间戳是以1900年1月1日0点0分0秒为起点,而linux时间戳从1970年1月1日0点0分0秒开始记秒数,即记录到SNTP结构体中的时间包含了JAN_1970(从1900到1970共70年的秒数)。在拿到SNTP时间后,往linux同步时间时,需要减掉JAN_1970。

4 总结

  • UTCGMT时间基本相同;
  • 硬件时钟系统时钟同步后,会分开独立运行;
  • 网络时钟的精度都比较高,可以用SNTPNITZ来进行同步,尤其SNTP时间同步精度可以达到毫秒级。
  • linux系统的计时起点为1970年1月1日0点0分0秒,其他嵌入式系统在做网络时间同步时,也一定要确认好计时起点。

参考资料

[1]

维基百科: https://zh.wikipedia.org/zh-hans/%E6%97%B6%E5%8C%BA?wprov=sfla1

分类:

后端

标签:

后端

作者介绍

橙子随记
V1

记录code、感悟。公众号:橙子随记