1
1
/* mbed Microcontroller Library
2
2
*******************************************************************************
3
- * Copyright (c) 2016 , STMicroelectronics
3
+ * Copyright (c) 2017 , STMicroelectronics
4
4
* All rights reserved.
5
5
*
6
6
* Redistribution and use in source and binary forms, with or without
27
27
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
*******************************************************************************
29
29
*/
30
+
30
31
#if DEVICE_RTC
31
32
32
- #include "rtc_api.h"
33
33
#include "rtc_api_hal.h"
34
34
#include "mbed_error.h"
35
35
#include "mbed_mktime.h"
36
36
37
37
static RTC_HandleTypeDef RtcHandle ;
38
38
39
- #if RTC_LSI
40
- #define RTC_CLOCK LSI_VALUE
41
- #else
42
- #define RTC_CLOCK LSE_VALUE
43
- #endif
44
-
45
- #if DEVICE_LOWPOWERTIMER
46
- #define RTC_ASYNCH_PREDIV ((RTC_CLOCK - 1) / 0x8000)
47
- #define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1)
48
- #else
49
- #define RTC_ASYNCH_PREDIV (0x007F)
50
- #define RTC_SYNCH_PREDIV (RTC_CLOCK / (RTC_ASYNCH_PREDIV + 1) - 1)
51
- #endif
52
-
53
39
#if DEVICE_LOWPOWERTIMER
54
40
static void (* irq_handler )(void );
55
41
static void RTC_IRQHandler (void );
@@ -61,38 +47,38 @@ void rtc_init(void)
61
47
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0 };
62
48
63
49
// Enable access to Backup domain
50
+ __HAL_RCC_PWR_CLK_ENABLE ();
64
51
HAL_PWR_EnableBkUpAccess ();
65
52
66
- RtcHandle .Instance = RTC ;
67
- RtcHandle .State = HAL_RTC_STATE_RESET ;
53
+ if (rtc_isenabled ()) {
54
+ return ;
55
+ }
68
56
69
- #if ! RTC_LSI
70
- RCC_OscInitStruct .OscillatorType = RCC_OSCILLATORTYPE_LSE ;
57
+ #if MBED_CONF_TARGET_LSE_AVAILABLE
58
+ RCC_OscInitStruct .OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE ;
71
59
RCC_OscInitStruct .PLL .PLLState = RCC_PLL_NONE ; // Mandatory, otherwise the PLL is reconfigured!
72
60
RCC_OscInitStruct .LSEState = RCC_LSE_ON ;
73
61
RCC_OscInitStruct .LSIState = RCC_LSI_OFF ;
74
62
75
- if (HAL_RCC_OscConfig (& RCC_OscInitStruct ) == HAL_OK ) {
76
- __HAL_RCC_RTC_CLKPRESCALER (RCC_RTCCLKSOURCE_LSE );
77
- __HAL_RCC_RTC_CONFIG (RCC_RTCCLKSOURCE_LSE );
78
- } else {
63
+ if (HAL_RCC_OscConfig (& RCC_OscInitStruct ) != HAL_OK ) {
79
64
error ("Cannot initialize RTC with LSE\n" );
80
65
}
81
66
67
+ __HAL_RCC_RTC_CLKPRESCALER (RCC_RTCCLKSOURCE_LSE );
68
+ __HAL_RCC_RTC_CONFIG (RCC_RTCCLKSOURCE_LSE );
69
+
82
70
PeriphClkInitStruct .PeriphClockSelection = RCC_PERIPHCLK_RTC ;
83
71
PeriphClkInitStruct .RTCClockSelection = RCC_RTCCLKSOURCE_LSE ;
84
72
if (HAL_RCCEx_PeriphCLKConfig (& PeriphClkInitStruct ) != HAL_OK ) {
85
73
error ("PeriphClkInitStruct RTC failed with LSE\n" );
86
74
}
87
- #else /* !RTC_LSI */
88
- __HAL_RCC_PWR_CLK_ENABLE ();
89
-
75
+ #else /* MBED_CONF_TARGET_LSE_AVAILABLE */
90
76
// Reset Backup domain
91
77
__HAL_RCC_BACKUPRESET_FORCE ();
92
78
__HAL_RCC_BACKUPRESET_RELEASE ();
93
79
94
80
// Enable LSI clock
95
- RCC_OscInitStruct .OscillatorType = RCC_OSCILLATORTYPE_LSI ;
81
+ RCC_OscInitStruct .OscillatorType = RCC_OSCILLATORTYPE_LSI | RCC_OSCILLATORTYPE_LSE ;
96
82
RCC_OscInitStruct .PLL .PLLState = RCC_PLL_NONE ; // Mandatory, otherwise the PLL is reconfigured!
97
83
RCC_OscInitStruct .LSEState = RCC_LSE_OFF ;
98
84
RCC_OscInitStruct .LSIState = RCC_LSI_ON ;
@@ -108,46 +94,50 @@ void rtc_init(void)
108
94
if (HAL_RCCEx_PeriphCLKConfig (& PeriphClkInitStruct ) != HAL_OK ) {
109
95
error ("PeriphClkInitStruct RTC failed with LSI\n" );
110
96
}
111
- #endif /* !RTC_LSI */
97
+ #endif /* MBED_CONF_TARGET_LSE_AVAILABLE */
112
98
113
99
// Enable RTC
114
100
__HAL_RCC_RTC_ENABLE ();
115
101
102
+ RtcHandle .Instance = RTC ;
103
+ RtcHandle .State = HAL_RTC_STATE_RESET ;
104
+
116
105
#if TARGET_STM32F1
117
106
RtcHandle .Init .AsynchPrediv = RTC_AUTO_1_SECOND ;
118
107
#else /* TARGET_STM32F1 */
119
108
RtcHandle .Init .HourFormat = RTC_HOURFORMAT_24 ;
120
- RtcHandle .Init .AsynchPrediv = RTC_ASYNCH_PREDIV ;
121
- RtcHandle .Init .SynchPrediv = RTC_SYNCH_PREDIV ;
109
+
110
+ /* PREDIV_A : 7-bit asynchronous prescaler */
111
+ #if DEVICE_LOWPOWERTIMER
112
+ /* PREDIV_A is set to a small value to improve the SubSeconds resolution */
113
+ /* with a 32768Hz clock, PREDIV_A=7 gives a precision of 244us */
114
+ RtcHandle .Init .AsynchPrediv = 7 ;
115
+ #else
116
+ /* PREDIV_A is set to the maximum value to improve the consumption */
117
+ RtcHandle .Init .AsynchPrediv = 0x007F ;
118
+ #endif
119
+ /* PREDIV_S : 15-bit synchronous prescaler */
120
+ /* PREDIV_S is set in order to get a 1 Hz clock */
121
+ RtcHandle .Init .SynchPrediv = RTC_CLOCK / (RtcHandle .Init .AsynchPrediv + 1 ) - 1 ;
122
122
RtcHandle .Init .OutPut = RTC_OUTPUT_DISABLE ;
123
123
RtcHandle .Init .OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH ;
124
124
RtcHandle .Init .OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN ;
125
125
#endif /* TARGET_STM32F1 */
126
126
127
127
if (HAL_RTC_Init (& RtcHandle ) != HAL_OK ) {
128
- error ("RTC error: RTC initialization failed. " );
128
+ error ("RTC initialization failed" );
129
129
}
130
130
131
- #if DEVICE_LOWPOWERTIMER
131
+ rtc_synchronize (); // Wait for RSF
132
132
133
- #if !RTC_LSI
134
- if (!rtc_isenabled ())
135
- #endif /* !RTC_LSI */
136
- {
133
+ if (!rtc_isenabled ()) {
137
134
rtc_write (0 );
138
135
}
139
-
140
- NVIC_ClearPendingIRQ (RTC_WKUP_IRQn );
141
- NVIC_DisableIRQ (RTC_WKUP_IRQn );
142
- NVIC_SetVector (RTC_WKUP_IRQn , (uint32_t )RTC_IRQHandler );
143
- NVIC_EnableIRQ (RTC_WKUP_IRQn );
144
-
145
- #endif /* DEVICE_LOWPOWERTIMER */
146
136
}
147
137
148
138
void rtc_free (void )
149
139
{
150
- #if RTC_LSI
140
+ #if ! MBED_CONF_TARGET_LSE_AVAILABLE
151
141
// Enable Power clock
152
142
__HAL_RCC_PWR_CLK_ENABLE ();
153
143
@@ -279,8 +269,12 @@ void rtc_write(time_t t)
279
269
#endif /* TARGET_STM32F1 */
280
270
281
271
// Change the RTC current date/time
282
- HAL_RTC_SetDate (& RtcHandle , & dateStruct , RTC_FORMAT_BIN );
283
- HAL_RTC_SetTime (& RtcHandle , & timeStruct , RTC_FORMAT_BIN );
272
+ if (HAL_RTC_SetDate (& RtcHandle , & dateStruct , RTC_FORMAT_BIN ) != HAL_OK ) {
273
+ error ("HAL_RTC_SetDate error\n" );
274
+ }
275
+ if (HAL_RTC_SetTime (& RtcHandle , & timeStruct , RTC_FORMAT_BIN ) != HAL_OK ) {
276
+ error ("HAL_RTC_SetTime error\n" );
277
+ }
284
278
}
285
279
286
280
int rtc_isenabled (void )
@@ -292,6 +286,13 @@ int rtc_isenabled(void)
292
286
#endif /* TARGET_STM32F1 */
293
287
}
294
288
289
+ void rtc_synchronize (void )
290
+ {
291
+ if (HAL_RTC_WaitForSynchro (& RtcHandle ) != HAL_OK ) {
292
+ error ("rtc_synchronize error\n" );
293
+ }
294
+ }
295
+
295
296
#if DEVICE_LOWPOWERTIMER
296
297
297
298
static void RTC_IRQHandler (void )
@@ -304,23 +305,42 @@ static void RTC_IRQHandler(void)
304
305
}
305
306
}
306
307
307
- void rtc_set_irq_handler (uint32_t handler )
308
- {
309
- irq_handler = (void (* )(void ))handler ;
310
- }
311
-
312
308
uint32_t rtc_read_subseconds (void )
313
309
{
314
- return 1000000.f * ((double )(RTC_SYNCH_PREDIV - RTC -> SSR ) / (RTC_SYNCH_PREDIV + 1 ));
310
+ return 1000000.f * ((double )(( RTC -> PRER & RTC_PRER_PREDIV_S ) - RTC -> SSR ) / (( RTC -> PRER & RTC_PRER_PREDIV_S ) + 1 ));
315
311
}
316
312
317
313
void rtc_set_wake_up_timer (uint32_t delta )
318
314
{
319
- uint32_t wake_up_counter = delta / (2000000 / RTC_CLOCK );
315
+ /* Ex for Wakeup period resolution with RTCCLK=32768 Hz :
316
+ * RTCCLK_DIV2: ~122us < wakeup period < ~4s
317
+ * RTCCLK_DIV4: ~244us < wakeup period < ~8s
318
+ * RTCCLK_DIV8: ~488us < wakeup period < ~16s
319
+ * RTCCLK_DIV16: ~976us < wakeup period < ~32s
320
+ * CK_SPRE_16BITS: 1s < wakeup period < (0xFFFF+ 1) x 1 s = 65536 s (18 hours)
321
+ * CK_SPRE_17BITS: 18h+1s < wakeup period < (0x1FFFF+ 1) x 1 s = 131072 s (36 hours)
322
+ */
323
+ uint32_t WakeUpClock [6 ] = {RTC_WAKEUPCLOCK_RTCCLK_DIV2 , RTC_WAKEUPCLOCK_RTCCLK_DIV4 , RTC_WAKEUPCLOCK_RTCCLK_DIV8 , RTC_WAKEUPCLOCK_RTCCLK_DIV16 , RTC_WAKEUPCLOCK_CK_SPRE_16BITS , RTC_WAKEUPCLOCK_CK_SPRE_17BITS };
324
+ uint8_t ClockDiv [4 ] = {2 , 4 , 8 , 16 };
325
+ uint32_t WakeUpCounter ;
326
+ uint8_t DivIndex = 0 ;
327
+
328
+ do {
329
+ WakeUpCounter = delta / (ClockDiv [DivIndex ] * 1000000 / RTC_CLOCK );
330
+ DivIndex ++ ;
331
+ } while ( (WakeUpCounter > 0xFFFF ) && (DivIndex < 4 ) );
332
+
333
+ if (WakeUpCounter > 0xFFFF ) {
334
+ WakeUpCounter = delta / 1000000 ;
335
+ DivIndex ++ ;
336
+ }
320
337
321
- if (HAL_RTCEx_SetWakeUpTimer_IT (& RtcHandle , wake_up_counter ,
322
- RTC_WAKEUPCLOCK_RTCCLK_DIV2 ) != HAL_OK ) {
323
- error ("Set wake up timer failed\n" );
338
+ irq_handler = (void (* )(void ))lp_ticker_irq_handler ;
339
+ NVIC_SetVector (RTC_WKUP_IRQn , (uint32_t )RTC_IRQHandler );
340
+ NVIC_EnableIRQ (RTC_WKUP_IRQn );
341
+
342
+ if (HAL_RTCEx_SetWakeUpTimer_IT (& RtcHandle , 0xFFFF & WakeUpCounter , WakeUpClock [DivIndex - 1 ]) != HAL_OK ) {
343
+ error ("rtc_set_wake_up_timer init error (%d)\n" , DivIndex );
324
344
}
325
345
}
326
346
@@ -329,10 +349,6 @@ void rtc_deactivate_wake_up_timer(void)
329
349
HAL_RTCEx_DeactivateWakeUpTimer (& RtcHandle );
330
350
}
331
351
332
- void rtc_synchronize (void )
333
- {
334
- HAL_RTC_WaitForSynchro (& RtcHandle );
335
- }
336
352
#endif /* DEVICE_LOWPOWERTIMER */
337
353
338
354
#endif /* DEVICE_RTC */
0 commit comments