mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
2a00ec13e5
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>
146 lines
3.7 KiB
C
146 lines
3.7 KiB
C
/*
|
|
* Copyright (C) 2022 Christian Amsüss
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup cpu_efm32
|
|
* @ingroup drivers_periph_gpio_ll
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Peripheral GPIO Low-Level API implementation for the EFM32 family
|
|
*
|
|
* @author Christian Amsüss <chrysn@fsfe.org>
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#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)
|
|
{
|
|
GPIO_Mode_TypeDef mode;
|
|
|
|
bool initial = conf->initial_value;
|
|
|
|
switch (conf->state) {
|
|
case GPIO_DISCONNECT:
|
|
/* ignoring pull */
|
|
mode = gpioModeDisabled;
|
|
break;
|
|
case GPIO_INPUT:
|
|
switch (conf->pull) {
|
|
case GPIO_FLOATING:
|
|
mode = gpioModeInput;
|
|
break;
|
|
case GPIO_PULL_UP:
|
|
initial = true;
|
|
mode = gpioModeInputPull;
|
|
break;
|
|
case GPIO_PULL_DOWN:
|
|
initial = false;
|
|
mode = gpioModeInputPull;
|
|
break;
|
|
default:
|
|
return -ENOTSUP;
|
|
}
|
|
break;
|
|
case GPIO_OUTPUT_PUSH_PULL:
|
|
/* ignoring pull */
|
|
mode = gpioModePushPull;
|
|
break;
|
|
case GPIO_OUTPUT_OPEN_DRAIN:
|
|
switch (conf->pull) {
|
|
case GPIO_FLOATING:
|
|
mode = gpioModeWiredAnd;
|
|
break;
|
|
case GPIO_PULL_UP:
|
|
mode = gpioModeWiredAndPullUp;
|
|
break;
|
|
default: /* including PULL_DOWN, which makes no sense here*/
|
|
return -ENOTSUP;
|
|
}
|
|
break;
|
|
case GPIO_OUTPUT_OPEN_SOURCE:
|
|
switch (conf->pull) {
|
|
case GPIO_FLOATING:
|
|
mode = gpioModeWiredOr;
|
|
break;
|
|
case GPIO_PULL_DOWN:
|
|
mode = gpioModeWiredOrPullDown;
|
|
break;
|
|
default: /* including PULL_UP, which makes no sense here*/
|
|
return -ENOTSUP;
|
|
}
|
|
break;
|
|
case GPIO_USED_BY_PERIPHERAL:
|
|
/* Needs to be configured to what the peripheral actually needs
|
|
* instead (eg. DISABLED for analog input, some output for timers and
|
|
* UARTs etc); fall-through */
|
|
default:
|
|
/* Some probably are by the hardware, but not yet by this
|
|
* implementation */
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
GPIO_PinModeSet(port, pin, mode, initial);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin)
|
|
{
|
|
memset(dest, 0, sizeof(*dest));
|
|
|
|
GPIO_Mode_TypeDef mode = GPIO_PinModeGet(port, pin);
|
|
|
|
dest->pull = GPIO_FLOATING;
|
|
|
|
switch (mode) {
|
|
case gpioModePushPull:
|
|
dest->state = GPIO_OUTPUT_PUSH_PULL;
|
|
break;
|
|
case gpioModeWiredOr:
|
|
dest->state = GPIO_OUTPUT_OPEN_SOURCE;
|
|
break;
|
|
case gpioModeWiredOrPullDown:
|
|
dest->state = GPIO_OUTPUT_OPEN_SOURCE;
|
|
dest->pull = GPIO_PULL_DOWN;
|
|
break;
|
|
case gpioModeWiredAnd:
|
|
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
|
|
break;
|
|
case gpioModeWiredAndPullUp:
|
|
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
|
|
dest->pull = GPIO_PULL_UP;
|
|
break;
|
|
case gpioModeInput:
|
|
dest->state = GPIO_INPUT;
|
|
break;
|
|
case gpioModeInputPull:
|
|
dest->state = GPIO_INPUT;
|
|
dest->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;
|
|
break;
|
|
}
|
|
|
|
dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1;
|
|
}
|