1 /***************************************************************************//**
2 * @file
3 * @brief DCDC Coulomb Counter (DCDC_COULOMB_COUNTER) peripheral API
4 *******************************************************************************
5 * # License
6 * <b>Copyright 2024 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 #ifndef SL_HAL_DCDC_COULOMB_COUNTER_H
32 #define SL_HAL_DCDC_COULOMB_COUNTER_H
33
34 #include "em_device.h"
35
36 #if defined(DCDC_COUNT) && (DCDC_COUNT > 0) && defined(DCDC_CCCTRL_CCEN)
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 #include <stdbool.h>
43 #include "sl_hal_dcdc_coulomb_counter_compat.h"
44 #include "sl_enum.h"
45 #include "em_cmu.h"
46 #include "em_emu.h"
47
48 /***************************************************************************//**
49 * @addtogroup dcdccoulombcounter
50 * @{
51 ******************************************************************************/
52
53 /*******************************************************************************
54 ********************************* ENUM ************************************
55 ******************************************************************************/
56
57 /** DCDC_COULOMB_COUNTER supported energy mode. */
SL_ENUM(sl_hal_dcdc_coulomb_counter_emode_t)58 SL_ENUM(sl_hal_dcdc_coulomb_counter_emode_t) {
59 SL_HAL_DCDC_COULOMB_COUNTER_EM0 = 0, /**< EM0/1 energy mode. */
60 SL_HAL_DCDC_COULOMB_COUNTER_EM2 = 1, /**< EM2/3 energy mode. */
61 };
62
63 /** DCDC_COULOMB_COUNTER Calibration Load Current Level setting. */
SL_ENUM(sl_hal_dcdc_coulomb_counter_calibration_load_level_t)64 SL_ENUM(sl_hal_dcdc_coulomb_counter_calibration_load_level_t) {
65 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD0 = _DCDC_CCCALCTRL_CCLVL_LOAD0, /**< Nominal Load 0.25mA. */
66 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD1 = _DCDC_CCCALCTRL_CCLVL_LOAD1, /**< Nominal Load 0.50mA. */
67 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD2 = _DCDC_CCCALCTRL_CCLVL_LOAD2, /**< Nominal Load 1.00mA. */
68 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD3 = _DCDC_CCCALCTRL_CCLVL_LOAD3, /**< Nominal Load 1.50mA. */
69 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD4 = _DCDC_CCCALCTRL_CCLVL_LOAD4, /**< Nominal Load 2.00mA. */
70 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD5 = _DCDC_CCCALCTRL_CCLVL_LOAD5, /**< Nominal Load 4.00mA. */
71 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD6 = _DCDC_CCCALCTRL_CCLVL_LOAD6, /**< Nominal Load 6.00mA. */
72 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD7 = _DCDC_CCCALCTRL_CCLVL_LOAD7, /**< Nominal Load 8.00mA. */
73 };
74
75 /*******************************************************************************
76 ******************************* STRUCTS ***********************************
77 ******************************************************************************/
78
79 /// DCDC_COULOMB_COUNTER configuration structure.
80 typedef struct {
81 uint16_t counter_threshold_em0; ///< Coulomb Counter Threshold in EM0.
82 uint16_t counter_threshold_em2; ///< Coulomb Counter Threshold in EM2.
83 } sl_hal_dcdc_coulomb_counter_config_t;
84
85 /// DCDC_COULOMB_COUNTER calibration configuration structure.
86 typedef struct {
87 CMU_Select_TypeDef reference_clk; ///< Coulomb Counter Calibration Reference Clock.
88 int8_t cal_count; ///< Coulomb Counter Calibration Reference Count.
89 sl_hal_dcdc_coulomb_counter_emode_t cal_emode; ///< Coulomb Counter Calibration Energy Mode.
90 sl_hal_dcdc_coulomb_counter_calibration_load_level_t cal_load_level; ///< Coulomb Counter Calibration Power Load.
91 } sl_hal_dcdc_coulomb_counter_calibration_config_t;
92
93 /// Suggested default values for DCDC_COULOMB_COUNTER configuration structure.
94 #define DCDC_COULOMB_COUNTER_CONFIG_DEFAULT \
95 { \
96 0x8000, /* Coulomb Counter EM0 Threshold. */ \
97 0x8000, /* Coulomb Counter EM2 Threshold. */ \
98 }
99
100 /// Suggested default values for DCDC_COULOMB_COUNTER calibration configuration structure.
101 #define DCDC_COULOMB_COUNTER_CALIBRATION_CONFIG_DEFAULT \
102 { \
103 cmuSelect_HFXO, /* Coulomb Counter Calibration Reference Clock. */ \
104 8, /* Coulomb Counter Calibration Reference Count. */ \
105 SL_HAL_DCDC_COULOMB_COUNTER_EM0, /* Coulomb Counter Calibration DC-DC energy mode. */ \
106 SL_HAL_DCDC_COULOMB_COUNTER_CAL_LOAD3, /* Coulomb Counter Calibration Load. */ \
107 }
108
109 /*******************************************************************************
110 ***************************** PROTOTYPES **********************************
111 ******************************************************************************/
112
113 /***************************************************************************//**
114 * Initializes DCDC_COULOMB_COUNTER module.
115 *
116 * @param[in] p_config A pointer to the DCDC_COULOMB_COUNTER initialization
117 * structure variable.
118 ******************************************************************************/
119 void sl_hal_dcdc_coulomb_counter_init(const sl_hal_dcdc_coulomb_counter_config_t *p_config);
120
121 /***************************************************************************//**
122 * Enables DCDC_COULOMB_COUNTER module.
123 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_enable(void)124 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_enable(void)
125 {
126 EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
127 DCDC->CCCTRL_SET = DCDC_CCCTRL_CCEN;
128 }
129
130 /***************************************************************************//**
131 * Disables DCDC_COULOMB_COUNTER module.
132 ******************************************************************************/
133 void sl_hal_dcdc_coulomb_counter_disable(void);
134
135 /***************************************************************************//**
136 * Waits for the DCDC_COULOMB_COUNTER to complete START command.
137 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_wait_start(void)138 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_wait_start(void)
139 {
140 EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
141 while ((DCDC->CCSTATUS & _DCDC_CCSTATUS_CCRUNNING_MASK) == 0U) {
142 /* Wait for counters to start. */
143 }
144 }
145
146 /***************************************************************************//**
147 * Waits for the DCDC_COULOMB_COUNTER to complete STOP command.
148 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_wait_stop(void)149 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_wait_stop(void)
150 {
151 EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
152 while ((DCDC->CCSTATUS & _DCDC_CCSTATUS_CCRUNNING_MASK) == DCDC_CCSTATUS_CCRUNNING) {
153 /* Wait for counters to stop. */
154 }
155 }
156
157 /***************************************************************************//**
158 * Waits for the DCDC_COULOMB_COUNTER to complete CLR command.
159 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_wait_clear_counters(void)160 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_wait_clear_counters(void)
161 {
162 EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
163 while ((DCDC->CCSTATUS & _DCDC_CCSTATUS_CLRBSY_MASK) == DCDC_CCSTATUS_CLRBSY) {
164 /* Wait for counters to clear. */
165 }
166 }
167
168 /***************************************************************************//**
169 * Starts DCDC_COULOMB_COUNTER operation.
170 *
171 * @note This function will send a start command to the DCDC_COULOMB_COUNTER peripheral.
172 * The sl_hal_dcdc_coulomb_counter_wait_start() function can be used to wait for the start
173 * command to be executed.
174 *
175 * @note This function requires the DCDC_COULOMB_COUNTER to be enabled.
176 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_start(void)177 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_start(void)
178 {
179 EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
180 DCDC->CCCMD_SET = DCDC_CCCMD_START;
181 }
182
183 /***************************************************************************//**
184 * Stops the DCDC_COULOMB_COUNTER operation.
185 *
186 * @note This function will send a stop command to the DCDC_COULOMB_COUNTER peripheral.
187 * The sl_hal_dcdc_coulomb_counter_wait_stop() function can be used to wait for the stop
188 * command to be executed.
189 *
190 * @note This function requires the DCDC_COULOMB_COUNTER to be enabled.
191 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_stop(void)192 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_stop(void)
193 {
194 EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
195 DCDC->CCCMD_SET = DCDC_CCCMD_STOP;
196 }
197
198 /***************************************************************************//**
199 * Clears the DCDC_COULOMB_COUNTER counters.
200 *
201 * @note This function will send a clear command to the DCDC_COULOMB_COUNTER peripheral.
202 * The sl_hal_dcdc_coulomb_counter_wait_clear_counters() function can be used
203 * to wait for the clear command to be executed.
204 *
205 * @note This function requires the DCDC_COULOMB_COUNTER to be enabled.
206 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_clear_counters(void)207 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_clear_counters(void)
208 {
209 EMU_DCDCSync(_DCDC_SYNCBUSY_MASK);
210 DCDC->CCCMD_SET = DCDC_CCCMD_CLR;
211 }
212
213 /***************************************************************************//**
214 * Gets the DCDC_COULOMB_COUNTER count for the selected energy mode.
215 *
216 * @param[in] emode The energy mode requested will select the appropriate counter.
217 *
218 * @return Coulomb Counter Count Value.
219 ******************************************************************************/
220 uint32_t sl_hal_dcdc_coulomb_counter_get_count(sl_hal_dcdc_coulomb_counter_emode_t emode);
221
222 /***************************************************************************//**
223 * Gets DCDC_COULOMB_COUNTER STATUS register value.
224 *
225 * @return Current STATUS register value.
226 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_get_status(void)227 __STATIC_INLINE uint32_t sl_hal_dcdc_coulomb_counter_get_status(void)
228 {
229 return DCDC->CCSTATUS;
230 }
231
232 /***************************************************************************//**
233 * Enables one or more DCDC_COULOMB_COUNTER interrupts.
234 *
235 * @note Depending on the use, a pending interrupt may already be set prior to
236 * enabling the interrupt. To ignore a pending interrupt, consider using
237 * sl_hal_dcdc_coulomb_counter_clear_interrupts() prior to enabling the interrupt.
238 *
239 * @param[in] flags DCDC_COULOMB_COUNTER interrupt sources to enable.
240 * Use a set of interrupt flags OR-ed together to set
241 * multiple interrupt sources.
242 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_enable_interrupts(uint32_t flags)243 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_enable_interrupts(uint32_t flags)
244 {
245 DCDC->CCIEN_SET = flags;
246 }
247
248 /***************************************************************************//**
249 * Disables one or more DCDC_COULOMB_COUNTER interrupts.
250 *
251 * @param[in] flags DCDC_COULOMB_COUNTER interrupt sources to disable.
252 * Use a set of interrupt flags OR-ed together to disable
253 * multiple interrupt sources.
254 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_disable_interrupts(uint32_t flags)255 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_disable_interrupts(uint32_t flags)
256 {
257 DCDC->CCIEN_CLR = flags;
258 }
259
260 /***************************************************************************//**
261 * Clears one or more pending DCDC_COULOMB_COUNTER interrupts.
262 *
263 * @param[in] flags DCDC_COULOMB_COUNTER interrupt sources to clear.
264 * Use a set of interrupt flags OR-ed together to clear
265 * multiple interrupt sources.
266 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_clear_interrupts(uint32_t flags)267 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_clear_interrupts(uint32_t flags)
268 {
269 DCDC->CCIF_CLR = flags;
270 }
271
272 /***************************************************************************//**
273 * Gets pending DCDC_COULOMB_COUNTER interrupt flags.
274 *
275 * @note Event bits are not cleared by using this function.
276 *
277 * @return Pending DCDC_COULOMB_COUNTER interrupt sources.
278 * Returns a set of interrupt flags OR-ed together for multiple
279 * interrupt sources.
280 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_get_interrupts(void)281 __STATIC_INLINE uint32_t sl_hal_dcdc_coulomb_counter_get_interrupts(void)
282 {
283 return DCDC->CCIF;
284 }
285
286 /***************************************************************************//**
287 * Gets enabled and pending DCDC_COULOMB_COUNTER interrupt flags.
288 * Useful for handling more interrupt sources in the same interrupt handler.
289 *
290 * @note Interrupt flags are not cleared by using this function.
291 *
292 * @return Pending and enabled DCDC_COULOMB_COUNTER interrupt sources.
293 * The return value is the bitwise AND of
294 * - the enabled interrupt sources in DCDC_COULOMB_COUNTER_IEN and
295 * - the pending interrupt flags DCDC_COULOMB_COUNTER_IF.
296 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_get_enabled_interrupts(void)297 __STATIC_INLINE uint32_t sl_hal_dcdc_coulomb_counter_get_enabled_interrupts(void)
298 {
299 uint32_t ccif = DCDC->CCIF & _DCDC_CCIF_MASK;
300 uint32_t ccien = DCDC->CCIEN & _DCDC_CCIEN_MASK;
301
302 return ccif & ccien;
303 }
304
305 /***************************************************************************//**
306 * Sets one or more pending DCDC_COULOMB_COUNTER interrupts from Software.
307 *
308 * @param[in] flags DCDC_COULOMB_COUNTER interrupt sources to set to pending.
309 * Use a set of interrupt flags OR-ed together to set
310 * multiple interrupt sources.
311 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_set_interrupts(uint32_t flags)312 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_set_interrupts(uint32_t flags)
313 {
314 DCDC->CCIF_SET = flags;
315 }
316
317 /***************************************************************************//**
318 * Initializes the calibration of the DCDC Coulomb Counter.
319 *
320 * @param[in] config DCDC_COULOMB_COUNTER calibration configuration structure.
321 *
322 * @note The charge per pulse is measured using known on-chip calibration
323 * loads, a PRS channel, and the CMU RC oscillator calibration circuitry.
324 ******************************************************************************/
325 void sl_hal_dcdc_coulomb_counter_cal_init(sl_hal_dcdc_coulomb_counter_calibration_config_t config);
326
327 /***************************************************************************//**
328 * Starts DCDC_COULOMB_COUNTER calibration sequence.
329 ******************************************************************************/
330 void sl_hal_dcdc_coulomb_counter_cal_start(void);
331
332 /***************************************************************************//**
333 * Stops DCDC_COULOMB_COUNTER calibration sequence.
334 *
335 * @note The Calibration Load will be disabled.
336 ******************************************************************************/
337 void sl_hal_dcdc_coulomb_counter_cal_stop(void);
338
339 /***************************************************************************//**
340 * Enables the Calibration Load.
341 ******************************************************************************/
342 void sl_hal_dcdc_coulomb_counter_enable_cal_load(void);
343
344 /***************************************************************************//**
345 * Disables the Calibration Load.
346 ******************************************************************************/
347 void sl_hal_dcdc_coulomb_counter_disable_cal_load(void);
348
349 /***************************************************************************//**
350 * Sets the Calibration Load level.
351 *
352 * @param[in] emode The energy mode requested will adjust the compensation circuit.
353 * @param[in] load_level The load level to adjust the load current.
354 ******************************************************************************/
355 void sl_hal_dcdc_coulomb_counter_set_cal_load_level(sl_hal_dcdc_coulomb_counter_emode_t emode,
356 sl_hal_dcdc_coulomb_counter_calibration_load_level_t load_level);
357
358 /***************************************************************************//**
359 * Gets the calibration load current from the stored value
360 * in DEVINFO as measured during production testing.
361 *
362 * @param[in] load_level The load level requested.
363 *
364 * @return The calibration load current.
365 *
366 * @note The returned value can be converted into uA by dividing by 5.
367 *
368 * @note Each calibration load setting is a 16-bit value
369 * with each LSB representing 200 nA.
370 ******************************************************************************/
371 uint16_t sl_hal_dcdc_coulomb_counter_get_cal_load_current(sl_hal_dcdc_coulomb_counter_calibration_load_level_t load_level);
372
373 /***************************************************************************//**
374 * Gets the frequency (in Hz) of the CMU Calibration Up-Counter source.
375 *
376 * @return The frequency (in Hz) of the currently selected CMU Up-Counter clock
377 * source.
378 ******************************************************************************/
379 uint32_t sl_hal_dcdc_coulomb_counter_get_cal_reference_freq(void);
380
381 /***************************************************************************//**
382 * Sets the calibration Halt Flag.
383 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_set_calhalt(void)384 __STATIC_INLINE void sl_hal_dcdc_coulomb_counter_set_calhalt(void)
385 {
386 DCDC->CCCALCTRL_SET = DCDC_CCCALCTRL_CCCALHALT;
387 }
388
389 /***************************************************************************//**
390 * Gets the calibration Halt Flag.
391 *
392 * @return true if Halt Flag is set.
393 ******************************************************************************/
sl_hal_dcdc_coulomb_counter_calhalt_is_set(void)394 __STATIC_INLINE bool sl_hal_dcdc_coulomb_counter_calhalt_is_set(void)
395 {
396 return (DCDC->CCCALCTRL & _DCDC_CCCALCTRL_CCCALHALT_MASK) == DCDC_CCCALCTRL_CCCALHALT;
397 }
398
399 /** @} (end addtogroup dcdccoulombcounter) */
400
401 #ifdef __cplusplus
402 }
403 #endif
404
405 #endif /* defined(DCDC_COULOMB_COUNTER_COUNT) && (DCDC_COULOMB_COUNTER_COUNT > 0) && defined(DCDC_CCCTRL_CCEN) */
406 #endif /* SL_HAL_DCDC_COULOMB_COUNTER_H */
407