1 /*
2 * Copyright (c) 2021 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #ifndef HPM_GPIO_DRV_H
9 #define HPM_GPIO_DRV_H
10
11 #include "hpm_common.h"
12 #include "hpm_gpio_regs.h"
13 #include "hpm_soc_feature.h"
14
15 #ifndef PORT_PIN_COUNT
16 #define PORT_PIN_COUNT (32U)
17 #endif
18 #define GPIO_GET_PORT_INDEX(x) (x / PORT_PIN_COUNT)
19 #define GPIO_GET_PIN_INDEX(x) (x % PORT_PIN_COUNT)
20
21 /**
22 *
23 * @brief GPIO driver APIs
24 * @defgroup gpio_interface GPIO driver APIs
25 * @ingroup io_interfaces
26 * @{
27 */
28
29 /**
30 * @brief Interrupt trigger type
31 */
32 typedef enum gpio_interrupt_trigger {
33 gpio_interrupt_trigger_level_high = 0,
34 gpio_interrupt_trigger_level_low,
35 gpio_interrupt_trigger_edge_rising,
36 gpio_interrupt_trigger_edge_falling,
37 #if defined(GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT) && (GPIO_SOC_HAS_EDGE_BOTH_INTERRUPT == 1)
38 gpio_interrupt_trigger_edge_both,
39 #endif
40 } gpio_interrupt_trigger_t;
41
42 #ifdef __cplusplus
43 extern "C" {
44 #endif
45
46 /**
47 * @brief Read target pin level
48 *
49 * @param ptr GPIO base address
50 * @param port Port index
51 * @param pin Pin index
52 *
53 * @return Pin status mask
54 */
gpio_read_pin(GPIO_Type * ptr,uint32_t port,uint8_t pin)55 static inline uint8_t gpio_read_pin(GPIO_Type *ptr, uint32_t port, uint8_t pin)
56 {
57 return (ptr->DI[port].VALUE & (1 << pin)) >> pin;
58 }
59
60 /**
61 * @brief Read target pin output state
62 *
63 * @param ptr GPIO base address
64 * @param port Port index
65 * @param pin Pin index
66 *
67 * @return Pin output state
68 */
gpio_get_pin_output_status(GPIO_Type * ptr,uint32_t port,uint8_t pin)69 static inline uint32_t gpio_get_pin_output_status(GPIO_Type *ptr, uint32_t port, uint8_t pin)
70 {
71 return (ptr->DO[port].VALUE & (1 << pin)) >> pin;
72 }
73
74 /**
75 * @brief Toggle pin level
76 *
77 * @param ptr GPIO base address
78 * @param port Port index
79 * @param pin Pin index
80 */
gpio_toggle_pin(GPIO_Type * ptr,uint32_t port,uint8_t pin)81 static inline void gpio_toggle_pin(GPIO_Type *ptr, uint32_t port, uint8_t pin)
82 {
83 ptr->DO[port].TOGGLE = 1 << pin;
84 }
85
86 /**
87 * @brief Write pin level
88 *
89 * @param ptr GPIO base address
90 * @param port Port index
91 * @param pin Pin index
92 * @param high Pin level set to high when it is set to true
93 */
gpio_write_pin(GPIO_Type * ptr,uint32_t port,uint8_t pin,uint8_t high)94 static inline void gpio_write_pin(GPIO_Type *ptr, uint32_t port, uint8_t pin, uint8_t high)
95 {
96 if (high) {
97 ptr->DO[port].SET = 1 << pin;
98 } else {
99 ptr->DO[port].CLEAR = 1 << pin;
100 }
101 }
102
103 /**
104 * @brief Set pin to input mode
105 *
106 * @param ptr GPIO base address
107 * @param port Port index
108 * @param pin Pin index
109 */
gpio_set_pin_input(GPIO_Type * ptr,uint32_t port,uint8_t pin)110 static inline void gpio_set_pin_input(GPIO_Type *ptr, uint32_t port, uint8_t pin)
111 {
112 ptr->OE[port].CLEAR = 1 << pin;
113 }
114
115 /**
116 * @brief Set pin to output mode
117 *
118 * @param ptr GPIO base address
119 * @param port Port index
120 * @param pin Pin index
121 */
gpio_set_pin_output(GPIO_Type * ptr,uint32_t port,uint8_t pin)122 static inline void gpio_set_pin_output(GPIO_Type *ptr, uint32_t port, uint8_t pin)
123 {
124 ptr->OE[port].SET = 1 << pin;
125 }
126
127 /**
128 * @brief Set pin to output mode with initial value
129 *
130 * @param ptr GPIO base address
131 * @param port Port index
132 * @param pin Pin index
133 * @param initial Initial value
134 */
135 void gpio_set_pin_output_with_initial(GPIO_Type *ptr, uint32_t port, uint8_t pin, uint8_t initial);
136
137 /**
138 * @brief Check specific pin interrupt status
139 *
140 * @param ptr GPIO base address
141 * @param port Port index
142 * @param pin Pin index
143 *
144 * @return true if interrupt flag is set
145 */
gpio_check_pin_interrupt_flag(GPIO_Type * ptr,uint32_t port,uint8_t pin)146 static inline bool gpio_check_pin_interrupt_flag(GPIO_Type *ptr, uint32_t port, uint8_t pin)
147 {
148 return ptr->IF[port].VALUE & (1 << pin);
149 }
150
151 /**
152 * @brief Clear specific pin interrupt flag
153 *
154 * @param ptr GPIO base address
155 * @param port Port index
156 * @param pin Pin index
157 */
gpio_clear_pin_interrupt_flag(GPIO_Type * ptr,uint32_t port,uint8_t pin)158 static inline void gpio_clear_pin_interrupt_flag(GPIO_Type *ptr, uint32_t port, uint8_t pin)
159 {
160 ptr->IF[port].VALUE = 1 << pin;
161 }
162
163 /**
164 * @brief Check if specific pin interrupt is enabled or not
165 *
166 * @param ptr GPIO base address
167 * @param port Port index
168 * @param pin Pin index
169 *
170 * @return true if interrupt is enabled
171 */
gpio_check_pin_interrupt_enabled(GPIO_Type * ptr,uint32_t port,uint8_t pin)172 static inline bool gpio_check_pin_interrupt_enabled(GPIO_Type *ptr, uint32_t port, uint8_t pin)
173 {
174 return (ptr->IE[port].VALUE & (1 << pin)) == (uint32_t) (1 << pin);
175 }
176
177 /**
178 * @brief Enable interrupt for specific pin
179 *
180 * @param ptr GPIO base address
181 * @param port Port index
182 * @param pin Pin index
183 */
gpio_enable_pin_interrupt(GPIO_Type * ptr,uint32_t port,uint8_t pin)184 static inline void gpio_enable_pin_interrupt(GPIO_Type *ptr, uint32_t port, uint8_t pin)
185 {
186 ptr->IE[port].SET = 1 << pin;
187 }
188
189 /**
190 * @brief Disable interrupt for specific pin
191 *
192 * @param ptr GPIO base address
193 * @param port Port index
194 * @param pin Pin index
195 */
gpio_disable_pin_interrupt(GPIO_Type * ptr,uint32_t port,uint8_t pin)196 static inline void gpio_disable_pin_interrupt(GPIO_Type *ptr, uint32_t port, uint8_t pin)
197 {
198 ptr->IE[port].CLEAR = 1 << pin;
199 }
200
201 /**
202 * @brief Check interrupt flag of specific pin and clear if it is set
203 *
204 * @param ptr GPIO base address
205 * @param port Port index
206 * @param pin Pin index
207 *
208 * @return true if the interrupt flag is set and cleared
209 * @return false if the interrupt flag is not set
210 */
gpio_check_clear_interrupt_flag(GPIO_Type * ptr,uint32_t port,uint8_t pin)211 static inline bool gpio_check_clear_interrupt_flag(GPIO_Type *ptr, uint32_t port, uint8_t pin)
212 {
213 if (!gpio_check_pin_interrupt_flag(ptr, port, pin)) {
214 return false;
215 }
216 gpio_clear_pin_interrupt_flag(ptr, port, pin);
217 return true;
218 }
219
220
221 /**
222 * @brief Read all pins level on specific port
223 *
224 * @param ptr GPIO base address
225 * @param port Port index
226 *
227 * @return Port pin level status
228 */
gpio_read_port(GPIO_Type * ptr,uint32_t port)229 static inline uint32_t gpio_read_port(GPIO_Type *ptr, uint32_t port)
230 {
231 return ptr->DI[port].VALUE;
232 }
233
234 /**
235 * @brief Toggle port with specific pin mask
236 *
237 * @param ptr GPIO base address
238 * @param port Port index
239 * @param mask Mask pins to be toggled
240 */
gpio_toggle_port_with_mask(GPIO_Type * ptr,uint32_t port,uint32_t mask)241 static inline void gpio_toggle_port_with_mask(GPIO_Type *ptr, uint32_t port, uint32_t mask)
242 {
243 ptr->DO[port].TOGGLE = mask;
244 }
245
246 /**
247 * @brief Write specific port with value
248 *
249 * @param ptr GPIO base address
250 * @param port Port index
251 * @param value Value to be written
252 */
gpio_write_port(GPIO_Type * ptr,uint32_t port,uint32_t value)253 static inline void gpio_write_port(GPIO_Type *ptr, uint32_t port, uint32_t value)
254 {
255 ptr->DO[port].VALUE = value;
256 }
257
258 /**
259 * @brief Set spcific port pin high according to the given mask
260 *
261 * @param ptr GPIO base address
262 * @param port Port index
263 * @param mask Mask of pins to be set to low
264 */
gpio_set_port_low_with_mask(GPIO_Type * ptr,uint32_t port,uint32_t mask)265 static inline void gpio_set_port_low_with_mask(GPIO_Type *ptr, uint32_t port, uint32_t mask)
266 {
267 ptr->DO[port].CLEAR = mask;
268 }
269
270 /**
271 * @brief Set spcific port pin high according to the given mask
272 *
273 * @param ptr GPIO base address
274 * @param port Port index
275 * @param mask Mask of pins to be set to high
276 */
gpio_set_port_high_with_mask(GPIO_Type * ptr,uint32_t port,uint32_t mask)277 static inline void gpio_set_port_high_with_mask(GPIO_Type *ptr, uint32_t port, uint32_t mask)
278 {
279 ptr->DO[port].SET = mask;
280 }
281
282 /**
283 * @brief Enable pins output of specific port according to the given mask
284 *
285 * @param ptr GPIO base address
286 * @param port Port index
287 * @param mask Mask of pins to be enabled
288 */
gpio_enable_port_output_with_mask(GPIO_Type * ptr,uint32_t port,uint32_t mask)289 static inline void gpio_enable_port_output_with_mask(GPIO_Type *ptr, uint32_t port, uint32_t mask)
290 {
291 ptr->OE[port].SET = mask;
292 }
293
294 /**
295 * @brief Disable pins output of specific port according to the given mask
296 *
297 * @param ptr GPIO base address
298 * @param port Port index
299 * @param mask Mask of pins to be disabled
300 */
gpio_disable_port_output_with_mask(GPIO_Type * ptr,uint32_t port,uint32_t mask)301 static inline void gpio_disable_port_output_with_mask(GPIO_Type *ptr, uint32_t port, uint32_t mask)
302 {
303 ptr->OE[port].CLEAR = mask;
304 }
305
306 /**
307 * @brief Get current interrupt flags on specific port
308 *
309 * @param ptr GPIO base address
310 * @param port Port index
311 *
312 * @return Current interrupt flags on specific port
313 */
gpio_get_port_interrupt_flags(GPIO_Type * ptr,uint32_t port)314 static inline uint32_t gpio_get_port_interrupt_flags(GPIO_Type *ptr, uint32_t port)
315 {
316 return ptr->IF[port].VALUE;
317 }
318
319
320 /**
321 * @brief Clear interrupt flags with given mask on specific port
322 *
323 * @param ptr GPIO base address
324 * @param port Port index
325 * @param mask Mask of interrupts to be cleared
326 */
gpio_clear_port_interrupt_flags_with_mask(GPIO_Type * ptr,uint32_t port,uint32_t mask)327 static inline void gpio_clear_port_interrupt_flags_with_mask(GPIO_Type *ptr, uint32_t port, uint32_t mask)
328 {
329 ptr->IF[port].VALUE |= mask;
330 }
331
332 /**
333 * @brief Enable interrupts with given mask on specific port
334 *
335 * @param ptr GPIO base address
336 * @param port Port index
337 * @param mask Mask of interrupts to be enabled
338 */
gpio_enable_port_interrupt_with_mask(GPIO_Type * ptr,uint32_t port,uint8_t mask)339 static inline void gpio_enable_port_interrupt_with_mask(GPIO_Type *ptr, uint32_t port, uint8_t mask)
340 {
341 ptr->IE[port].SET = mask;
342 }
343
344 /**
345 * @brief Disable interrupts with given mask on specific port
346 *
347 * @param ptr GPIO base address
348 * @param port Port index
349 * @param mask Mask of interrupts to be disabled
350 */
gpio_disable_port_interrupt_with_mask(GPIO_Type * ptr,uint32_t port,uint8_t mask)351 static inline void gpio_disable_port_interrupt_with_mask(GPIO_Type *ptr, uint32_t port, uint8_t mask)
352 {
353 ptr->IE[port].CLEAR = mask;
354 }
355
356
357 /**
358 * @brief Config pin interrupt
359 *
360 * @param ptr GPIO base address
361 * @param port Port index
362 * @param pin Pin index
363 * @param trigger Trigger type
364 */
365 void gpio_config_pin_interrupt(GPIO_Type *ptr, uint32_t port, uint8_t pin, gpio_interrupt_trigger_t trigger);
366
367
368 /**
369 * @brief Toggle pin interrupt trigger polarity
370 *
371 * @param ptr GPIO base address
372 * @param port Port index
373 * @param pin Pin index
374 */
375 void gpio_toggle_pin_interrupt_trigger_polarity(GPIO_Type *ptr, uint32_t port, uint8_t pin);
376
377 /**
378 * @brief Toggle pin interrupt trigger type
379 *
380 * @param ptr GPIO base address
381 * @param port Port index
382 * @param pin Pin index
383 */
384 void gpio_toggle_pin_interrupt_trigger_type(GPIO_Type *ptr, uint32_t port, uint8_t pin);
385 #ifdef __cplusplus
386 }
387 #endif
388 /**
389 * @}
390 */
391 #endif /* HPM_GPIO_DRV_H */
392