Initial commit of firmware
This commit is contained in:
521
Libs/platform/driver/gpio/inc/sl_gpio.h
Normal file
521
Libs/platform/driver/gpio/inc/sl_gpio.h
Normal file
@@ -0,0 +1,521 @@
|
||||
/***************************************************************************//**
|
||||
* @file
|
||||
* @brief General Purpose IO (GPIO) driver API
|
||||
*******************************************************************************
|
||||
* # License
|
||||
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* SPDX-License-Identifier: Zlib
|
||||
*
|
||||
* The licensor of this software is Silicon Laboratories Inc.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SL_GPIO_H
|
||||
#define SL_GPIO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "sl_status.h"
|
||||
#include "sl_device_gpio.h"
|
||||
|
||||
#ifndef EM_GPIO_H
|
||||
#define gpioPortA 0
|
||||
#define gpioPortB 1
|
||||
#define gpioPortC 2
|
||||
#define gpioPortD 3
|
||||
#define gpioPortE 4
|
||||
#define gpioPortF 5
|
||||
#define gpioPortG 6
|
||||
#define gpioPortH 7
|
||||
#define gpioPortI 8
|
||||
#define gpioPortJ 9
|
||||
#define gpioPortK 10
|
||||
#endif
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
// *****************************************************************************
|
||||
/// @addtogroup gpio GPIO - General Purpose Input Output
|
||||
/// @brief General Purpose Input Output driver
|
||||
///
|
||||
/// @li @ref gpio_intro
|
||||
///
|
||||
///@n @section gpio_intro Introduction
|
||||
/// This module contains functions to control the GPIO peripheral of Silicon Labs 32-bit MCUs and SoCs.
|
||||
/// The GPIO driver is used for external and EM4 interrupt configuration, port and pin configuration.
|
||||
/// as well as manages the interrupt handler.
|
||||
///
|
||||
/// @{
|
||||
// *****************************************************************************
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*******************************************************************************
|
||||
******************************** ENUMS ************************************
|
||||
******************************************************************************/
|
||||
|
||||
/// GPIO Pin directions.
|
||||
SL_ENUM(sl_gpio_pin_direction_t) {
|
||||
/// Input direction.
|
||||
SL_GPIO_PIN_DIRECTION_IN = 0,
|
||||
/// Output direction.
|
||||
SL_GPIO_PIN_DIRECTION_OUT
|
||||
};
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* STRUCTS ***********************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Structure for GPIO port and pin configuration.
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
sl_gpio_mode_t mode;
|
||||
sl_gpio_pin_direction_t direction;
|
||||
} sl_gpio_pin_config_t;
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* TYPEDEFS **********************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* GPIO interrupt callback function pointer.
|
||||
*
|
||||
* @param int_no The pin interrupt number to which the callback function is invoked for.
|
||||
* @param context Pointer to callback context.
|
||||
******************************************************************************/
|
||||
typedef void (*sl_gpio_irq_callback_t)(uint8_t int_no, void *context);
|
||||
|
||||
/*******************************************************************************
|
||||
***************************** PROTOTYPES **********************************
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* Initialization of GPIO driver module.
|
||||
*
|
||||
* @return SL_STATUS_OK if initialization is successful.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_init(void);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets the pin direction of GPIO pin.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
* @param[in] pin_dir Pin direction of GPIO pin.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMATER if any of the port, pin, direction parameters are invalid.
|
||||
* SL_STATUS_INVALID_STATE if GPIO configuration is in lock state.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin_direction(const sl_gpio_t *gpio,
|
||||
sl_gpio_pin_direction_t pin_dir);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Set the pin mode and set/clear the pin for GPIO pin.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
* @param[in] mode The desired pin mode.
|
||||
* @param[in] output_value Value to set/clear for pin output on the port.
|
||||
* Determines the pull-up/pull-down direction of the pin for
|
||||
* some input mode configurations.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if any of the port, pin, mode parameters are invalid.
|
||||
* SL_STATUS_INVALID_STATE if GPIO configuration is in locked state.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin_mode(const sl_gpio_t *gpio,
|
||||
sl_gpio_mode_t mode,
|
||||
bool output_value);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the current configuration selected pin on selected port.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
* @param[out] pin_config Pointer to pin configuration such as mode and direction.
|
||||
* Pointer acts as an output and returns the configuration of
|
||||
* selected pin on selected port.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if any of the port, pin parameters are invalid.
|
||||
* SL_STATUS_NULL_POINTER if pin_config is passed as null.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_pin_config(const sl_gpio_t *gpio,
|
||||
sl_gpio_pin_config_t *pin_config);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets the selected pin of the selected port.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin(const sl_gpio_t *gpio);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Clears the selected pin of the selected port.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_clear_pin(const sl_gpio_t *gpio);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Toggles the state of selected pin on selected port.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_toggle_pin(const sl_gpio_t *gpio);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the output state of selected pin on selected port.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
* @param[out] pin_value Pointer to return output state of selected pin on selected port
|
||||
* when configured to output mode.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
|
||||
* SL_STATUS_NULL_POINTER if pin_value passed as null.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_pin_output(const sl_gpio_t *gpio,
|
||||
bool *pin_value);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the input state of selected pin on selected port.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
* @param[out] pin_value Pointer to return input state of selected pin on selected port
|
||||
* when configured to input mode.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMATER if any of the port, pin parameters are invalid.
|
||||
* SL_STATUS_NULL_POINTER if pin_value passed as null.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_pin_input(const sl_gpio_t *gpio,
|
||||
bool *pin_value);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets the selected pin(s) of selected port.
|
||||
*
|
||||
* @param[in] port The GPIO port to access.
|
||||
* @param[in] pins Bit mask for pins to set.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if port is invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_port(sl_gpio_port_t port,
|
||||
uint32_t pins);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Clears the selected pin(s) of selected port.
|
||||
*
|
||||
* @param[in] port The GPIO Port to access.
|
||||
* @param[in] pins Bit mask for bits to clear.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if port is invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_clear_port(sl_gpio_port_t port,
|
||||
uint32_t pins);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the output state of pins of selected port.
|
||||
*
|
||||
* @param[in] gpio The GPIO Port to access.
|
||||
* @param[out] port_value Pointer to return output state of pins on selected port.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if port is invalid.
|
||||
* SL_STATUS_NULL_POINTER if port_value passed as null.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_port_output(sl_gpio_port_t port,
|
||||
uint32_t *port_value);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the input state of pins of selected port.
|
||||
*
|
||||
* @param[in] gpio The GPIO Port to access.
|
||||
* @param[out] port_value Pointer to return output state of pins on selected port.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if port is invalid.
|
||||
* SL_STATUS_NULL_POINTER if port_value passed as null.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_port_input(sl_gpio_port_t port,
|
||||
uint32_t *port_value);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Configures the GPIO pin interrupt.
|
||||
*
|
||||
* @details By default, this function can be used to register a callback which shall be called upon
|
||||
* interrupt generated for a given pin interrupt number and enables interrupt.
|
||||
* This function configures and enables the external interrupt and performs
|
||||
* callback registration.
|
||||
* It is recommended to use sl_gpio_deconfigure_external_interrupt()
|
||||
* to disable the interrupt and unregister the callback.
|
||||
* see @ref sl_gpio_deconfigure_external_interrupt for more information.
|
||||
* If a valid interrupt number is provided, operation will proceed accordingly.
|
||||
* Otherwise, a valid interrupt number will be generated based on provided port and
|
||||
* pin and used for subsequent operations.
|
||||
*
|
||||
* @note If the user has a valid interrupt number to provide as input, it can be used.
|
||||
* If the user does not have an interrupt number, they can pass -1 (SL_GPIO_INTERRUPT_UNAVAILABLE)
|
||||
* as value to variable int_no.
|
||||
* The int_no parameter serves even as an output, a pointer to convey the interrupt number
|
||||
* for cases where user lacks an interrupt number.
|
||||
* @note the pin number can be selected freely within a group.
|
||||
* Interrupt numbers are divided into 4 groups (int_no / 4) and valid pin
|
||||
* number within the interrupt groups are:
|
||||
* 0: pins 0-3 (interrupt number 0-3)
|
||||
* 1: pins 4-7 (interrupt number 4-7)
|
||||
* 2: pins 8-11 (interrupt number 8-11)
|
||||
* 3: pins 12-15 (interrupt number 12-15)
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
* @param[in/out] int_no Pointer to interrupt number to trigger.
|
||||
* Pointer that serves as both an input and an output to return int_no
|
||||
* when the user lacks an int_no.
|
||||
* @param[in] flags Interrupt flags for interrupt configuration.
|
||||
* Determines the interrupt to get trigger based on rising/falling edge.
|
||||
* @param[in] gpio_callback A pointer to gpio callback function.
|
||||
* @param[in] context A pointer to the callback context.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if any of the port, pin, flag parameters are invalid.
|
||||
* SL_STATUS_NULL_POINTER if the int_no is passed as NULL.
|
||||
* SL_STATUS_NOT_FOUND if there's no available interrupt number.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
|
||||
int32_t *int_no,
|
||||
sl_gpio_interrupt_flag_t flags,
|
||||
sl_gpio_irq_callback_t gpio_callback,
|
||||
void *context);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Deconfigures the GPIO external pin interrupt.
|
||||
*
|
||||
* @details This function can be used to deconfigure the external GPIO interrupt.
|
||||
* This function performs callback unregistration, clears and disables the
|
||||
* given interrupt.
|
||||
*
|
||||
* @note the pin number can be selected freely within a group.
|
||||
* Interrupt numbers are divided into 4 groups (int_no / 4) and valid pin
|
||||
* number within the interrupt groups are:
|
||||
* 0: pins 0-3 (interrupt number 0-3)
|
||||
* 1: pins 4-7 (interrupt number 4-7)
|
||||
* 2: pins 8-11 (interrupt number 8-11)
|
||||
* 3: pins 12-15 (interrupt number 12-15)
|
||||
*
|
||||
* @param[in] int_no Interrupt number to unregister and disable.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if int_no is invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_deconfigure_external_interrupt(int32_t int_no);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Enables one or more GPIO Interrupts.
|
||||
*
|
||||
* @param[in] int_mask Mask for GPIO Interrupt sources to enable.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_enable_interrupts(uint32_t int_mask);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Disables one or more GPIO Interrupts.
|
||||
*
|
||||
* @param[in] int_mask Mask for GPIO Interrupt sources to disable.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_disable_interrupts(uint32_t int_mask);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Configuration EM4WU pins as external level-sensitive interrupts.
|
||||
*
|
||||
* @details By default, this function performs callback registration, enables GPIO pin wake-up from EM4,
|
||||
* sets the wake-up polarity, enables GPIO pin retention and enables the EM4 wake-up interrupt.
|
||||
* It is recommended to use sl_gpio_deconfigure_wakeup_em4_interrupt()
|
||||
* to unregister the callback and disable the em4 interrupt as well as GPIO pin wake-up from EM4.
|
||||
* It is recommended to use sl_gpio_set_pin_em4_retention() to enable/disable the GPIO pin retention.
|
||||
* see @ref sl_gpio_deconfigure_wakeup_em4_interrupt() and @ref sl_gpio_set_pin_em4_retention().
|
||||
* If a valid EM4 wake-up interrupt number is provided, operation will proceed accordingly.
|
||||
* Otherwise, a valid EM4 interrupt number will be generated based on provided EM4 configured
|
||||
* port and pin and used for subsequent operations.
|
||||
*
|
||||
* @note If the user has a valid em4 interrupt number to provide as input, it can be used.
|
||||
* If the user does not have an interrupt number, they can pass -1 (SL_GPIO_INTERRUPT_UNAVAILABLE)
|
||||
* as value to variable em4_int_no.
|
||||
* The em4_int_no parameter serves even as an output, a pointer to convey the em4 interrupt number
|
||||
* for cases where user lacks an em4 interrupt number.
|
||||
* @note There are specific ports and pins mapped to an existent EM4WU interrupt
|
||||
* Each EM4WU signal is connected to a fixed pin and port.
|
||||
* Based on chip, EM4 wake up interrupts configured port and pin might vary.
|
||||
*
|
||||
* @param[in] gpio Pointer to GPIO structure with port and pin
|
||||
* @param[in/out] em4_int_no Pointer to interrupt number to trigger.
|
||||
* Pointer that serves as both an input and an output to return em4_int_no
|
||||
* when the user lacks an em4_int_no.
|
||||
* @param[in] polarity Determines the wakeup polarity.
|
||||
* true = Active high level-sensitive interrupt.
|
||||
* false = Active low level-sensitive interrupt.
|
||||
* @param[in] gpio_callback A pointer to callback.
|
||||
* @param[in] context A pointer to callback context.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if any of the port, pin parameters are invalid.
|
||||
* SL_STATUS_NULL_POINTER if the int_no is passed as NULL.
|
||||
* SL_STATUS_NOT_FOUND if there's no available interrupt number.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_configure_wakeup_em4_interrupt(const sl_gpio_t *gpio,
|
||||
int32_t *em4_int_no,
|
||||
bool polarity,
|
||||
sl_gpio_irq_callback_t gpio_callback,
|
||||
void *context);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Utilize this function to deconfigure the EM4 GPIO pin interrupt.
|
||||
* It serves to unregister a callback, disable/clear interrupt and clear em4 wakeup source.
|
||||
*
|
||||
* @details This function performs callback unregistration, clears and disables given em4
|
||||
* interrupt and disables GPIO pin wake-up from EM4.
|
||||
*
|
||||
* @param[in] em4_int_no EM4 wakeup interrupt number.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if em4_int_no is invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_deconfigure_wakeup_em4_interrupt(int32_t em4_int_no);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Enable EM4 GPIO pin Wake-up bit.
|
||||
* Sets the wakeup and polarity of the EM4 wakeup.
|
||||
*
|
||||
* @param[in] em4_int_mask Mask for setting desired EM4 wake up interrupt to enable.
|
||||
* Mask contains the bitwise logic OR of which EM4 wake up interrupt to
|
||||
* enable.
|
||||
* @param[in] em4_polarity_mask Mask for setting the wake up polarity for the EM4 wake up interrupt.
|
||||
* Mask contains the bitwise logic OR of EM4 wake-up interrupt polarity.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_enable_pin_em4_wakeup(uint32_t em4_int_mask,
|
||||
uint32_t em4_polarity_mask);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Disabled the GPIO wake up from EM4.
|
||||
*
|
||||
* @param[in] pinmask Mask for clearing desired EM4 wake up interrupt to disable.
|
||||
* Mask contains the bitwise logic OR of which EM4 wake up interrupt to
|
||||
* disable.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_disable_pin_em4_wakeup(uint32_t em4_int_mask);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Enable/Disable GPIO pin retention of output enable, output value, pull enable, and pull direction in EM4.
|
||||
*
|
||||
* @param[in] enable true - enables EM4 pin retention.
|
||||
* false - disables EM4 pin retention.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin_em4_retention(bool enable);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets slewrate for selected port.
|
||||
*
|
||||
* @param[in] port The GPIO port to configure.
|
||||
* @param[in] slewrate The slewrate to configure the GPIO port.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if port is invalid.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_slew_rate(sl_gpio_port_t port,
|
||||
uint8_t slewrate);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets slewrate for selected port.
|
||||
*
|
||||
* @param[in] port The GPIO port to get slewrate.
|
||||
* @param[out] slewrate Pointer to store the slewrate of selected port.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_INVALID_PARAMETER if port is invalid.
|
||||
* SL_STATUS_NULL_POINTER if slewrate is passed as null.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_slew_rate(sl_gpio_port_t port,
|
||||
uint8_t *slewrate);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Locks the GPIO Configuration.
|
||||
*
|
||||
* @note This API locks the functionalities such as sl_gpio_set_pin_mode(),
|
||||
* sl_gpio_configure_external_interrupt() and sl_gpio_configure_wakeup_em4_interrupt().
|
||||
* After locking the GPIO configuration, use sl_gpio_unlock API to unlock
|
||||
* the GPIO configuration to use mentioned functionalities.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_lock(void);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Unlocks the GPIO Configuration.
|
||||
*
|
||||
* @note After locking the GPIO configuration it is recommended to unlock the GPIO configuration
|
||||
* using sl_gpio_unlock(). You can determine if the GPIO configuration is locked or unlocked
|
||||
* by using the sl_gpio_is_locked() function.
|
||||
* Before using certain functions like sl_gpio_set_pin_mode(),
|
||||
* sl_gpio_configure_external_interrupt(), and sl_gpio_configure_wakeup_em4_interrupt(),
|
||||
* it's important to check if the GPIO configuration lock is unlocked.
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_unlock(void);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets current GPIO Lock status.
|
||||
*
|
||||
* @note This function helps check the current status of GPIO configuration.
|
||||
*
|
||||
* @param[out] state Pointer to current state of GPIO configuration (lock/unlock).
|
||||
*
|
||||
* @return SL_STATUS_OK if there's no error.
|
||||
* SL_STATUS_NULL_POINTER if state is passed as null.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_is_locked(bool *state);
|
||||
|
||||
/** @} (end addtogroup gpio driver) */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SL_GPIO_H */
|
||||
824
Libs/platform/driver/gpio/src/sl_gpio.c
Normal file
824
Libs/platform/driver/gpio/src/sl_gpio.c
Normal file
@@ -0,0 +1,824 @@
|
||||
/***************************************************************************//**
|
||||
* @file
|
||||
* @brief General Purpose IO (GPIO) driver API
|
||||
*******************************************************************************
|
||||
* # License
|
||||
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* SPDX-License-Identifier: Zlib
|
||||
*
|
||||
* The licensor of this software is Silicon Laboratories Inc.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "sl_core.h"
|
||||
#include "sl_common.h"
|
||||
#include "sl_interrupt_manager.h"
|
||||
#include "sl_clock_manager.h"
|
||||
#include "sl_hal_gpio.h"
|
||||
#include "sl_gpio.h"
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* DEFINES ***********************************
|
||||
******************************************************************************/
|
||||
|
||||
/// Define for supporting gpiointerrupt porting
|
||||
#define SL_GPIO_PORT_INTERRUPT (0xFF)
|
||||
|
||||
/// Pin direction validation.
|
||||
#define SL_GPIO_DIRECTION_IS_VALID(direction) (direction <= SL_GPIO_PIN_DIRECTION_OUT)
|
||||
|
||||
/*******************************************************************************
|
||||
******************************* STRUCTS ***********************************
|
||||
******************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
// Pin interrupt number in range 0 to 15.
|
||||
uint32_t int_no;
|
||||
// Pointer to callback function.
|
||||
void *callback;
|
||||
// Pointer to callback context.
|
||||
void *context;
|
||||
} sl_gpio_callback_desc_t;
|
||||
|
||||
typedef struct {
|
||||
// An array of user callbacks for external interrupts.
|
||||
// We have external interrupts configured from 0 to 15 bits.
|
||||
sl_gpio_callback_desc_t callback_ext[SL_HAL_GPIO_INTERRUPT_MAX];
|
||||
// An array of user callbacks for EM4 interrupts.
|
||||
// We have EM4 interrupts configured from 16 to 31 bits.
|
||||
sl_gpio_callback_desc_t callback_em4[SL_HAL_GPIO_INTERRUPT_MAX];
|
||||
} sl_gpio_callbacks_t;
|
||||
|
||||
/*******************************************************************************
|
||||
******************************** GLOBALS **********************************
|
||||
******************************************************************************/
|
||||
|
||||
// Variable to manage and organize the callback functions for External and EM4 interrupts.
|
||||
static sl_gpio_callbacks_t gpio_interrupts = { 0 };
|
||||
|
||||
/*******************************************************************************
|
||||
****************************** LOCAL FUCTIONS *****************************
|
||||
******************************************************************************/
|
||||
static void sl_gpio_dispatch_interrupt(uint32_t iflags);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Driver GPIO Initialization.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_init()
|
||||
{
|
||||
sl_clock_manager_enable_bus_clock(SL_BUS_CLOCK_GPIO);
|
||||
|
||||
if (sl_interrupt_manager_is_irq_disabled(GPIO_ODD_IRQn)) {
|
||||
sl_interrupt_manager_clear_irq_pending(GPIO_ODD_IRQn);
|
||||
sl_interrupt_manager_enable_irq(GPIO_ODD_IRQn);
|
||||
}
|
||||
if (sl_interrupt_manager_is_irq_disabled(GPIO_EVEN_IRQn)) {
|
||||
sl_interrupt_manager_clear_irq_pending(GPIO_EVEN_IRQn);
|
||||
sl_interrupt_manager_enable_irq(GPIO_EVEN_IRQn);
|
||||
}
|
||||
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets the pin direction for GPIO pin.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin_direction(const sl_gpio_t *gpio,
|
||||
sl_gpio_pin_direction_t pin_direction)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin) || !SL_GPIO_DIRECTION_IS_VALID(pin_direction)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (sl_hal_gpio_get_lock_status() != 0) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_STATE;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
if (pin_direction == SL_GPIO_PIN_DIRECTION_OUT) {
|
||||
sl_hal_gpio_set_pin_mode(gpio, SL_GPIO_MODE_PUSH_PULL, 1);
|
||||
} else if (pin_direction == SL_GPIO_PIN_DIRECTION_IN) {
|
||||
sl_hal_gpio_set_pin_mode(gpio, SL_GPIO_MODE_INPUT, 0);
|
||||
}
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets the mode for GPIO pin and pin direction.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin_mode(const sl_gpio_t *gpio,
|
||||
sl_gpio_mode_t mode,
|
||||
bool output_value)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_MODE_IS_VALID(mode) || !SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (sl_hal_gpio_get_lock_status() != 0) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_STATE;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_set_pin_mode(gpio, mode, output_value);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the current configuration selected pin on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_pin_config(const sl_gpio_t *gpio,
|
||||
sl_gpio_pin_config_t *pin_config)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL || pin_config == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
pin_config->mode = sl_hal_gpio_get_pin_mode(gpio);
|
||||
switch (pin_config->mode) {
|
||||
case SL_GPIO_MODE_INPUT:
|
||||
case SL_GPIO_MODE_INPUT_PULL:
|
||||
case SL_GPIO_MODE_INPUT_PULL_FILTER:
|
||||
pin_config->direction = SL_GPIO_PIN_DIRECTION_IN;
|
||||
break;
|
||||
|
||||
case SL_GPIO_MODE_DISABLED:
|
||||
case SL_GPIO_MODE_PUSH_PULL:
|
||||
case SL_GPIO_MODE_PUSH_PULL_ALTERNATE:
|
||||
case SL_GPIO_MODE_WIRED_OR:
|
||||
case SL_GPIO_MODE_WIRED_OR_PULL_DOWN:
|
||||
case SL_GPIO_MODE_WIRED_AND:
|
||||
case SL_GPIO_MODE_WIRED_AND_FILTER:
|
||||
case SL_GPIO_MODE_WIRED_AND_PULLUP:
|
||||
case SL_GPIO_MODE_WIRED_AND_PULLUP_FILTER:
|
||||
case SL_GPIO_MODE_WIRED_AND_ALTERNATE:
|
||||
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_FILTER:
|
||||
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP:
|
||||
case SL_GPIO_MODE_WIRED_AND_ALTERNATE_PULLUP_FILTER:
|
||||
pin_config->direction = SL_GPIO_PIN_DIRECTION_OUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
CORE_EXIT_ATOMIC();
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_MODE;
|
||||
}
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets the DOUT of selected pin on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin(const sl_gpio_t *gpio)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_set_pin(gpio);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Clears the DOUT of selected pin on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_clear_pin(const sl_gpio_t *gpio)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_clear_pin(gpio);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Toggles the DOUT of selected pin on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_toggle_pin(const sl_gpio_t *gpio)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_toggle_pin(gpio);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the output state of selected pin on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_pin_output(const sl_gpio_t *gpio,
|
||||
bool *pin_value)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL || pin_value == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
*pin_value = sl_hal_gpio_get_pin_output(gpio);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the input state of selected pin on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_pin_input(const sl_gpio_t *gpio,
|
||||
bool *pin_value)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL || pin_value == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
*pin_value = sl_hal_gpio_get_pin_input(gpio);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets the selected pin(s) on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_port(sl_gpio_port_t port,
|
||||
uint32_t pins)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_set_port(port, pins);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Clears the selected pin on selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_clear_port(sl_gpio_port_t port,
|
||||
uint32_t pins)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_clear_port(port, pins);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the output state of pins of selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_port_output(sl_gpio_port_t port,
|
||||
uint32_t *port_value)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (port_value == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
*port_value = sl_hal_gpio_get_port_output(port);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the input state of pins of selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_port_input(sl_gpio_port_t port,
|
||||
uint32_t *port_value)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (port_value == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
*port_value = sl_hal_gpio_get_port_input(port);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Configuring the GPIO external pin interrupt.
|
||||
* This API can be used to configure interrupt and to register the callback.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_configure_external_interrupt(const sl_gpio_t *gpio,
|
||||
int32_t *int_no,
|
||||
sl_gpio_interrupt_flag_t flags,
|
||||
sl_gpio_irq_callback_t gpio_callback,
|
||||
void *context)
|
||||
{
|
||||
uint32_t enabled_interrupts;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL || int_no == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin) && (gpio->port != SL_GPIO_PORT_INTERRUPT)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (!SL_GPIO_FLAG_IS_VALID(flags)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
|
||||
*int_no = sl_hal_gpio_configure_external_interrupt(gpio, *int_no, flags);
|
||||
}
|
||||
|
||||
if (*int_no == SL_GPIO_INTERRUPT_UNAVAILABLE && gpio->port == SL_GPIO_PORT_INTERRUPT) {
|
||||
enabled_interrupts = sl_hal_gpio_get_enabled_interrupts();
|
||||
*int_no = sl_hal_gpio_get_external_interrupt_number(gpio->pin, enabled_interrupts);
|
||||
}
|
||||
|
||||
if (*int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) {
|
||||
// Callback registration.
|
||||
gpio_interrupts.callback_ext[*int_no].callback = (void *)gpio_callback;
|
||||
gpio_interrupts.callback_ext[*int_no].context = context;
|
||||
|
||||
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
|
||||
sl_hal_gpio_enable_interrupts(1 << *int_no);
|
||||
}
|
||||
} else {
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Deconfigures the GPIO external pin interrupt.
|
||||
* This API can be used to deconfigure the interrupt and to unregister the callback.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_deconfigure_external_interrupt(int32_t int_no)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!((int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) && (int_no <= SL_HAL_GPIO_INTERRUPT_MAX) && (int_no >= 0))) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
// Clear pending interrupt.
|
||||
sl_hal_gpio_clear_interrupts(1 << int_no);
|
||||
sl_hal_gpio_disable_interrupts(1 << int_no);
|
||||
|
||||
// Callback deregistration.
|
||||
gpio_interrupts.callback_ext[int_no].callback = NULL;
|
||||
gpio_interrupts.callback_ext[int_no].context = NULL;
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Enables one or more GPIO interrupts.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_enable_interrupts(uint32_t flags)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_enable_interrupts(flags);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Disables one or more GPIO interrupts.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_disable_interrupts(uint32_t flags)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_disable_interrupts(flags);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Configures the EM4WU pin as external level interrupts for waking up from EM mode.
|
||||
* Registering/unregistering the callbacks and Configuring the EM4 interrupts to enable/disable
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_configure_wakeup_em4_interrupt(const sl_gpio_t *gpio,
|
||||
int32_t *em4_int_no,
|
||||
bool polarity,
|
||||
sl_gpio_irq_callback_t gpio_callback,
|
||||
void *context)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (gpio == NULL || em4_int_no == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (!SL_HAL_GPIO_PORT_PIN_IS_VALID(gpio->port, gpio->pin) && (gpio->port != SL_GPIO_PORT_INTERRUPT)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
|
||||
*em4_int_no = sl_hal_gpio_configure_wakeup_em4_external_interrupt(gpio, *em4_int_no, polarity);
|
||||
}
|
||||
|
||||
if (*em4_int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) {
|
||||
// Callback registration.
|
||||
gpio_interrupts.callback_em4[*em4_int_no].callback = (void *)gpio_callback;
|
||||
gpio_interrupts.callback_em4[*em4_int_no].context = context;
|
||||
|
||||
if (gpio->port != SL_GPIO_PORT_INTERRUPT) {
|
||||
sl_hal_gpio_enable_interrupts(1 << (*em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
|
||||
}
|
||||
} else {
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Deconfigures the EM4 GPIO pin interrupt.
|
||||
* Unregisters a callback, disable/clear interrupt and clear em4 wakeup source
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_deconfigure_wakeup_em4_interrupt(int32_t em4_int_no)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!((em4_int_no != SL_GPIO_INTERRUPT_UNAVAILABLE) && (em4_int_no <= SL_HAL_GPIO_INTERRUPT_MAX) && (em4_int_no >= 0))) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
// Clear any pending interrupt.
|
||||
sl_hal_gpio_clear_interrupts(1 << (em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
|
||||
sl_hal_gpio_disable_pin_em4_wakeup(1 << (em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
|
||||
sl_hal_gpio_disable_interrupts(1 << (em4_int_no + SL_HAL_GPIO_EM4WUEN_SHIFT));
|
||||
|
||||
/* Callback deregistration */
|
||||
gpio_interrupts.callback_em4[em4_int_no].callback = NULL;
|
||||
gpio_interrupts.callback_em4[em4_int_no].context = NULL;
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets GPIO EM4 Wake up interrupt to Enable and EM4 Wake up interrupt polarity
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_enable_pin_em4_wakeup(uint32_t em4_int_mask,
|
||||
uint32_t em4_polarity_mask)
|
||||
{
|
||||
uint32_t int_mask = 0;
|
||||
uint32_t polarity_mask = 0;
|
||||
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
// Enable EM4WU function and set polarity.
|
||||
int_mask |= (em4_int_mask << _GPIO_EM4WUEN_EM4WUEN_SHIFT);
|
||||
polarity_mask |= (em4_polarity_mask << _GPIO_EM4WUEN_EM4WUEN_SHIFT);
|
||||
sl_hal_gpio_enable_pin_em4_wakeup(int_mask, polarity_mask);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Clears GPIO EM4 Wake up enable
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_disable_pin_em4_wakeup(uint32_t em4_int_mask)
|
||||
{
|
||||
uint32_t int_mask = 0;
|
||||
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
// Disable EM4WU function.
|
||||
int_mask |= (em4_int_mask << _GPIO_EM4WUEN_EM4WUEN_SHIFT);
|
||||
sl_hal_gpio_disable_pin_em4_wakeup(int_mask);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Enable GPIO pin retention of output enable, output value, pull direction, pull enable in EM4
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_pin_em4_retention(bool enable)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_set_pin_em4_retention(enable);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Sets slewrate for selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_set_slew_rate(sl_gpio_port_t port,
|
||||
uint8_t slewrate)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
sl_hal_gpio_set_slew_rate(port, slewrate);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets slewrate for selected port.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_get_slew_rate(sl_gpio_port_t port,
|
||||
uint8_t *slewrate)
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (!SL_HAL_GPIO_PORT_IS_VALID(port)) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
if (slewrate == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
*slewrate = sl_hal_gpio_get_slew_rate(port);
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Locks the GPIO Configuration
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_lock(void)
|
||||
{
|
||||
sl_hal_gpio_lock();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Unlocks the GPIO Configuration
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_unlock(void)
|
||||
{
|
||||
sl_hal_gpio_unlock();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Gets the GPIO State
|
||||
******************************************************************************/
|
||||
sl_status_t sl_gpio_is_locked(bool *state)
|
||||
{
|
||||
uint32_t status;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if (state == NULL) {
|
||||
EFM_ASSERT(false);
|
||||
return SL_STATUS_NULL_POINTER;
|
||||
}
|
||||
|
||||
CORE_ENTER_ATOMIC();
|
||||
|
||||
status = sl_hal_gpio_get_lock_status();
|
||||
if (status) {
|
||||
// true - GPIO configuration registers are locked.
|
||||
*state = true;
|
||||
} else {
|
||||
// false - GPIO configuration registers are unlocked.
|
||||
*state = false;
|
||||
}
|
||||
|
||||
CORE_EXIT_ATOMIC();
|
||||
return SL_STATUS_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* Function calls users callback for registered pin interrupts.
|
||||
*
|
||||
* @details This function is called when GPIO interrupts are handled by the IRQHandlers.
|
||||
* Function gets even or odd interrupt flags and calls user callback
|
||||
* registered for that pin. Function iterates on flags starting from MSB.
|
||||
*
|
||||
* @param iflags Interrupt flags which shall be handled by the dispatcher.
|
||||
******************************************************************************/
|
||||
static void sl_gpio_dispatch_interrupt(uint32_t iflags)
|
||||
{
|
||||
uint32_t irq_idx;
|
||||
sl_gpio_callback_desc_t *callback;
|
||||
sl_gpio_irq_callback_t func;
|
||||
|
||||
// Check for flags set in IF register.
|
||||
while (iflags != 0) {
|
||||
irq_idx = SL_CTZ(iflags);
|
||||
iflags &= ~(1UL << irq_idx);
|
||||
|
||||
if (irq_idx <= SL_HAL_GPIO_INTERRUPT_MAX) {
|
||||
callback = &gpio_interrupts.callback_ext[irq_idx];
|
||||
} else {
|
||||
callback = &gpio_interrupts.callback_em4[irq_idx - SL_HAL_GPIO_EM4WUEN_SHIFT];
|
||||
irq_idx = irq_idx - SL_HAL_GPIO_EM4WUEN_SHIFT;
|
||||
}
|
||||
// Call user callback.
|
||||
if (callback->callback) {
|
||||
func = (sl_gpio_irq_callback_t)(callback->callback);
|
||||
func((uint8_t)irq_idx, callback->context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* GPIO EVEN interrupt handler. Interrupt handler clears all IF even flags and
|
||||
* call the dispatcher passing the flags which triggered the interrupt.
|
||||
******************************************************************************/
|
||||
void GPIO_EVEN_IRQHandler(void)
|
||||
{
|
||||
uint32_t even_flags;
|
||||
|
||||
// Gets all enabled and pending even interrupts.
|
||||
even_flags = sl_hal_gpio_get_enabled_pending_interrupts() & SL_HAL_GPIO_INT_IF_EVEN_MASK;
|
||||
// Clears only even interrupts.
|
||||
sl_hal_gpio_clear_interrupts(even_flags);
|
||||
|
||||
sl_gpio_dispatch_interrupt(even_flags);
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* GPIO ODD interrupt handler. Interrupt handler clears all IF odd flags and
|
||||
* call the dispatcher passing the flags which triggered the interrupt.
|
||||
******************************************************************************/
|
||||
void GPIO_ODD_IRQHandler(void)
|
||||
{
|
||||
uint32_t odd_flags;
|
||||
|
||||
// Gets all enabled and pending odd interrupts.
|
||||
odd_flags = sl_hal_gpio_get_enabled_pending_interrupts() & SL_HAL_GPIO_INT_IF_ODD_MASK;
|
||||
// Clears only odd interrupts.
|
||||
sl_hal_gpio_clear_interrupts(odd_flags);
|
||||
|
||||
sl_gpio_dispatch_interrupt(odd_flags);
|
||||
}
|
||||
Reference in New Issue
Block a user