1 /**
2   ******************************************************************************
3   * @file    rtl8721d_rtc.c
4   * @author
5   * @version V1.0.0
6   * @date    2016-05-17
7   * @brief   This file provides firmware functions to manage the following
8   *          functionalities of the Real-Time Clock (RTC) peripheral:
9   *           - Initialization
10   *           - Calendar (Time and Date) configuration
11   *           - Alarms configuration
12   *           - WakeUp Timer configuration
13   *           - Daylight Saving configuration
14   *           - Output pin Configuration
15   *           - Smooth digital Calibration configuration
16   *           - TimeStamp configuration
17   *           - Interrupts and flags management
18   ******************************************************************************
19   * @attention
20   *
21   * This module is a confidential and proprietary property of RealTek and
22   * possession or use of this module requires written permission of RealTek.
23   *
24   * Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved.
25   ******************************************************************************
26   */
27 #include "ameba_soc.h"
28 
29 /**
30   * @brief  Converts a 2 digit decimal to BCD format.
31   * @param  Value: Byte to be converted.
32   * @retval Converted byte
33   */
RTC_ByteToBcd2(u8 Value)34 u8 RTC_ByteToBcd2(u8 Value)
35 {
36 	u8 bcdhigh = 0;
37 
38 	while (Value >= 10) {
39 		bcdhigh++;
40 		Value -= 10;
41 	}
42 
43 	return  ((u8)(bcdhigh << 4) | Value);
44 }
45 
46 /**
47   * @brief  Convert from 2 digit BCD to Binary.
48   * @param  Value: BCD value to be converted.
49   * @retval Converted word
50   */
RTC_Bcd2ToByte(u8 Value)51 u8 RTC_Bcd2ToByte(u8 Value)
52 {
53 	u8 tmp = 0;
54 	tmp = (u8)(((Value & 0xF0) >> 0x4) * 10);
55 	return ((u8)(tmp + (Value & 0x0F)));
56 }
57 
58 /**
59   * @brief  Enters the RTC Initialization mode.
60   * @note  the time, date and prescaler registers can be updated in init mode.
61   * @param  None
62   * @retval status value:
63   *          - 1: RTC is in Init mode
64   *          - 0: RTC is not in Init mode
65   */
RTC_EnterInitMode(void)66 u32 RTC_EnterInitMode(void)
67 {
68 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
69 	u32 counter = 0x00;
70 	u32 status = 0;
71 	u32 initstatus = 0x00;
72 
73 	/* Check if the Initialization mode is set */
74 	if ((RTC->ISR & RTC_ISR_INITF) == 0) {
75 		/* Set the Initialization mode */
76 		RTC->ISR |= (u32)RTC_ISR_INIT;
77 
78 		/* Wait till RTC is in INIT state and if Time out is reached exit */
79 		do {
80 			/* check Calendar registers update is allowed */
81 			initstatus = RTC->ISR & RTC_ISR_INITF;
82 			counter++;
83 		} while((counter != INITMODE_TIMEOUT) && (initstatus == 0x00));
84 
85 		if (RTC->ISR & RTC_ISR_INITF) {
86 			status = 1;
87 		} else {
88 			status = 0;
89 		}
90 	} else {
91 		status = 1;
92 	}
93 
94 	return (status);
95 }
96 
97 /**
98   * @brief  Exits the RTC Initialization mode.
99   * @note   When the initialization sequence is complete, the calendar restarts
100   *         counting after 4 RTCCLK cycles.
101   * @param  None
102   * @retval None
103   * @about 3 RTC clock
104   */
RTC_ExitInitMode(void)105 void RTC_ExitInitMode(void)
106 {
107 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
108 
109 	/* Exit Initialization mode */
110 	RTC->ISR &= ~RTC_ISR_INIT;
111 }
112 
113 /**
114   * @brief  Waits until the RTC Time register (RTC_TR) is
115   *         synchronized with RTC APB clock.
116   * @note   To read the calendar through the shadow registers after Calendar
117   *         initialization, calendar update or after wakeup from low power modes
118   *         the software must first clear the RSF flag.
119   *         The software must then wait until it is set again before reading
120   *         the calendar, which means that the calendar registers have been
121   *         correctly copied into the RTC_TR shadow registers.
122   * @param  None
123   * @retval status value:
124   *          - 1: RTC registers are synchronised
125   *          - 0: RTC registers are not synchronised
126   * @about 2 RTC clock
127   */
RTC_WaitForSynchro(void)128 u32 RTC_WaitForSynchro(void)
129 {
130 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
131 	u32 counter = 0;
132 	u32 status = 0;
133 	u32 synchrostatus = 0x00;
134 
135 	/* we can not poll RTC_ISR_RSF when RTC_CR_BYPSHAD */
136 	if (RTC->CR & RTC_CR_BYPSHAD) {
137 		return 1;
138 	}
139 
140 	/* Disable the write protection for RTC registers */
141 	RTC->WPR = 0xCA;
142 	RTC->WPR = 0x53;
143 
144 	/* write 1 to Clear RSF flag */
145 	RTC->ISR |= RTC_ISR_RSF;
146 
147 	/* Wait the registers to be synchronised */
148 	do {
149 		synchrostatus = RTC->ISR & RTC_ISR_RSF; /* 6bus cycle one time */
150 		counter++;
151 	} while ((counter != SYNCHRO_TIMEOUT) && (synchrostatus == 0x00));
152 
153 	if (RTC->ISR & RTC_ISR_RSF) {
154 		status = 1;
155 	} else {
156 		status = 0;
157 	}
158 
159 	/* Enable the write protection for RTC registers */
160 	RTC->WPR = 0xFF;
161 
162 	return (status);
163 }
164 
165 /**
166   * @brief  Enables or Disables the Bypass Shadow feature.
167   * @note   When the Bypass Shadow is enabled the calendar value are taken
168   *         directly from the Calendar counter.
169   * @param  NewState: new state of the Bypass Shadow feature.
170   *         This parameter can be: ENABLE or DISABLE.
171   * @retval None
172 */
RTC_BypassShadowCmd(u32 NewState)173 u32 RTC_BypassShadowCmd(u32 NewState)
174 {
175 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
176 	u32 status;
177 
178 	/* Disable the write protection for RTC registers */
179 	RTC->WPR = 0xCA;
180 	RTC->WPR = 0x53;
181 
182 	/* Set Initialization mode */
183 	if (RTC_EnterInitMode()) {
184 		if (NewState != DISABLE) {
185 			/* Set the BYPSHAD bit */
186 			RTC->CR |= RTC_CR_BYPSHAD;
187 		} else {
188 			/* Reset the BYPSHAD bit */
189 			RTC->CR &= ~RTC_CR_BYPSHAD;
190 		}
191 
192 		/* Exit Initialization mode */
193 		RTC_ExitInitMode();
194 
195 		if (RTC_WaitForSynchro()) {
196 			status = 1;
197 		} else {
198 			status = 0;
199 		}
200 	} else {
201 		status = 0;
202 	}
203 
204 	/* Enable the write protection for RTC registers */
205 	RTC->WPR = 0xFF;
206 
207 	return status;
208 }
209 
210 /**
211   * @brief  Fills each RTC_InitStruct member with its default value.
212   * @param  RTC_InitStruct: pointer to a RTC_InitTypeDef structure which will be
213   *         initialized.
214   * @retval None
215   */
RTC_StructInit(RTC_InitTypeDef * RTC_InitStruct)216 void RTC_StructInit(RTC_InitTypeDef* RTC_InitStruct)
217 {
218 	/* Initialize the RTC_HourFormat member */
219 	RTC_InitStruct->RTC_HourFormat = RTC_HourFormat_24;
220 
221 	/* Initialize the RTC_AsynchPrediv member */
222 	RTC_InitStruct->RTC_AsynchPrediv = (u32)0x7F; /* 32768 /128 = 256Hz */
223 
224 	/* Initialize the RTC_SynchPrediv member */
225 	RTC_InitStruct->RTC_SynchPrediv = (u32)0xFF; /* 256 /256 = 1Hz*/
226 
227 	/*Initialize the RTC_Day_Threshold member*/
228 	RTC_InitStruct->RTC_DayThreshold = 365;
229 }
230 
231 /**
232   * @brief  Initializes the RTC registers according to the specified parameters
233   *         in RTC_InitStruct.
234   * @param  RTC_InitStruct: pointer to a RTC_InitTypeDef structure that contains
235   *         the configuration information for the RTC peripheral.
236   * @note   The RTC Prescaler register is write protected and can be written in
237   *         initialization mode only.
238   * @retval status value:
239   *          - 1: RTC registers are initialized
240   *          - 0: RTC registers are not initialized
241   */
RTC_Init(RTC_InitTypeDef * RTC_InitStruct)242 u32 RTC_Init(RTC_InitTypeDef* RTC_InitStruct)
243 {
244 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
245 	u32 Temp = 0;
246 	u32 status = 0;
247 
248 	/* Check the parameters */
249 	assert_param(IS_RTC_HOUR_FORMAT(RTC_InitStruct->RTC_HourFormat));
250 	assert_param(IS_RTC_ASYNCH_PREDIV(RTC_InitStruct->RTC_AsynchPrediv));
251 	assert_param(IS_RTC_SYNCH_PREDIV(RTC_InitStruct->RTC_SynchPrediv));
252 	assert_param(IS_RTC_DAY_THRES(RTC_InitStruct->RTC_DayThreshold));
253 
254 	/* Disable the write protection for RTC registers */
255 	RTC->WPR = 0xCA;
256 	RTC->WPR = 0x53;
257 
258 	/* Set Initialization mode */
259 	if (RTC_EnterInitMode()) {
260 		/* Configure the RTC PRER to provide 1Hz to the Calendar */
261 		Temp = (RTC_InitStruct->RTC_SynchPrediv) | (RTC_InitStruct->RTC_AsynchPrediv << 16);
262 		RTC->PRER = Temp;
263 
264 		/* Set RTC CR FMT Bit */
265 		Temp = RTC->CR;
266 		Temp &= ((u32)~(RTC_CR_FMT | RTC_DAYTHRES_MSK | RTC_CR_DOVTHIE));
267 		Temp |=  ((u32)((RTC_InitStruct->RTC_HourFormat) | (RTC_InitStruct->RTC_DayThreshold<<23)));
268 
269 		/* Reset the BYPSHAD bit, get counter from shadow registger */
270 		Temp &= ~RTC_CR_BYPSHAD;
271 		RTC->CR = Temp;
272 
273 		/* Exit Initialization mode */
274 		RTC_ExitInitMode();
275 
276 		if (RTC_WaitForSynchro()) {
277 			status = 1;
278 		} else {
279 			status = 0;
280 		}
281 	} else {
282 		status = 0;
283 	}
284 
285 	/* Enable the write protection for RTC registers */
286 	RTC->WPR = 0xFF;
287 
288 	return status;
289 }
290 
291 /**
292   * @brief  Fills each RTC_TimeStruct member with its default value
293   *         (Time = 00d:00h:00min:00sec).
294   * @param  RTC_TimeStruct: pointer to a RTC_TimeTypeDef structure which will be
295   *         initialized.
296   * @retval None
297   */
RTC_TimeStructInit(RTC_TimeTypeDef * RTC_TimeStruct)298 void RTC_TimeStructInit(RTC_TimeTypeDef* RTC_TimeStruct)
299 {
300 	/* Time = 00h:00min:00sec */
301 	RTC_TimeStruct->RTC_H12_PMAM = RTC_H12_AM;
302 	RTC_TimeStruct->RTC_Hours = 0;
303 	RTC_TimeStruct->RTC_Minutes = 0;
304 	RTC_TimeStruct->RTC_Seconds = 0;
305 	RTC_TimeStruct->RTC_Days = 0;
306 }
307 
308 /**
309   * @brief  Set the RTC current time.
310   * @param  RTC_Format: specifies the format of the entered parameters.
311   *          This parameter can be  one of the following values:
312   *            @arg RTC_Format_BIN:  Binary data format
313   *            @arg RTC_Format_BCD:  BCD data format
314   * @param  RTC_TimeStruct: pointer to a RTC_TimeTypeDef structure that contains
315   *                        the time configuration information for the RTC.
316   * @retval status value:
317   *          - 1: RTC Time register is configured
318   *          - 0: RTC Time register is not configured
319   */
RTC_SetTime(u32 RTC_Format,RTC_TimeTypeDef * RTC_TimeStruct)320 u32 RTC_SetTime(u32 RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct)
321 {
322 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
323 	u32 tmpreg = 0;
324 	u32 status = 0;
325 
326 	/* Check the parameters */
327 	assert_param(IS_RTC_FORMAT(RTC_Format));
328 
329 	if (RTC_Format == RTC_Format_BIN) {
330 		if ((RTC->CR & RTC_CR_FMT) != RTC_HourFormat_24) {
331 			assert_param(IS_RTC_HOUR12(RTC_TimeStruct->RTC_Hours));
332 			assert_param(IS_RTC_H12_AMPM(RTC_TimeStruct->RTC_H12_PMAM));
333 		} else {
334 			RTC_TimeStruct->RTC_H12_PMAM = 0x00;
335 			assert_param(IS_RTC_HOUR24(RTC_TimeStruct->RTC_Hours));
336 		}
337 		assert_param(IS_RTC_MINUTES(RTC_TimeStruct->RTC_Minutes));
338 		assert_param(IS_RTC_SECONDS(RTC_TimeStruct->RTC_Seconds));
339 	} else {
340 		if ((RTC->CR & RTC_CR_FMT) != RTC_HourFormat_24) {
341 			tmpreg = RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Hours);
342 			assert_param(IS_RTC_HOUR12(tmpreg));
343 			assert_param(IS_RTC_H12_AMPM(RTC_TimeStruct->RTC_H12_PMAM));
344 		} else {
345 			RTC_TimeStruct->RTC_H12_PMAM = 0x00;
346 			assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Hours)));
347 		}
348 		assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Minutes)));
349 		assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Seconds)));
350 	}
351 
352 	/* Check the input parameters format */
353 	if (RTC_Format != RTC_Format_BIN) {
354 		tmpreg = (((u32)(RTC_TimeStruct->RTC_Hours) << 16) | \
355 			((u32)(RTC_TimeStruct->RTC_Minutes) << 8) | \
356 			((u32)RTC_TimeStruct->RTC_Seconds) | \
357 			((u32)(RTC_TimeStruct->RTC_H12_PMAM) << 22));
358 	} else {
359 		tmpreg = (u32)(((u32)RTC_ByteToBcd2(RTC_TimeStruct->RTC_Hours) << 16) | \
360 			((u32)RTC_ByteToBcd2(RTC_TimeStruct->RTC_Minutes) << 8) | \
361 			((u32)RTC_ByteToBcd2(RTC_TimeStruct->RTC_Seconds)) | \
362 			(((u32)RTC_TimeStruct->RTC_H12_PMAM) << 22));
363 	}
364 
365 	/* set Days */
366 	tmpreg |= (u32)(RTC_TimeStruct->RTC_Days) << 23;
367 
368 	/* Disable the write protection for RTC registers */
369 	RTC->WPR = 0xCA;
370 	RTC->WPR = 0x53;
371 
372 	/* Set Initialization mode */
373 	if (RTC_EnterInitMode()) {
374 		/* Set the RTC_TR register */
375 		RTC->TR = (u32)(tmpreg & RTC_TR_RESERVED_MASK);
376 
377 		/* Exit Initialization mode */
378 		RTC_ExitInitMode();
379 
380 		if (RTC_WaitForSynchro()) {
381 			status = 1;
382 		} else {
383 			status = 0;
384 		}
385 	} else {
386 		status = 0;
387 	}
388 
389 	/* Enable the write protection for RTC registers */
390 	RTC->WPR = 0xFF;
391 
392 	return status;
393 }
394 
395 /**
396   * @brief  Get the RTC current Time.
397   * @param  RTC_Format: specifies the format of the returned parameters.
398   *          This parameter can be  one of the following values:
399   *            @arg RTC_Format_BIN:  Binary data format
400   *            @arg RTC_Format_BCD:  BCD data format
401   * @param  RTC_TimeStruct: pointer to a RTC_TimeTypeDef structure that will
402   *                        contain the returned current time configuration.
403   * @retval None
404   */
RTC_GetTime(u32 RTC_Format,RTC_TimeTypeDef * RTC_TimeStruct)405 void RTC_GetTime(u32 RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct)
406 {
407 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
408 	u32 tmpreg = 0;
409 
410 	/* Check the parameters */
411 	assert_param(IS_RTC_FORMAT(RTC_Format));
412 
413 	/* Get the RTC_TR register */
414 	tmpreg = (u32)(RTC->TR & RTC_TR_RESERVED_MASK);
415 
416 	/* Fill the structure fields with the read parameters */
417 	RTC_TimeStruct->RTC_Hours = (u8)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
418 	RTC_TimeStruct->RTC_Minutes = (u8)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8);
419 	RTC_TimeStruct->RTC_Seconds = (u8)(tmpreg & (RTC_TR_ST | RTC_TR_SU));
420 	RTC_TimeStruct->RTC_H12_PMAM = (u8)((tmpreg & (RTC_TR_PM)) >> 22);
421 	RTC_TimeStruct->RTC_Days = (u16)((tmpreg & RTC_TR_DAY) >> 23);
422 
423 	/* Check the input parameters format */
424 	if (RTC_Format == RTC_Format_BIN) {
425 		/* Convert the structure parameters to Binary format */
426 		RTC_TimeStruct->RTC_Hours = (u8)RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Hours);
427 		RTC_TimeStruct->RTC_Minutes = (u8)RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Minutes);
428 		RTC_TimeStruct->RTC_Seconds = (u8)RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Seconds);
429 	}
430 }
431 
432 /**
433   * @brief  clear day over threshold pending interrupt.
434   * @retval None
435   */
RTC_DayIntClear(void)436 void RTC_DayIntClear(void)
437 {
438 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
439 	u32 isr = RTC->ISR;
440 	u32 counter = 0;
441 
442 	/*not clear alarm flag*/
443 	isr &= ~RTC_ISR_ALRAF;
444 
445 	isr |= RTC_ISR_DOVTHF;
446 
447 	RTC->ISR = isr;
448 
449 	while (1) {
450 		/* check Alarm flag clear success*/
451 		if ((RTC->ISR & RTC_ISR_DOVTHF) == 0)
452 			break;
453 		if (counter >= ALARMDIS_TIMEOUT)
454 			break;
455 
456 		counter++;
457 	}
458 
459 	/*delay one 32.768k clock cycle for actual interrupt signal clear*/
460 	DelayUs(36);
461 }
462 
463 /**
464   * @brief  Enables or disables the RTC day over threshold interrupt.
465   * @param  NewState: new state of the RTC day over threshold interrupt.
466   *          This parameter can be: ENABLE or DISABLE.
467   */
RTC_DayIntCmd(u32 NewState)468 u32 RTC_DayIntCmd(u32 NewState)
469 {
470 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
471 	u32 status = 0;
472 
473 	/* Disable the write protection for RTC registers */
474 	RTC->WPR = 0xCA;
475 	RTC->WPR = 0x53;
476 
477 	/* Set Initialization mode */
478 	if (RTC_EnterInitMode()) {
479 		/* clear isr, or set will fail */
480 		RTC_DayIntClear();
481 
482 		/* Configure the day over threshold interrupt state */
483 		if (NewState != DISABLE) {
484 			/*enable day over threshold interrupt*/
485 			RTC->CR |= (u32)(RTC_CR_DOVTHIE);
486 		} else {
487 			RTC->CR &= (u32)~(RTC_CR_DOVTHIE);
488 		}
489 
490 		/* Exit Initialization mode */
491 		RTC_ExitInitMode();
492 
493 		if (RTC_WaitForSynchro()) {
494 			status = 1;
495 		} else {
496 			status = 0;
497 		}
498 	} else {
499 		status = 0;
500 	}
501 
502 	/* Enable the write protection for RTC registers */
503 	RTC->WPR = 0xFF;
504 
505 	return status;
506 }
507 
508 /**
509   * @brief  Set the RTC day threshold.
510   * @param  DayThres: specifies the day threshold to be configured.
511   *          This parameter can be a value of @ref RTC_Day_Threshold.
512   * @retval status value:
513   *          - 1: RTC day threshold is configured
514   *          - 0: RTC day threshold is not configured
515   */
RTC_DayThresSet(u32 DayThres)516 u32 RTC_DayThresSet(u32 DayThres)
517 {
518 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
519 	u32 temp = RTC->CR;
520 	u32 status;
521 
522 	assert_param(IS_RTC_DAY_THRES(DayThres));
523 
524 	temp &= ~RTC_DAYTHRES_MSK;
525 	temp |= (u32)((DayThres) << 23);
526 
527 	/* Disable the write protection for RTC registers */
528 	RTC->WPR = 0xCA;
529 	RTC->WPR = 0x53;
530 
531 	/* Set Initialization mode */
532 	if (RTC_EnterInitMode()) {
533 		/*Set the RTC_CR register*/
534 		RTC->CR = temp;
535 
536 		/* Exit Initialization mode */
537 		RTC_ExitInitMode();
538 
539 		if (RTC_WaitForSynchro()) {
540 			status = 1;
541 		} else {
542 			status = 0;
543 		}
544 	} else {
545 		status = 0;
546 	}
547 
548 	/* Enable the write protection for RTC registers */
549 	RTC->WPR = 0xFF;
550 
551 	return status;
552 }
553 
554 /**
555   * @brief  Get the RTC day threshold value in RTC_CR register.
556   * @retval RTC day threshold value
557   */
RTC_DayThresGet(void)558 u32 RTC_DayThresGet(void)
559 {
560 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
561 
562 	return ((RTC->CR & RTC_DAYTHRES_MSK) >>23);
563 }
564 
565 /**
566   * @brief  Set the specified RTC Alarm.
567   * @note   The Alarm register can only be written when the corresponding Alarm
568   *         is disabled (Use the RTC_AlarmCmd(DISABLE)).
569   * @param  RTC_Format: specifies the format of the returned parameters.
570   *          This parameter can be one of the following values:
571   *            @arg RTC_Format_BIN: Binary data format
572   *            @arg RTC_Format_BCD: BCD data format
573   * @param  RTC_AlarmStruct: pointer to a RTC_AlarmTypeDef structure that
574   *                          contains the alarm configuration parameters.
575   * @retval status value:
576   *          - 1: RTC Time Alarm is configured
577   *          - 0: RTC Time Alarm is not configured
578   */
RTC_SetAlarm(u32 RTC_Format,RTC_AlarmTypeDef * RTC_AlarmStruct)579 u32 RTC_SetAlarm(u32 RTC_Format, RTC_AlarmTypeDef* RTC_AlarmStruct)
580 {
581 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
582 	u32 tmpreg = 0;
583 	u32 counter = 0;
584 	u32 status = 0;
585 
586 	/* Check the parameters */
587 	assert_param(IS_RTC_FORMAT(RTC_Format));
588 	assert_param(IS_ALARM_MASK(RTC_AlarmStruct->RTC_AlarmMask));
589 	assert_param(IS_ALARM2_MASK(RTC_AlarmStruct->RTC_Alarm2Mask));
590 
591 	if (RTC_Format == RTC_Format_BIN) {
592 		if ((RTC->CR & RTC_CR_FMT) != RTC_HourFormat_24) {
593 			assert_param(IS_RTC_HOUR12(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours));
594 			assert_param(IS_RTC_H12_AMPM(RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM));
595 		} else {
596 			RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM = 0x00;
597 			assert_param(IS_RTC_HOUR24(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours));
598 		}
599 		assert_param(IS_RTC_MINUTES(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes));
600 		assert_param(IS_RTC_SECONDS(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds));
601 	} else {
602 		if ((RTC->CR & RTC_CR_FMT) != RTC_HourFormat_24) {
603 			tmpreg = RTC_Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours);
604 			assert_param(IS_RTC_HOUR12(tmpreg));
605 			assert_param(IS_RTC_H12_AMPM(RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM));
606 		} else {
607 			RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM = 0x00;
608 			assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours)));
609 		}
610 
611 		assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes)));
612 		assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds)));
613 	}
614 
615 	/* Check the input parameters format */
616 	if (RTC_Format != RTC_Format_BIN) {
617 		tmpreg = (((u32)(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours) << 16) | \
618 			((u32)(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes) << 8) | \
619 			((u32)RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds) | \
620 			((u32)(RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM) << 22) | \
621 			((u32)RTC_AlarmStruct->RTC_AlarmMask));
622 	} else {
623 		tmpreg = (((u32)RTC_ByteToBcd2(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours) << 16) | \
624 			((u32)RTC_ByteToBcd2(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes) << 8) | \
625 			((u32)RTC_ByteToBcd2(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds)) | \
626 			((u32)(RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM) << 22) | \
627 			((u32)RTC_AlarmStruct->RTC_AlarmMask));
628 	}
629 
630 	/* Disable the write protection for RTC registers */
631 	RTC->WPR = 0xCA;
632 	RTC->WPR = 0x53;
633 
634 	/* Disable Alarm */
635 	RTC->CR &= ~RTC_Alarm;
636 	while (1) {
637 		/* check Alarm update allowed */
638 		if (RTC->ISR & RTC_ISR_ALMWF)
639 			break;
640 		if (counter >= ALARMDIS_TIMEOUT)
641 			break;
642 
643 		counter++;
644 	}
645 
646 	/* clear isr, or set wll fail */
647 	RTC->ISR |= RTC_ISR_ALRAF;
648 
649 	if (RTC->ISR & RTC_ISR_ALMWF) {
650 		/* Configure the Alarm1 register H:M:S */
651 		RTC->ALMR1L = (u32)tmpreg;
652 
653 		/* Configure the Alarm2 register D */
654 		RTC->ALMR1H = ((u32)RTC_AlarmStruct->RTC_AlarmTime.RTC_Days) | ((u32)RTC_AlarmStruct->RTC_Alarm2Mask);
655 
656 		status = 1;
657 	} else {
658 		status = 0;
659 	}
660 
661 	/* Enable Alarm after this function */
662 
663 	/* Enable the write protection for RTC registers */
664 	RTC->WPR = 0xFF;
665 
666 	return status;
667 }
668 
669 /**
670   * @brief  Fills each RTC_AlarmStruct member with its default value
671   *         (Time = 00d:00h:00mn:20sec / Date = 1st day of the month/Mask =
672   *         all fields are masked except Alarm Seconds field).
673   * @param  RTC_AlarmStruct: pointer to a @ref RTC_AlarmTypeDef structure which
674   *         will be initialized.
675   * @retval None
676   */
RTC_AlarmStructInit(RTC_AlarmTypeDef * RTC_AlarmStruct)677 void RTC_AlarmStructInit(RTC_AlarmTypeDef* RTC_AlarmStruct)
678 {
679 	/* Alarm Time Settings : Time = 00h:00mn:00sec */
680 	RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM = RTC_H12_AM;
681 	RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours = 0;
682 	RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes = 0;
683 	RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds = 20;
684 	RTC_AlarmStruct->RTC_AlarmTime.RTC_Days = 0;
685 
686 	/* Alarm Masks Settings : Mask =  all fields are not masked */
687 	RTC_AlarmStruct->RTC_AlarmMask = RTC_AlarmMask_Hours | RTC_AlarmMask_Minutes;
688 
689 	/* Alarm2 Mask: Day */
690 	RTC_AlarmStruct->RTC_Alarm2Mask = RTC_Alarm2Mask_Days;
691 }
692 
693 /**
694   * @brief  Get the RTC Alarm value and masks.
695   * @param  RTC_Format: specifies the format of the output parameters.
696   *          This parameter can be one of the following values:
697   *            @arg RTC_Format_BIN: Binary data format
698   *            @arg RTC_Format_BCD: BCD data format
699   * @param  RTC_AlarmStruct: pointer to a RTC_AlarmTypeDef structure that will
700   *                          contains the output alarm configuration values.
701   * @retval None
702   */
RTC_GetAlarm(u32 RTC_Format,RTC_AlarmTypeDef * RTC_AlarmStruct)703 void RTC_GetAlarm(u32 RTC_Format, RTC_AlarmTypeDef* RTC_AlarmStruct)
704 {
705 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
706 	u32 tmpreg = 0;
707 
708 	/* Check the parameters */
709 	assert_param(IS_RTC_FORMAT(RTC_Format));
710 
711 	/* Get the RTC_ALRMxR register */
712 	tmpreg = (u32)(RTC->ALMR1L);
713 
714 	/* Fill the structure with the read parameters */
715 	RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours = (u8)((tmpreg & (RTC_ALRMAR_HT | RTC_ALRMAR_HU)) >> 16);
716  	RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes = (u8)((tmpreg & (RTC_ALRMAR_MNT | RTC_ALRMAR_MNU)) >> 8);
717 	RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds = (u8)(tmpreg & (RTC_ALRMAR_ST | RTC_ALRMAR_SU));
718 	RTC_AlarmStruct->RTC_AlarmTime.RTC_H12_PMAM = (u8)((tmpreg & RTC_ALRMAR_PM) >> 22);
719 	RTC_AlarmStruct->RTC_AlarmMask = (u32)(tmpreg & RTC_AlarmMask_All);
720 
721 	if (RTC_Format == RTC_Format_BIN) {
722 		RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours = RTC_Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Hours);
723 		RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes = RTC_Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Minutes);
724 		RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds = RTC_Bcd2ToByte(RTC_AlarmStruct->RTC_AlarmTime.RTC_Seconds);
725 	}
726 
727 	/* Get Days */
728 	RTC_AlarmStruct->RTC_AlarmTime.RTC_Days = (u16)((RTC->ALMR1H) & RTC_ALRMBR_DT);
729 	RTC_AlarmStruct->RTC_Alarm2Mask = (u32)((RTC->ALMR1H) & RTC_ALRMBR_MSK3);
730 }
731 
732 /**
733   * @brief  Enables or disables the specified RTC Alarm.
734   * @param  NewState: new state of the specified alarm.
735   *          This parameter can be: ENABLE or DISABLE.
736   */
RTC_AlarmCmd(u32 NewState)737 void RTC_AlarmCmd(u32 NewState)
738 {
739 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
740 	u32 counter = 0;
741 
742 	/* Disable the write protection for RTC registers */
743 	RTC->WPR = 0xCA;
744 	RTC->WPR = 0x53;
745 
746 	/* Configure the Alarm state */
747 	if (NewState != DISABLE) {
748 		RTC->ISR |= RTC_ISR_ALRAF;
749 
750 		RTC->CR |= (u32)(RTC_Alarm | RTC_Alarm_IntEn);
751 
752 		/* we should wait shadow reigster sync ok */
753 		RTC_WaitForSynchro();
754 	} else {
755 		/* clear isr, or set will fail */
756 		RTC->ISR |= RTC_ISR_ALRAF;
757 
758 		/* Disable the Alarm in RTC_CR register */
759 		RTC->CR &= (u32)~(RTC_Alarm | RTC_Alarm_IntEn);
760 
761 		/* wait alarm disable */
762 		while (1) {
763 			/* check Alarm update allowed */
764 			if (RTC->ISR & RTC_ISR_ALMWF)
765 				break;
766 			if (counter >= ALARMDIS_TIMEOUT)
767 				break;
768 
769 			counter++;
770 		}
771 	}
772 
773 	/* Enable the write protection for RTC registers */
774 	RTC->WPR = 0xFF;
775 }
776 
777 /**
778   * @brief  clear alarm pending interrupt.
779   * @retval None
780   */
RTC_AlarmClear(void)781 void RTC_AlarmClear(void)
782 {
783 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
784 	u32 isr = RTC->ISR;
785 	u32 counter = 0;
786 
787 	/*not clear day over thres flag*/
788 	isr &= ~RTC_ISR_DOVTHF;
789 
790 	isr |= RTC_ISR_ALRAF;
791 
792 	RTC->ISR = isr;
793 
794 	while (1) {
795 		/* check Alarm flag clear success*/
796 		if ((RTC->ISR & RTC_ISR_ALRAF) == 0)
797 			break;
798 		if (counter >= ALARMDIS_TIMEOUT)
799 			break;
800 
801 		counter++;
802 	}
803 
804 	/*delay one 32.768k clock cycle for actual interrupt signal clear*/
805 	DelayUs(36);
806 }
807 
808 /**
809   * @brief  Adds or substract one hour from the current time.
810   * @param  RTC_DayLightSaving: the value of hour adjustment.
811   *          This parameter can be one of the following values:
812   *            @arg RTC_DayLightSaving_SUB1H: Substract one hour (winter time)
813   *            @arg RTC_DayLightSaving_ADD1H: Add one hour (summer time)
814   * @param  RTC_StoreOperation: Specifies the value to be written in the BCK bit
815   *                            in CR register to store the operation.
816   *          This parameter can be one of the following values:
817   *            @arg RTC_StoreOperation_Reset: BCK Bit Reset
818   *            @arg RTC_StoreOperation_Set: BCK Bit Set
819   * @retval None
820   */
RTC_DayLightSavingConfig(u32 RTC_DayLightSaving,u32 RTC_StoreOperation)821 u32 RTC_DayLightSavingConfig(u32 RTC_DayLightSaving, u32 RTC_StoreOperation)
822 {
823 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
824 	u32 CRTmp = RTC->CR;
825 	u32 status = 0;
826 
827 	/* Check the parameters */
828 	assert_param(IS_RTC_DAYLIGHT_SAVING(RTC_DayLightSaving));
829 	assert_param(IS_RTC_STORE_OPERATION(RTC_StoreOperation));
830 
831 	/* Disable the write protection for RTC registers */
832 	RTC->WPR = 0xCA;
833 	RTC->WPR = 0x53;
834 
835 	/* Clear the bits to be configured */
836 	CRTmp &= (u32)~(RTC_CR_BCK);
837 
838 	/* Configure the RTC_CR register */
839 	CRTmp |= (u32)(RTC_DayLightSaving | RTC_StoreOperation);
840 
841 	/* Set Initialization mode */
842 	if (RTC_EnterInitMode()) {
843 		/* write CR */
844 		RTC->CR = CRTmp;
845 
846 		/* Exit Initialization mode */
847 		RTC_ExitInitMode();
848 
849 		if (RTC_WaitForSynchro()) {
850 			status = 1;
851 		} else {
852 			status = 0;
853 		}
854 	} else {
855 		status = 0;
856 	}
857 
858 	/* Enable the write protection for RTC registers */
859 	RTC->WPR = 0xFF;
860 
861 	//RTC_WaitForSynchro();
862 
863 	return status;
864 }
865 
866 /**
867   * @brief  Returns the RTC Day Light Saving stored operation.
868   * @retval RTC Day Light Saving stored operation.
869   *          - RTC_StoreOperation_Reset
870   *          - RTC_StoreOperation_Set
871   */
RTC_GetStoreOperation(void)872 u32 RTC_GetStoreOperation(void)
873 {
874 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
875 
876 	return (RTC->CR & RTC_CR_BCK);
877 }
878 
879 /**
880   * @brief  Configures the RTC output.
881   * @param  RTC_Output: Specifies which signal will be routed to the RTC output.
882   *          This parameter can be one of the following values:
883   *            @arg RTC_Output_Disable: No output selected
884   *            @arg RTC_Output_Alarm: signal of Alarm mapped to output
885   *            @arg RTC_Output_clkspre: signal of clkspre mapped to output
886   *            @arg RTC_Output_clkapre: signal of clkapre mapped to output
887   * @retval None
888   */
RTC_OutputConfig(u32 RTC_Output)889 u32 RTC_OutputConfig(u32 RTC_Output)
890 {
891 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
892 	u32 CRTmp = RTC->CR;
893 	u32 status;
894 
895 	/* Check the parameters */
896 	assert_param(IS_RTC_OUTPUT(RTC_Output));
897 
898 	/* Disable the write protection for RTC registers */
899 	RTC->WPR = 0xCA;
900 	RTC->WPR = 0x53;
901 
902 	/* Clear the bits to be configured */
903 	CRTmp &= (u32)~(RTC_CR_OSEL);
904 
905 	/* Configure the output selection and polarity */
906 	CRTmp |= (u32)(RTC_Output);
907 
908 	/* Set Initialization mode */
909 	if (RTC_EnterInitMode()) {
910 		/* write CR */
911 		RTC->CR = CRTmp;
912 
913 		/* Exit Initialization mode */
914 		RTC_ExitInitMode();
915 
916 		if (RTC_WaitForSynchro()) {
917 			status = 1;
918 		} else {
919 			status = 0;
920 		}
921 	} else {
922 		status = 0;
923 	}
924 
925 	/* Enable the write protection for RTC registers */
926 	RTC->WPR = 0xFF;
927 
928 	return status;
929 }
930 
931 /**
932   * @brief  Configures the Coarse calibration parameters.
933   * @param  CalibSign: CalibSign specifies the sign of the coarse calibration value.
934   *          This parameter can be  one of the following values:
935   *            @arg RTC_CalibSign_Positive: The value sign is positive
936   *            @arg RTC_CalibSign_Negative: The value sign is negative
937   * @param  Value: value of coarse calibration expressed in ppm (coded on 7 bits).
938   * @param  CalibPeriod: Calibration period, Compensate DC clkapre cycles every (CALP+1) minutes (coded on 3 bits).
939   *   This parameter can be one of the following values:
940   *		 @arg RTC_CalibPeriod_1MIN
941   *		 @arg RTC_CalibPeriod_2MIN
942   *		 @arg RTC_CalibPeriod_3MIN
943   *		 @arg RTC_CalibPeriod_4MIN
944   *		 @arg RTC_CalibPeriod_5MIN
945   *		 @arg RTC_CalibPeriod_6MIN
946   *		 @arg RTC_CalibPeriod_7MIN
947   *		 @arg RTC_CalibPeriod_8MIN
948   * @param  Calib_Enable: RTC_Calib_Disable or RTC_Calib_Enable .
949   * @retval status value:
950   *          - 1: RTC Coarse calibration are initialized
951   *          - 0: RTC Coarse calibration are not initialized
952   */
RTC_SmoothCalibConfig(u32 CalibSign,u32 Value,u32 CalibPeriod,u32 Calib_Enable)953 u32 RTC_SmoothCalibConfig(u32 CalibSign, u32 Value, u32 CalibPeriod, u32 Calib_Enable)
954 {
955 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
956 	u32 counter = 0;
957 	u32 status = 0;
958 	u32 temp = 0;
959 
960 	/* Check the parameters */
961 	assert_param(IS_RTC_CALIB_SIGN(CalibSign));
962 	assert_param(IS_RTC_CALIB_VALUE(Value));
963 	assert_param(IS_RTC_CALIB_PERIOD(CalibPeriod));
964 	assert_param(IS_RTC_CALIB_ENABLE(Calib_Enable));
965 
966 	/* Disable the write protection for RTC registers */
967 	RTC->WPR = 0xCA;
968 	RTC->WPR = 0x53;
969 
970 	/* check if a calibration is pending*/
971 	/* wait until the Calibration is completed*/
972 	while (1) {
973 		temp = RTC->ISR;
974 
975 		if ((temp & RTC_ISR_RECALPF) == 0)
976 			break;
977 		if (counter >= RECALPF_TIMEOUT)
978 			break;
979 
980 		counter++;
981 	}
982 
983 	/* check if the calibration pending is completed or if there is no calibration operation at all*/
984 	if ((RTC->ISR & RTC_ISR_RECALPF) == 0) {
985 		if (Calib_Enable == RTC_Calib_Disable) {
986 			RTC->CALIBR &= ~RTC_Calib_Enable;
987 		} else {
988 			RTC->CALIBR = (u32)(Value | CalibSign | Calib_Enable | CalibPeriod);
989 		}
990 		status = 1;
991 	} else {
992 		status = 0;
993 	}
994 
995 	/* Enable the write protection for RTC registers */
996 	RTC->WPR = 0xFF;
997 
998 	return status;
999 }
1000 
1001 /**
1002   * @brief  Configures the 32K auto calibration parameters.
1003   * @param  Cal_Period: value of auto calibration period (coded on 6 bits), unit is based on Unit_Sel.
1004   * @param  Unit_Sel: Autocal_sel specifies the sign of the auto calibration.
1005   *          This parameter can be  one of the following values:
1006   *            @arg RTC_32K_AUTOCAL_DISABLE: The auto calibration counter is disable
1007   *            @arg RTC_32K_AUTOCAL_MINUTES: The auto calibration counter update per minute
1008   *            @arg RTC_32K_AUTOCAL_HOURS: The auto calibration counter update per hour
1009   *            @arg RTC_32K_AUTOCAL_DAYS: The auto calibration counter update per day
1010   * @retval status value:
1011   *          - 1: RTC 32K auto calibration are configured ok
1012   *          - 0: RTC 32K auto calibration are configured fail
1013   * @note:
1014   *          - RTC ACAL_CNT[5:0] will be cleared by hardware
1015   */
RTC_32KAutoCalibConfig(u32 Cal_Period,u32 Unit_Sel)1016 u32 RTC_32KAutoCalibConfig(u32 Cal_Period, u32 Unit_Sel)
1017 {
1018 	RTC_TypeDef* RTC = ((RTC_TypeDef *) RTC_BASE);
1019 	u32 clkacalr = 0;
1020 	u32 status;
1021 
1022 	/* Check the parameters */
1023 	assert_param(IS_RTC_32K_AUTOCALIB_THRES(Cal_Period));
1024 	assert_param(IS_RTC_32K_AUTOCAL_SIGN(Unit_Sel));
1025 	if (Unit_Sel != RTC_32K_AUTOCAL_DISABLE)
1026 		assert_param((Cal_Period) > 0);
1027 
1028 	clkacalr |= (u32)(((Cal_Period)<< 2) | Unit_Sel);
1029 
1030 	/* Disable the write protection for RTC registers */
1031 	RTC->WPR = 0xCA;
1032 	RTC->WPR = 0x53;
1033 
1034 	/* Set Initialization mode */
1035 	if (RTC_EnterInitMode()) {
1036 		/*Write CLKACALR */
1037 		RTC->CLKACALR = clkacalr;
1038 
1039 		/* Exit Initialization mode */
1040 		RTC_ExitInitMode();
1041 
1042 		/*Wait shadow reigster sync ok, then ACAL_CNT[5:0] will be cleared by hardware */
1043 		if (RTC_WaitForSynchro()) {
1044 			status = 1;
1045 		} else {
1046 			status = 0;
1047 		}
1048 	} else {
1049 		status = 0;
1050 	}
1051 
1052 	/* Enable the write protection for RTC registers */
1053 	RTC->WPR = 0xFF;
1054 
1055 	return status;
1056 }
1057 
1058 /******************* (C) COPYRIGHT 2016 Realtek Semiconductor *****END OF FILE****/
1059