mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #20290 from maribu/drivers/periph/gpio_ll/features
drivers/periph_gpio_ll: Fix GPIO_DISCONNECT handling and add compile time feature checks
This commit is contained in:
commit
8bf61336a2
@ -8,6 +8,7 @@ FEATURES_PROVIDED += atmega_pcint0
|
||||
FEATURES_PROVIDED += periph_eeprom
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_unmask
|
||||
|
@ -231,6 +231,16 @@ typedef enum {
|
||||
GPIO_TRIGGER_LEVEL_HIGH = 0xff, /**< not supported */
|
||||
} gpio_irq_trig_t;
|
||||
|
||||
#define HAVE_GPIO_STATE_T
|
||||
typedef enum {
|
||||
GPIO_INPUT,
|
||||
GPIO_OUTPUT_PUSH_PULL,
|
||||
GPIO_OUTPUT_OPEN_DRAIN, /**< not supported */
|
||||
GPIO_OUTPUT_OPEN_SOURCE, /**< not supported */
|
||||
GPIO_USED_BY_PERIPHERAL, /**< not supported */
|
||||
GPIO_DISCONNECT = GPIO_INPUT,
|
||||
} gpio_state_t;
|
||||
|
||||
#define HAVE_GPIO_LL_PREPARE_WRITE_ALL_PINS
|
||||
#define HAVE_GPIO_LL_PREPARE_WRITE
|
||||
|
||||
|
@ -40,7 +40,7 @@ static void _set_dir(gpio_port_t port, uint8_t pin, bool output)
|
||||
p->ddr |= 1U << pin;
|
||||
}
|
||||
else {
|
||||
p-> ddr &= ~(1U << pin);
|
||||
p->ddr &= ~(1U << pin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,8 +59,7 @@ static void _set_pull_config(gpio_port_t port, uint8_t pin, gpio_pull_t pull)
|
||||
int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
|
||||
{
|
||||
if ((conf.pull > GPIO_PULL_UP)
|
||||
|| (conf.state == GPIO_OUTPUT_OPEN_DRAIN)
|
||||
|| (conf.state == GPIO_OUTPUT_OPEN_SOURCE)) {
|
||||
|| (conf.state > GPIO_OUTPUT_PUSH_PULL)) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,13 @@ FEATURES_PROVIDED += periph_flashpage_in_address_space
|
||||
FEATURES_PROVIDED += periph_flashpage_pagewise
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_disconnect
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_down
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_source
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_source_pull_down
|
||||
FEATURES_PROVIDED += periph_rtt_set_counter
|
||||
FEATURES_PROVIDED += periph_rtt_overflow
|
||||
FEATURES_PROVIDED += periph_uart_modecfg
|
||||
|
@ -34,8 +34,8 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
|
||||
|
||||
switch (conf.state) {
|
||||
case GPIO_DISCONNECT:
|
||||
/* ignoring pull */
|
||||
mode = gpioModeDisabled;
|
||||
initial = (conf.pull == GPIO_PULL_UP);
|
||||
break;
|
||||
case GPIO_INPUT:
|
||||
switch (conf.pull) {
|
||||
@ -135,6 +135,9 @@ gpio_conf_t gpio_ll_query_conf(gpio_port_t port, uint8_t pin)
|
||||
/* Fall-through: There is no error reporting here */
|
||||
default:
|
||||
result.state = GPIO_DISCONNECT;
|
||||
if (GPIO_PinOutGet(port, pin)) {
|
||||
result.pull = GPIO_PULL_UP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -22,9 +22,14 @@ FEATURES_PROVIDED += periph_flashpage
|
||||
FEATURES_PROVIDED += periph_flashpage_in_address_space
|
||||
FEATURES_PROVIDED += periph_flashpage_pagewise
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_disconnect
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_down
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain_pull_up
|
||||
FEATURES_PROVIDED += periph_spi_reconfigure
|
||||
FEATURES_PROVIDED += puf_sram
|
||||
|
||||
|
@ -5,9 +5,13 @@ FEATURES_PROVIDED += periph_clic
|
||||
FEATURES_PROVIDED += periph_gpio
|
||||
FEATURES_PROVIDED += periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_disconnect
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_down
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain
|
||||
FEATURES_PROVIDED += periph_rtc
|
||||
FEATURES_PROVIDED += periph_rtc_mem
|
||||
FEATURES_PROVIDED += periph_rtt
|
||||
|
@ -239,7 +239,7 @@ typedef union gpio_conf_gd32v gpio_conf_t;
|
||||
* @ingroup drivers_periph_gpio_ll
|
||||
*/
|
||||
union gpio_conf_gd32v {
|
||||
uint16_t bits; /**< the raw bits */
|
||||
uint8_t bits; /**< the raw bits */
|
||||
struct {
|
||||
/**
|
||||
* @brief State of the pin
|
||||
@ -259,18 +259,6 @@ union gpio_conf_gd32v {
|
||||
* configured to @ref GPIO_OUTPUT_PUSH_PULL or @ref GPIO_OUTPUT_OPEN_DRAIN.
|
||||
*/
|
||||
gpio_slew_t slew_rate : 2;
|
||||
/**
|
||||
* @brief Whether to disable the input Schmitt trigger
|
||||
*
|
||||
* @details This could be called `schmitt_trigger` with inverse
|
||||
* meaning, but the API contract says that additional
|
||||
* members in the structure should have a sane
|
||||
* default when zero.
|
||||
*
|
||||
* This value is ignored *unless* @ref gpio_conf_stm32::state is
|
||||
* configured to @ref GPIO_INPUT.
|
||||
*/
|
||||
bool schmitt_trigger_disabled : 1;
|
||||
/**
|
||||
* @brief Initial value of the output
|
||||
*
|
||||
@ -285,7 +273,6 @@ union gpio_conf_gd32v {
|
||||
* consulted.
|
||||
*/
|
||||
bool initial_value : 1;
|
||||
uint8_t : 7; /*< padding */
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -60,7 +60,6 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
|
||||
|
||||
switch (conf.state) {
|
||||
case GPIO_DISCONNECT:
|
||||
*ctrl |= 0x1 << (pos + 2);
|
||||
pin_used[GPIO_PORT_NUM(port)] &= ~(1 << pin);
|
||||
if (pin_used[GPIO_PORT_NUM(port)] == 0) {
|
||||
periph_clk_dis(APB2, (RCU_APB2EN_PAEN_Msk << GPIO_PORT_NUM(port)));
|
||||
@ -121,14 +120,14 @@ gpio_conf_t gpio_ll_query_conf(gpio_port_t port, uint8_t pin)
|
||||
result.state = GPIO_INPUT;
|
||||
switch (ctrl) {
|
||||
case 0:
|
||||
result.state = GPIO_USED_BY_PERIPHERAL;
|
||||
result.state = GPIO_DISCONNECT;
|
||||
break;
|
||||
case 1:
|
||||
result.pull = GPIO_FLOATING;
|
||||
break;
|
||||
case 2:
|
||||
result.pull = (((GPIO_Type *)port)->OCTL & (1UL << pin)) ? GPIO_PULL_UP
|
||||
: GPIO_PULL_DOWN;
|
||||
: GPIO_PULL_DOWN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -173,8 +172,4 @@ void gpio_ll_print_conf(gpio_conf_t conf)
|
||||
gpio_ll_print_conf_common(conf);
|
||||
print_str(", slew: ");
|
||||
print_str(slew_strs[conf.slew_rate]);
|
||||
|
||||
if (conf.schmitt_trigger_disabled) {
|
||||
print_str(", Schmitt trigger disabled");
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,16 @@ FEATURES_PROVIDED += periph_uart_modecfg
|
||||
FEATURES_PROVIDED += periph_wdt periph_wdt_cb
|
||||
|
||||
ifeq (,$(filter nrf5340_app,$(CPU_MODEL)))
|
||||
FEATURES_PROVIDED += periph_gpio_ll periph_gpio_ll_irq periph_gpio_ll_irq_unmask
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_disconnect
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_down
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_unmask
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_source
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_source_pull_down
|
||||
endif
|
||||
|
||||
# nRF9160/nRF5340 don't support these drivers right now
|
||||
|
@ -14,6 +14,9 @@ FEATURES_PROVIDED += periph_flashpage_pagewise
|
||||
FEATURES_PROVIDED += periph_flashpage_rwee
|
||||
FEATURES_PROVIDED += periph_gpio periph_gpio_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_disconnect
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_down
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low
|
||||
|
@ -13,9 +13,17 @@ FEATURES_PROVIDED += periph_rtt_overflow
|
||||
FEATURES_PROVIDED += periph_uart_modecfg
|
||||
FEATURES_PROVIDED += periph_uart_nonblocking
|
||||
FEATURES_PROVIDED += periph_gpio_ll
|
||||
FEATURES_PROVIDED += periph_gpio_ll_disconnect
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_down
|
||||
FEATURES_PROVIDED += periph_gpio_ll_input_pull_up
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_high
|
||||
FEATURES_PROVIDED += periph_gpio_ll_irq_level_triggered_low
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain
|
||||
|
||||
ifneq (f1,$(CPU_FAM))
|
||||
FEATURES_PROVIDED += periph_gpio_ll_open_drain_pull_up
|
||||
endif
|
||||
|
||||
ifneq (,$(filter $(CPU_FAM),c0 f0 f1 f3 g0 g4 l0 l1 l4 l5 u5 wb wl))
|
||||
FEATURES_PROVIDED += periph_flashpage
|
||||
|
@ -102,14 +102,33 @@ typedef enum {
|
||||
GPIO_TRIGGER_LEVEL_LOW = GPIO_TRIGGER_LEVEL | GPIO_TRIGGER_EDGE_FALLING,
|
||||
} gpio_irq_trig_t;
|
||||
|
||||
/**
|
||||
* @brief Possible modes to write to the STM32 GPIOx MODER register
|
||||
*/
|
||||
typedef enum {
|
||||
GPIOX_MODER_INPUT = 0x0, /**< Pin is used as input (reset value) */
|
||||
GPIOX_MODER_OUTPUT = 0x1, /**< Pin is used as output */
|
||||
GPIOX_MODER_AF = 0x2, /**< Pin is routed to peripheral (alternate function) */
|
||||
GPIOX_MODER_ANALOG = 0x3, /**< Pin is in analog mode (least current leakage) */
|
||||
} gpiox_moder_t;
|
||||
|
||||
/**
|
||||
* @brief Check if gpio_state_t requires open drain mode
|
||||
*/
|
||||
#define GPIO_STATE_T_OPEN_DRAIN_FLAG 0x4
|
||||
/**
|
||||
* @brief Bitmask to extract moder config
|
||||
*/
|
||||
#define GPIO_STATE_T_MODER_Msk 0x3
|
||||
|
||||
#define HAVE_GPIO_STATE_T
|
||||
typedef enum {
|
||||
GPIO_OUTPUT_PUSH_PULL,
|
||||
GPIO_OUTPUT_OPEN_DRAIN,
|
||||
GPIO_OUTPUT_OPEN_SOURCE,
|
||||
GPIO_INPUT,
|
||||
GPIO_USED_BY_PERIPHERAL,
|
||||
GPIO_DISCONNECT,
|
||||
GPIO_INPUT = GPIOX_MODER_INPUT,
|
||||
GPIO_OUTPUT_PUSH_PULL = GPIOX_MODER_OUTPUT,
|
||||
GPIO_OUTPUT_OPEN_DRAIN = GPIOX_MODER_OUTPUT | GPIO_STATE_T_OPEN_DRAIN_FLAG,
|
||||
GPIO_USED_BY_PERIPHERAL = GPIOX_MODER_AF,
|
||||
GPIO_DISCONNECT = GPIOX_MODER_ANALOG,
|
||||
GPIO_OUTPUT_OPEN_SOURCE = 0x7, /**< not supported */
|
||||
} gpio_state_t;
|
||||
|
||||
#define HAVE_GPIO_PULL_T
|
||||
@ -130,7 +149,7 @@ typedef union gpio_conf_stm32 gpio_conf_t;
|
||||
* @ingroup drivers_periph_gpio_ll
|
||||
*/
|
||||
union gpio_conf_stm32 {
|
||||
uint16_t bits; /**< the raw bits */
|
||||
uint8_t bits; /**< the raw bits */
|
||||
struct {
|
||||
/**
|
||||
* @brief State of the pin
|
||||
@ -150,18 +169,6 @@ union gpio_conf_stm32 {
|
||||
* configured to @ref GPIO_OUTPUT_PUSH_PULL or @ref GPIO_OUTPUT_OPEN_DRAIN.
|
||||
*/
|
||||
gpio_slew_t slew_rate : 2;
|
||||
/**
|
||||
* @brief Whether to disable the input Schmitt trigger
|
||||
*
|
||||
* @details This could be called `schmitt_trigger` with inverse
|
||||
* meaning, but the API contract says that additional
|
||||
* members in the structure should have a sane
|
||||
* default when zero.
|
||||
*
|
||||
* This value is ignored *unless* @ref gpio_conf_stm32::state is
|
||||
* configured to @ref GPIO_INPUT.
|
||||
*/
|
||||
bool schmitt_trigger_disabled : 1;
|
||||
/**
|
||||
* @brief Initial value of the output
|
||||
*
|
||||
@ -176,7 +183,6 @@ union gpio_conf_stm32 {
|
||||
* consulted.
|
||||
*/
|
||||
bool initial_value : 1;
|
||||
uint8_t : 7; /*< padding */
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -77,6 +77,22 @@ static inline void print_str(const char *str)
|
||||
# define GPIOAEN RCC_APB2ENR_IOPAEN
|
||||
#endif
|
||||
|
||||
/* Bitmask to extract a mode field of the mode register "MODER".
|
||||
* Note: Some families provide both, hence #elif */
|
||||
#ifdef GPIO_MODER_MODER0_Msk
|
||||
# define MODE_Msk GPIO_MODER_MODER0_Msk
|
||||
#elif GPIO_MODER_MODE0_Msk
|
||||
# define MODE_Msk GPIO_MODER_MODE0_Msk
|
||||
#endif
|
||||
|
||||
/* Number of bits a mode field in the mode register "MODER" is wide.
|
||||
* Note: Some families provide both, hence #elif */
|
||||
#ifdef GPIO_MODER_MODER1_Pos
|
||||
# define MODE_BITS GPIO_MODER_MODER1_Pos
|
||||
#elif GPIO_MODER_MODE1_Pos
|
||||
# define MODE_BITS GPIO_MODER_MODE1_Pos
|
||||
#endif
|
||||
|
||||
static void _init_clock(gpio_port_t port)
|
||||
{
|
||||
periph_clk_en(GPIO_BUS, (GPIOAEN << GPIO_PORT_NUM(port)));
|
||||
@ -90,14 +106,12 @@ static void _init_clock(gpio_port_t port)
|
||||
}
|
||||
|
||||
#if defined(GPIO_MODER_MODER0) || defined(GPIO_MODER_MODE0)
|
||||
static void _set_dir(gpio_port_t port, uint8_t pin, bool output)
|
||||
static void _set_mode(gpio_port_t port, uint8_t pin, gpiox_moder_t mode)
|
||||
{
|
||||
GPIO_TypeDef *p = (void *)port;
|
||||
uint32_t tmp = p->MODER;
|
||||
tmp &= ~(0x3 << (2 * pin));
|
||||
if (output) {
|
||||
tmp |= 1UL << (2 * pin);
|
||||
}
|
||||
tmp &= ~(MODE_Msk << (MODE_BITS * pin));
|
||||
tmp |= (unsigned)mode << (MODE_BITS * pin);
|
||||
p->MODER = tmp;
|
||||
}
|
||||
#endif
|
||||
@ -107,15 +121,19 @@ static void _set_dir(gpio_port_t port, uint8_t pin, bool output)
|
||||
static gpio_state_t _get_state(gpio_port_t port, uint8_t pin)
|
||||
{
|
||||
GPIO_TypeDef *p = (void *)port;
|
||||
uint32_t moder = (p->MODER >> (2 * pin)) & 0x3UL;
|
||||
gpiox_moder_t moder = (p->MODER >> (MODE_BITS * pin)) & MODE_Msk;
|
||||
switch (moder) {
|
||||
case 0:
|
||||
case GPIOX_MODER_INPUT:
|
||||
return GPIO_INPUT;
|
||||
case 1:
|
||||
case GPIOX_MODER_OUTPUT:
|
||||
return ((p->OTYPER >> pin) & 0x1UL) ? GPIO_OUTPUT_OPEN_DRAIN
|
||||
: GPIO_OUTPUT_PUSH_PULL;
|
||||
case GPIOX_MODER_ANALOG:
|
||||
return GPIO_DISCONNECT;
|
||||
default:
|
||||
case GPIOX_MODER_AF:
|
||||
return GPIO_USED_BY_PERIPHERAL;
|
||||
}
|
||||
return GPIO_USED_BY_PERIPHERAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -333,10 +351,10 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
|
||||
_set_legacy_f1_config(port, pin, conf);
|
||||
#else
|
||||
/* modern STM32 style GPIO configuration register layout */
|
||||
_set_output_type(port, pin, conf.state == GPIO_OUTPUT_OPEN_DRAIN);
|
||||
_set_output_type(port, pin, conf.state & GPIO_STATE_T_OPEN_DRAIN_FLAG);
|
||||
_set_pull_config(port, pin, conf.pull);
|
||||
_set_slew_rate(port, pin, conf.slew_rate);
|
||||
_set_dir(port, pin, conf.state < GPIO_INPUT);
|
||||
_set_mode(port, pin, conf.state & GPIO_STATE_T_MODER_Msk);
|
||||
#endif
|
||||
irq_restore(state);
|
||||
|
||||
@ -386,8 +404,4 @@ void gpio_ll_print_conf(gpio_conf_t conf)
|
||||
gpio_ll_print_conf_common(conf);
|
||||
print_str(", slew: ");
|
||||
print_str(slew_strs[conf.slew_rate]);
|
||||
|
||||
if (conf.schmitt_trigger_disabled) {
|
||||
print_str(", Schmitt trigger disabled");
|
||||
}
|
||||
}
|
||||
|
@ -134,6 +134,8 @@ typedef enum {
|
||||
/**
|
||||
* @brief Use pin as output in push-pull configuration
|
||||
*
|
||||
* @note This is supported and implemented on all MCUs.
|
||||
*
|
||||
* | Logical Value | Electrical Behavior |
|
||||
* |:-------------- |:--------------------------------- |
|
||||
* | `0` | Low |
|
||||
@ -143,6 +145,10 @@ typedef enum {
|
||||
/**
|
||||
* @brief Use pin as output in open collector configuration
|
||||
*
|
||||
* @note The feature `periph_gpio_ll_open_drain` is used to indicate
|
||||
* support for this GPIO mode. However, it may not be available on
|
||||
* all pins.
|
||||
*
|
||||
* | Logical Value | Electrical Behavior |
|
||||
* |:-------------- |:--------------------------------- |
|
||||
* | `0` | Low |
|
||||
@ -152,13 +158,22 @@ typedef enum {
|
||||
/**
|
||||
* @brief Use pin as output in open emitter configuration
|
||||
*
|
||||
* @note The feature `periph_gpio_ll_open_source` is used to indicate
|
||||
* support for this GPIO mode. However, it may not be available on
|
||||
* all pins.
|
||||
*
|
||||
* | Logical Value | Electrical Behavior |
|
||||
* |:-------------- |:--------------------------------- |
|
||||
* | `0` | High Impedance (Disconnected) |
|
||||
* | `1` | High |
|
||||
*/
|
||||
GPIO_OUTPUT_OPEN_SOURCE,
|
||||
GPIO_INPUT, /**< Use pin as input */
|
||||
/**
|
||||
* @brief Use pin as input
|
||||
*
|
||||
* @note This is supported and implemented on all MCUs.
|
||||
*/
|
||||
GPIO_INPUT,
|
||||
/**
|
||||
* @brief The GPIO pin is used by a peripheral
|
||||
*
|
||||
@ -175,6 +190,12 @@ typedef enum {
|
||||
/**
|
||||
* @brief Disconnect pin from all peripherals
|
||||
*
|
||||
* @note This may be an alias for GPIO_INPUT when the MCU does not
|
||||
* support support disconnecting GPIO pins from the GPIO
|
||||
* peripheral. The feature `periph_gpio_ll_disconnect` indicates
|
||||
* that disconnecting pins from all peripherals (including the
|
||||
* GPIO peripheral) is supported.
|
||||
*
|
||||
* The implementation should aim to reduce power consumption of the pin
|
||||
* when this state is entered, if this is feasible. For pins where it is
|
||||
* possible and sensible, this should electrically disconnect them
|
||||
|
@ -1,4 +1,14 @@
|
||||
# Always use periph_gpio_irq_unmask, if available
|
||||
# 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_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
|
||||
endif
|
||||
|
@ -33,24 +33,33 @@ void gpio_ll_print_conf_common(const gpio_conf_t conf)
|
||||
|
||||
print_str("state: ");
|
||||
switch (conf.state) {
|
||||
case GPIO_OUTPUT_PUSH_PULL:
|
||||
print_str("out-pp");
|
||||
break;
|
||||
case GPIO_OUTPUT_OPEN_DRAIN:
|
||||
print_str("out-od");
|
||||
break;
|
||||
case GPIO_OUTPUT_OPEN_SOURCE:
|
||||
print_str("out-os");
|
||||
break;
|
||||
case GPIO_INPUT:
|
||||
print_str("in");
|
||||
break;
|
||||
case GPIO_OUTPUT_PUSH_PULL:
|
||||
print_str("out-pp");
|
||||
break;
|
||||
#if MODULE_PERIPH_GPIO_LL_OPEN_DRAIN
|
||||
case GPIO_OUTPUT_OPEN_DRAIN:
|
||||
print_str("out-od");
|
||||
break;
|
||||
#endif
|
||||
#if MODULE_PERIPH_GPIO_LL_OPEN_SOURCE
|
||||
case GPIO_OUTPUT_OPEN_SOURCE:
|
||||
print_str("out-os");
|
||||
break;
|
||||
#endif
|
||||
case GPIO_USED_BY_PERIPHERAL:
|
||||
print_str("periph");
|
||||
break;
|
||||
#if MODULE_PERIPH_GPIO_LL_DISCONNECT
|
||||
case GPIO_DISCONNECT:
|
||||
print_str("off");
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
print_str("?");
|
||||
break;
|
||||
}
|
||||
|
||||
if (conf.state != GPIO_OUTPUT_PUSH_PULL) {
|
||||
|
@ -27,3 +27,8 @@ Implementations are allowed to not electrically disconnect GPIO pins in state
|
||||
disconnected. For every MCU supported by GPIO LL so far at least some pins can
|
||||
be electrically disconnected. You might need to change the GPIO pins tested
|
||||
if the test for disconnected GPIOs being also electrically disconnected.
|
||||
|
||||
When features such as `periph_gpio_ll_pull_up` or `periph_gpio_ll_open_drain`
|
||||
are provided, this test expect those to be available on the tested pins. If
|
||||
those features are not available on all pins, suitable pins need to be
|
||||
selected for the test to pass.
|
||||
|
@ -23,13 +23,14 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "flash_utils.h"
|
||||
#include "irq.h"
|
||||
#include "modules.h"
|
||||
#include "mutex.h"
|
||||
#include "periph/gpio_ll.h"
|
||||
#include "periph/gpio_ll_irq.h"
|
||||
#include "timex.h"
|
||||
#include "time_units.h"
|
||||
#include "ztimer.h"
|
||||
#include "flash_utils.h"
|
||||
|
||||
#ifndef LOW_ROM
|
||||
#define LOW_ROM 0
|
||||
@ -125,22 +126,15 @@ static void print_conf(gpio_conf_t conf)
|
||||
puts("");
|
||||
}
|
||||
|
||||
static void test_gpio_ll_init(void)
|
||||
static void test_gpio_ll_init_input_configs(void)
|
||||
{
|
||||
bool is_supported;
|
||||
puts_optional("\n"
|
||||
"Testing gpip_ng_init()\n"
|
||||
"======================\n"
|
||||
"\n"
|
||||
"Testing is_gpio_port_num_valid() is true for PORT_OUT and "
|
||||
"PORT_IN:");
|
||||
expect(is_gpio_port_num_valid(PORT_IN));
|
||||
expect(is_gpio_port_num_valid(PORT_OUT));
|
||||
|
||||
puts_optional("\nTesting input configurations for PIN_IN_0:");
|
||||
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pu));
|
||||
printf_optional("Support for input with pull up: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_INPUT_PULL_UP));
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
|
||||
print_conf(conf);
|
||||
@ -150,6 +144,8 @@ static void test_gpio_ll_init(void)
|
||||
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pd));
|
||||
printf_optional("Support for input with pull down: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_INPUT_PULL_DOWN));
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
|
||||
print_conf(conf);
|
||||
@ -159,6 +155,8 @@ static void test_gpio_ll_init(void)
|
||||
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pk));
|
||||
printf_optional("Support for input with pull to bus level: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_INPUT_PULL_KEEP));
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
|
||||
print_conf(conf);
|
||||
@ -175,7 +173,11 @@ static void test_gpio_ll_init(void)
|
||||
}
|
||||
/* Support for floating inputs is mandatory */
|
||||
expect(is_supported);
|
||||
}
|
||||
|
||||
static void test_gpio_ll_init_output_configs(void)
|
||||
{
|
||||
bool is_supported;
|
||||
puts_optional("\nTesting output configurations for PIN_OUT_0:");
|
||||
{
|
||||
gpio_conf_t conf = {
|
||||
@ -188,7 +190,9 @@ static void test_gpio_ll_init(void)
|
||||
"LOW: %s\n",
|
||||
noyes[is_supported]);
|
||||
|
||||
if (is_supported) {
|
||||
/* this is mandatory */
|
||||
expect(is_supported);
|
||||
{
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
print_conf(conf);
|
||||
expect((conf.state == GPIO_OUTPUT_PUSH_PULL) && !conf.initial_value);
|
||||
@ -218,7 +222,9 @@ static void test_gpio_ll_init(void)
|
||||
"HIGH: %s\n",
|
||||
noyes[is_supported]);
|
||||
|
||||
if (is_supported) {
|
||||
/* this is mandatory */
|
||||
expect(is_supported);
|
||||
{
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
print_conf(conf);
|
||||
expect((conf.state == GPIO_OUTPUT_PUSH_PULL) && conf.initial_value);
|
||||
@ -239,6 +245,8 @@ static void test_gpio_ll_init(void)
|
||||
printf_optional("Support for output (open drain with pull up) with initial "
|
||||
"value of LOW: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_DRAIN_PULL_UP));
|
||||
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
@ -262,6 +270,8 @@ static void test_gpio_ll_init(void)
|
||||
printf_optional("Support for output (open drain with pull up) with initial "
|
||||
"value of HIGH: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_DRAIN_PULL_UP));
|
||||
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
@ -285,6 +295,8 @@ static void test_gpio_ll_init(void)
|
||||
printf_optional("Support for output (open drain) with initial value of "
|
||||
"LOW: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_DRAIN));
|
||||
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
@ -308,6 +320,8 @@ static void test_gpio_ll_init(void)
|
||||
printf_optional("Support for output (open drain) with initial value of "
|
||||
"HIGH: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_DRAIN));
|
||||
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
@ -355,6 +369,8 @@ static void test_gpio_ll_init(void)
|
||||
printf_optional("Support for output (open source) with initial value of "
|
||||
"LOW: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_SOURCE));
|
||||
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
@ -404,6 +420,8 @@ static void test_gpio_ll_init(void)
|
||||
printf_optional("Support for output (open source) with initial value of "
|
||||
"HIGH: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_SOURCE));
|
||||
|
||||
if (is_supported) {
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
@ -424,9 +442,11 @@ static void test_gpio_ll_init(void)
|
||||
};
|
||||
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
|
||||
}
|
||||
printf_optional("Support for output (open source with pull up) with initial "
|
||||
printf_optional("Support for output (open source with pull down) with initial "
|
||||
"value of HIGH: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_SOURCE_PULL_DOWN));
|
||||
|
||||
if (is_supported) {
|
||||
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
|
||||
@ -443,9 +463,11 @@ static void test_gpio_ll_init(void)
|
||||
};
|
||||
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
|
||||
}
|
||||
printf_optional("Support for output (open source with pull up) with initial "
|
||||
printf_optional("Support for output (open source with pull down) with initial "
|
||||
"value of LOW: %s\n",
|
||||
noyes[is_supported]);
|
||||
/* check if this matches compile time checks */
|
||||
expect(is_supported == IS_USED(MODULE_PERIPH_GPIO_LL_OPEN_SOURCE_PULL_DOWN));
|
||||
|
||||
if (is_supported) {
|
||||
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
|
||||
@ -453,19 +475,40 @@ static void test_gpio_ll_init(void)
|
||||
printf_optional("Output is indeed LOW: %s\n", noyes[is_supported]);
|
||||
expect(is_supported);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_gpio_ll_init(void)
|
||||
{
|
||||
bool is_supported;
|
||||
puts_optional("\n"
|
||||
"Testing gpip_ng_init()\n"
|
||||
"======================\n"
|
||||
"\n"
|
||||
"Testing is_gpio_port_num_valid() is true for PORT_OUT and "
|
||||
"PORT_IN:");
|
||||
expect(is_gpio_port_num_valid(PORT_IN));
|
||||
expect(is_gpio_port_num_valid(PORT_OUT));
|
||||
|
||||
/* first, iterate through input configurations and test them one by one */
|
||||
test_gpio_ll_init_input_configs();
|
||||
|
||||
/* second, iterate through output configurations and test them */
|
||||
test_gpio_ll_init_output_configs();
|
||||
|
||||
/* finally, test disconnecting pins */
|
||||
{
|
||||
gpio_conf_t conf = {
|
||||
.state = GPIO_DISCONNECT,
|
||||
};
|
||||
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
|
||||
}
|
||||
printf_optional("Support for disconnecting GPIO: %s\n", noyes[is_supported]);
|
||||
printf_optional("\nSupport for disconnecting GPIO: %s\n", noyes[is_supported]);
|
||||
/* This is mandatory */
|
||||
expect(is_supported);
|
||||
|
||||
/* Ensure that gpio_ll_query_conf() correctly detects the state as
|
||||
* disconnected. */
|
||||
* disconnected. On MCUs that don't support this (e.g. ATmega),
|
||||
* GPIO_DISCONNECT must be an alias of GPIO_INPUT. */
|
||||
{
|
||||
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
|
||||
gpio_ll_print_conf(conf);
|
||||
@ -808,17 +851,15 @@ static void test_irq_level(void)
|
||||
|
||||
static void test_irq(void)
|
||||
{
|
||||
if (IS_USED(MODULE_PERIPH_GPIO_LL_IRQ)) {
|
||||
puts_optional("\n"
|
||||
"Testing External IRQs\n"
|
||||
"=====================\n");
|
||||
puts_optional("\n"
|
||||
"Testing External IRQs\n"
|
||||
"=====================\n");
|
||||
|
||||
expect(0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in));
|
||||
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, gpio_ll_out));
|
||||
expect(0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in));
|
||||
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, gpio_ll_out));
|
||||
|
||||
test_irq_edge();
|
||||
test_irq_level();
|
||||
}
|
||||
test_irq_edge();
|
||||
test_irq_level();
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
Loading…
Reference in New Issue
Block a user