1 /***************************************************************************//**
2 * @file
3 * @brief General Purpose IO (GPIO) 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 #ifndef SL_HAL_GPIO_H
32 #define SL_HAL_GPIO_H
33
34 #include "em_device.h"
35
36 #if defined(GPIO_PRESENT)
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41
42 #include <stdbool.h>
43 #include <stddef.h>
44 #include "sl_assert.h"
45 #include "sl_device_gpio.h"
46 #include "sl_code_classification.h"
47
48 /* *INDENT-OFF* */
49 // *****************************************************************************
50 /// @addtogroup gpio GPIO - General Purpose Input Output
51 /// @brief General Purpose Input Output peripheral
52 ///
53 /// @li @ref gpio_intro
54 ///
55 ///@n @section gpio_intro Introduction
56 /// This module contains functions to control the GPIO peripheral of Silicon Labs 32-bit MCUs and SoCs.
57 /// The GPIO peripheral is used for interrupt configuration, pin configuration and direct pin manipulation
58 /// as well as routing for peripheral pin connections.
59 ///
60 /// @{
61 // *****************************************************************************
62 /* *INDENT-ON* */
63
64 /*******************************************************************************
65 ******************************** DEFINES **********************************
66 ******************************************************************************/
67
68 /// Define for port specific pin mask
69 #if defined(GPIO_PA_MASK)
70 #define SL_HAL_GPIO_PORT_A_PIN_MASK (GPIO_PA_MASK)
71 #else
72 #define SL_HAL_GPIO_PORT_A_PIN_MASK 0
73 #endif
74 #if defined(GPIO_PB_MASK)
75 #define SL_HAL_GPIO_PORT_B_PIN_MASK (GPIO_PB_MASK)
76 #else
77 #define SL_HAL_GPIO_PORT_B_PIN_MASK 0
78 #endif
79 #if defined(GPIO_PC_MASK)
80 #define SL_HAL_GPIO_PORT_C_PIN_MASK (GPIO_PC_MASK)
81 #else
82 #define SL_HAL_GPIO_PORT_C_PIN_MASK 0
83 #endif
84 #if defined(GPIO_PD_MASK)
85 #define SL_HAL_GPIO_PORT_D_PIN_MASK (GPIO_PD_MASK)
86 #else
87 #define SL_HAL_GPIO_PORT_D_PIN_MASK 0
88 #endif
89 #if defined(GPIO_PE_MASK)
90 #define SL_HAL_GPIO_PORT_E_PIN_MASK (GPIO_PE_MASK)
91 #else
92 #define SL_HAL_GPIO_PORT_E_PIN_MASK 0
93 #endif
94 #if defined(GPIO_PF_MASK)
95 #define SL_HAL_GPIO_PORT_F_PIN_MASK (GPIO_PF_MASK)
96 #else
97 #define SL_HAL_GPIO_PORT_F_PIN_MASK 0
98 #endif
99 #if defined(GPIO_PG_MASK)
100 #define SL_HAL_GPIO_PORT_G_PIN_MASK (GPIO_PG_MASK)
101 #else
102 #define SL_HAL_GPIO_PORT_G_PIN_MASK 0
103 #endif
104 #if defined(GPIO_PH_MASK)
105 #define SL_HAL_GPIO_PORT_H_PIN_MASK (GPIO_PH_MASK)
106 #else
107 #define SL_HAL_GPIO_PORT_H_PIN_MASK 0
108 #endif
109 #if defined(GPIO_PI_MASK)
110 #define SL_HAL_GPIO_PORT_I_PIN_MASK (GPIO_PI_MASK)
111 #else
112 #define SL_HAL_GPIO_PORT_I_PIN_MASK 0
113 #endif
114 #if defined(GPIO_PJ_MASK)
115 #define SL_HAL_GPIO_PORT_J_PIN_MASK (GPIO_PJ_MASK)
116 #else
117 #define SL_HAL_GPIO_PORT_J_PIN_MASK 0
118 #endif
119 #if defined(GPIO_PK_MASK)
120 #define SL_HAL_GPIO_PORT_K_PIN_MASK (GPIO_PK_MASK)
121 #else
122 #define SL_HAL_GPIO_PORT_K_PIN_MASK 0
123 #endif
124
125 /// Define for port specific pin count
126 #if defined(GPIO_PA_COUNT)
127 #define SL_HAL_GPIO_PORT_A_PIN_COUNT (GPIO_PA_COUNT)
128 #else
129 #define SL_HAL_GPIO_PORT_A_PIN_COUNT 0
130 #endif
131 #if defined(GPIO_PB_COUNT)
132 #define SL_HAL_GPIO_PORT_B_PIN_COUNT (GPIO_PB_COUNT)
133 #else
134 #define SL_HAL_GPIO_PORT_B_PIN_COUNT 0
135 #endif
136 #if defined(GPIO_PC_COUNT)
137 #define SL_HAL_GPIO_PORT_C_PIN_COUNT (GPIO_PC_COUNT)
138 #else
139 #define SL_HAL_GPIO_PORT_C_PIN_COUNT 0
140 #endif
141 #if defined(GPIO_PD_COUNT)
142 #define SL_HAL_GPIO_PORT_D_PIN_COUNT (GPIO_PD_COUNT)
143 #else
144 #define SL_HAL_GPIO_PORT_D_PIN_COUNT 0
145 #endif
146 #if defined(GPIO_PE_COUNT)
147 #define SL_HAL_GPIO_PORT_E_PIN_COUNT (GPIO_PE_COUNT)
148 #else
149 #define SL_HAL_GPIO_PORT_E_PIN_COUNT 0
150 #endif
151 #if defined(GPIO_PF_COUNT)
152 #define SL_HAL_GPIO_PORT_F_PIN_COUNT (GPIO_PF_COUNT)
153 #else
154 #define SL_HAL_GPIO_PORT_F_PIN_COUNT 0
155 #endif
156 #if defined(GPIO_PG_COUNT)
157 #define SL_HAL_GPIO_PORT_G_PIN_COUNT (GPIO_PG_COUNT)
158 #else
159 #define SL_HAL_GPIO_PORT_G_PIN_COUNT 0
160 #endif
161 #if defined(GPIO_PH_COUNT)
162 #define SL_HAL_GPIO_PORT_H_PIN_COUNT (GPIO_PH_COUNT)
163 #else
164 #define SL_HAL_GPIO_PORT_H_PIN_COUNT 0
165 #endif
166 #if defined(GPIO_PI_COUNT)
167 #define SL_HAL_GPIO_PORT_I_PIN_COUNT (GPIO_PI_COUNT)
168 #else
169 #define SL_HAL_GPIO_PORT_I_PIN_COUNT 0
170 #endif
171 #if defined(GPIO_PJ_COUNT)
172 #define SL_HAL_GPIO_PORT_J_PIN_COUNT (GPIO_PJ_COUNT)
173 #else
174 #define SL_HAL_GPIO_PORT_J_PIN_COUNT 0
175 #endif
176 #if defined(GPIO_PK_COUNT)
177 #define SL_HAL_GPIO_PORT_K_PIN_COUNT (GPIO_PK_COUNT)
178 #else
179 #define SL_HAL_GPIO_PORT_K_PIN_COUNT 0
180 #endif
181
182 /// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
183
184 /// Highest GPIO port number.
185
186 #if (SL_HAL_GPIO_PORT_K_PIN_COUNT > 0)
187 #define SL_HAL_GPIO_PORT_MAX 10
188 #elif (SL_HAL_GPIO_PORT_J_PIN_COUNT > 0)
189 #define SL_HAL_GPIO_PORT_MAX 9
190 #elif (SL_HAL_GPIO_PORT_I_PIN_COUNT > 0)
191 #define SL_HAL_GPIO_PORT_MAX 8
192 #elif (SL_HAL_GPIO_PORT_H_PIN_COUNT > 0)
193 #define SL_HAL_GPIO_PORT_MAX 7
194 #elif (SL_HAL_GPIO_PORT_G_PIN_COUNT > 0)
195 #define SL_HAL_GPIO_PORT_MAX 6
196 #elif (SL_HAL_GPIO_PORT_F_PIN_COUNT > 0)
197 #define SL_HAL_GPIO_PORT_MAX 5
198 #elif (SL_HAL_GPIO_PORT_E_PIN_COUNT > 0)
199 #define SL_HAL_GPIO_PORT_MAX 4
200 #elif (SL_HAL_GPIO_PORT_D_PIN_COUNT > 0)
201 #define SL_HAL_GPIO_PORT_MAX 3
202 #elif (SL_HAL_GPIO_PORT_C_PIN_COUNT > 0)
203 #define SL_HAL_GPIO_PORT_MAX 2
204 #elif (SL_HAL_GPIO_PORT_B_PIN_COUNT > 0)
205 #define SL_HAL_GPIO_PORT_MAX 1
206 #elif (SL_HAL_GPIO_PORT_A_PIN_COUNT > 0)
207 #define SL_HAL_GPIO_PORT_MAX 0
208 #else
209 #error "Max GPIO port number is undefined for this part."
210 #endif
211
212 /// Highest GPIO pin number.
213 #define SL_HAL_GPIO_PIN_MAX 15
214
215 /// @endcond
216
217 #define SL_HAL_GPIO_PORT_SIZE(port) ( \
218 (port) == 0 ? SL_HAL_GPIO_PORT_A_PIN_COUNT \
219 : (port) == 1 ? SL_HAL_GPIO_PORT_B_PIN_COUNT \
220 : (port) == 2 ? SL_HAL_GPIO_PORT_C_PIN_COUNT \
221 : (port) == 3 ? SL_HAL_GPIO_PORT_D_PIN_COUNT \
222 : (port) == 4 ? SL_HAL_GPIO_PORT_E_PIN_COUNT \
223 : (port) == 5 ? SL_HAL_GPIO_PORT_F_PIN_COUNT \
224 : (port) == 6 ? SL_HAL_GPIO_PORT_G_PIN_COUNT \
225 : (port) == 7 ? SL_HAL_GPIO_PORT_H_PIN_COUNT \
226 : (port) == 8 ? SL_HAL_GPIO_PORT_I_PIN_COUNT \
227 : (port) == 9 ? SL_HAL_GPIO_PORT_J_PIN_COUNT \
228 : (port) == 10 ? SL_HAL_GPIO_PORT_K_PIN_COUNT \
229 : 0)
230
231 #define SL_HAL_GPIO_PORT_MASK(port) ( \
232 ((int)port) == 0 ? SL_HAL_GPIO_PORT_A_PIN_MASK \
233 : ((int)port) == 1 ? SL_HAL_GPIO_PORT_B_PIN_MASK \
234 : ((int)port) == 2 ? SL_HAL_GPIO_PORT_C_PIN_MASK \
235 : ((int)port) == 3 ? SL_HAL_GPIO_PORT_D_PIN_MASK \
236 : ((int)port) == 4 ? SL_HAL_GPIO_PORT_E_PIN_MASK \
237 : ((int)port) == 5 ? SL_HAL_GPIO_PORT_F_PIN_MASK \
238 : ((int)port) == 6 ? SL_HAL_GPIO_PORT_G_PIN_MASK \
239 : ((int)port) == 7 ? SL_HAL_GPIO_PORT_H_PIN_MASK \
240 : ((int)port) == 8 ? SL_HAL_GPIO_PORT_I_PIN_MASK \
241 : ((int)port) == 9 ? SL_HAL_GPIO_PORT_J_PIN_MASK \
242 : ((int)port) == 10 ? SL_HAL_GPIO_PORT_K_PIN_MASK \
243 : 0UL)
244
245 /// Validation of port.
246 #define SL_HAL_GPIO_PORT_IS_VALID(port) (SL_HAL_GPIO_PORT_MASK(port) != 0x0UL)
247
248 /// Validation of port and pin.
249 #define SL_HAL_GPIO_PORT_PIN_IS_VALID(port, pin) ((((SL_HAL_GPIO_PORT_MASK(port)) >> (pin)) & 0x1UL) == 0x1UL)
250
251 /// Max interrupt lines for external and EM4 interrupts.
252 #define SL_HAL_GPIO_INTERRUPT_MAX 15
253
254 /// Shift value for EM4WUEN
255 #define SL_HAL_GPIO_EM4WUEN_SHIFT _GPIO_EM4WUEN_EM4WUEN_SHIFT
256
257 /// Masks for even and odd interrupt bits.
258 #define SL_HAL_GPIO_INT_IF_EVEN_MASK ((_GPIO_IF_MASK) & 0x55555555UL)
259 #define SL_HAL_GPIO_INT_IF_ODD_MASK ((_GPIO_IF_MASK) & 0xAAAAAAAAUL)
260
261 /// Validation of mode.
262 #define SL_HAL_GPIO_MODE_IS_VALID(mode) ((mode & _GPIO_P_MODEL_MODE0_MASK) == mode)
263
264 /// Validation of interrupt number and pin.
265 #define SL_HAL_GPIO_INTNO_PIN_VALID(int_no, pin) (((int_no) & ~_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK) == ((pin) & ~_GPIO_EXTIPINSELL_EXTIPINSEL0_MASK))
266
267 /*******************************************************************************
268 ******************************** ENUMS ************************************
269 ******************************************************************************/
270
271 /*******************************************************************************
272 ***************************** PROTOTYPES **********************************
273 ******************************************************************************/
274
275 /***************************************************************************//**
276 * Set the mode for a GPIO pin.
277 *
278 * @param[in] gpio Pointer to GPIO structure with port and pin
279 * @param[in] mode The desired pin mode.
280 * @param[in] output_value A value to set for the pin in the DOUT register. The DOUT setting is important for
281 * some input mode configurations to determine the pull-up/down direction.
282 ******************************************************************************/
283 void sl_hal_gpio_set_pin_mode(const sl_gpio_t *gpio,
284 sl_gpio_mode_t mode,
285 bool output_value);
286
287 /***************************************************************************//**
288 * Get the mode for a GPIO pin.
289 *
290 * @param[in] gpio Pointer to GPIO structure with port and pin
291 *
292 * @return Return the pin mode.
293 ******************************************************************************/
294 sl_gpio_mode_t sl_hal_gpio_get_pin_mode(const sl_gpio_t *gpio);
295
296 /***************************************************************************//**
297 * Configure the GPIO external pin interrupt by connecting external interrupt id with gpio pin.
298 *
299 * @note This function configure the pin interrupt with pin ,port and external interrupt id as input.
300 * If external interrupt id is provided as input it will be considered as the input or else
301 * available interrupt number will be generated by looping through the interrupt group and will be used.
302 * User can provide SL_HAL_GPIO_INTERRUPT_UNAVAILABLE if user don't want to provide interrupt id.
303 * @note the pin number can be selected freely within a group.
304 * Interrupt numbers are divided into 4 groups (int_no / 4) and valid pin
305 * number within the interrupt groups are:
306 * 0: pins 0-3 (interrupt number 0-3)
307 * 1: pins 4-7 (interrupt number 4-7)
308 * 2: pins 8-11 (interrupt number 8-11)
309 * 3: pins 12-15 (interrupt number 12-15)
310 * @note It is recommended to disable interrupts before configuring the GPIO pin interrupt.
311 * See @ref sl_hal_gpio_disable_interrupts() for more information.
312 * The GPIO interrupt handler must be in place before enabling the interrupt.
313 * Notice that any pending interrupt for the selected interrupt is cleared by this function.
314 * Notice that only interrupt will be configured by this function. It is not enabled.
315 * It is recommended to enable interrupts after configuring the GPIO pin interrupt if needed.
316 * See @ref sl_hal_gpio_enable_interrupts() for more information.
317 *
318 * @param[in] gpio Pointer to GPIO structure with port and pin
319 * @param[in] int_no The interrupt number to trigger.
320 * @param[in] flags Interrupt configuration flags. @ref sl_hal_gpio_interrupt_flag_t for more information.
321 *
322 * @return Return the available interrupt number
323 ******************************************************************************/
324 int32_t sl_hal_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
325 int32_t int_no,
326 sl_gpio_interrupt_flag_t flags);
327
328 /**************************************************************************//**
329 * Enable GPIO pin wake-up from EM4. When the function exits,
330 * EM4 mode can be safely entered.
331 *
332 * @note It is assumed that the GPIO pin modes are set correctly.
333 * Valid modes are SL_GPIO_MODE_INPUT and SL_GPIO_MODE_INPUT_PULL.
334 *
335 * @param[in] pinmask A bitmask containing the bitwise logic OR of which GPIO pin(s) to enable.
336 * @param[in] polaritymask A bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity.
337 *****************************************************************************/
338 void sl_hal_gpio_enable_pin_em4_wakeup(uint32_t pinmask,
339 uint32_t polaritymask);
340
341 /***************************************************************************//**
342 * Configure EM4WU pins as external level-sensitive interrupts.
343 *
344 * @note It is recommended to disable interrupts before configuring the GPIO pin interrupt.
345 * See @ref sl_hal_gpio_disable_interrupts() for more information.
346 * The provided port, pin and int_no inputs should be valid EM4 related parameters
347 * because there are dedicated port, pin and EM4 Wakeup interrupt combination for
348 * configuring the port, pin for EM4 functionality.
349 * User can provide SL_HAL_GPIO_INTERRUPT_UNAVAILABLE if user don't want to provide interrupt id.
350 * The GPIO interrupt handler must be in place before enabling the interrupt.
351 * Notice that any pending interrupt for the selected interrupt is cleared by this function.
352 * Notice that any only EM4WU interrupt is configured by this function. It is not enabled.
353 * It is recommended to enable interrupts after configuring the GPIO pin interrupt if needed.
354 * See @ref sl_hal_gpio_enable_interrupts() for more information.
355 *
356 * @param[in] gpio Pointer to GPIO structure with port and pin
357 * @param[in] int_no The EM4WU interrupt number to trigger.
358 * @param[in] polarity true = Active high level-sensitive interrupt.
359 * false = Active low level-sensitive interrupt.
360 *
361 * @return Return the available EM4WU interrupt number
362 ******************************************************************************/
363 int32_t sl_hal_gpio_configure_wakeup_em4_external_interrupt(const sl_gpio_t *gpio,
364 int32_t int_no,
365 bool polarity);
366
367 /***************************************************************************//**
368 * Lock the GPIO configuration.
369 *
370 * @note Configuration lock affects the GPIO_Px_MODEL, GPIO_Px_MODEH, GPIO_Px_CTRL,
371 * GPIO_Px_PINLOCKN, GPIO_EXTIPSELL, GPIO_EXTIPSELH, GPIO_EXTIPINSELL,
372 * GPIO_EXTIPINSELH, GPIO_INSENSE, GPIO_ROUTE, GPIO_ROUTEPEN, and
373 * GPIO_ROUTELOC0 registers when they are present on a specific device.
374 * @note Unwanted or accidental changes to GPIO configuration can be avoided by
375 * using the configuration lock register. Any value other than 0xA534 written to
376 * GPIO_LOCK enables the configuration lock. Pins are unlocked by a reset or
377 * by writing 0xA534 to the GPIO_LOCK register.
378 ******************************************************************************/
sl_hal_gpio_lock(void)379 __INLINE void sl_hal_gpio_lock(void)
380 {
381 GPIO->LOCK = ~GPIO_LOCK_LOCKKEY_UNLOCK;
382 }
383
384 /***************************************************************************//**
385 * Unlock the GPIO configuration.
386 *
387 * @note Configuration lock affects the GPIO_Px_MODEL, GPIO_Px_MODEH, GPIO_Px_CTRL,
388 * GPIO_Px_PINLOCKN, GPIO_EXTIPSELL, GPIO_EXTIPSELH, GPIO_EXTIPINSELL,
389 * GPIO_EXTIPINSELH, GPIO_INSENSE, GPIO_ROUTE, GPIO_ROUTEPEN, and
390 * GPIO_ROUTELOC0 registers when they are present on a specific device.
391 * @note Unwanted or accidental changes to GPIO configuration can be avoided by
392 * using the configuration lock register. Any value other than 0xA534 written to
393 * GPIO_LOCK enables the configuration lock. Pins are unlocked by a reset or
394 * by writing 0xA534 to the GPIO_LOCK register.
395 ******************************************************************************/
sl_hal_gpio_unlock(void)396 __INLINE void sl_hal_gpio_unlock(void)
397 {
398 GPIO->LOCK = GPIO_LOCK_LOCKKEY_UNLOCK;
399 }
400
401 /***************************************************************************//**
402 * Gets the GPIO configuration state.
403 *
404 * @return Return the GPIO lock state.
405 ******************************************************************************/
sl_hal_gpio_get_lock_status(void)406 __INLINE uint32_t sl_hal_gpio_get_lock_status(void)
407 {
408 return GPIO->GPIOLOCKSTATUS;
409 }
410
411 /***************************************************************************//**
412 * Set a single pin in GPIO data out register to 1.
413 *
414 * @param[in] gpio Pointer to GPIO structure with port and pin
415 ******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_GPIO,SL_CODE_CLASS_TIME_CRITICAL)416 SL_CODE_CLASSIFY(SL_CODE_COMPONENT_HAL_GPIO, SL_CODE_CLASS_TIME_CRITICAL)
417 __INLINE void sl_hal_gpio_set_pin(const sl_gpio_t *gpio)
418 {
419 EFM_ASSERT(gpio != NULL);
420 EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
421
422 GPIO->P_SET[gpio->port].DOUT = 1UL << gpio->pin;
423 }
424
425 /***************************************************************************//**
426 * Set bits GPIO data out register to 1.
427 *
428 * @param[in] port The GPIO port to access.
429 * @param[in] pins Bit mask for bits to set to 1 in DOUT register.
430 ******************************************************************************/
sl_hal_gpio_set_port(sl_gpio_port_t port,uint32_t pins)431 __INLINE void sl_hal_gpio_set_port(sl_gpio_port_t port,
432 uint32_t pins)
433 {
434 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
435 GPIO->P_SET[port].DOUT = pins;
436 }
437
438 /***************************************************************************//**
439 * Set GPIO port data out register.
440 *
441 * @param[in] port The GPIO port to access.
442 * @param[in] val Value to write to port data out register.
443 * @param[in] mask Mask indicating which bits to modify.
444 ******************************************************************************/
sl_hal_gpio_set_port_value(sl_gpio_port_t port,uint32_t val,uint32_t mask)445 __INLINE void sl_hal_gpio_set_port_value(sl_gpio_port_t port,
446 uint32_t val,
447 uint32_t mask)
448 {
449 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
450 GPIO->P[port].DOUT = (GPIO->P[port].DOUT & ~mask) | (val & mask);
451 }
452
453 /***************************************************************************//**
454 * Set slewrate for pins on a GPIO port which are configured into normal modes.
455 *
456 * @param[in] port The GPIO port to configure.
457 * @param[in] slewrate The slewrate to configure for pins on this GPIO port.
458 ******************************************************************************/
sl_hal_gpio_set_slew_rate(sl_gpio_port_t port,uint8_t slewrate)459 __INLINE void sl_hal_gpio_set_slew_rate(sl_gpio_port_t port,
460 uint8_t slewrate)
461 {
462 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
463 EFM_ASSERT(slewrate <= (_GPIO_P_CTRL_SLEWRATE_MASK
464 >> _GPIO_P_CTRL_SLEWRATE_SHIFT));
465
466 GPIO->P[port].CTRL = (GPIO->P[port].CTRL
467 & ~_GPIO_P_CTRL_SLEWRATE_MASK)
468 | (slewrate << _GPIO_P_CTRL_SLEWRATE_SHIFT);
469 }
470
471 /***************************************************************************//**
472 * Set slewrate for pins on a GPIO port which are configured into alternate modes.
473 *
474 * @param[in] port The GPIO port to configure.
475 * @param[in] slewrate_alt The slewrate to configure for pins using alternate modes on this GPIO port.
476 ******************************************************************************/
sl_hal_gpio_set_slew_rate_alternate(sl_gpio_port_t port,uint8_t slewrate_alt)477 __INLINE void sl_hal_gpio_set_slew_rate_alternate(sl_gpio_port_t port,
478 uint8_t slewrate_alt)
479 {
480 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
481 EFM_ASSERT(slewrate_alt <= (_GPIO_P_CTRL_SLEWRATEALT_MASK
482 >> _GPIO_P_CTRL_SLEWRATEALT_SHIFT));
483
484 GPIO->P[port].CTRL = (GPIO->P[port].CTRL
485 & ~_GPIO_P_CTRL_SLEWRATEALT_MASK)
486 | (slewrate_alt << _GPIO_P_CTRL_SLEWRATEALT_SHIFT);
487 }
488
489 /***************************************************************************//**
490 * Get slewrate for pins on a GPIO port.
491 *
492 * @param[in] port The GPIO port to access to get slew rate.
493 *
494 * @return Return the slewrate setting for the selected GPIO port.
495 ******************************************************************************/
sl_hal_gpio_get_slew_rate(sl_gpio_port_t port)496 __INLINE uint8_t sl_hal_gpio_get_slew_rate(sl_gpio_port_t port)
497 {
498 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
499
500 return (GPIO->P[port].CTRL & _GPIO_P_CTRL_SLEWRATE_MASK) >> _GPIO_P_CTRL_SLEWRATE_SHIFT;
501 }
502
503 /***************************************************************************//**
504 * Get slewrate for pins on a GPIO port which are configured into alternate modes.
505 *
506 * @param[in] port The GPIO port to access to get slew rate.
507 *
508 * @return Return the alternate slewrate setting for selected GPIO port.
509 ******************************************************************************/
sl_hal_gpio_get_slew_rate_alternate(sl_gpio_port_t port)510 __INLINE uint8_t sl_hal_gpio_get_slew_rate_alternate(sl_gpio_port_t port)
511 {
512 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
513
514 return (GPIO->P[port].CTRL & _GPIO_P_CTRL_SLEWRATEALT_MASK) >> _GPIO_P_CTRL_SLEWRATEALT_SHIFT;
515 }
516
517 /***************************************************************************//**
518 * Set a single pin in GPIO data out port register to 0.
519 *
520 * @param[in] gpio Pointer to GPIO structure with port and pin
521 ******************************************************************************/
sl_hal_gpio_clear_pin(const sl_gpio_t * gpio)522 __INLINE void sl_hal_gpio_clear_pin(const sl_gpio_t *gpio)
523 {
524 EFM_ASSERT(gpio != NULL);
525 EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
526
527 GPIO->P_CLR[gpio->port].DOUT = 1UL << gpio->pin;
528 }
529
530 /***************************************************************************//**
531 * Set bits in DOUT register for a port to 0.
532 *
533 * @param[in] port The GPIO port to access.
534 * @param[in] pins Bit mask for bits to clear in DOUT register.
535 ******************************************************************************/
sl_hal_gpio_clear_port(sl_gpio_port_t port,uint32_t pins)536 __INLINE void sl_hal_gpio_clear_port(sl_gpio_port_t port,
537 uint32_t pins)
538 {
539 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
540
541 GPIO->P_CLR[port].DOUT = pins;
542 }
543
544 /***************************************************************************//**
545 * Read the pad value for a single pin in a GPIO port.
546 *
547 * @param[in] gpio Pointer to GPIO structure with port and pin.
548 *
549 * @return The pin value, 0 or 1.
550 ******************************************************************************/
sl_hal_gpio_get_pin_input(const sl_gpio_t * gpio)551 __INLINE bool sl_hal_gpio_get_pin_input(const sl_gpio_t *gpio)
552 {
553 EFM_ASSERT(gpio != NULL);
554 EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
555
556 bool pin_input = ((GPIO->P[gpio->port].DIN) >> gpio->pin) & 1UL;
557
558 return pin_input;
559 }
560
561 /***************************************************************************//**
562 * Get current setting for a pin in a GPIO port data out register.
563 *
564 * @param[in] gpio Pointer to GPIO structure with port and pin.
565 *
566 * @return The DOUT setting for the requested pin, 0 or 1.
567 ******************************************************************************/
sl_hal_gpio_get_pin_output(const sl_gpio_t * gpio)568 __INLINE bool sl_hal_gpio_get_pin_output(const sl_gpio_t *gpio)
569 {
570 EFM_ASSERT(gpio != NULL);
571 EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
572
573 bool pin_output = ((GPIO->P[gpio->port].DOUT) >> gpio->pin) & 1UL;
574
575 return pin_output;
576 }
577
578 /***************************************************************************//**
579 * Read the pad values for GPIO port.
580 *
581 * @param[in] port The GPIO port to access.
582 *
583 * @return The pad values for the GPIO port.
584 ******************************************************************************/
sl_hal_gpio_get_port_input(sl_gpio_port_t port)585 __INLINE uint32_t sl_hal_gpio_get_port_input(sl_gpio_port_t port)
586 {
587 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
588
589 return GPIO->P[port].DIN;
590 }
591
592 /***************************************************************************//**
593 * Get current setting for a GPIO port data out register.
594 *
595 * @param[in] port The GPIO port to access.
596 *
597 * @return The data out setting for the requested port.
598 ******************************************************************************/
sl_hal_gpio_get_port_output(sl_gpio_port_t port)599 __INLINE uint32_t sl_hal_gpio_get_port_output(sl_gpio_port_t port)
600 {
601 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
602
603 return GPIO->P[port].DOUT;
604 }
605
606 /***************************************************************************//**
607 * Toggle a single pin in GPIO port data out register.
608 *
609 * @param[in] gpio Pointer to GPIO structure with port and pin.
610 ******************************************************************************/
sl_hal_gpio_toggle_pin(const sl_gpio_t * gpio)611 __INLINE void sl_hal_gpio_toggle_pin(const sl_gpio_t *gpio)
612 {
613 EFM_ASSERT(gpio != NULL);
614 EFM_ASSERT(SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin));
615
616 GPIO->P_TGL[gpio->port].DOUT = 1UL << gpio->pin;
617 }
618
619 /***************************************************************************//**
620 * Toggle pins in GPIO port data out register.
621 *
622 * @param[in] port The GPIO port to access.
623 * @param[in] pins Bit mask with pins to toggle.
624 ******************************************************************************/
sl_hal_gpio_toggle_port(sl_gpio_port_t port,uint32_t pins)625 __INLINE void sl_hal_gpio_toggle_port(sl_gpio_port_t port,
626 uint32_t pins)
627 {
628 EFM_ASSERT(SL_HAL_GPIO_PORT_IS_VALID(port));
629
630 GPIO->P_TGL[port].DOUT = pins;
631 }
632
633 /***************************************************************************//**
634 * Enable one or more GPIO interrupts.
635 *
636 * @param[in] flags GPIO interrupt sources to enable.
637 ******************************************************************************/
sl_hal_gpio_enable_interrupts(uint32_t flags)638 __INLINE void sl_hal_gpio_enable_interrupts(uint32_t flags)
639 {
640 GPIO->IEN_SET = flags;
641 }
642
643 /***************************************************************************//**
644 * Disable one or more GPIO interrupts.
645 *
646 * @param[in] flags GPIO interrupt sources to disable.
647 ******************************************************************************/
sl_hal_gpio_disable_interrupts(uint32_t flags)648 __INLINE void sl_hal_gpio_disable_interrupts(uint32_t flags)
649 {
650 GPIO->IEN_CLR = flags;
651 }
652
653 /***************************************************************************//**
654 * Clear one or more pending GPIO interrupts.
655 *
656 * @param[in] flags Bitwise logic OR of GPIO interrupt sources to clear.
657 ******************************************************************************/
sl_hal_gpio_clear_interrupts(uint32_t flags)658 __INLINE void sl_hal_gpio_clear_interrupts(uint32_t flags)
659 {
660 GPIO->IF_CLR = flags;
661 }
662
663 /**************************************************************************//**
664 * Set one or more pending GPIO interrupts from SW.
665 *
666 * @param[in] flags GPIO interrupt sources to set to pending.
667 *****************************************************************************/
sl_hal_gpio_set_interrupts(uint32_t flags)668 __INLINE void sl_hal_gpio_set_interrupts(uint32_t flags)
669 {
670 GPIO->IF_SET = flags;
671 }
672
673 /***************************************************************************//**
674 * Get pending GPIO interrupts.
675 *
676 * @return GPIO interrupt sources pending.
677 ******************************************************************************/
sl_hal_gpio_get_pending_interrupts(void)678 __INLINE uint32_t sl_hal_gpio_get_pending_interrupts(void)
679 {
680 return GPIO->IF;
681 }
682
683 /***************************************************************************//**
684 * Get enabled GPIO interrupts.
685 *
686 * @return Enabled GPIO interrupt sources.
687 ******************************************************************************/
sl_hal_gpio_get_enabled_interrupts(void)688 __INLINE uint32_t sl_hal_gpio_get_enabled_interrupts(void)
689 {
690 return GPIO->IEN;
691 }
692
693 /***************************************************************************//**
694 * Get enabled and pending GPIO interrupt flags.
695 *
696 * @return Enabled and pending interrupt sources.
697 *
698 * @note Useful for handling more interrupt sources in the same interrupt handler.
699 ******************************************************************************/
sl_hal_gpio_get_enabled_pending_interrupts(void)700 __INLINE uint32_t sl_hal_gpio_get_enabled_pending_interrupts(void)
701 {
702 uint32_t tmp;
703
704 tmp = GPIO->IEN;
705
706 return GPIO->IF & tmp;
707 }
708
709 /***************************************************************************//**
710 * The available external interrupt number getter.
711 *
712 * @param[in] pin The GPIO pin to access.
713 * @param[in] enabled_interrupts_mask Contains enabled GPIO interrupts mask.
714 *
715 * @return The available interrupt number based on interrupt and pin grouping.
716 ******************************************************************************/
sl_hal_gpio_get_external_interrupt_number(uint8_t pin,uint32_t enabled_interrupts_mask)717 __INLINE int32_t sl_hal_gpio_get_external_interrupt_number(uint8_t pin,
718 uint32_t enabled_interrupts_mask)
719 {
720 uint32_t interrupt_to_check;
721 uint32_t int_group_start = (pin & 0xFFC);
722 int32_t int_no = -1;
723 // loop through the interrupt group, starting
724 // from the pin number, and take
725 // the first available.
726 for (uint8_t i = 0; i < 4; i++) {
727 interrupt_to_check = int_group_start + ((pin + i) & 0x3); // modulo 4
728 if (((enabled_interrupts_mask >> interrupt_to_check) & 0x1) == 0) {
729 int_no = interrupt_to_check;
730 break;
731 }
732 }
733 return int_no;
734 }
735
736 /***************************************************************************//**
737 * The available em4 wakeup interrupt number getter.
738 *
739 * @param[in] gpio Pointer to GPIO structure with port and pin.
740 *
741 * @return The available em4 wakeup interrupt number based on associated port and pin.
742 ******************************************************************************/
sl_hal_gpio_get_em4_interrupt_number(const sl_gpio_t * gpio)743 __INLINE int32_t sl_hal_gpio_get_em4_interrupt_number(const sl_gpio_t *gpio)
744 {
745 EFM_ASSERT(gpio != NULL);
746 int32_t em4_int_no;
747
748 if (false) {
749 // Check all the EM4WU Pins and check if given port, pin matches any of them.
750 #if defined(GPIO_EM4WU0_PORT)
751 } else if (GPIO_EM4WU0_PORT == gpio->port && GPIO_EM4WU0_PIN == gpio->pin) {
752 em4_int_no = 0;
753 #endif
754 #if defined(GPIO_EM4WU1_PORT)
755 } else if (GPIO_EM4WU1_PORT == gpio->port && GPIO_EM4WU1_PIN == gpio->pin) {
756 em4_int_no = 1;
757 #endif
758 #if defined(GPIO_EM4WU3_PORT)
759 } else if (GPIO_EM4WU3_PORT == gpio->port && GPIO_EM4WU3_PIN == gpio->pin) {
760 em4_int_no = 3;
761 #endif
762 #if defined(GPIO_EM4WU4_PORT)
763 } else if (GPIO_EM4WU4_PORT == gpio->port && GPIO_EM4WU4_PIN == gpio->pin) {
764 em4_int_no = 4;
765 #endif
766 #if defined(GPIO_EM4WU6_PORT)
767 } else if (GPIO_EM4WU6_PORT == gpio->port && GPIO_EM4WU6_PIN == gpio->pin) {
768 em4_int_no = 6;
769 #endif
770 #if defined(GPIO_EM4WU7_PORT)
771 } else if (GPIO_EM4WU7_PORT == gpio->port && GPIO_EM4WU7_PIN == gpio->pin) {
772 em4_int_no = 7;
773 #endif
774 #if defined(GPIO_EM4WU8_PORT)
775 } else if (GPIO_EM4WU8_PORT == gpio->port && GPIO_EM4WU8_PIN == gpio->pin) {
776 em4_int_no = 8;
777 #endif
778 #if defined(GPIO_EM4WU9_PORT)
779 } else if (GPIO_EM4WU9_PORT == gpio->port && GPIO_EM4WU9_PIN == gpio->pin) {
780 em4_int_no = 9;
781 #endif
782 #if defined(GPIO_EM4WU10_PORT)
783 } else if (GPIO_EM4WU10_PORT == gpio->port && GPIO_EM4WU10_PIN == gpio->pin) {
784 em4_int_no = 10;
785 #endif
786 } else {
787 em4_int_no = -1;
788 }
789
790 return em4_int_no;
791 }
792
793 /*************************************************************************//**
794 * Disable GPIO pin wake-up from EM4.
795 *
796 * @param[in] pinmask Bit mask containing the bitwise logic OR of which GPIO pin(s) to disable.
797 *****************************************************************************/
sl_hal_gpio_disable_pin_em4_wakeup(uint32_t pinmask)798 __INLINE void sl_hal_gpio_disable_pin_em4_wakeup(uint32_t pinmask)
799 {
800 EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0UL);
801
802 GPIO->EM4WUEN &= ~pinmask;
803 }
804
805 /**************************************************************************//**
806 * Enable GPIO pin retention of output enable, output value, pull enable, and
807 * pull direction in EM4.
808 *
809 * @note The behavior of this function depends on the configured GPIO retention mode.
810 * If the GPIO retention mode is configured to be "SWUNLATCH" then this
811 * function will not change anything. If the retention mode is anything else
812 * then this function will set the GPIO retention mode to "EM4EXIT" when the
813 * enable argument is true, and "Disabled" when false.
814 *
815 * @param[in] enable true - enable EM4 pin retention.
816 * false - disable EM4 pin retention.
817 *****************************************************************************/
sl_hal_gpio_set_pin_em4_retention(bool enable)818 __INLINE void sl_hal_gpio_set_pin_em4_retention(bool enable)
819 {
820 // Leave configuration alone when software unlatch is used.
821 uint32_t mode = EMU->EM4CTRL & _EMU_EM4CTRL_EM4IORETMODE_MASK;
822
823 if (mode == EMU_EM4CTRL_EM4IORETMODE_SWUNLATCH) {
824 return;
825 }
826
827 if (enable) {
828 EMU->EM4CTRL = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4IORETMODE_MASK)
829 | EMU_EM4CTRL_EM4IORETMODE_EM4EXIT;
830 } else {
831 EMU->EM4CTRL = (EMU->EM4CTRL & ~_EMU_EM4CTRL_EM4IORETMODE_MASK)
832 | EMU_EM4CTRL_EM4IORETMODE_DISABLE;
833 }
834 }
835
836 /**************************************************************************//**
837 * Check which GPIO pin(s) that caused a wake-up from EM4.
838 *
839 * @return Bit mask containing the bitwise logic OR of which GPIO pin(s) caused the wake-up.
840 *****************************************************************************/
sl_hal_gpio_get_pin_em4_wakeup_cause(void)841 __INLINE uint32_t sl_hal_gpio_get_pin_em4_wakeup_cause(void)
842 {
843 return GPIO->IF & _GPIO_EM4WUEN_EM4WUEN_MASK;
844 }
845
846 /***************************************************************************//**
847 * Enable/Disable serial wire output pin.
848 *
849 * @note Enabling this pin is not sufficient to fully enable serial wire output,
850 * which is also dependent on issues outside the GPIO module.
851 * @note If debug port is locked, SWO pin is not disabled automatically. To avoid
852 * information leakage through SWO, disable SWO pin after locking debug port.
853 *
854 * @param[in] enable false - disable serial wire viewer pin (default after reset).
855 * true - enable serial wire viewer pin.
856 ******************************************************************************/
sl_hal_gpio_enable_debug_swo(bool enable)857 __INLINE void sl_hal_gpio_enable_debug_swo(bool enable)
858 {
859 uint32_t bit = enable ? 0x1UL : 0x0UL;
860
861 if (bit != 0U) {
862 GPIO->TRACEROUTEPEN_SET = 1UL << _GPIO_TRACEROUTEPEN_SWVPEN_SHIFT;
863 } else {
864 GPIO->TRACEROUTEPEN_CLR = 1UL << _GPIO_TRACEROUTEPEN_SWVPEN_SHIFT;
865 }
866 }
867
868 /***************************************************************************//**
869 * Enable/disable serial wire clock pin.
870 *
871 * @note Disabling SWDClk will disable the debug interface, which may result in
872 * a lockout if done early in startup (before debugger is able to halt core).
873 *
874 * @param[in] enable false - disable serial wire clock.
875 * true - enable serial wire clock (default after reset).
876 ******************************************************************************/
sl_hal_gpio_enable_debug_swd_clk(bool enable)877 __INLINE void sl_hal_gpio_enable_debug_swd_clk(bool enable)
878 {
879 uint32_t bit = enable ? 0x1UL : 0x0UL;
880
881 if (bit != 0U) {
882 GPIO->DBGROUTEPEN_SET = 1UL << _GPIO_DBGROUTEPEN_SWCLKTCKPEN_SHIFT;
883 } else {
884 GPIO->DBGROUTEPEN_CLR = 1UL << _GPIO_DBGROUTEPEN_SWCLKTCKPEN_SHIFT;
885 }
886 }
887
888 /***************************************************************************//**
889 * Enable/disable serial wire data I/O pin.
890 *
891 * @note Disabling SWDClk will disable the debug interface, which may result in
892 * a lockout if done early in startup (before debugger is able to halt core).
893 *
894 * @param[in] enable false - disable serial wire data pin.
895 * true - enable serial wire data pin (default after reset).
896 ******************************************************************************/
sl_hal_gpio_enable_debug_swd_io(bool enable)897 __INLINE void sl_hal_gpio_enable_debug_swd_io(bool enable)
898 {
899 uint32_t bit = enable ? 0x1UL : 0x0UL;
900
901 if (bit != 0U) {
902 GPIO->DBGROUTEPEN_SET = 1UL << _GPIO_DBGROUTEPEN_SWDIOTMSPEN_SHIFT;
903 } else {
904 GPIO->DBGROUTEPEN_CLR = 1UL << _GPIO_DBGROUTEPEN_SWDIOTMSPEN_SHIFT;
905 }
906 }
907
908 /** @} (end addtogroup gpio) */
909
910 #ifdef __cplusplus
911 }
912 #endif
913
914 #endif /* GPIO_PRESENT */
915 #endif /* SL_HAL_GPIO_H */
916