1 /***************************************************************************//**
2 * @file
3 * @brief Real Time Counter with Calendar (RTCC) Peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
7 *******************************************************************************
8 *
9 * SPDX-License-Identifier: Zlib
10 *
11 * The licensor of this software is Silicon Laboratories Inc.
12 *
13 * This software is provided 'as-is', without any express or implied
14 * warranty. In no event will the authors be held liable for any damages
15 * arising from the use of this software.
16 *
17 * Permission is granted to anyone to use this software for any purpose,
18 * including commercial applications, and to alter it and redistribute it
19 * freely, subject to the following restrictions:
20 *
21 * 1. The origin of this software must not be misrepresented; you must not
22 * claim that you wrote the original software. If you use this software
23 * in a product, an acknowledgment in the product documentation would be
24 * appreciated but is not required.
25 * 2. Altered source versions must be plainly marked as such, and must not be
26 * misrepresented as being the original software.
27 * 3. This notice may not be removed or altered from any source distribution.
28 *
29 ******************************************************************************/
30
31 #include "em_rtcc.h"
32 #if defined(RTCC_COUNT) && (RTCC_COUNT == 1)
33 #include "em_bus.h"
34
35 /***************************************************************************//**
36 * @addtogroup rtcc RTCC - Real Timer Counter/Calendar
37 * @brief Real Time Counter and Calendar (RTCC) Peripheral API
38 * @details
39 * This module contains functions to control the RTCC peripheral of Silicon
40 * Labs 32-bit MCUs and SoCs. The RTCC ensures timekeeping in low energy modes.
41 * The RTCC also includes a BCD calendar mode for easy time and date keeping.
42 * @{
43 ******************************************************************************/
44
45 /*******************************************************************************
46 ******************************* DEFINES ***********************************
47 ******************************************************************************/
48
49 /*******************************************************************************
50 ************************** LOCAL FUNCTIONS ********************************
51 ******************************************************************************/
52
53 /*******************************************************************************
54 ************************** GLOBAL FUNCTIONS *******************************
55 ******************************************************************************/
56
57 /***************************************************************************//**
58 * @brief
59 * Configure the selected capture/compare channel of the RTCC.
60 *
61 * @details
62 * Use this function to configure an RTCC channel.
63 * Select capture/compare mode, match output action, overflow output action,
64 * and PRS input configuration.
65 * See the configuration structure @ref RTCC_CCChConf_TypeDef for more
66 * details.
67 *
68 * @param[in] ch
69 * A channel selector.
70 *
71 * @param[in] confPtr
72 * A pointer to the configuration structure.
73 ******************************************************************************/
RTCC_ChannelInit(int ch,RTCC_CCChConf_TypeDef const * confPtr)74 void RTCC_ChannelInit(int ch, RTCC_CCChConf_TypeDef const *confPtr)
75 {
76 EFM_ASSERT(RTCC_CH_VALID(ch));
77
78 #if defined(_SILICON_LABS_32B_SERIES_1)
79 EFM_ASSERT((uint32_t)confPtr->compMask
80 < (_RTCC_CC_CTRL_COMPMASK_MASK >> _RTCC_CC_CTRL_COMPMASK_SHIFT)
81 + 1U);
82
83 /** Configure the selected capture/compare channel. */
84 RTCC->CC[ch].CTRL = ((uint32_t)confPtr->chMode << _RTCC_CC_CTRL_MODE_SHIFT)
85 | ((uint32_t)confPtr->compMatchOutAction << _RTCC_CC_CTRL_CMOA_SHIFT)
86 | ((uint32_t)confPtr->prsSel << _RTCC_CC_CTRL_PRSSEL_SHIFT)
87 | ((uint32_t)confPtr->inputEdgeSel << _RTCC_CC_CTRL_ICEDGE_SHIFT)
88 | ((uint32_t)confPtr->compBase << _RTCC_CC_CTRL_COMPBASE_SHIFT)
89 | ((uint32_t)confPtr->compMask << _RTCC_CC_CTRL_COMPMASK_SHIFT)
90 | ((uint32_t)confPtr->dayCompMode << _RTCC_CC_CTRL_DAYCC_SHIFT);
91 #else
92
93 /** Configure the selected capture/compare channel. */
94 RTCC->CC[ch].CTRL = ( (uint32_t)confPtr->chMode << _RTCC_CC_CTRL_MODE_SHIFT)
95 | ( (uint32_t)confPtr->compMatchOutAction << _RTCC_CC_CTRL_CMOA_SHIFT)
96 | ( (uint32_t)confPtr->inputEdgeSel << _RTCC_CC_CTRL_ICEDGE_SHIFT)
97 | ( (uint32_t)confPtr->compBase << _RTCC_CC_CTRL_COMPBASE_SHIFT);
98 if (confPtr->chMode == rtccCapComChModeCapture) {
99 volatile uint32_t *reg = &PRS->CONSUMER_RTCC_CC0;
100 reg[ch] = confPtr->prsSel;
101 }
102 #endif
103 }
104
105 /***************************************************************************//**
106 * @brief
107 * Enable/disable RTCC counting.
108 *
109 * @param[in] enable
110 * True to enable RTCC counting, false to disable counting.
111 ******************************************************************************/
RTCC_Enable(bool enable)112 void RTCC_Enable(bool enable)
113 {
114 #if defined (_RTCC_CTRL_ENABLE_SHIFT)
115 /* Bitbanding the enable bit in the CTRL register (atomic). */
116 BUS_RegBitWrite((&RTCC->CTRL), _RTCC_CTRL_ENABLE_SHIFT, (uint32_t)enable);
117 #elif defined (RTCC_CMD_START)
118
119 /* Quick exit if we want to disable RTCC and it's already disabled. */
120 if ((RTCC->EN == 0U) && !enable) {
121 return;
122 }
123
124 if (RTCC->EN != 0U) {
125 /* Modifying the enable bit while synchronization is active will BusFault */
126 RTCC_SyncWait();
127 }
128
129 if (enable) {
130 RTCC->EN_SET = RTCC_EN_EN;
131 RTCC_Start();
132 } else {
133 RTCC_Stop();
134 RTCC_SyncWait();
135 RTCC->EN_CLR = RTCC_EN_EN;
136 }
137 #endif
138 }
139
140 /***************************************************************************//**
141 * @brief
142 * Initialize RTCC.
143 *
144 * @details
145 * Note that the compare values must be set separately with RTCC_CompareSet(),
146 * which should probably be done prior to the use of this function if
147 * configuring the RTCC to start when initialization is completed.
148 *
149 * @param[in] init
150 * A pointer to the RTCC initialization structure.
151 ******************************************************************************/
RTCC_Init(const RTCC_Init_TypeDef * init)152 void RTCC_Init(const RTCC_Init_TypeDef *init)
153 {
154 #if defined (_RTCC_CTRL_MASK)
155 RTCC->CTRL = ((init->enable ? 1UL : 0UL) << _RTCC_CTRL_ENABLE_SHIFT)
156 | ((init->debugRun ? 1UL : 0UL) << _RTCC_CTRL_DEBUGRUN_SHIFT)
157 | ((init->precntWrapOnCCV0 ? 1UL : 0UL) << _RTCC_CTRL_PRECCV0TOP_SHIFT)
158 | ((init->cntWrapOnCCV1 ? 1UL : 0UL) << _RTCC_CTRL_CCV1TOP_SHIFT)
159 | ((uint32_t)init->presc << _RTCC_CTRL_CNTPRESC_SHIFT)
160 | ((uint32_t)init->prescMode << _RTCC_CTRL_CNTTICK_SHIFT)
161 #if defined(_RTCC_CTRL_BUMODETSEN_MASK)
162 | ((uint32_t)init->enaBackupModeSet << _RTCC_CTRL_BUMODETSEN_SHIFT)
163 #endif
164 | ((init->enaOSCFailDetect ? 1UL : 0UL) << _RTCC_CTRL_OSCFDETEN_SHIFT)
165 | ((uint32_t)init->cntMode << _RTCC_CTRL_CNTMODE_SHIFT)
166 | ((init->disLeapYearCorr ? 1UL : 0UL) << _RTCC_CTRL_LYEARCORRDIS_SHIFT);
167
168 #elif defined (_RTCC_CFG_MASK)
169 if (RTCC->EN != 0U) {
170 RTCC_SyncWait();
171 }
172 RTCC->EN_CLR = RTCC_EN_EN;
173 RTCC->CFG = ((init->debugRun ? 1UL : 0UL) << _RTCC_CFG_DEBUGRUN_SHIFT)
174 | ( (init->precntWrapOnCCV0 ? 1UL : 0UL) << _RTCC_CFG_PRECNTCCV0TOP_SHIFT)
175 | ( (init->cntWrapOnCCV1 ? 1UL : 0UL) << _RTCC_CFG_CNTCCV1TOP_SHIFT)
176 | ( (uint32_t)init->presc << _RTCC_CFG_CNTPRESC_SHIFT)
177 | ( (uint32_t)init->prescMode << _RTCC_CFG_CNTTICK_SHIFT);
178 RTCC->EN_SET = RTCC_EN_EN;
179 RTCC->CMD = init->enable ? RTCC_CMD_START : RTCC_CMD_STOP;
180 #endif
181 }
182
183 /***************************************************************************//**
184 * @brief
185 * Restore RTCC to its reset state.
186 ******************************************************************************/
RTCC_Reset(void)187 void RTCC_Reset(void)
188 {
189 unsigned int i;
190
191 #if defined(_RTCC_CTRL_MASK)
192 /* Restore all RTCC registers to their default values. */
193 RTCC_Unlock();
194 RTCC->CTRL = _RTCC_CTRL_RESETVALUE;
195 RTCC->PRECNT = _RTCC_PRECNT_RESETVALUE;
196 RTCC->CNT = _RTCC_CNT_RESETVALUE;
197 RTCC->TIME = _RTCC_TIME_RESETVALUE;
198 RTCC->DATE = _RTCC_DATE_RESETVALUE;
199 RTCC->IEN = _RTCC_IEN_RESETVALUE;
200 RTCC->IFC = _RTCC_IFC_MASK;
201 RTCC_StatusClear();
202 RTCC->EM4WUEN = _RTCC_EM4WUEN_RESETVALUE;
203
204 for (i = 0; i < RTCC_CC_NUM; i++) {
205 RTCC->CC[i].CTRL = _RTCC_CC_CTRL_RESETVALUE;
206 RTCC->CC[i].CCV = _RTCC_CC_CCV_RESETVALUE;
207 RTCC->CC[i].TIME = _RTCC_CC_TIME_RESETVALUE;
208 RTCC->CC[i].DATE = _RTCC_CC_DATE_RESETVALUE;
209 }
210
211 #elif defined(_RTCC_CFG_MASK)
212
213 /* Restore all RTCC registers to their default values. */
214 RTCC_Unlock();
215 RTCC->EN_SET = RTCC_EN_EN;
216 RTCC_Stop();
217 RTCC_SyncWait();
218 RTCC->PRECNT = _RTCC_PRECNT_RESETVALUE;
219 RTCC->CNT = _RTCC_CNT_RESETVALUE;
220 RTCC->IEN = _RTCC_IEN_RESETVALUE;
221 RTCC_IntClear(_RTCC_IF_MASK);
222 RTCC_StatusClear();
223
224 for (i = 0; i < RTCC_CC_NUM; i++) {
225 RTCC->CC[i].CTRL = _RTCC_CC_CTRL_RESETVALUE;
226 RTCC->CC[i].OCVALUE = _RTCC_CC_OCVALUE_RESETVALUE;
227 }
228 RTCC_SyncWait();
229 RTCC->EN_CLR = RTCC_EN_EN;
230 RTCC->CFG = _RTCC_CFG_RESETVALUE;
231 #endif
232 }
233
234 /***************************************************************************//**
235 * @brief
236 * Clear the STATUS register.
237 ******************************************************************************/
RTCC_StatusClear(void)238 void RTCC_StatusClear(void)
239 {
240 #if defined (RTCC_CMD_CLRSTATUS)
241 while ((RTCC->SYNCBUSY & RTCC_SYNCBUSY_CMD) != 0U) {
242 // Wait for synchronization.
243 }
244 RTCC->CMD = RTCC_CMD_CLRSTATUS;
245 #endif
246 }
247
248 /** @} (end addtogroup rtcc) */
249
250 #endif /* defined( RTCC_COUNT ) && ( RTCC_COUNT == 1 ) */
251