1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/include/periph/gpio_ll_irq.h
2023-02-04 11:33:44 +01:00

172 lines
6.0 KiB
C

/*
* Copyright (C) 2020 Gunar Schorcht
* 2021 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup drivers_periph_gpio_ll_irq IRQ Support in Peripheral GPIO Low-Level API
* @ingroup drivers_periph_gpio_ll
* @brief IRQ Support in Peripheral GPIO Low-Level API
*
* @warning This API is not stable yet and intended for internal use only
* as of now.
* @note This API can only be used, if the features `periph_gpio_ll_irq`
* is used. Not every MCU will implement the features required for
* this API or will have a suitable driver
* available.
*
* # Motivation
*
* The IRQ related GPIO Low-Level API is very similar to the one of @ref
* drivers_periph_gpio - however two aspects have been changed (in addition to
* using separate port and pin parameters): First, level triggered IRQs that
* many MCUs support are now exposed. (Note: They can also be trivially be
* emulated, see the STM32 implementation as example.) Second, the
* configuration of the GPIO pin and the associated IRQ have been split into
* two functions. This allows reconfiguring the trigger of an IRQ with less
* overhead. This can result in reconfiguring the IRQ trigger being less effort
* than filtering out unneeded events and hence consume power due to longer
* power saving phases.
*
* @{
* @file
* @brief IRQ Support in Peripheral GPIO Low-Level API
*
* @author Marian Buschsieweke <marian.buschsieweke@ovgu.de>
*
* @warning This API is not stable yet and intended for internal use only
* as of now.
*/
#ifndef PERIPH_GPIO_LL_IRQ_H
#define PERIPH_GPIO_LL_IRQ_H
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include "periph/gpio_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(HAVE_GPIO_IRQ_TRIG_T) || defined(DOXYGEN)
/**
* @brief Definition of possible IRQ triggers
*/
typedef enum {
GPIO_TRIGGER_EDGE_FALLING, /**< edge triggered IRQ on falling flanks only
*/
GPIO_TRIGGER_EDGE_RISING, /**< edge triggered IRQ on rising flanks only */
GPIO_TRIGGER_EDGE_BOTH, /**< edge triggered IRQ on falling *AND* rising
flanks */
GPIO_TRIGGER_LEVEL_HIGH, /**< level triggered IRQ on high input */
GPIO_TRIGGER_LEVEL_LOW /**< level triggered IRQ on low input */
} gpio_irq_trig_t;
#endif
/**
* @brief Signature of event callback function that is called on IRQs
* @param[in] arg optional context for the callback
* @warning This function is called in IRQ context
*/
typedef void (*gpio_ll_cb_t)(void *arg);
/**
* @brief Set up an IRQ for the given GPIO pin and activate it
*
* @param[in] port port the pin belongs to
* @param[in] pin number of the pin to setup IRQs on
* @param[in] trig define what triggers the IRQ
* @param[in] cb callback that is called from interrupt context
* @param[in] arg argument to be passed to the callback
*
* @pre The given GPIO pin has been initialized using
* @ref gpio_ll_init prior to this call
* @pre The trigger in @p trig is supported by the MCU
*
* @retval 0 Success
* @retval -ENOTSUP No external IRQs supported for @p port and @p pin
* @retval -EBUSY All hardware entities that monitor GPIOs and issue IRQs
* are busy monitoring other GPIOs. Call
* @ref gpio_ll_irq_off on one of those and retry.
*/
int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig,
gpio_ll_cb_t cb, void *arg);
/**
* @brief Mask IRQs on the given GPIO pin
*
* @param[in] port port the pin belongs to
* @param[in] pin number of the pin to disable IRQs on
*
* @note IRQs can be re-enabled without reconfiguration using
* @ref gpio_ll_irq_unmask
*
* If IRQs are not needed for a longer term, consider using @ref
* gpio_ll_irq_off instead.
*/
void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin);
#if MODULE_PERIPH_GPIO_LL_IRQ_UNMASK || defined(DOXYGEN)
/**
* @brief Unmask IRQs on the given GPIO pin
*
* Same as @ref gpio_ll_irq_unmask_and_clear except that IRQs that came in while
* masked are not lost.
*
* @warning On some MCUs (most notably STM32) this is impossible to implement.
* The feature `periph_gpio_ll_irq_unmask` is provided, if this
* function is available.
*
* @ref gpio_ll_irq_unmask_and_clear is a portable alternative that might suit your
* use case equally well.
*
* @param[in] port port the pin belongs to
* @param[in] pin number of the pin to unmask IRQs on
*/
void gpio_ll_irq_unmask(gpio_port_t port, uint8_t pin);
#endif
/**
* @brief Unmask IRQs on the given GPIO pin and clear pending IRQs
*
* @pre IRQs on the given pin have been previously configured via
* @ref gpio_ll_irq
* @post IRQs will be acted upon again from now on. If one or more IRQs came
* in while masked, this IRQs are silently lost.
*
* @param[in] port port the pin belongs to
* @param[in] pin number of the pin to unmask IRQs on
*/
void gpio_ll_irq_unmask_and_clear(gpio_port_t port, uint8_t pin);
/**
* @brief Disable IRQs on the given GPIO pin
*
* @post Signals on the specified pin will no longer triggers IRQs until an
* IRQ is reconfigured using @ref gpio_ll_irq
*
* @param[in] port port the pin belongs to
* @param[in] pin number of the pin disable IRQs on
*
* @note The implementation should consume power by disabling trigger
* detection on the given pin.
*
* Unlike @ref gpio_ll_irq_mask IRQs cannot be re-enabled with a call to
* @ref gpio_ll_irq_unmask.
*/
void gpio_ll_irq_off(gpio_port_t port, uint8_t pin);
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_GPIO_LL_IRQ_H */
/** @} */