mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/periph/gpio_ll: Add API to switch direction
This adds two functions: void gpio_ll_switch_dir_output(gpio_port_t port, uword_t outputs); void gpio_ll_switch_dir_input(gpio_port_t port, uword_t inputs); The first configures GPIO pins specified by a bitmask as output, the second configures the specified pins as input. The main use case is to allow bit-banging bidirectional protocols using more basic GPIO peripherals that do not implement open drain mode, such as found e.g. on MSP430, ATmega, or SAM0. It is not intended to implement this feature on modern MCUs with sophisticated GPIO peripherals.
This commit is contained in:
parent
8bf61336a2
commit
6fb369d4fc
@ -69,13 +69,13 @@
|
||||
#ifndef PERIPH_GPIO_LL_H
|
||||
#define PERIPH_GPIO_LL_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "architecture.h"
|
||||
#include "periph_cpu.h"
|
||||
#include "periph/gpio.h"
|
||||
#include "periph_cpu.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -706,6 +706,47 @@ static inline uword_t gpio_ll_prepare_write(gpio_port_t port, uword_t mask,
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Turn GPIO pins specified by the bitmask @p outputs to outputs
|
||||
*
|
||||
* @param[in] port GPIO port to modify
|
||||
* @param[in] outputs Bitmask specifying the GPIO pins to set in output
|
||||
* mode
|
||||
* @pre The feature `gpio_ll_switch_dir` is available
|
||||
* @pre Each affected GPIO pin is either configured as input or as
|
||||
* push-pull output.
|
||||
*
|
||||
* @note This is a makeshift solution to implement bit-banging of
|
||||
* bidirectional protocols on less sophisticated GPIO peripherals
|
||||
* that do not support open drain mode.
|
||||
* @warning Use open drain mode instead, if supported.
|
||||
*/
|
||||
static inline void gpio_ll_switch_dir_output(gpio_port_t port, uword_t outputs);
|
||||
|
||||
/**
|
||||
* @brief Turn GPIO pins specified by the bitmask @p inputs to inputs
|
||||
*
|
||||
* @param[in] port GPIO port to modify
|
||||
* @param[in] inputs Bitmask specifying the GPIO pins to set in input
|
||||
* mode
|
||||
* @pre The feature `gpio_ll_switch_dir` is available
|
||||
* @pre Each affected GPIO pin is either configured as input or as
|
||||
* push-pull output.
|
||||
*
|
||||
* @warning The state of the output register may be intermixed with the
|
||||
* input configuration. Specifically, on AVR the output register
|
||||
* enables/disables the internal pull up, on SAM0 MCUs the output
|
||||
* register controls the pull resistor direction (if the pull
|
||||
* resistor is enabled). Hence, the bits in the output
|
||||
* register of the pins switched to input should be restored
|
||||
* just after this call.
|
||||
* @note This is a makeshift solution to implement bit-banging of
|
||||
* bidirectional protocols on less sophisticated GPIO peripherals
|
||||
* that do not support open drain mode.
|
||||
* @warning Use open drain mode instead, if supported.
|
||||
*/
|
||||
static inline void gpio_ll_switch_dir_input(gpio_port_t port, uword_t inputs);
|
||||
|
||||
/**
|
||||
* @brief Perform a masked write operation on the I/O register of the port
|
||||
*
|
||||
@ -786,6 +827,39 @@ static inline gpio_port_t gpio_port_pack_addr(void *addr);
|
||||
*/
|
||||
static inline void * gpio_port_unpack_addr(gpio_port_t port);
|
||||
|
||||
#ifndef DOXYGEN
|
||||
#if !MODULE_PERIPH_GPIO_LL_SWITCH_DIR
|
||||
static inline void gpio_ll_switch_dir_output(gpio_port_t port, uword_t outputs)
|
||||
{
|
||||
(void)port;
|
||||
(void)outputs;
|
||||
/* Hack: If this function is only used guarded by some
|
||||
*
|
||||
* if (IS_USED(MODULE_PERIPH_GPIO_LL_SWITCH_DIR)) {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* as intended, all calls to the following fake function will be optimized
|
||||
* due to the elimination of dead branches. If used incorrectly, a linking
|
||||
* failure will be the result. The error message will not be ideal, but a
|
||||
* compile time error is much better than a runtime error.
|
||||
*/
|
||||
extern void gpio_ll_switch_dir_output_used_but_feature_gpio_ll_switch_dir_is_not_provided(void);
|
||||
gpio_ll_switch_dir_output_used_but_feature_gpio_ll_switch_dir_is_not_provided();
|
||||
}
|
||||
|
||||
static inline void gpio_ll_switch_dir_input(gpio_port_t port, uword_t inputs)
|
||||
{
|
||||
(void)port;
|
||||
(void)inputs;
|
||||
/* Same hack as above */
|
||||
extern void gpio_ll_switch_dir_input_used_but_feature_gpio_ll_switch_dir_is_not_provided(void);
|
||||
gpio_ll_switch_dir_input_used_but_feature_gpio_ll_switch_dir_is_not_provided();
|
||||
}
|
||||
|
||||
#endif /* !MODULE_PERIPH_GPIO_LL_SWITCH_DIR */
|
||||
#endif /* !DOXYGEN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,14 +1,15 @@
|
||||
# Always use hardware features, if available
|
||||
ifneq (,$(filter periph_gpio_ll%,$(USEMODULE)))
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_disconnect
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_irq_level_triggered_high
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_input_pull_down
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_input_pull_keep
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_input_pull_up
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_irq_level_triggered_high
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_irq_level_triggered_low
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_irq_unmask
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_open_drain
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_open_drain_pull_up
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_open_source
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_open_source_pull_down
|
||||
FEATURES_OPTIONAL += periph_gpio_ll_switch_dir
|
||||
endif
|
||||
|
Loading…
Reference in New Issue
Block a user