AceTimeClock  1.3.0
Clock classes for Arduino that can synchronize from an NTP server or an RTC chip
Stm32F1Rtc.h
1 /*
2  * MIT License
3  * Copyright (c) 2021 Brian T. Park
4  *
5  * Extracted from https://github.com/ZulNs/STM32F1_RTC/
6  * MIT License
7  * Copyright (c) 2019 ZulNs
8  */
9 
10 #ifndef ACE_TIME_STM32_F1_RTC_H
11 #define ACE_TIME_STM32_F1_RTC_H
12 
13 // This class works ONLY on the STM32F1, whose most common board is probably the
14 // "Blue Pill".
15 #if defined(STM32F1xx)
16 
17 #include <Arduino.h> // RTC, RCC, PWR, BKP
18 
19 #define RTC_CRH RTC->CRH
20 #define RTC_CRL RTC->CRL
21 #define RTC_PRLH RTC->PRLH
22 #define RTC_PRLL RTC->PRLL
23 #define RTC_CNTH RTC->CNTH
24 #define RTC_CNTL RTC->CNTL
25 
26 #define RCC_APB1ENR RCC->APB1ENR
27 #define RCC_BDCR RCC->BDCR
28 #define PWR_CR PWR->CR
29 
30 // Set the RTC_INIT_REG to to hold the 'init' bit, indicating that the RTC
31 // counter has been set to a valid epochSeconds value.
32 //
33 // If the default DR1 register causes conflicts with some other library, we can
34 // make this a configurable parameter in the begin() method. But that would
35 // require a bit hacking. Currently, the DR registers are accessible only
36 // through the `BKP` pointer which points to the `BKP_TypeDef` struct. If we
37 // want to refer to the backup registers using a numeric index (e.g. 1, 2), we
38 // would need to do some pointer casting. In other words, cast the `BKP` to a
39 // `__IO uint32_t* drp = (__IO uint32*) BKP`, then use `drp[index]` to get to
40 // the specific `DR{index}` register.
41 #define RTC_INIT_REG BKP->DR1
42 #define RTC_INIT_BIT 0
43 #define RTC_INIT_FLAG (1 << RTC_INIT_BIT)
44 
45 #include <stdint.h>
46 
47 namespace ace_time {
48 namespace hw {
49 
64 class Stm32F1Rtc {
65  public:
74  bool begin();
75 
77  void init();
78 
80  void setTime(uint32_t time);
81 
83  uint32_t getTime();
84 
89  bool isInitialized() {
90  return (RTC_INIT_REG & RTC_INIT_FLAG) == RTC_INIT_FLAG;
91  }
92 
93  private:
94  void waitSync() {
95  RTC_CRL &= ~RTC_CRL_RSF;
96  while ((RTC_CRL & RTC_CRL_RSF) == 0);
97  }
98 
99  void waitFinished() {
100  while ((RTC_CRL & RTC_CRL_RTOFF) == 0);
101  }
102 
103  void enableBackupWrites() {
104  PWR_CR |= PWR_CR_DBP;
105  }
106 
107  void disableBackupWrites() {
108  PWR_CR &= ~PWR_CR_DBP;
109  }
110 
111  void enterConfigMode() {
112  RTC_CRL |= RTC_CRL_CNF;
113  }
114 
115  void exitConfigMode() {
116  RTC_CRL &= ~RTC_CRL_CNF;
117  }
118 
119  void enableClockInterface() {
120  RCC_APB1ENR |= RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
121  }
122 };
123 
124 } // hw
125 } // ace_time
126 
127 #endif // defined(STM32F1xx)
128 
129 #endif