1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-01-21 charlown first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13 #include <sys/time.h>
14 #include "board.h"
15
16 #ifdef BSP_USING_RTC
17
18 #define LOG_TAG "drv.rtc"
19 #include "drv_log.h"
20
21 #ifndef BKP_DR1
22 #define BKP_DR1 RT_NULL
23 #endif
24
25 #define BKUP_REG_DATA 0xA5A5
26
27 static struct rt_rtc_device rtc;
28
rt_rtc_config(void)29 static void rt_rtc_config(void)
30 {
31 /* Allow access to BKP Domain */
32 PWR_BackupAccessCmd(ENABLE);
33
34 #if defined(BSP_USING_RTC_LSI) && defined(LSI_VALUE)
35 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
36 #else
37 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
38 #endif
39
40 RCC_RTCCLKCmd(ENABLE);
41
42 RTC_WaitForLastTask();
43
44 RTC_WaitForSynchro();
45
46 if (BKP_ReadBackupRegister(BKP_DR1) != BKUP_REG_DATA)
47 {
48 LOG_I("RTC hasn't been configured, please use <date> command to config.");
49 /* Set RTC prescaler: set RTC period to 1sec */
50 RTC_SetPrescaler(32767);
51 /* Wait until last write operation on RTC registers has finished */
52 RTC_WaitForLastTask();
53 }
54 }
55
ch32f2_rt_rtc_init(void)56 static rt_err_t ch32f2_rt_rtc_init(void)
57 {
58
59 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
60 PWR_BackupAccessCmd(ENABLE);
61
62 #if defined(BSP_USING_RTC_LSI) && defined(LSI_VALUE)
63 RCC_LSICmd(ENABLE);
64
65 while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
66 ;
67 #else
68
69 RCC_LSEConfig(RCC_LSE_ON);
70 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
71 ;
72 #endif
73
74 rt_rtc_config();
75
76 return RT_EOK;
77 }
78
ch32f2_get_secs(time_t * args)79 static rt_err_t ch32f2_get_secs(time_t *args)
80 {
81 *(rt_uint32_t *)args = RTC_GetCounter();
82 LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)args);
83
84 return RT_EOK;
85 }
86
ch32f2_set_secs(time_t * args)87 static rt_err_t ch32f2_set_secs(time_t *args)
88 {
89 /* Set the RTC counter value */
90 RTC_SetCounter(*(rt_uint32_t *)args);
91 /* Wait until last write operation on RTC registers has finished */
92 RTC_WaitForLastTask();
93
94 LOG_D("set rtc time.");
95 BKP_WriteBackupRegister(BKP_DR1, BKUP_REG_DATA);
96
97 LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)args);
98
99 return RT_EOK;
100 }
101
102 const static struct rt_rtc_ops rtc_ops =
103 {
104 .init = ch32f2_rt_rtc_init,
105 .get_secs = ch32f2_get_secs,
106 .set_secs = ch32f2_set_secs,
107 .get_alarm = RT_NULL,
108 .set_alarm = RT_NULL,
109 .get_timeval = RT_NULL,
110 .set_timeval = RT_NULL};
111
rt_hw_rtc_init(void)112 int rt_hw_rtc_init(void)
113 {
114 rt_err_t result;
115
116 rtc.ops = &rtc_ops;
117
118 result = rt_hw_rtc_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
119 if (result != RT_EOK)
120 {
121 LOG_E("rtc register err code: %d", result);
122 return result;
123 }
124 LOG_D("rtc init success");
125
126 return RT_EOK;
127 }
128
129 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
130
131 #endif /* BSP_USING_RTC */
132