GCC Code Coverage Report


Directory: src/drv/
File: src/drv/rtc/src/rtc_driver.c
Date: 2024-01-25 15:03:18
Exec Total Coverage
Lines: 0 210 0.0%
Branches: 0 41 0.0%

Line Branch Exec Source
1 /********************************************************************************************************//**
2 * @file rtc_driver.c
3 *
4 * @brief File containing the APIs for configuring the RTC peripheral.
5 *
6 * Public Functions:
7 * - void RTC_PerClkCtrl(uint8_t en_or_di)
8 * - void RTC_ClkSource(RTC_ClkSource_t clk_source)
9 * - void RTC_Init(RTC_Config_t RTC_Cfg)
10 * - void RTC_SetTime(RTC_Time_t time)
11 * - void RTC_GetTime(RTC_Time_t* time)
12 * - void RTC_SetDate(RTC_Date_t date)
13 * - void RTC_GetDate(RTC_Date_t* date)
14 * - void RTC_ClearRSF(void)
15 * - uint8_t RTC_GetRSF(void)
16 * - void RTC_SetAlarm(RTC_Alarm_t alarm)
17 * - void RTC_GetAlarm(RTC_Alarm_t* alarm)
18 * - uint8_t RTC_CheckAlarm(RTC_AlarmSel_t alarm)
19 * - uint8_t RTC_ClearAlarm(RTC_AlarmSel_t alarm)
20 * - uint8_t RTC_DisableAlarm(RTC_AlarmSel_t alarm)
21 * - void RTC_Alarm_IRQHandling(void)
22 * - void RTC_AlarmEventCallback(RTC_AlarmSel_t alarm)
23 *
24 * @note
25 * For further information about functions refer to the corresponding header file.
26 */
27
28 #include "rtc_driver.h"
29 #include "stm32f446xx.h"
30 #include <stdint.h>
31
32 /***********************************************************************************************************/
33 /* Static Function Prototypes */
34 /***********************************************************************************************************/
35
36 /**
37 * @brief Function for unlocking the RTC write protected registers.
38 * @return void.
39 */
40 static void RTC_Unlock(void);
41
42 /**
43 * @brief Function for entering in configuration mode for the RTC.
44 * @return void.
45 */
46 static void RTC_EnterConfig(void);
47
48 /**
49 * @brief Function for exiting from configuration mode for the RTC.
50 * @return void.
51 */
52 static void RTC_ExitConfig(void);
53
54 /***********************************************************************************************************/
55 /* Public API Definitions */
56 /***********************************************************************************************************/
57
58 void RTC_PerClkCtrl(uint8_t en_or_di){
59
60 if(en_or_di == ENABLE){
61 RTC_PCLK_EN();
62 }
63 else{
64 RTC_PCLK_DI();
65 }
66 }
67
68 void RTC_ClkSource(RTC_ClkSource_t clk_source){
69
70 /* Disable backup protection */
71 PWR_PCLK_EN();
72 PWR->CR |= (1 << PWR_CR_DBP);
73
74 RCC->BDCR &= ~(0x3 << RCC_BDCR_RTCSEL);
75 RCC->BDCR |= (clk_source << RCC_BDCR_RTCSEL);
76 }
77
78 void RTC_Init(RTC_Config_t RTC_Cfg){
79
80 uint32_t temp = 0;
81
82 RTC_Unlock();
83 RTC_EnterConfig();
84
85 /* Set hours format */
86 RTC->CR &= ~(1 << RTC_CR_FMT);
87 RTC->CR |= (RTC_Cfg.RTC_HoursFormat << RTC_CR_FMT);
88
89 temp |= ((RTC_Cfg.RTC_Time.SecondUnits << RTC_TR_SU) |
90 (RTC_Cfg.RTC_Time.SecondTens << RTC_TR_ST) |
91 (RTC_Cfg.RTC_Time.MinuteUnits << RTC_TR_MNU) |
92 (RTC_Cfg.RTC_Time.MinuteTens << RTC_TR_MNT) |
93 (RTC_Cfg.RTC_Time.HourUnits << RTC_TR_HU) |
94 (RTC_Cfg.RTC_Time.HourTens << RTC_TR_HT) |
95 (RTC_Cfg.RTC_Time.PM << RTC_TR_PM));
96
97 /* Set time */
98 RTC->TR &= ~(0xFFFFFFFF);
99 RTC->TR = temp;
100
101 temp = 0;
102 temp |= ((RTC_Cfg.RTC_Date.DateUnits << RTC_DR_DU) |
103 (RTC_Cfg.RTC_Date.DateTens << RTC_DR_DT) |
104 (RTC_Cfg.RTC_Date.MonthUnits << RTC_DR_MU) |
105 (RTC_Cfg.RTC_Date.MonthTens << RTC_DR_MT) |
106 (RTC_Cfg.RTC_Date.WeekDayUnits << RTC_DR_WDU) |
107 (RTC_Cfg.RTC_Date.YearUnits << RTC_DR_YU) |
108 (RTC_Cfg.RTC_Date.YearTens << RTC_DR_YT));
109
110 /* Set date */
111 RTC->DR &= ~(0xFFFFFFFF);
112 RTC->DR = temp;
113
114 RTC_ExitConfig();
115 }
116
117 void RTC_SetTime(RTC_Time_t time){
118
119 uint32_t temp = 0;
120
121 temp |= ((time.SecondUnits << RTC_TR_SU) |
122 (time.SecondTens << RTC_TR_ST) |
123 (time.MinuteUnits << RTC_TR_MNU) |
124 (time.MinuteTens << RTC_TR_MNT) |
125 (time.HourUnits << RTC_TR_HU) |
126 (time.HourTens << RTC_TR_HT) |
127 (time.PM << RTC_TR_PM));
128
129 RTC_Unlock();
130 RTC_EnterConfig();
131
132 /* Set time */
133 RTC->TR &= ~(0xFFFFFFFF);
134 RTC->TR = temp;
135
136 RTC_ExitConfig();
137 }
138
139 void RTC_GetTime(RTC_Time_t* time){
140
141 time->SecondUnits = (RTC->TR >> RTC_TR_SU) & 0xF;
142 time->SecondTens = (RTC->TR >> RTC_TR_ST) & 0x7;
143 time->MinuteUnits = (RTC->TR >> RTC_TR_MNU) & 0xF;
144 time->MinuteTens = (RTC->TR >> RTC_TR_MNT) & 0x7;
145 time->HourUnits = (RTC->TR >> RTC_TR_HU) & 0xF;
146 time->HourTens = (RTC->TR >> RTC_TR_HT) & 0x3;
147 time->PM = (RTC->TR >> RTC_TR_PM) & 0x1;
148 }
149
150 void RTC_SetDate(RTC_Date_t date){
151
152 uint32_t temp = 0;
153
154 temp |= ((date.DateUnits << RTC_DR_DU) |
155 (date.DateTens << RTC_DR_DT) |
156 (date.MonthUnits << RTC_DR_MU) |
157 (date.MonthTens << RTC_DR_MT) |
158 (date.WeekDayUnits << RTC_DR_WDU) |
159 (date.YearUnits << RTC_DR_YU) |
160 (date.YearTens << RTC_DR_YT));
161
162 RTC_Unlock();
163 RTC_EnterConfig();
164
165 /* Set date */
166 RTC->DR &= ~(0xFFFFFFFF);
167 RTC->DR = temp;
168
169 RTC_ExitConfig();
170 }
171
172 void RTC_GetDate(RTC_Date_t* date){
173
174 date->DateUnits = (RTC->DR >> RTC_DR_DU) & 0xF;
175 date->DateTens = (RTC->DR >> RTC_DR_DT) & 0x3;
176 date->WeekDayUnits = (RTC->DR >> RTC_DR_WDU) & 0x7;
177 date->MonthUnits = (RTC->DR >> RTC_DR_MU) & 0xF;
178 date->MonthTens = (RTC->DR >> RTC_DR_MT) & 0x1;
179 date->YearUnits = (RTC->DR >> RTC_DR_YU) & 0xF;
180 date->YearTens = (RTC->DR >> RTC_DR_YT) & 0xF;
181 }
182
183 void RTC_ClearRSF(void){
184
185 RTC_Unlock();
186 RTC->ISR &= ~(1 << RTC_ISR_RSF);
187 }
188
189 uint8_t RTC_GetRSF(void){
190
191 uint8_t ret = 0;
192
193 if(RTC->ISR & (1 << RTC_ISR_RSF)){
194 ret = 1;
195 }
196
197 return ret;
198 }
199
200 void RTC_SetAlarm(RTC_Alarm_t alarm){
201
202 uint32_t temp = 0;
203
204 temp |= ((alarm.DateMask << RTC_ALRMxR_MSK4) |
205 (alarm.WeekDaySelec << RTC_ALRMxR_WDSEL) |
206 (alarm.DateTens << RTC_ALRMxR_DT) |
207 (alarm.DateUnits << RTC_ALRMxR_DU) |
208 (alarm.HoursMask << RTC_ALRMxR_MSK3) |
209 (alarm.PM << RTC_ALRMxR_PM) |
210 (alarm.HourTens << RTC_ALRMxR_HT) |
211 (alarm.HourUnits << RTC_ALRMxR_HU) |
212 (alarm.MinutesMask << RTC_ALRMxR_MSK2) |
213 (alarm.MinuteTens << RTC_ALRMxR_MNT) |
214 (alarm.MinuteUnits << RTC_ALRMxR_MNU) |
215 (alarm.SecondsMask << RTC_ALRMxR_MSK1) |
216 (alarm.SecondTens << RTC_ALRMxR_ST) |
217 (alarm.SecondUnits << RTC_ALRMxR_SU));
218
219 /* Configure and enable the EXTI Line 17 in interrupt mode and select the rising edge sensitivity */
220 if(alarm.IRQ == 1){
221 EXTI->IMR |= (1 << 17);
222 EXTI->RTSR |= (1 << 17);
223 }
224
225 RTC_Unlock();
226
227 switch(alarm.AlarmSel){
228 case RTC_ALARM_A:
229 /* Clear ALRAE in RTC_CR register to disable Alarm A */
230 RTC->CR &= ~(1 << RTC_CR_ALRAE);
231 /* Poll ALRAWF in RTC_ISR until it is set to make sure the access to alarm reg is allowed */
232 while(!(RTC->ISR & (1 << RTC_ISR_ALRAWF)));
233 /* Set alarm A values */
234 RTC->ALRMAR &= ~(0xFFFFFFFF);
235 RTC->ALRMAR = temp;
236 /* Set ALRAE in the RTC_CR register to enable Alarm A */
237 RTC->CR |= (1 << RTC_CR_ALRAE);
238 /* Set ALRAIE in the RTC CR register to enable Alarm A interrupt */
239 if(alarm.IRQ == 1){
240 RTC->CR |= (1 << RTC_CR_ALRAIE);
241 }
242 break;
243 case RTC_ALARM_B:
244 /* Clear ALRBE in RTC_CR register to disable Alarm B */
245 RTC->CR &= ~(1 << RTC_CR_ALRBE);
246 /* Poll ALRBWF in RTC_ISR until it is set to make sure the access to alarm reg is allowed */
247 while(!(RTC->ISR & (1 << RTC_ISR_ALRBWF)));
248 /* Set alarm B values */
249 RTC->ALRMBR &= ~(0xFFFFFFFF);
250 RTC->ALRMBR = temp;
251 /* Set ALRBE in the RTC_CR register to enable Alarm B */
252 RTC->CR |= (1 << RTC_CR_ALRBE);
253 /* Set ALRBIE in the RTC CR register to enable Alarm B interrupt */
254 if(alarm.IRQ == 1){
255 RTC->CR |= (1 << RTC_CR_ALRBIE);
256 }
257 break;
258 default:
259 break;
260 }
261 }
262
263 void RTC_GetAlarm(RTC_Alarm_t* alarm){
264
265 uint32_t alarm_reg;
266
267 switch(alarm->AlarmSel){
268 case RTC_ALARM_A:
269 alarm_reg = RTC->ALRMAR;
270 break;
271 case RTC_ALARM_B:
272 alarm_reg = RTC->ALRMBR;
273 break;
274 default:
275 break;
276 }
277
278 alarm->DateMask = (alarm_reg >> RTC_ALRMxR_MSK4) & 0x1;
279 alarm->WeekDaySelec = (alarm_reg >> RTC_ALRMxR_WDSEL) & 0x1;
280 alarm->DateTens = (alarm_reg >> RTC_ALRMxR_DT) & 0x3;
281 alarm->DateUnits = (alarm_reg >> RTC_ALRMxR_DU) & 0xF;
282 alarm->HoursMask = (alarm_reg >> RTC_ALRMxR_MSK3) & 0x1;
283 alarm->PM = (alarm_reg >> RTC_ALRMxR_PM) & 0x1;
284 alarm->HourTens = (alarm_reg >> RTC_ALRMxR_HT) & 0x3;
285 alarm->HourUnits = (alarm_reg >> RTC_ALRMxR_HU) & 0xF;
286 alarm->MinutesMask = (alarm_reg >> RTC_ALRMxR_MSK2) & 0x1;
287 alarm->MinuteTens = (alarm_reg >> RTC_ALRMxR_MNT) & 0x7;
288 alarm->MinuteUnits = (alarm_reg >> RTC_ALRMxR_MNU) & 0xF;
289 alarm->SecondsMask = (alarm_reg >> RTC_ALRMxR_MSK1) & 0x1;
290 alarm->SecondTens = (alarm_reg >> RTC_ALRMxR_ST) & 0x7;
291 alarm->SecondUnits = (alarm_reg >> RTC_ALRMxR_SU) & 0xF;
292 }
293
294 uint8_t RTC_CheckAlarm(RTC_AlarmSel_t alarm){
295
296 uint8_t ret = 0;
297
298 switch(alarm){
299 case RTC_ALARM_A:
300 if(RTC->ISR & (1 << RTC_ISR_ALRAF)){
301 ret = 1;
302 }
303 break;
304 case RTC_ALARM_B:
305 if(RTC->ISR & (1 << RTC_ISR_ALRBF)){
306 ret = 1;
307 }
308 break;
309 default:
310 ret = 2;
311 break;
312 }
313
314 return ret;
315 }
316
317 uint8_t RTC_ClearAlarm(RTC_AlarmSel_t alarm){
318
319 uint8_t ret = 0;
320
321 switch(alarm){
322 case RTC_ALARM_A:
323 RTC->ISR &= ~(1 << RTC_ISR_ALRAF);
324 break;
325 case RTC_ALARM_B:
326 RTC->ISR &= ~(1 << RTC_ISR_ALRBF);
327 break;
328 default:
329 ret = 1;
330 break;
331 }
332
333 return ret;
334 }
335
336 uint8_t RTC_DisableAlarm(RTC_AlarmSel_t alarm){
337
338 uint8_t ret = 0;
339
340 RTC_Unlock();
341
342 switch(alarm){
343 case RTC_ALARM_A:
344 RTC->CR &= ~(1 << RTC_CR_ALRAE);
345 break;
346 case RTC_ALARM_B:
347 RTC->CR &= ~(1 << RTC_CR_ALRBE);
348 break;
349 default:
350 ret = 1;
351 break;
352 }
353
354 return ret;
355 }
356
357 void RTC_Alarm_IRQHandling(void){
358
359 /* Clear the EXTI PR register corresponding to the Alarm (EXTI 17) */
360 if(EXTI->PR & (1 << 17)){
361 /* clear */
362 EXTI->PR |= (1 << 17);
363 }
364
365 if(RTC->ISR & (1 << RTC_ISR_ALRAF)){
366 RTC_AlarmEventCallback(RTC_ALARM_A);
367 }
368 else if(RTC->ISR & (1 << RTC_ISR_ALRBF)){
369 RTC_AlarmEventCallback(RTC_ALARM_B);
370 }
371 else{
372 /* do nothing */
373 }
374 }
375
376 __attribute__((weak)) void RTC_AlarmEventCallback(RTC_AlarmSel_t alarm){
377
378 /* This is a weak implementation. The application may override this function */
379 (void)alarm;
380 }
381
382 /***********************************************************************************************************/
383 /* Static Function Definitions */
384 /***********************************************************************************************************/
385
386 static void RTC_Unlock(void){
387
388 RTC->WPR |= 0xCA;
389 RTC->WPR |= 0x53;
390 }
391
392 static void RTC_EnterConfig(void){
393
394 /* Set INIT bit to 1 in the RTC_ISR register to enter initialization mode */
395 RTC->ISR |= (1 << RTC_ISR_INIT);
396 /* Poll INITF bit of in the RTC_ISR register */
397 while(!(RTC->ISR & (1 << RTC_ISR_INITF)));
398 }
399
400 static void RTC_ExitConfig(void){
401
402 /* Exit the initialization mode by clearing the INIT bit */
403 RTC->ISR &= ~(1 << RTC_ISR_INIT);
404 }
405