Skip to content

Conversation

@dongly
Copy link
Contributor

@dongly dongly commented Oct 30, 2025

拉取/合并请求描述:(PR description)

[

为什么提交这份PR (why to submit this PR)

启用 soft rtc 后, RT_DEVICE_CTRL_RTC_GET_TIMEVAL/RT_DEVICE_CTRL_RTC_GET_TIMESPEC 会出错

10-30 11:54:41.-282 D/ntp: Time calculation: server=1761796480.672346, network_delay=0.119000, half_delay=0.059000
10-30 11:54:41.-270 D/ntp: Time offset calculated: tv_sec=1761796480, tv_usec=0
10-30 11:54:41.-261 D/ntp: NTP response processing completed successfully
10-30 11:54:41.-253 D/ntp: NTP time synchronization successful from server 1
10-30 11:54:40.732 I/ntp: Get time from NTP server(ntp.aliyun.com): 2025-10-30T11:54:40.731+08:00(+0.026s)
msh />ntp_sync
10-30 11:54:41.1161 I/ntp: Trying get time from NTP server: ntp.ntsc.ac.cn
10-30 11:54:41.1170 D/ntp: Server 0: hostname validation passed for ntp.ntsc.ac.cn
10-30 11:54:41.1179 D/ntp: Trying server 0: ntp.ntsc.ac.cn
10-30 11:54:41.1186 D/ntp: NTP packet prepared: T1=435730 ms, sec=268453568, frac=2208989235

你的解决方案是什么 (what is your solution)

  • soft rtc 统一使用了一个 init_ts(或 init_ktime_ts), 替代了 init_time / init_tv
  • 重新实现了, set_rtc_time(),
  • 新增了 get_rtc_time()
  • 简化了 soft_rtc_control()

请提供验证的bsp和config (provide the config and bsp)

  • BSP:
  • .config:
    RT_USING_SOFT_RTC
  • action:

]

当前拉取/合并请求的状态 Intent for your PR

必须选择一项 Choose one (Mandatory):

  • 本拉取/合并请求是一个草稿版本 This PR is for a code-review and is intended to get feedback
  • 本拉取/合并请求是一个成熟版本 This PR is mature, and ready to be integrated into the repo

代码质量 Code Quality:

我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:

  • 已经仔细查看过代码改动的对比 Already check the difference between PR and old code
  • 代码风格正确,包括缩进空格,命名及其他风格 Style guide is adhered to, including spacing, naming and other styles
  • 没有垃圾代码,代码尽量精简,不包含#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up
  • 所有变更均有原因及合理的,并且不会影响到其他软件组件代码或BSP All modifications are justified and not affect other components or BSP
  • 对难懂代码均提供对应的注释 I've commented appropriately where code is tricky
  • 代码是高质量的 Code in this PR is of high quality
  • 已经使用formatting 等源码格式化工具确保格式符合RT-Thread代码规范 This PR complies with RT-Thread code specification
  • 如果是新增bsp, 已经添加ci检查到.github/ALL_BSP_COMPILE.json 详细请参考链接BSP自查

@github-actions
Copy link

👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread!

为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。
To ensure your code complies with RT-Thread's coding style, please run the code formatting workflow by following the steps below (If the formatting of CI fails to run).


🛠 操作步骤 | Steps

  1. 前往 Actions 页面 | Go to the Actions page
    点击进入工作流 → | Click to open workflow →

  2. 点击 Run workflow | Click Run workflow

  • 设置需排除的文件/目录(目录请以"/"结尾)
    Set files/directories to exclude (directories should end with "/")
  • 将目标分支设置为 \ Set the target branch to:fix_soft_rtc
  • 设置PR number为 \ Set the PR number to:10874
  1. 等待工作流完成 | Wait for the workflow to complete
    格式化后的代码将自动推送至你的分支。
    The formatted code will be automatically pushed to your branch.

完成后,提交将自动更新至 fix_soft_rtc 分支,关联的 Pull Request 也会同步更新。
Once completed, commits will be pushed to the fix_soft_rtc branch automatically, and the related Pull Request will be updated.

如有问题欢迎联系我们,再次感谢您的贡献!💐
If you have any questions, feel free to reach out. Thanks again for your contribution!

@CLAassistant
Copy link

CLAassistant commented Oct 30, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ dongly
❌ github-actions[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions
Copy link

github-actions bot commented Oct 30, 2025

📌 Code Review Assignment

🏷️ Tag: components

Reviewers: @Maihuanyi

Changed Files (Click to expand)
  • components/drivers/rtc/dev_soft_rtc.c

📊 Current Review Status (Last Updated: 2025-11-16 10:32 CST)


📝 Review Instructions

  1. 维护者可以通过单击此处来刷新审查状态: 🔄 刷新状态
    Maintainers can refresh the review status by clicking here: 🔄 Refresh Status

  2. 确认审核通过后评论 LGTM/lgtm
    Comment LGTM/lgtm after confirming approval

  3. PR合并前需至少一位维护者确认
    PR must be confirmed by at least one maintainer before merging

ℹ️ 刷新CI状态操作需要具备仓库写入权限。
ℹ️ Refresh CI status operation requires repository Write permission.

@dongly dongly changed the title [soft_rtc]修正GET_TIMESPEC/GET_TIMEVAL 获取 ns/us 的错误; 优化soft_rtc实现 [soft_rtc]fix timespec/timeval error, optimize soft_rtc implementation Oct 30, 2025
@dongly
Copy link
Contributor Author

dongly commented Oct 30, 2025

@Maihuanyi 请审核

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR fixes timespec/timeval handling errors in the soft RTC implementation and optimizes the overall code structure. The main issue addressed is that RT_DEVICE_CTRL_RTC_GET_TIMEVAL and RT_DEVICE_CTRL_RTC_GET_TIMESPEC commands were producing incorrect results when soft RTC was enabled.

Key Changes:

  • Unified time storage using a single init_ts (timespec) baseline instead of separate init_time, init_tv, and conditional init_ts variables
  • Added new get_rtc_time() function and reimplemented set_rtc_time() to work with timespec structures consistently
  • Simplified soft_rtc_control() by removing platform-specific #ifdef RT_USING_KTIME conditions and using the unified get/set functions
  • Added comprehensive documentation comments following doxygen format for all functions
  • Introduced spinlock protection for thread-safe access to shared time variables

Comment on lines +147 to +148
ts->tv_sec = init_ktime_ts.tv_sec + (current_ts.tv_sec - init_ktime_ts.tv_sec);
ts->tv_nsec = init_ktime_ts.tv_nsec + (current_ts.tv_nsec - init_ktime_ts.tv_nsec);
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug / 错误: Incorrect time calculation logic in get_rtc_time()

English: The calculation on line 147 is incorrect. It adds the difference (current_ts.tv_sec - init_ktime_ts.tv_sec) to init_ktime_ts.tv_sec, which effectively just results in current_ts.tv_sec. The correct calculation should add the elapsed time to init_ts.tv_sec (the RTC baseline time), not to init_ktime_ts.tv_sec (the system time when baseline was set).

中文: 第147行的计算逻辑有误。它将差值 (current_ts.tv_sec - init_ktime_ts.tv_sec) 加到 init_ktime_ts.tv_sec 上,这实际上只是得到 current_ts.tv_sec。正确的计算应该是将经过的时间加到 init_ts.tv_sec(RTC基准时间)上,而不是加到 init_ktime_ts.tv_sec(设置基准时的系统时间)上。

Correct implementation / 正确实现:

ts->tv_sec = init_ts.tv_sec + (current_ts.tv_sec - init_ktime_ts.tv_sec);
ts->tv_nsec = init_ts.tv_nsec + (current_ts.tv_nsec - init_ktime_ts.tv_nsec);
Suggested change
ts->tv_sec = init_ktime_ts.tv_sec + (current_ts.tv_sec - init_ktime_ts.tv_sec);
ts->tv_nsec = init_ktime_ts.tv_nsec + (current_ts.tv_nsec - init_ktime_ts.tv_nsec);
ts->tv_sec = init_ts.tv_sec + (current_ts.tv_sec - init_ktime_ts.tv_sec);
ts->tv_nsec = init_ts.tv_nsec + (current_ts.tv_nsec - init_ktime_ts.tv_nsec);

Copilot uses AI. Check for mistakes.
init_tick = rt_tick_get();
init_time = timegm(&time_new);
#endif
init_ts.tv_sec = timegm(&time_new);
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug / 错误: Missing initialization of init_ts.tv_nsec

English: When initializing the RTC device, only init_ts.tv_sec is set on line 322, but init_ts.tv_nsec is never initialized. This could lead to unpredictable nanosecond values. The nanosecond field should be explicitly set to 0.

中文: 在初始化 RTC 设备时,第322行只设置了 init_ts.tv_sec,但从未初始化 init_ts.tv_nsec。这可能导致纳秒值不可预测。应该明确将纳秒字段设置为0。

Suggestion / 建议:

init_ts.tv_sec = timegm(&time_new);
init_ts.tv_nsec = 0;
Suggested change
init_ts.tv_sec = timegm(&time_new);
init_ts.tv_sec = timegm(&time_new);
init_ts.tv_nsec = 0;

Copilot uses AI. Check for mistakes.
#else
rt_tick_t tick = rt_tick_get_delta(init_tick);
ts->tv_sec = init_ts.tv_sec + tick / RT_TICK_PER_SECOND;
ts->tv_nsec = init_ts.tv_nsec + ((tick % RT_TICK_PER_SECOND) * (1000000000UL / RT_TICK_PER_SECOND));
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug / 错误: Potential overflow in nanosecond calculation

English: On line 152, the calculation (tick % RT_TICK_PER_SECOND) * (1000000000UL / RT_TICK_PER_SECOND) may lose precision due to integer division. For example, if RT_TICK_PER_SECOND is 1000, the expression 1000000000UL / RT_TICK_PER_SECOND equals 1000000, but if RT_TICK_PER_SECOND is not a divisor of 1000000000, precision will be lost. A more accurate approach would be to use ((tick % RT_TICK_PER_SECOND) * 1000000000UL) / RT_TICK_PER_SECOND.

中文: 第152行的计算 (tick % RT_TICK_PER_SECOND) * (1000000000UL / RT_TICK_PER_SECOND) 可能由于整数除法而损失精度。例如,如果 RT_TICK_PER_SECOND 是1000,表达式 1000000000UL / RT_TICK_PER_SECOND 等于1000000,但如果 RT_TICK_PER_SECOND 不是1000000000的除数,精度将会损失。更准确的方法是使用 ((tick % RT_TICK_PER_SECOND) * 1000000000UL) / RT_TICK_PER_SECOND

Suggestion / 建议:

ts->tv_nsec = init_ts.tv_nsec + (((tick % RT_TICK_PER_SECOND) * 1000000000UL) / RT_TICK_PER_SECOND);
Suggested change
ts->tv_nsec = init_ts.tv_nsec + ((tick % RT_TICK_PER_SECOND) * (1000000000UL / RT_TICK_PER_SECOND));
ts->tv_nsec = init_ts.tv_nsec + (((tick % RT_TICK_PER_SECOND) * 1000000000UL) / RT_TICK_PER_SECOND);

Copilot uses AI. Check for mistakes.
Comment on lines +59 to +66
/**
* @brief Alarm timeout callback function
* @param param Pointer to RTC device
* @return None
*
* This function is called when the alarm timer expires and updates
* the alarm system.
*/
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Documentation / 文档问题: Incorrect parameter name in function documentation

English: The parameter documentation on line 60 says @param param Pointer to RTC device, but the actual parameter name in the function signature on line 67 is param. However, the description "Pointer to RTC device" is misleading because looking at the function call context, param is actually a void* that's passed to rt_alarm_update(), not necessarily a pointer to an RTC device. The documentation should be more accurate about what this parameter represents.

中文: 第60行的参数文档说 @param param Pointer to RTC device,虽然第67行的函数签名中参数名确实是 param,但描述"Pointer to RTC device"具有误导性,因为从函数调用上下文来看,param 实际上是传递给 rt_alarm_update()void*,不一定是指向 RTC 设备的指针。文档应该更准确地描述此参数的含义。

Suggestion / 建议:

/**
 * @brief Alarm timeout callback function
 * @param param User data passed to alarm update function
 * @return None
 * 
 * This function is called when the alarm timer expires and updates
 * the alarm system.
 */

Copilot uses AI. Check for mistakes.

rt_device_control(&soft_rtc_dev, RT_DEVICE_CTRL_RTC_GET_TIME, &time);
set_rtc_time(time);
struct timespec ts = { time, 0 };
Copy link

Copilot AI Nov 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Maintainability / 可维护性: Redundant synchronization in rt_soft_rtc_sync()

English: The function rt_soft_rtc_sync() gets the current time and then immediately sets it back as the baseline. This effectively resets the soft RTC to the current time, which loses any accumulated drift. This seems counterintuitive for a "sync" function. The purpose appears to be updating alarm status (called in set_rtc_time()), but the logic could be clearer. Consider adding a comment explaining why getting and immediately setting the same time is the intended behavior.

中文: 函数 rt_soft_rtc_sync() 获取当前时间,然后立即将其设置回基准时间。这实际上将软 RTC 重置为当前时间,这会丢失任何累积的漂移。对于"同步"函数来说,这似乎违反直觉。其目的似乎是更新闹钟状态(在 set_rtc_time() 中调用),但逻辑可以更清晰。建议添加注释解释为什么获取并立即设置相同时间是预期行为。

Suggestion / 建议:
Add a comment explaining the purpose of this operation, or reconsider if this is the correct synchronization logic.

Suggested change
struct timespec ts = { time, 0 };
struct timespec ts = { time, 0 };
/*
* Intentionally reset the soft RTC baseline to the current time.
* This operation updates alarm status and synchronizes the soft RTC
* with the external time source, discarding any accumulated drift.
* This is the intended behavior for synchronization in this context.
*/

Copilot uses AI. Check for mistakes.
@Rbb666
Copy link
Member

Rbb666 commented Nov 16, 2025

@xqyjlj 一起帮忙review下呗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants