clock_time.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * Copyright (c) 2006-2025, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2025-01-01 RT-Thread Unified clock_time subsystem implementation
  9. */
  10. #include <rtthread.h>
  11. #include <rtdevice.h>
  12. #include <drivers/clock_time.h>
  13. #define DBG_TAG "clock_time"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. /* Default system clock time device */
  17. static rt_clock_time_t _default_device = RT_NULL;
  18. /**
  19. * @brief Register a clock time device
  20. */
  21. rt_err_t rt_clock_time_device_register(struct rt_clock_time_device *dev,
  22. const char *name,
  23. rt_uint8_t caps)
  24. {
  25. rt_err_t result;
  26. RT_ASSERT(dev != RT_NULL);
  27. RT_ASSERT(name != RT_NULL);
  28. RT_ASSERT(dev->ops != RT_NULL);
  29. /* Initialize parent device structure */
  30. dev->parent.type = RT_Device_Class_Timer;
  31. dev->parent.rx_indicate = RT_NULL;
  32. dev->parent.tx_complete = RT_NULL;
  33. dev->parent.init = RT_NULL;
  34. dev->parent.open = RT_NULL;
  35. dev->parent.close = RT_NULL;
  36. dev->parent.read = RT_NULL;
  37. dev->parent.write = RT_NULL;
  38. dev->parent.control = RT_NULL;
  39. dev->caps = caps;
  40. /* Calculate resolution scale factor */
  41. if (dev->ops->get_freq)
  42. {
  43. rt_uint64_t freq = dev->ops->get_freq();
  44. if (freq > 0)
  45. {
  46. /* res_scale = (1e9 * RT_CLOCK_TIME_RESMUL) / freq
  47. * To avoid overflow, we check if freq is very small.
  48. * For freq >= 1000, this calculation is safe on 64-bit.
  49. * For very small frequencies, limit the scale factor.
  50. */
  51. if (freq >= 1000)
  52. {
  53. dev->res_scale = ((1000000000ULL * RT_CLOCK_TIME_RESMUL) / freq);
  54. }
  55. else
  56. {
  57. /* For very low frequencies, calculate more carefully */
  58. dev->res_scale = (1000000ULL * RT_CLOCK_TIME_RESMUL) / freq * 1000;
  59. }
  60. }
  61. else
  62. {
  63. dev->res_scale = RT_CLOCK_TIME_RESMUL;
  64. }
  65. }
  66. else
  67. {
  68. dev->res_scale = RT_CLOCK_TIME_RESMUL;
  69. }
  70. /* Register device */
  71. result = rt_device_register(&dev->parent, name, RT_DEVICE_FLAG_RDWR);
  72. if (result != RT_EOK)
  73. {
  74. LOG_E("Failed to register clock_time device: %s", name);
  75. return result;
  76. }
  77. /* Set as default if none exists */
  78. if (_default_device == RT_NULL)
  79. {
  80. _default_device = dev;
  81. LOG_D("Set %s as default clock_time device", name);
  82. }
  83. LOG_I("Registered clock_time device: %s (caps: 0x%02x)", name, caps);
  84. return RT_EOK;
  85. }
  86. /**
  87. * @brief Get the default system clock time device
  88. */
  89. rt_clock_time_t rt_clock_time_default(void)
  90. {
  91. return _default_device;
  92. }
  93. /**
  94. * @brief Set the default system clock time device
  95. */
  96. rt_err_t rt_clock_time_set_default(rt_clock_time_t dev)
  97. {
  98. RT_ASSERT(dev != RT_NULL);
  99. _default_device = dev;
  100. LOG_D("Changed default clock_time device to: %s", dev->parent.parent.name);
  101. return RT_EOK;
  102. }