BeRTOS
|
00001 00038 #include "clock_stm32.h" 00039 00040 #include <cfg/compiler.h> 00041 #include <cfg/module.h> 00042 #include <cfg/debug.h> 00043 00044 #include <io/stm32.h> 00045 #include <io/stm32_pwr.h> 00046 00047 #include <cpu/power.h> // cpu_relax() 00048 00049 #include <drv/rtc.h> 00050 00051 /* PWR registers base */ 00052 static struct PWR *PWR = (struct PWR *)PWR_BASE; 00053 00054 /* RTC clock source: LSE */ 00055 #define RTC_CLKSRC 0x00000100 00056 /* RTC clock: 32768 Hz */ 00057 #define RTC_CLOCK 32768 00058 /* RTC clock period (in ms) */ 00059 #define RTC_PERIOD 1000 00060 00061 /* RTC control register */ 00062 #define RTC_CRH (*(reg16_t *)(RTC_BASE + 0x00)) 00063 #define RTC_CRL (*(reg16_t *)(RTC_BASE + 0x04)) 00064 00065 #define RTC_CRL_SECIE BV(0) 00066 #define RTC_CRL_ALRIE BV(1) 00067 #define RTC_CRL_OWIE BV(2) 00068 00069 #define RTC_CRL_SECF BV(0) 00070 #define RTC_CRL_ALRF BV(1) 00071 #define RTC_CRL_OWF BV(2) 00072 #define RTC_CRL_RSF BV(3) 00073 #define RTC_CRL_CNF BV(4) 00074 #define RTC_CRL_RTOFF BV(5) 00075 00076 /* RTC prescaler load register */ 00077 #define RTC_PRLH (*(reg16_t *)(RTC_BASE + 0x08)) 00078 #define RTC_PRLL (*(reg16_t *)(RTC_BASE + 0x0c)) 00079 00080 /* RTC prescaler divider register */ 00081 #define RTC_DIVH (*(reg16_t *)(RTC_BASE + 0x10)) 00082 #define RTC_DIVL (*(reg16_t *)(RTC_BASE + 0x14)) 00083 00084 /* RTC counter register */ 00085 #define RTC_CNTH (*(reg16_t *)(RTC_BASE + 0x18)) 00086 #define RTC_CNTL (*(reg16_t *)(RTC_BASE + 0x1c)) 00087 00088 /* RTC alarm register */ 00089 #define RTC_ALRH (*(reg16_t *)(RTC_BASE + 0x20)) 00090 #define RTC_ALRL (*(reg16_t *)(RTC_BASE + 0x24)) 00091 00092 static void rtc_enterConfig(void) 00093 { 00094 /* Enter configuration mode */ 00095 RTC_CRL |= RTC_CRL_CNF; 00096 } 00097 00098 static void rtc_exitConfig(void) 00099 { 00100 /* Exit from configuration mode */ 00101 RTC_CRL &= ~RTC_CRL_CNF; 00102 while (!(RTC_CRL & RTC_CRL_RTOFF)) 00103 cpu_relax(); 00104 } 00105 00106 uint32_t rtc_time(void) 00107 { 00108 return (RTC_CNTH << 16) | RTC_CNTL; 00109 } 00110 00111 void rtc_setTime(uint32_t val) 00112 { 00113 rtc_enterConfig(); 00114 RTC_CNTH = (val >> 16) & 0xffff; 00115 RTC_CNTL = val & 0xffff; 00116 rtc_exitConfig(); 00117 } 00118 00119 /* Initialize the RTC clock */ 00120 int rtc_init(void) 00121 { 00122 #if CONFIG_KERN 00123 MOD_CHECK(proc); 00124 #endif 00125 /* Enable clock for Power interface */ 00126 RCC->APB1ENR |= RCC_APB1_PWR; 00127 00128 /* Enable access to RTC registers */ 00129 PWR->CR |= PWR_CR_DBP; 00130 00131 /* Enable LSE */ 00132 RCC->BDCR |= RCC_BDCR_LSEON; 00133 /* Wait for LSE ready */ 00134 while (!(RCC->BDCR & RCC_BDCR_LSERDY)) 00135 cpu_relax(); 00136 00137 /* Set clock source and enable RTC peripheral */ 00138 RCC->BDCR |= RTC_CLKSRC | RCC_BDCR_RTCEN; 00139 00140 rtc_enterConfig(); 00141 00142 /* Set prescaler */ 00143 RTC_PRLH = ((RTC_PERIOD * RTC_CLOCK / 1000 - 1) >> 16) & 0xff; 00144 RTC_PRLL = ((RTC_PERIOD * RTC_CLOCK / 1000 - 1)) & 0xffff; 00145 00146 rtc_exitConfig(); 00147 00148 /* Disable access to the RTC registers */ 00149 PWR->CR &= ~PWR_CR_DBP; 00150 00151 return 0; 00152 }