Skip to content

Commit

Permalink
Merge pull request #20236 from maribu/periph/gpio_ll/smaller_type
Browse files Browse the repository at this point in the history
drivers/periph/gpio_ll: shrink gpio_conf_t
  • Loading branch information
maribu authored Jan 21, 2024
2 parents 504c169 + 9222762 commit 3d1f651
Show file tree
Hide file tree
Showing 19 changed files with 762 additions and 510 deletions.
8 changes: 0 additions & 8 deletions cpu/atmega_common/include/periph_cpu_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,6 @@ typedef enum {
GPIO_TRIGGER_LEVEL_HIGH = 0xff, /**< not supported */
} gpio_irq_trig_t;

#define HAVE_GPIO_PULL_T
typedef enum {
GPIO_FLOATING = 0,
GPIO_PULL_UP = 1,
GPIO_PULL_DOWN = 0xfe, /*< not supported */
GPIO_PULL_KEEP = 0xff, /*< not supported */
} gpio_pull_t;

#define HAVE_GPIO_LL_PREPARE_WRITE_ALL_PINS
#define HAVE_GPIO_LL_PREPARE_WRITE

Expand Down
37 changes: 17 additions & 20 deletions cpu/atmega_common/periph/gpio_ll.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,45 +56,42 @@ static void _set_pull_config(gpio_port_t port, uint8_t pin, gpio_pull_t pull)
p->port |= pull << pin;
}

int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
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)) {
if ((conf.pull > GPIO_PULL_UP)
|| (conf.state == GPIO_OUTPUT_OPEN_DRAIN)
|| (conf.state == GPIO_OUTPUT_OPEN_SOURCE)) {
return -ENOTSUP;
}

unsigned state = irq_disable();
if (conf->initial_value) {
if (conf.initial_value) {
gpio_ll_set(port, 1UL << pin);
}
else {
gpio_ll_clear(port, 1UL << pin);
}
_set_dir(port, pin, conf->state == GPIO_OUTPUT_PUSH_PULL);
if (conf->state == GPIO_INPUT) {
_set_pull_config(port, pin, conf->pull);
_set_dir(port, pin, conf.state == GPIO_OUTPUT_PUSH_PULL);
if (conf.state == GPIO_INPUT) {
_set_pull_config(port, pin, conf.pull);
}
irq_restore(state);

return 0;
}

void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin)
gpio_conf_t gpio_ll_query_conf(gpio_port_t port, uint8_t pin)
{
assert(dest);
memset(dest, 0, sizeof(*dest));
/* E.g. the schematics in figure 14-5 in the ATmega328P datasheet shows that
* a Schmitt Trigger is always connected before the digital input signal.
* Let's assume this is also true for all other ATmegas */
dest->schmitt_trigger = true;
gpio_conf_t result = { 0 };
if (_is_output(port, pin)) {
dest->state = GPIO_OUTPUT_PUSH_PULL;
dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1U;
result.state = GPIO_OUTPUT_PUSH_PULL;
result.initial_value = (gpio_ll_read_output(port) >> pin) & 1U;
}
else {
dest->state = GPIO_INPUT;
dest->pull = (gpio_ll_read_output(port) >> pin) & 1U;
dest->initial_value = (gpio_ll_read(port) >> pin) & 1U;
result.state = GPIO_INPUT;
result.pull = (gpio_ll_read_output(port) >> pin) & 1U;
result.initial_value = (gpio_ll_read(port) >> pin) & 1U;
}

return result;
}
56 changes: 22 additions & 34 deletions cpu/efm32/periph/gpio_ll.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,26 @@
* @}
*/

#include <assert.h>
#include <errno.h>
#include <string.h>

#include "cpu.h"
#include "periph/gpio_ll.h"
#include "periph_cpu.h"
#include "periph_conf.h"

int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
{
GPIO_Mode_TypeDef mode;

bool initial = conf->initial_value;
bool initial = conf.initial_value;

switch (conf->state) {
switch (conf.state) {
case GPIO_DISCONNECT:
/* ignoring pull */
mode = gpioModeDisabled;
break;
case GPIO_INPUT:
switch (conf->pull) {
switch (conf.pull) {
case GPIO_FLOATING:
mode = gpioModeInput;
break;
Expand All @@ -61,7 +59,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
mode = gpioModePushPull;
break;
case GPIO_OUTPUT_OPEN_DRAIN:
switch (conf->pull) {
switch (conf.pull) {
case GPIO_FLOATING:
mode = gpioModeWiredAnd;
break;
Expand All @@ -73,7 +71,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
}
break;
case GPIO_OUTPUT_OPEN_SOURCE:
switch (conf->pull) {
switch (conf.pull) {
case GPIO_FLOATING:
mode = gpioModeWiredOr;
break;
Expand All @@ -99,58 +97,48 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
return 0;
}

void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin)
gpio_conf_t gpio_ll_query_conf(gpio_port_t port, uint8_t pin)
{
memset(dest, 0, sizeof(*dest));

gpio_conf_t result = { 0 };
GPIO_Mode_TypeDef mode = GPIO_PinModeGet(port, pin);

dest->pull = GPIO_FLOATING;
result.pull = GPIO_FLOATING;

switch (mode) {
case gpioModePushPull:
dest->state = GPIO_OUTPUT_PUSH_PULL;
result.state = GPIO_OUTPUT_PUSH_PULL;
break;
case gpioModeWiredOr:
dest->state = GPIO_OUTPUT_OPEN_SOURCE;
result.state = GPIO_OUTPUT_OPEN_SOURCE;
break;
case gpioModeWiredOrPullDown:
dest->state = GPIO_OUTPUT_OPEN_SOURCE;
dest->pull = GPIO_PULL_DOWN;
result.state = GPIO_OUTPUT_OPEN_SOURCE;
result.pull = GPIO_PULL_DOWN;
break;
case gpioModeWiredAnd:
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
result.state = GPIO_OUTPUT_OPEN_DRAIN;
break;
case gpioModeWiredAndPullUp:
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
dest->pull = GPIO_PULL_UP;
result.state = GPIO_OUTPUT_OPEN_DRAIN;
result.pull = GPIO_PULL_UP;
break;
case gpioModeInput:
dest->state = GPIO_INPUT;
result.state = GPIO_INPUT;
break;
case gpioModeInputPull:
dest->state = GPIO_INPUT;
dest->pull = GPIO_PinOutGet(port, pin) ?
result.state = GPIO_INPUT;
result.pull = GPIO_PinOutGet(port, pin) ?
GPIO_PULL_UP :
GPIO_PULL_DOWN;
break;
case gpioModeDisabled:
/* Fall-through: There is no error reporting here */
default:
dest->state = GPIO_DISCONNECT;
result.state = GPIO_DISCONNECT;
break;
}

/* as good as any */
dest->slew_rate = GPIO_SLEW_FAST;

/* It's always on as long as they're in a mode in which it matters, judging
* from https://www.silabs.com/documents/public/application-notes/an0027.pdf */
dest->schmitt_trigger = true;

dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1;
result.initial_value = (gpio_ll_read_output(port) >> pin) & 1;

/* Using 'strong' her already as that fits with what the hardware has
* (lowest, low, standard, high) */
dest->drive_strength = GPIO_DRIVE_STRONG;
return result;
}
59 changes: 57 additions & 2 deletions cpu/esp32/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ typedef enum {
GPIO_FLOATING = 0,
GPIO_PULL_UP = 1,
GPIO_PULL_DOWN = 2,
GPIO_PULL_KEEP = 0xff /*< not supported */
GPIO_PULL_KEEP = 3 /*< not supported */
} gpio_pull_t;

/**
Expand All @@ -212,9 +212,64 @@ typedef enum {
#define GPIO_DRIVE_20 GPIO_DRIVE_STRONG /**< 20 mA (default) */
#define GPIO_DRIVE_30 GPIO_DRIVE_STRONGEST /**< 30 mA */

/* END: GPIO LL overwrites */
#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_state_t;

#define HAVE_GPIO_CONF_T
typedef union gpio_conf_esp32 gpio_conf_t;

#endif /* ndef DOXYGEN */

/**
* @brief GPIO pin configuration for ESP32/ESP32Cx/ESP32Sx MCUs
* @ingroup drivers_periph_gpio_ll
*/
union gpio_conf_esp32 {
uint8_t bits; /**< the raw bits */
struct {
/**
* @brief State of the pin
*/
gpio_state_t state : 3;
/**
* @brief Pull resistor configuration
*/
gpio_pull_t pull : 2;
/**
* @brief Drive strength of the GPIO
*
* @warning If the requested drive strength is not available, the closest
* fit supported will be configured instead.
*
* This value is ignored when @ref gpio_conf_esp32::state is configured
* to @ref GPIO_INPUT or @ref GPIO_DISCONNECT.
*/
gpio_drive_strength_t drive_strength : 2;
/**
* @brief Initial value of the output
*
* Ignored if @ref gpio_conf_esp32::state is set to @ref GPIO_INPUT or
* @ref GPIO_DISCONNECT. If the pin was previously in a high impedance
* state, it is guaranteed to directly transition to the given initial
* value.
*
* @ref gpio_ll_query_conf will write the current value of the specified
* pin here, which is read from the input register when the state is
* @ref GPIO_INPUT, otherwise the state from the output register is
* consulted.
*/
bool initial_value : 1;
};
};

/* END: GPIO LL overwrites */
/** @} */

/**
Expand Down
Loading

0 comments on commit 3d1f651

Please sign in to comment.