1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2009-01-05 Bernard the first version
9 * 2010-12-27 onelife Modify for EFM32
10 * 2011-06-16 onelife Modify init function for efm32lib v2 upgrading
11 * 2011-12-14 onelife Move LFXO enabling routine to driver initialization function (board.c)
12 */
13
14 /***************************************************************************//**
15 * @addtogroup efm32
16 * @{
17 ******************************************************************************/
18
19 /* Includes ------------------------------------------------------------------*/
20
21 #include <rtdevice.h>
22 #include "board.h"
23 #include "hdl_interrupt.h"
24 #include "drv_rtc.h"
25
26 #if defined(RT_USING_RTC)
27 /* Private typedef -----------------------------------------------------------*/
28 /* Private define ------------------------------------------------------------*/
29 /* Private macro -------------------------------------------------------------*/
30 #ifdef RT_RTC_DEBUG
31 #define rtc_debug(format,args...) rt_kprintf(format, ##args)
32 #else
33 #define rtc_debug(format,args...)
34 #endif
35
36 /* Private variables ---------------------------------------------------------*/
37 static struct rt_device rtc;
38 static rt_uint32_t rtc_time;
39
40 /* Private function prototypes -----------------------------------------------*/
41 /* Private functions ---------------------------------------------------------*/
rt_rtc_open(rt_device_t dev,rt_uint16_t oflag)42 static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
43 {
44 if (dev->rx_indicate != RT_NULL)
45 {
46 /* Open Interrupt */
47 }
48
49 return RT_EOK;
50 }
51
rt_rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)52 static rt_ssize_t rt_rtc_read(
53 rt_device_t dev,
54 rt_off_t pos,
55 void* buffer,
56 rt_size_t size)
57 {
58 return 0;
59 }
60
61 /***************************************************************************//**
62 * @brief
63 * Configure RTC device
64 *
65 * @details
66 *
67 * @note
68 *
69 * @param[in] dev
70 * Pointer to device descriptor
71 *
72 * @param[in] cmd
73 * RTC control command
74 *
75 * @param[in] args
76 * Arguments
77 *
78 * @return
79 * Error code
80 ******************************************************************************/
rt_rtc_control(rt_device_t dev,int cmd,void * args)81 static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args)
82 {
83 RT_ASSERT(dev != RT_NULL);
84
85 switch (cmd)
86 {
87 case RT_DEVICE_CTRL_RTC_GET_TIME:
88 *(rt_uint32_t *)args = rtc_time + RTC_CounterGet();
89 rtc_debug("RTC: get rtc_time %x + %x\n", rtc_time, RTC_CounterGet());
90 break;
91
92 case RT_DEVICE_CTRL_RTC_SET_TIME:
93 {
94 rtc_time = *(rt_uint32_t *)args;
95 rtc_debug("RTC: set rtc_time %x\n", rtc_time);
96
97 /* Reset counter */
98 RTC_CounterReset();
99 }
100 break;
101 }
102
103 return RT_EOK;
104 }
105
106 /***************************************************************************//**
107 * @brief
108 * RTC counter overflow interrupt handler
109 *
110 * @details
111 *
112 * @note
113 ******************************************************************************/
rt_hw_rtc_isr(rt_device_t device)114 void rt_hw_rtc_isr(rt_device_t device)
115 {
116 if (RTC->IF & RTC_IFC_OF)
117 {
118 rtc_time += _RTC_CNT_MASK;
119 }
120
121 RTC->IFC = _RTC_IFC_MASK;
122 }
123
124 /***************************************************************************//**
125 * @brief
126 * Initialize all RTC module related hardware and register RTC device to kernel
127 *
128 * @details
129 *
130 * @note
131 ******************************************************************************/
rt_hw_rtc_init(void)132 void rt_hw_rtc_init(void)
133 {
134 rt_uint32_t reset;
135
136 reset = RMU_ResetCauseGet();
137
138 // TODO: What is the current reset mode?
139 if (reset & RMU_RSTCAUSE_PORST || reset & RMU_RSTCAUSE_EXTRST)
140 {
141 RTC_Init_TypeDef rtcInit;
142 efm32_irq_hook_init_t hook;
143
144 rtcInit.enable = true;
145 rtcInit.debugRun = false;
146 rtcInit.comp0Top = false;
147
148 rtc_time = 0UL;
149
150 rt_kprintf("rtc is not configured\n");
151 rt_kprintf("please configure with set_date and set_time\n");
152
153 /* Configuring clock */
154 CMU_ClockDivSet(cmuClock_RTC,cmuClkDiv_32768);
155 CMU_ClockEnable(cmuClock_RTC, true);
156
157 /* Initialize and enable RTC */
158 RTC_Reset();
159 RTC_Init(&rtcInit);
160
161 hook.type = efm32_irq_type_rtc;
162 hook.unit = 0;
163 hook.cbFunc = rt_hw_rtc_isr;
164 hook.userPtr = RT_NULL;
165 efm32_irq_hook_register(&hook);
166
167 /* Enabling Interrupt from RTC */
168 RTC_IntEnable(RTC_IFC_OF);
169 RTC_IntClear(RTC_IFC_OF);
170
171 NVIC_ClearPendingIRQ(RTC_IRQn);
172 NVIC_SetPriority(RTC_IRQn, EFM32_IRQ_PRI_DEFAULT);
173 NVIC_EnableIRQ(RTC_IRQn);
174 }
175
176 /* register rtc device */
177 rtc.type = RT_Device_Class_RTC;
178 rtc.rx_indicate = RT_NULL;
179 rtc.tx_complete = RT_NULL;
180 rtc.init = RT_NULL;
181 rtc.open = rt_rtc_open;
182 rtc.close = RT_NULL;
183 rtc.read = rt_rtc_read;
184 rtc.write = RT_NULL;
185 rtc.control = rt_rtc_control;
186 rtc.user_data = RT_NULL; /* no private */
187
188 rt_device_register(&rtc, RT_RTC_NAME, RT_DEVICE_FLAG_RDWR | EFM32_NO_DATA);
189 }
190
191 #endif
192
193 /***************************************************************************//**
194 * @}
195 ******************************************************************************/
196