test_rtc.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /* Copyright (c) 2023, Canaan Bright Sight Co., Ltd
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are met:
  5. * 1. Redistributions of source code must retain the above copyright
  6. * notice, this list of conditions and the following disclaimer.
  7. * 2. Redistributions in binary form must reproduce the above copyright
  8. * notice, this list of conditions and the following disclaimer in the
  9. * documentation and/or other materials provided with the distribution.
  10. *
  11. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  12. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  13. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  14. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  16. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  17. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  18. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  19. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  21. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  22. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  23. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. /*
  26. * Copyright (c) 2006-2025 RT-Thread Development Team
  27. *
  28. * SPDX-License-Identifier: Apache-2.0
  29. */
  30. #include <rtthread.h>
  31. #include <rtdevice.h>
  32. #include <time.h>
  33. #include <utest.h>
  34. #include <finsh.h>
  35. #include "drv_rtc.h"
  36. /*
  37. * 测试 RTC 的时间功能与闹钟功能,在RTCd的寄存器中保存的时间信息
  38. * 是以 UTC 时间保存的,要使用本地时间需要配置时区,当前配置的时
  39. * 区是东八区,即北京时间(CST)
  40. *
  41. * 在设置时间日期时使用 set_time() 与 set_date() 接口,设置的时
  42. * 间这两个接口内部会做时区转换
  43. *
  44. * 测试说明:
  45. * 基于庐山派开发板测试(01Studio 的开发板无法使用硬件RTC,
  46. * 因为没有接 int0/4 的上拉)
  47. * RTC 为 K230 自带的 RTC
  48. * RTC 的时钟源为外部 32.768KHz 晶振
  49. * 在测试终端运行该测试后,会分别进行 test_rtc_set(),
  50. * test_rtc_alarm() 与 test_rtc_interface() 三个测试。
  51. * 其中 test_rtc_set() 会通过 set_time() 与 set_date() 设置时间,
  52. * 注意设置的时间需要为本地时间,内部会转换成 UTC 时间,然后调用
  53. * drv_rtc.c 内的接口设置到 RTC 寄存器中;
  54. * test_rtc_alarm() 会设置一个 5 秒后的闹钟时间,并注册一个闹钟
  55. * 中断回调函数,同样用户设置的闹钟时间为本地时间,内部会转换成UTC
  56. * 时间然后保存进 RTC 中;
  57. * test_rtc_interface() 会测试读写 RTC 的接口,写 RTC 时同样需要
  58. * 提供本地时间,读出来后需要转换成本地时间(如果有需要)。
  59. */
  60. #define RTC_NAME "rtc"
  61. static void test_rtc_set(void)
  62. {
  63. rt_err_t ret = RT_EOK;
  64. time_t now;
  65. uint32_t i;
  66. rt_device_t rtc_dev = RT_NULL;
  67. LOG_I("rtc set time test\n");
  68. rtc_dev = rt_device_find(RTC_NAME);
  69. uassert_not_null(rtc_dev);
  70. ret = rt_device_open(rtc_dev, RT_DEVICE_OFLAG_RDWR);
  71. uassert_int_equal(ret, RT_EOK);
  72. ret = set_time(23, 59, 59);
  73. uassert_int_equal(ret, RT_EOK);
  74. ret = set_date(2025, 9, 16);
  75. uassert_int_equal(ret, RT_EOK);
  76. rt_thread_mdelay(500);
  77. /* 设置完时间后打印10次时间 */
  78. for (i=0; i<10; i++)
  79. {
  80. now = time(RT_NULL);
  81. LOG_I("%s\n", ctime(&now));
  82. rt_thread_mdelay(1000);
  83. }
  84. rt_device_close(rtc_dev);
  85. }
  86. static void test_rtc_alarm_callback(void)
  87. {
  88. LOG_I("rtc alarm triggered!\n");
  89. }
  90. static void test_rtc_alarm(void)
  91. {
  92. rt_err_t ret = RT_EOK;
  93. time_t now;
  94. uint32_t i;
  95. struct tm p_tm;
  96. rt_device_t rtc_dev = RT_NULL;
  97. struct rt_alarm *alarm = RT_NULL;
  98. rtc_alarm_setup_t setup;
  99. LOG_I("rtc alarm test\n");
  100. rtc_dev = rt_device_find(RTC_NAME);
  101. uassert_not_null(rtc_dev);
  102. ret = rt_device_open(rtc_dev, RT_DEVICE_OFLAG_RDWR);
  103. uassert_int_equal(ret, RT_EOK);
  104. ret = set_time(23, 59, 59);
  105. uassert_int_equal(ret, RT_EOK);
  106. ret = set_date(2025, 9, 16);
  107. uassert_int_equal(ret, RT_EOK);
  108. rt_thread_mdelay(500);
  109. now = time(RT_NULL);
  110. LOG_I("%s\n", ctime(&now));
  111. now += 5; //alarm after 5s
  112. localtime_r(&now, &p_tm);
  113. setup.flag = RTC_INT_ALARM_MINUTE | RTC_INT_ALARM_SECOND;
  114. setup.tm.tm_year = p_tm.tm_year;
  115. setup.tm.tm_mon = p_tm.tm_mon;
  116. setup.tm.tm_mday = p_tm.tm_mday;
  117. setup.tm.tm_wday = p_tm.tm_wday;
  118. setup.tm.tm_hour = p_tm.tm_hour;
  119. setup.tm.tm_min = p_tm.tm_min;
  120. setup.tm.tm_sec = p_tm.tm_sec;
  121. rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_SET_CALLBACK, &test_rtc_alarm_callback); //set rtc intr callback
  122. rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_SET_ALARM, &setup); //set alarm time
  123. rt_memset(&p_tm, 0, sizeof(p_tm));
  124. rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_GET_ALARM, &p_tm); //get alarm time
  125. now = timegm(&p_tm);
  126. LOG_I("get alarm time: %s\n", ctime(&now));
  127. for (i=0; i<10; i++)
  128. {
  129. now = time(RT_NULL);
  130. LOG_I("%s\n", ctime(&now));
  131. rt_thread_mdelay(1000);
  132. }
  133. rt_device_control(rtc_dev, RT_DEVICE_CTRL_RTC_STOP_ALARM, RT_NULL); //stop alarm
  134. rt_device_close(rtc_dev);
  135. }
  136. static void test_rtc_interface(void)
  137. {
  138. rt_err_t ret = RT_EOK;
  139. uint32_t i;
  140. rt_device_t rtc_dev = RT_NULL;
  141. time_t now;
  142. struct tm tm;
  143. LOG_I("rtc interface test\n");
  144. rtc_dev = rt_device_find(RTC_NAME);
  145. uassert_not_null(rtc_dev);
  146. ret = rt_device_open(rtc_dev, RT_DEVICE_OFLAG_RDWR);
  147. uassert_int_equal(ret, RT_EOK);
  148. LOG_I("write rtc\n");
  149. tm.tm_year = 2025 - 1900;
  150. tm.tm_mon = 9 - 1;
  151. tm.tm_mday = 16;
  152. tm.tm_wday = 2;
  153. tm.tm_hour = 23;
  154. tm.tm_min = 59;
  155. tm.tm_sec = 59;
  156. rt_device_write(rtc_dev, RT_NULL, (void*)&tm, sizeof(tm));
  157. rt_thread_mdelay(500);
  158. /* 设置完时间后打印10次时间 */
  159. for (i=0; i<10; i++)
  160. {
  161. now = time(RT_NULL);
  162. LOG_I("[sys]:%s\n", ctime(&now));
  163. rt_thread_mdelay(1000);
  164. }
  165. LOG_I("read rtc\n");
  166. for (i=0; i<10; i++)
  167. {
  168. rt_device_read(rtc_dev, RT_NULL, (void*)&now, sizeof(now));
  169. LOG_I("[read]: %s\n", ctime(&now));
  170. rt_thread_mdelay(1000);
  171. }
  172. rt_device_close(rtc_dev);
  173. }
  174. static void test_rtc(void)
  175. {
  176. test_rtc_set();
  177. test_rtc_alarm();
  178. test_rtc_interface();
  179. }
  180. static void testcase(void)
  181. {
  182. LOG_I("This is a rtc test case.\n");
  183. UTEST_UNIT_RUN(test_rtc);
  184. }
  185. static rt_err_t utest_tc_init(void)
  186. {
  187. return RT_EOK;
  188. }
  189. static rt_err_t utest_tc_cleanup(void)
  190. {
  191. return RT_EOK;
  192. }
  193. UTEST_TC_EXPORT(testcase, "bsp.k230.drivers.rtc", utest_tc_init, utest_tc_cleanup, 100);