|
31 | 31 |
|
32 | 32 | #if DEVICE_RTC
|
33 | 33 |
|
| 34 | +#include "wait_api.h" |
| 35 | + |
| 36 | +#define LSE_STARTUP_TIMEOUT ((uint16_t)500) // delay in ms |
| 37 | + |
34 | 38 | static int rtc_inited = 0;
|
35 | 39 |
|
36 | 40 | void rtc_init(void) {
|
| 41 | + uint32_t StartUpCounter = 0; |
| 42 | + uint32_t LSEStatus = 0; |
| 43 | + uint32_t rtc_freq = 0; |
| 44 | + |
37 | 45 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); // Enable PWR clock
|
38 | 46 |
|
39 |
| - PWR_BackupAccessCmd(ENABLE); // Enable access to RTC |
| 47 | + PWR_BackupAccessCmd(ENABLE); // Enable access to Backup domain |
40 | 48 |
|
41 |
| - // Be sure to start correctly |
| 49 | + // Reset back up registers |
42 | 50 | RCC_BackupResetCmd(ENABLE);
|
43 | 51 | RCC_BackupResetCmd(DISABLE);
|
44 |
| - |
45 |
| - // Note: the LSI is used as RTC source clock |
46 |
| - // The RTC Clock may vary due to LSI frequency dispersion. |
47 |
| - RCC_LSICmd(ENABLE); // Enable LSI |
48 |
| - |
49 |
| - while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} // Wait until ready |
50 |
| - |
51 |
| - RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // Select LSI as RTC Clock Source |
52 |
| - |
53 |
| - RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock |
54 |
| - |
| 52 | + |
| 53 | + // Enable LSE clock |
| 54 | + RCC_LSEConfig(RCC_LSE_ON); |
| 55 | + |
| 56 | + // Wait till LSE is ready |
| 57 | + do { |
| 58 | + LSEStatus = RCC_GetFlagStatus(RCC_FLAG_LSERDY); |
| 59 | + wait_ms(1); |
| 60 | + StartUpCounter++; |
| 61 | + } while((LSEStatus == 0) && (StartUpCounter <= LSE_STARTUP_TIMEOUT)); |
| 62 | + |
| 63 | + if (StartUpCounter > LSE_STARTUP_TIMEOUT) { |
| 64 | + // The LSE has not started, use LSI instead. |
| 65 | + // The RTC Clock may vary due to LSI frequency dispersion. |
| 66 | + RCC_LSEConfig(RCC_LSE_OFF); |
| 67 | + RCC_LSICmd(ENABLE); // Enable LSI |
| 68 | + while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} // Wait until ready |
| 69 | + RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI); // Select the RTC Clock Source |
| 70 | + rtc_freq = 40000; // [TODO] To be measured precisely using a timer input capture |
| 71 | + } |
| 72 | + else { |
| 73 | + // The LSE has correctly started |
| 74 | + RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); // Select the RTC Clock Source |
| 75 | + rtc_freq = LSE_VALUE; |
| 76 | + } |
| 77 | + |
| 78 | + RCC_RTCCLKCmd(ENABLE); // Enable RTC Clock |
| 79 | + |
55 | 80 | RTC_WaitForSynchro(); // Wait for RTC registers synchronization
|
56 | 81 |
|
57 |
| - uint32_t lsi_freq = 40000; // [TODO] To be measured precisely using a timer input capture |
58 |
| - |
59 | 82 | RTC_InitTypeDef RTC_InitStructure;
|
60 | 83 | RTC_InitStructure.RTC_AsynchPrediv = 127;
|
61 |
| - RTC_InitStructure.RTC_SynchPrediv = (lsi_freq / 128) - 1; |
| 84 | + RTC_InitStructure.RTC_SynchPrediv = (rtc_freq / 128) - 1; |
62 | 85 | RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
|
63 | 86 | RTC_Init(&RTC_InitStructure);
|
64 |
| - |
| 87 | + |
| 88 | + PWR_BackupAccessCmd(DISABLE); // Disable access to Backup domain |
| 89 | + |
65 | 90 | rtc_inited = 1;
|
66 | 91 | }
|
67 | 92 |
|
|
0 commit comments