1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_GPTMR_DRV_H
9 #define HPM_GPTMR_DRV_H
10 #include "hpm_common.h"
11 #include "hpm_gptmr_regs.h"
12
13 /**
14 * @brief GPTMR driver APIs
15 * @defgroup gptmr_interface GPTMR driver APIs
16 * @ingroup io_interfaces
17 * @{
18 */
19
20 /**
21 * @brief GPTMR channel IRQ mask
22 */
23 #define GPTMR_CH_CMP_IRQ_MASK(ch, cmp) (1 << (ch * 4 + 2 + cmp))
24 #define GPTMR_CH_CAP_IRQ_MASK(ch) (1 << (ch * 4 + 1))
25 #define GPTMR_CH_RLD_IRQ_MASK(ch) (1 << (ch * 4))
26
27 /**
28 * @brief GPTMR channel status
29 */
30 #define GPTMR_CH_CMP_STAT_MASK(ch, cmp) (1 << (ch * 4 + 2 + cmp))
31 #define GPTMR_CH_CAP_STAT_MASK(ch) (1 << (ch * 4 + 1))
32 #define GPTMR_CH_RLD_STAT_MASK(ch) (1 << (ch * 4))
33
34 /**
35 * @brief GPTMR channel swsynct mask
36 */
37 #define GPTMR_CH_GCR_SWSYNCT_MASK(ch) (1 << ch)
38
39 /**
40 * @brief GPTMR one channel support output comparator count
41 */
42 #define GPTMR_CH_CMP_COUNT (2U)
43
44 /**
45 * @brief GPTMR synci valid edge
46 */
47 typedef enum gptmr_synci_edge {
48 gptmr_synci_edge_none = 0,
49 gptmr_synci_edge_falling = GPTMR_CHANNEL_CR_SYNCIFEN_MASK,
50 gptmr_synci_edge_rising = GPTMR_CHANNEL_CR_SYNCIREN_MASK,
51 gptmr_synci_edge_both = gptmr_synci_edge_falling | gptmr_synci_edge_rising,
52 } gptmr_synci_edge_t;
53
54 /**
55 * @brief GPTMR work mode
56 */
57 typedef enum gptmr_work_mode {
58 gptmr_work_mode_no_capture = 0,
59 gptmr_work_mode_capture_at_rising_edge = 1,
60 gptmr_work_mode_capture_at_falling_edge = 2,
61 gptmr_work_mode_capture_at_both_edge = 3,
62 gptmr_work_mode_measure_width = 4,
63 } gptmr_work_mode_t;
64
65 /**
66 * @brief GPTMR DMA request event
67 */
68 typedef enum gptmr_dma_request_event {
69 gptmr_dma_request_on_cmp0 = 0,
70 gptmr_dma_request_on_cmp1 = 1,
71 gptmr_dma_request_on_input_signal_toggle = 2,
72 gptmr_dma_request_on_reload = 3,
73 gptmr_dma_request_disabled = 0xFF,
74 } gptmr_dma_request_event_t;
75
76 /**
77 * @brief GPTMR counter type
78 */
79 typedef enum gptmr_counter_type {
80 gptmr_counter_type_rising_edge,
81 gptmr_counter_type_falling_edge,
82 gptmr_counter_type_measured_period,
83 gptmr_counter_type_measured_duty_cycle,
84 gptmr_counter_type_normal,
85 } gptmr_counter_type_t;
86
87 /**
88 * @brief GPTMR channel config
89 */
90 typedef struct gptmr_channel_config {
91 gptmr_work_mode_t mode;
92 gptmr_dma_request_event_t dma_request_event;
93 gptmr_synci_edge_t synci_edge;
94 uint32_t cmp[GPTMR_CH_CMP_COUNT];
95 uint32_t reload;
96 bool cmp_initial_polarity_high;
97 bool enable_cmp_output;
98 bool enable_sync_follow_previous_channel;
99 bool enable_software_sync;
100 bool debug_mode;
101 } gptmr_channel_config_t;
102
103 #ifdef __cplusplus
104 extern "C" {
105 #endif
106
107 /**
108 * @brief gptmr channel enable
109 *
110 * @param [in] ptr GPTMR base address
111 * @param [in] ch_index channel index
112 * @param [in] enable
113 * @arg true: enable
114 * @arg false: disable
115 */
gptmr_channel_enable(GPTMR_Type * ptr,uint8_t ch_index,bool enable)116 static inline void gptmr_channel_enable(GPTMR_Type *ptr, uint8_t ch_index, bool enable)
117 {
118 ptr->CHANNEL[ch_index].CR = (ptr->CHANNEL[ch_index].CR
119 & ~(GPTMR_CHANNEL_CR_CNTRST_MASK | GPTMR_CHANNEL_CR_CMPEN_MASK))
120 | GPTMR_CHANNEL_CR_CMPEN_SET(enable);
121 }
122
123 /**
124 * @brief gptmr channel reset counter
125 *
126 * @param [in] ptr GPTMR base address
127 * @param [in] ch_index channel index
128 */
gptmr_channel_reset_count(GPTMR_Type * ptr,uint8_t ch_index)129 static inline void gptmr_channel_reset_count(GPTMR_Type *ptr, uint8_t ch_index)
130 {
131 ptr->CHANNEL[ch_index].CR |= GPTMR_CHANNEL_CR_CNTRST_MASK;
132 ptr->CHANNEL[ch_index].CR &= ~GPTMR_CHANNEL_CR_CNTRST_MASK;
133 }
134
135 /**
136 * @brief gptmr channel update counter
137 *
138 * @param [in] ptr GPTMR base address
139 * @param [in] ch_index channel index
140 * @param [in] value updated vaue
141 */
gptmr_channel_update_count(GPTMR_Type * ptr,uint8_t ch_index,uint32_t value)142 static inline void gptmr_channel_update_count(GPTMR_Type *ptr,
143 uint8_t ch_index,
144 uint32_t value)
145 {
146 if (value > 0) {
147 value--;
148 }
149 ptr->CHANNEL[ch_index].CNTUPTVAL = GPTMR_CHANNEL_CNTUPTVAL_CNTUPTVAL_SET(value);
150 ptr->CHANNEL[ch_index].CR |= GPTMR_CHANNEL_CR_CNTUPT_MASK;
151 }
152
153 /**
154 * @brief gptmr channel slect synci valid edge
155 *
156 * @param [in] ptr GPTMR base address
157 * @param [in] ch_index channel index
158 * @param [in] edge gptmr_synci_edge_t
159 */
gptmr_channel_select_synci_valid_edge(GPTMR_Type * ptr,uint8_t ch_index,gptmr_synci_edge_t edge)160 static inline void gptmr_channel_select_synci_valid_edge(GPTMR_Type *ptr,
161 uint8_t ch_index,
162 gptmr_synci_edge_t edge)
163 {
164 ptr->CHANNEL[ch_index].CR = (ptr->CHANNEL[ch_index].CR
165 & ~(GPTMR_CHANNEL_CR_SYNCIFEN_MASK
166 | GPTMR_CHANNEL_CR_SYNCIREN_MASK)) | edge;
167 }
168
169 /**
170 * @brief gptmr channel enable dma request
171 *
172 * @param [in] ptr GPTMR base address
173 * @param [in] ch_index channel index
174 * @param [in] enable
175 * @arg true: enable
176 * @arg false: disable
177 */
gptmr_channel_enable_dma_request(GPTMR_Type * ptr,uint8_t ch_index,bool enable)178 static inline void gptmr_channel_enable_dma_request(GPTMR_Type *ptr,
179 uint8_t ch_index,
180 bool enable)
181 {
182 ptr->CHANNEL[ch_index].CR = (ptr->CHANNEL[ch_index].CR
183 & ~(GPTMR_CHANNEL_CR_DMAEN_MASK)) | GPTMR_CHANNEL_CR_DMAEN_SET(enable);
184 }
185
186 /**
187 * @brief gptmr channel get counter value
188 *
189 * @param [in] ptr GPTMR base address
190 * @param [in] ch_index channel index
191 * @param [in] capture gptmr_counter_type_t
192 */
gptmr_channel_get_counter(GPTMR_Type * ptr,uint8_t ch_index,gptmr_counter_type_t capture)193 static inline uint32_t gptmr_channel_get_counter(GPTMR_Type *ptr,
194 uint8_t ch_index,
195 gptmr_counter_type_t capture)
196 {
197 uint32_t value;
198 switch (capture) {
199 case gptmr_counter_type_rising_edge:
200 value = (ptr->CHANNEL[ch_index].CAPPOS & GPTMR_CHANNEL_CAPPOS_CAPPOS_MASK) >> GPTMR_CHANNEL_CAPPOS_CAPPOS_SHIFT;
201 break;
202 case gptmr_counter_type_falling_edge:
203 value = (ptr->CHANNEL[ch_index].CAPNEG & GPTMR_CHANNEL_CAPNEG_CAPNEG_MASK) >> GPTMR_CHANNEL_CAPNEG_CAPNEG_SHIFT;
204 break;
205 case gptmr_counter_type_measured_period:
206 value = (ptr->CHANNEL[ch_index].CAPPRD & GPTMR_CHANNEL_CAPPRD_CAPPRD_MASK) >> GPTMR_CHANNEL_CAPPRD_CAPPRD_SHIFT;
207 break;
208 case gptmr_counter_type_measured_duty_cycle:
209 value = (ptr->CHANNEL[ch_index].CAPDTY & GPTMR_CHANNEL_CAPDTY_MEAS_HIGH_MASK) >> GPTMR_CHANNEL_CAPDTY_MEAS_HIGH_SHIFT;
210 break;
211 default:
212 value = (ptr->CHANNEL[ch_index].CNT & GPTMR_CHANNEL_CNT_COUNTER_MASK) >> GPTMR_CHANNEL_CNT_COUNTER_SHIFT;
213 break;
214 }
215 return value;
216 }
217
218 /**
219 * @brief gptmr trigger channel software sync
220 *
221 * @param [in] ptr GPTMR base address
222 * @param [in] ch_index_mask channel index mask
223 */
gptmr_trigger_channel_software_sync(GPTMR_Type * ptr,uint32_t ch_index_mask)224 static inline void gptmr_trigger_channel_software_sync(GPTMR_Type *ptr, uint32_t ch_index_mask)
225 {
226 ptr->GCR = ch_index_mask;
227 }
228
229 /**
230 * @brief gptmr enable irq
231 *
232 * @param [in] ptr GPTMR base address
233 * @param [in] irq_mask irq mask
234 */
gptmr_enable_irq(GPTMR_Type * ptr,uint32_t irq_mask)235 static inline void gptmr_enable_irq(GPTMR_Type *ptr, uint32_t irq_mask)
236 {
237 ptr->IRQEN |= irq_mask;
238 }
239
240 /**
241 * @brief gptmr disable irq
242 *
243 * @param [in] ptr GPTMR base address
244 * @param [in] irq_mask irq mask
245 */
gptmr_disable_irq(GPTMR_Type * ptr,uint32_t irq_mask)246 static inline void gptmr_disable_irq(GPTMR_Type *ptr, uint32_t irq_mask)
247 {
248 ptr->IRQEN &= ~irq_mask;
249 }
250
251 /**
252 * @brief gptmr check status
253 *
254 * @param [in] ptr GPTMR base address
255 * @param [in] mask channel flag mask
256 */
gptmr_check_status(GPTMR_Type * ptr,uint32_t mask)257 static inline bool gptmr_check_status(GPTMR_Type *ptr, uint32_t mask)
258 {
259 return (ptr->SR & mask) == mask;
260 }
261
262 /**
263 * @brief gptmr clear status
264 *
265 * @param [in] ptr GPTMR base address
266 * @param [in] mask channel flag mask
267 */
gptmr_clear_status(GPTMR_Type * ptr,uint32_t mask)268 static inline void gptmr_clear_status(GPTMR_Type *ptr, uint32_t mask)
269 {
270 ptr->SR = mask;
271 }
272
273 /**
274 * @brief gptmr get status
275 *
276 * @param [in] ptr GPTMR base address
277 * @retval SR register value
278 */
gptmr_get_status(GPTMR_Type * ptr)279 static inline uint32_t gptmr_get_status(GPTMR_Type *ptr)
280 {
281 return ptr->SR;
282 }
283
284 /**
285 * @brief gptmr channel start counter
286 *
287 * @param [in] ptr GPTMR base address
288 * @param [in] ch_index channel index
289 */
gptmr_start_counter(GPTMR_Type * ptr,uint8_t ch_index)290 static inline void gptmr_start_counter(GPTMR_Type *ptr, uint8_t ch_index)
291 {
292 ptr->CHANNEL[ch_index].CR |= GPTMR_CHANNEL_CR_CEN_MASK;
293 }
294
295 /**
296 * @brief gptmr channel stop counter
297 *
298 * @param [in] ptr GPTMR base address
299 * @param [in] ch_index channel index
300 */
gptmr_stop_counter(GPTMR_Type * ptr,uint8_t ch_index)301 static inline void gptmr_stop_counter(GPTMR_Type *ptr, uint8_t ch_index)
302 {
303 ptr->CHANNEL[ch_index].CR &= ~GPTMR_CHANNEL_CR_CEN_MASK;
304 }
305
306 /**
307 * @brief gptmr channel enable compare output
308 *
309 * @param [in] ptr GPTMR base address
310 * @param [in] ch_index channel index
311 */
gptmr_enable_cmp_output(GPTMR_Type * ptr,uint8_t ch_index)312 static inline void gptmr_enable_cmp_output(GPTMR_Type *ptr, uint8_t ch_index)
313 {
314 ptr->CHANNEL[ch_index].CR |= GPTMR_CHANNEL_CR_CMPEN_MASK;
315 }
316
317 /**
318 * @brief gptmr channel disable compare output
319 *
320 * @param [in] ptr GPTMR base address
321 * @param [in] ch_index channel index
322 */
gptmr_disable_cmp_output(GPTMR_Type * ptr,uint8_t ch_index)323 static inline void gptmr_disable_cmp_output(GPTMR_Type *ptr, uint8_t ch_index)
324 {
325 ptr->CHANNEL[ch_index].CR &= ~GPTMR_CHANNEL_CR_CMPEN_MASK;
326 }
327
328 /**
329 * @brief gptmr channel set capmode
330 *
331 * @param [in] ptr GPTMR base address
332 * @param [in] ch_index channel index
333 */
gptmr_channel_set_capmode(GPTMR_Type * ptr,uint8_t ch_index,gptmr_work_mode_t mode)334 static inline void gptmr_channel_set_capmode(GPTMR_Type *ptr, uint8_t ch_index, gptmr_work_mode_t mode)
335 {
336 ptr->CHANNEL[ch_index].CR = (ptr->CHANNEL[ch_index].CR & ~GPTMR_CHANNEL_CR_CAPMODE_MASK) | GPTMR_CHANNEL_CR_CAPMODE_SET(mode);
337 }
338
339 /**
340 * @brief gptmr channel get capmode
341 *
342 * @param [in] ptr GPTMR base address
343 * @param [in] ch_index channel index
344 * @retval gptmr_work_mode_t enum gptmr_work_mode_capture_at_rising_edge or gptmr_work_mode_capture_at_falling_edge
345 */
gptmr_channel_get_capmode(GPTMR_Type * ptr,uint8_t ch_index)346 static inline gptmr_work_mode_t gptmr_channel_get_capmode(GPTMR_Type *ptr, uint8_t ch_index)
347 {
348 return GPTMR_CHANNEL_CR_CAPMODE_GET(ptr->CHANNEL[ch_index].CR);
349 }
350
351 /**
352 * @brief gptmr channel update comparator
353 *
354 * @param [in] ptr GPTMR base address
355 * @param [in] ch_index channel index
356 * @param [in] cmp_index comparator index
357 * @param [in] cmp comparator value
358 */
gptmr_update_cmp(GPTMR_Type * ptr,uint8_t ch_index,uint8_t cmp_index,uint32_t cmp)359 static inline void gptmr_update_cmp(GPTMR_Type *ptr, uint8_t ch_index, uint8_t cmp_index, uint32_t cmp)
360 {
361 if (cmp > 0) {
362 cmp--;
363 }
364 ptr->CHANNEL[ch_index].CMP[cmp_index] = GPTMR_CHANNEL_CMP_CMP_SET(cmp);
365 }
366
367 /**
368 * @brief gptmr channel get reload
369 *
370 * @param [in] ptr GPTMR base address
371 * @param [in] ch_index channel index
372 * @retval RLD register value
373 */
gptmr_channel_get_reload(GPTMR_Type * ptr,uint8_t ch_index)374 static inline uint32_t gptmr_channel_get_reload(GPTMR_Type *ptr, uint8_t ch_index)
375 {
376 return ptr->CHANNEL[ch_index].RLD;
377 }
378
379 /**
380 * @brief gptmr channel update reload
381 *
382 * @param [in] ptr GPTMR base address
383 * @param [in] ch_index channel index
384 * @param [in] reload reload value
385 */
gptmr_channel_config_update_reload(GPTMR_Type * ptr,uint8_t ch_index,uint32_t reload)386 static inline void gptmr_channel_config_update_reload(GPTMR_Type *ptr, uint8_t ch_index, uint32_t reload)
387 {
388 if (reload > 0) {
389 reload--;
390 }
391 ptr->CHANNEL[ch_index].RLD = GPTMR_CHANNEL_RLD_RLD_SET(reload);
392 }
393
394 /**
395 * @brief gptmr channel get dma request event
396 *
397 * @param [in] ptr GPTMR base address
398 * @param [in] ch_index channel index
399 * @retval gptmr_dma_request_event_t gptmr_dma_request_on_cmp0 or gptmr_dma_request_on_reload
400 */
gptmr_channel_get_dma_request_event(GPTMR_Type * ptr,uint8_t ch_index)401 static inline gptmr_dma_request_event_t gptmr_channel_get_dma_request_event(GPTMR_Type *ptr, uint8_t ch_index)
402 {
403 return GPTMR_CHANNEL_CR_DMASEL_GET(ptr->CHANNEL[ch_index].CR);
404 }
405
406 /**
407 * @brief gptmr channel config
408 *
409 * @param [in] ptr GPTMR base address
410 * @param [in] ch_index channel index
411 * @param [in] config gptmr_channel_config_t
412 * @param [in] enable
413 * @arg true: enable
414 * @arg false: disable
415 *
416 * @retval hpm_stat_t status_invalid_argument or status_success
417 */
418 hpm_stat_t gptmr_channel_config(GPTMR_Type *ptr,
419 uint8_t ch_index,
420 gptmr_channel_config_t *config,
421 bool enable);
422
423 /**
424 * @brief gptmr channel get default config
425 *
426 * @param [in] ptr GPTMR base address
427 * @param [out] config gptmr_channel_config_t
428 */
429 void gptmr_channel_get_default_config(GPTMR_Type *ptr, gptmr_channel_config_t *config);
430
431 /**
432 * @}
433 */
434
435 #ifdef __cplusplus
436 }
437 #endif
438
439 #endif /* HPM_GPTMR_DRV_H */
440