一、前言
RT-Thread 的 alarm 是系統提供的鬧鐘設備接口,提供了一系列用于管理定時事件的 API。然而,在實際使用過程中,遇到了一些與時間處理相關的問題。本文將圍繞這些問題展開分析,并提出對應的解決方案。

二、問題點
在使用先楫平臺的 drv_rtc 驅動時,發現兩個典型問題:
使用 local_time_r 設置鬧鐘時間時無法觸發回調函數
使用 gmtime_r 設置后雖然能觸發回調,但通過 list_alarm 命令打印出的鬧鐘時間顯示不正確。
例如:設置為 1719 的本地時間,實際輸出卻為 919,存在 8 小時的時間差。

這不單單在先楫平臺有所體現,在其他平臺比如STM32等都有類似現象。
三、原因分析
在解析原因之前,需要了解下rtthread對于ctime的實現。
(一)ctime相關接口的區別
在rtthread的rtc和alarm驅動中,需要調用ctime的各類時間函數,其中最主要的是時間接口區別是:
local_time和local_time_t是將時間戳(time_t)轉換本地時間函數,比如設置時區為東八區,那么相比UTC時間就會多8個小時。
gmtime和gmtime_r是將時間戳轉換為UTC時間。
(二)rtthread的時區支持
考慮到嵌入式的場景應用,rtthread采用的是輕量級的時區支持,沒有支持完整的時區數據庫。
默認的時區是東八區(北京時間)
代碼宏是RT_LIBC_USING_LIGHT_TZ_DST,對應的kconfig對應以下,如果需要支持其他時區時間,可以改變以下配置。

(三)rtthread的時間轉換支持
在rtthread的時區支持上,主要影響localtime和mktime的行為,localtime_r和localtime會根據時區時間做偏移轉換為本地時間。
mktime會根據時區時間偏移將本地時間轉換為UTC的時間戳。

在rtthread的alarm實現中,涉及到時間戳轉換日歷時間的接口都使用了UTC時間的函數接口gmtime_r,而當觸發鬧鐘更新的時候,需要使用鬧鐘時間與當前時間做判斷以便是否到達鬧鐘觸發事件,如果此時鬧鐘時間使用的是local_time,那么判斷將永遠不成立,也就無法觸發鬧鐘回調。而如果同樣使用的是gmtime,那么時間單位是一致的,就會觸發鬧鐘回調,但打印的鬧鐘列表是基于UTC時間。
由此可知:在 Alarm 模塊的實現中,時間戳轉日歷時間的操作均使用的是 UTC 時間函數(gmtime_r)。如果用戶傳入的是基于本地時間的結構體,則因未統一轉換而造成比較失敗,導致無法觸發回調。
三、修復
根據上述原因,問題的根本在于Alarm 模塊未正確支持本地時間的判斷邏輯。針對這一問題,社區已在最新主線代碼中進行了修復。

在對應的時間戳轉換日歷時間上加個宏定義來切換為本地時間計算還是UTC時間計算即可。
Kconfig配置上加了RT_ALARM_USING_LOCAL_TIME配置宏,如果打開就是基于本地時間來計算。默認不使能。
RT-Thread Components -> Device Drivers -> Using RTC device drivers-> Using RTC alarm -> Using local time for the alarm calculation
如果使能該配置,那么鬧鐘就是以本地時間local_time為準
如果禁能該配置,那么鬧鐘就是以UTC時間gmtime為準。
在使用rt_alarm_create增加鬧鐘時,配置的鬧鐘時間需要區分來,即可正常工作

在list_alarm命令中加入了timezone,查找鬧鐘列表更加直觀
1、使用UTC時間的alarm
2、使用東八區的本地時間的alarm
四、BSP的drv_rtc驅動注意點
1. 實現 set_timestamp 時注意時間轉換
當啟用了 RT_ALARM_USING_LOCAL_TIME 宏定義時,必須使用 local_time 進行時間轉換,否則可能導致時間偏差。

2、設置鬧鐘時必須完整填寫年月日字段
由于 RT_ALARM_ONESHOT 模式下,系統會將鬧鐘時間轉換為時間戳進行比較,因此必須提供完整的日歷時間結構(包括年、月、日)。否則可能因字段缺失導致匹配失敗。

而先楫只需要從鬧鐘寄存器中獲取即可。

五、總結
本文圍繞 RT-Thread 中的Alarm(鬧鐘)設備驅動展開討論,結合先楫平臺的實際開發經驗,深入分析了在使用 rt_alarm_create 設置本地時間鬧鐘時遇到的問題,并從底層機制出發,解釋了問題根源,最終提出了有效的解決方案。
核心結論如下:
Alarm 子系統默認使用 UTC 時間函數(如 gmtime_r)進行時間戳與日歷時間的轉換;
若傳入本地時間結構體但未統一轉換,會導致比較失敗,從而無法觸發鬧鐘回調;
rtthread社區已在主線中引入 RT_ALARM_USING_LOCAL_TIME 宏定義,支持基于本地時間的鬧鐘行為;
在使用 Alarm 功能時,開發者需關注系統時區設置以及是否啟用本地時間模式,以確保鬧鐘行為符合預期。
通過本文的分析與實踐,希望可以幫助開發者更好地理解和使用 RT-Thread 的 Alarm 子系統,提升嵌入式設備中定時任務管理的靈活性與準確性。
-
API
+關注
關注
2文章
1566瀏覽量
63688 -
設備
+關注
關注
2文章
4649瀏覽量
71566 -
RT-Thread
+關注
關注
32文章
1380瀏覽量
41630
發布評論請先 登錄
在RT-Thread系統上開啟RTC驅動模塊
RT-Thread編程指南
RT-Thread用戶手冊
RT-Thread全球技術大會:Kconfig在RT-Thread中的工作機制

RT-Thread學習筆記 RT-Thread的架構概述

RT-Thread文檔_RT-Thread 潘多拉 STM32L475 上手指南

RT-Thread v5.0.2 發布

評論