1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/periph_common/gpio_ll.c
Marian Buschsieweke 2a00ec13e5
drivers/periph/gpio_ll: shrink gpio_conf_t
This commit optimizes the `gpio_conf_t` type in the following
regards:

- The "base" `gpio_conf_t` is stripped from members that only some
  platforms support, e.g. drive strength, slew rate, and disabling of
  the Schmitt Trigger are no longer universally available but
  platform-specific extensions
- The `gpio_conf_t` is now crammed into a bit-field that is 8 bit or
  16 bit wide. This allows for storing lots of them e.g. in
  `driver_foo_params_t` or `uart_conf_t` etc.
- A `union` of the `struct` with bit-field members and a `bits` is used
  to allow accessing all bits in a simple C statement and to ensure
  alignment for efficient handling of the type

Co-authored-by: Gunar Schorcht <gunar@schorcht.net>
2024-01-21 08:38:40 +01:00

125 lines
3.2 KiB
C

/*
* Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include "periph/gpio_ll.h"
/* Optimizing for low stack usage by not using printf(), which on newlib is
* prohibitively costly. This will allow developers to use this for debugging
* even in ISR - hopefully without increasing the ISR stack size.
*
* If module fmt is used, there is a stack friendly print_str() provided.
* Otherwise, fall back to fputs(), which is still way more stack friendly than
* printf().
*/
#ifdef MODULE_FMT
#include "fmt.h"
#else
static inline void print_str(const char *str)
{
fputs(str, stdout);
}
#endif
const gpio_conf_t gpio_ll_in = {
.state = GPIO_INPUT,
.pull = GPIO_FLOATING,
};
const gpio_conf_t gpio_ll_in_pd = {
.state = GPIO_INPUT,
.pull = GPIO_PULL_DOWN,
};
const gpio_conf_t gpio_ll_in_pu = {
.state = GPIO_INPUT,
.pull = GPIO_PULL_UP,
};
const gpio_conf_t gpio_ll_in_pk = {
.state = GPIO_INPUT,
.pull = GPIO_PULL_KEEP,
};
const gpio_conf_t gpio_ll_out = {
.state = GPIO_OUTPUT_PUSH_PULL,
.initial_value = false,
};
const gpio_conf_t gpio_ll_pd = {
.state = GPIO_OUTPUT_OPEN_DRAIN,
.pull = GPIO_FLOATING,
.initial_value = true,
};
const gpio_conf_t gpio_ll_pd_pu = {
.state = GPIO_OUTPUT_OPEN_DRAIN,
.pull = GPIO_PULL_UP,
.initial_value = true,
};
void gpio_ll_print_conf_common(const gpio_conf_t *conf)
{
assert(conf);
const char *off_on[] = { "off", "on" };
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_USED_BY_PERIPHERAL:
print_str("periph");
break;
case GPIO_DISCONNECT:
print_str("off");
break;
}
if (conf->state != GPIO_OUTPUT_PUSH_PULL) {
print_str(", pull: ");
switch (conf->pull) {
default:
case GPIO_FLOATING:
print_str("none");
break;
case GPIO_PULL_UP:
print_str("up");
break;
case GPIO_PULL_DOWN:
print_str("down");
break;
case GPIO_PULL_KEEP:
print_str("keep");
break;
}
}
print_str(", value: ");
print_str(off_on[conf->initial_value]);
}
/* implement gpio_ll_print_conf as weak alias symbol for
* gpio_ll_print_conf_common - so that platform specific implementations can
* override gpio_ll_print_conf while reusing gpio_ll_print_conf_common()
*/
__attribute__((weak, alias("gpio_ll_print_conf_common")))
void gpio_ll_print_conf(const gpio_conf_t *conf);