mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/periph/gpio_ll: change gpio_ll_switch_dir API
It turns out that the feature to switch the GPIO direction quickly is not only a way to emulate open drain / open source mode for less sophisticated GPIO peripherals that do not natively support it. It also enables tri-state output (push-pull high, push-pull low, high impedance), which is useful e.g. for driven charlieplexed LEDs quickly. This changes the API by introducing a `gpio_ll_prepare_switch_dir()` function that prepares the value used to identify which pins should be switched to input or to output mode. This is useful for GPIO peripherals in which the GPIO mode register does not allocate one bit per pin (so that only the direction is given there), such as the one for STM32. This allows an STM32 implementation in which preparing the bitmask needed to modify the direction of pins is not trivial.
This commit is contained in:
parent
a1efa07c07
commit
a6b459eff3
@ -731,29 +731,39 @@ static inline uword_t gpio_ll_prepare_write(gpio_port_t port, uword_t mask,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DOXYGEN) || !defined(HAVE_GPIO_LL_PREPARE_SWITCH_DIR)
|
||||
/**
|
||||
* @brief Turn GPIO pins specified by the bitmask @p outputs to outputs
|
||||
* @brief Prepare bitmask for use with @ref gpio_ll_switch_dir_output
|
||||
* and @ref gpio_ll_switch_dir_input
|
||||
* @param[in] mask bitmask specifying the pins to switch the direction of
|
||||
*
|
||||
* @return Value to use in @ref gpio_ll_switch_dir_output or
|
||||
* @ref gpio_ll_switch_dir_input
|
||||
*/
|
||||
static inline uword_t gpio_ll_prepare_switch_dir(uword_t mask)
|
||||
{
|
||||
return mask;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Turn GPIO pins specified by @p pins (obtained from
|
||||
* @ref gpio_ll_prepare_switch_dir) to outputs
|
||||
*
|
||||
* @param[in] port GPIO port to modify
|
||||
* @param[in] outputs Bitmask specifying the GPIO pins to set in output
|
||||
* mode
|
||||
* @param[in] pins Output of @ref gpio_ll_prepare_switch_dir
|
||||
* @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);
|
||||
static inline void gpio_ll_switch_dir_output(gpio_port_t port, uword_t pins);
|
||||
|
||||
/**
|
||||
* @brief Turn GPIO pins specified by the bitmask @p inputs to inputs
|
||||
* @brief Turn GPIO pins specified by @p pins (obtained from
|
||||
* @ref gpio_ll_prepare_switch_dir) to inputs
|
||||
*
|
||||
* @param[in] port GPIO port to modify
|
||||
* @param[in] inputs Bitmask specifying the GPIO pins to set in input
|
||||
* mode
|
||||
* @param[in] pins Output of @ref gpio_ll_prepare_switch_dir
|
||||
* @pre The feature `gpio_ll_switch_dir` is available
|
||||
* @pre Each affected GPIO pin is either configured as input or as
|
||||
* push-pull output.
|
||||
@ -765,12 +775,8 @@ static inline void gpio_ll_switch_dir_output(gpio_port_t port, uword_t outputs);
|
||||
* 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);
|
||||
static inline void gpio_ll_switch_dir_input(gpio_port_t port, uword_t pins);
|
||||
|
||||
/**
|
||||
* @brief Perform a masked write operation on the I/O register of the port
|
||||
|
@ -567,9 +567,9 @@ groups:
|
||||
help: The GPIO LL driver allows switching the direction between input
|
||||
and (push-pull) output in an efficient manner. The main use case
|
||||
is bit-banging bidirectional protocols when open-drain / open-source
|
||||
mode is not supported. GPIO LL drivers for peripherals that do
|
||||
support open drain mode typically do not bother implementing this,
|
||||
even if the hardware would allow it.
|
||||
mode is not supported. Another use case is controlling GPIOs
|
||||
at high speed with three output states (high, low, high impedance),
|
||||
as e.g. needed for Charlieplexing
|
||||
|
||||
- title: Serial Interfaces
|
||||
help: Features related to serial interfaces
|
||||
|
@ -905,6 +905,7 @@ static void test_switch_dir(void)
|
||||
"===========================\n");
|
||||
|
||||
uword_t mask_out = 1U << PIN_OUT_0;
|
||||
uword_t pins_out = gpio_ll_prepare_switch_dir(mask_out);
|
||||
uword_t mask_in = 1U << PIN_IN_0;
|
||||
|
||||
/* floating input must be supported by every MCU */
|
||||
@ -924,7 +925,7 @@ static void test_switch_dir(void)
|
||||
uword_t out_state = gpio_ll_read_output(port_out);
|
||||
|
||||
/* now, switch to output mode and verify the switch */
|
||||
gpio_ll_switch_dir_output(port_out, mask_out);
|
||||
gpio_ll_switch_dir_output(port_out, pins_out);
|
||||
conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
test_passed = (conf.state == GPIO_OUTPUT_PUSH_PULL);
|
||||
printf_optional("Input pin can be switched to output (push-pull) mode: %s\n",
|
||||
@ -940,7 +941,7 @@ static void test_switch_dir(void)
|
||||
expect(test_passed);
|
||||
|
||||
/* switch back to input mode */
|
||||
gpio_ll_switch_dir_input(port_out, mask_out);
|
||||
gpio_ll_switch_dir_input(port_out, pins_out);
|
||||
/* restore out state from before the switch */
|
||||
gpio_ll_write(port_out, out_state);
|
||||
/* verify we are back at the old config */
|
||||
|
Loading…
Reference in New Issue
Block a user