1
0
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:
Marian Buschsieweke 2024-02-05 07:30:54 +00:00 committed by GitHub
commit 8bf61336a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 236 additions and 99 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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 */
};
};

View File

@ -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");
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */
};
};

View File

@ -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");
}
}

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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.

View File

@ -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)