1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

drivers/periph/gpio_ll: pass gpio_conf_t by value

Now that `gpio_conf_t` is on all implemented platforms no larger than
a register, we can more efficiently pass it by value rather than via
pointer.
This commit is contained in:
Marian Buschsieweke 2024-01-19 14:44:45 +01:00
parent 718f277642
commit 922276296e
No known key found for this signature in database
GPG Key ID: 77AA882EC78084E6
13 changed files with 308 additions and 326 deletions

View File

@ -56,41 +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));
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;
}

View File

@ -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;
@ -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;
@ -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;
@ -99,47 +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;
}
dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1;
result.initial_value = (gpio_ll_read_output(port) >> pin) & 1;
return result;
}

View File

@ -80,10 +80,9 @@ const _esp32_port_t _esp32_ports[GPIO_PORT_NUMOF] = {
#endif
};
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)
{
assert(port);
assert(conf);
assert(GPIO_PORT_NUM(port) < GPIO_PORT_NUMOF);
assert(pin < GPIO_PORT_PIN_NUMOF(port));
@ -96,7 +95,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
.pull_down_en = false,
};
switch (conf->state) {
switch (conf.state) {
case GPIO_OUTPUT_PUSH_PULL:
cfg.mode = GPIO_MODE_DEF_OUTPUT;
break;
@ -113,7 +112,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
return -ENOTSUP;
}
switch (conf->pull) {
switch (conf.pull) {
case GPIO_FLOATING:
break;
case GPIO_PULL_UP:
@ -143,14 +142,14 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
_gpio_pin_pd[pin] = cfg.pull_down_en;
#endif
if (conf->state == GPIO_DISCONNECT) {
if (conf.state == GPIO_DISCONNECT) {
/* reset the pin to disconnects any other peripheral output configured
via GPIO Matrix, the pin is reconfigured according to given conf */
esp_idf_gpio_reset_pin(gpio);
}
/* since we can't read back the configuration, we have to save it */
_gpio_conf[gpio] = *conf;
_gpio_conf[gpio] = conf;
if (esp_idf_gpio_config(&cfg) != ESP_OK) {
return -ENOTSUP;
@ -158,7 +157,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
/* if output pin, try to set drive strength */
gpio_drive_cap_t strength;
switch (conf->drive_strength) {
switch (conf.drive_strength) {
case GPIO_DRIVE_WEAKEST:
strength = GPIO_DRIVE_CAP_0;
break;
@ -179,7 +178,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
return -ENOTSUP;
}
if (conf->initial_value) {
if (conf.initial_value) {
gpio_ll_set(port, 1UL << pin);
}
else {
@ -189,23 +188,25 @@ 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)
{
assert(dest);
gpio_conf_t result;
unsigned state = irq_disable();
*dest = _gpio_conf[GPIO_PIN(GPIO_PORT_NUM(port), pin)];
if (dest->state == GPIO_INPUT) {
dest->initial_value = (gpio_ll_read(port) >> pin) & 1UL;
result = _gpio_conf[GPIO_PIN(GPIO_PORT_NUM(port), pin)];
if (result.state == GPIO_INPUT) {
result.initial_value = (gpio_ll_read(port) >> pin) & 1UL;
}
else {
dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
result.initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
}
irq_restore(state);
return result;
}
void gpio_ll_print_conf(const gpio_conf_t *conf)
void gpio_ll_print_conf(gpio_conf_t conf)
{
static const char *drive_strs[] = {
[GPIO_DRIVE_WEAKEST] = "weakest",
@ -216,5 +217,5 @@ void gpio_ll_print_conf(const gpio_conf_t *conf)
gpio_ll_print_conf_common(conf);
print_str(", drive: ");
print_str(drive_strs[conf->drive_strength]);
print_str(drive_strs[conf.drive_strength]);
}

View File

@ -19,7 +19,6 @@
*/
#include <errno.h>
#include <string.h>
#include "cpu.h"
#include "bitarithm.h"
@ -39,11 +38,11 @@ static inline void print_str(const char *str)
uint16_t pin_used[GPIO_PORT_NUMOF] = {};
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_KEEP) ||
(conf->state == GPIO_OUTPUT_OPEN_SOURCE) ||
((conf->state != GPIO_INPUT) && (conf->pull != GPIO_FLOATING))) {
if ((conf.pull == GPIO_PULL_KEEP) ||
(conf.state == GPIO_OUTPUT_OPEN_SOURCE) ||
((conf.state != GPIO_INPUT) && (conf.pull != GPIO_FLOATING))) {
return -ENOTSUP;
}
@ -59,7 +58,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
/* reset configuration CTLx[1:0], MDx[1:0] (analogue, input mode) */
*ctrl &= ~(0xf << pos);
switch (conf->state) {
switch (conf.state) {
case GPIO_DISCONNECT:
*ctrl |= 0x1 << (pos + 2);
pin_used[GPIO_PORT_NUM(port)] &= ~(1 << pin);
@ -69,12 +68,12 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
break;
case GPIO_INPUT:
pin_used[GPIO_PORT_NUM(port)] |= 1 << pin;
if (conf->pull == GPIO_FLOATING) {
if (conf.pull == GPIO_FLOATING) {
*ctrl |= 0x1 << (pos + 2);
}
else {
*ctrl |= 0x2 << (pos + 2);
if (conf->pull == GPIO_PULL_UP) {
if (conf.pull == GPIO_PULL_UP) {
*octl |= 1 << pin;
}
else {
@ -85,9 +84,9 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
case GPIO_OUTPUT_PUSH_PULL:
case GPIO_OUTPUT_OPEN_DRAIN:
pin_used[GPIO_PORT_NUM(port)] |= 1 << pin;
*ctrl |= (conf->slew_rate + 1) << pos;
*ctrl |= (conf->state == GPIO_OUTPUT_OPEN_DRAIN ? 0x1 : 0x0) << (pos + 2);
if (conf->initial_value) {
*ctrl |= (conf.slew_rate + 1) << pos;
*ctrl |= (conf.state == GPIO_OUTPUT_OPEN_DRAIN ? 0x1 : 0x0) << (pos + 2);
if (conf.initial_value) {
gpio_ll_set(port, 1UL << pin);
}
else {
@ -104,14 +103,12 @@ 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)
{
assert(dest);
gpio_conf_t result = { 0 };
unsigned state = irq_disable();
memset(dest, 0, sizeof(*dest));
volatile uint32_t *ctrl_reg = (pin < 8) ? &((GPIO_Type *)port)->CTL0
: &((GPIO_Type *)port)->CTL1;
@ -121,16 +118,16 @@ void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin)
uint32_t ctrl = (*ctrl_reg >> (pos + 2)) & 0x3;
if (mode == 0) {
dest->state = GPIO_INPUT;
result.state = GPIO_INPUT;
switch (ctrl) {
case 0:
dest->state = GPIO_USED_BY_PERIPHERAL;
result.state = GPIO_USED_BY_PERIPHERAL;
break;
case 1:
dest->pull = GPIO_FLOATING;
result.pull = GPIO_FLOATING;
break;
case 2:
dest->pull = (((GPIO_Type *)port)->OCTL & (1UL << pin)) ? GPIO_PULL_UP
result.pull = (((GPIO_Type *)port)->OCTL & (1UL << pin)) ? GPIO_PULL_UP
: GPIO_PULL_DOWN;
break;
default:
@ -138,31 +135,33 @@ void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin)
}
}
else {
dest->slew_rate = mode - 1;
dest->pull = GPIO_FLOATING;
result.slew_rate = mode - 1;
result.pull = GPIO_FLOATING;
switch (ctrl) {
case 0:
dest->state = GPIO_OUTPUT_PUSH_PULL;
result.state = GPIO_OUTPUT_PUSH_PULL;
break;
case 1:
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
result.state = GPIO_OUTPUT_OPEN_DRAIN;
break;
default:
dest->state = GPIO_USED_BY_PERIPHERAL;
result.state = GPIO_USED_BY_PERIPHERAL;
break;
}
}
if (dest->state == GPIO_INPUT) {
dest->initial_value = (gpio_ll_read(port) >> pin) & 1UL;
if (result.state == GPIO_INPUT) {
result.initial_value = (gpio_ll_read(port) >> pin) & 1UL;
}
else {
dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
result.initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
}
irq_restore(state);
return result;
}
void gpio_ll_print_conf(const gpio_conf_t *conf)
void gpio_ll_print_conf(gpio_conf_t conf)
{
static const char *slew_strs[] = {
[GPIO_SLEW_SLOWEST] = "slowest",
@ -173,9 +172,9 @@ void gpio_ll_print_conf(const gpio_conf_t *conf)
gpio_ll_print_conf_common(conf);
print_str(", slew: ");
print_str(slew_strs[conf->slew_rate]);
print_str(slew_strs[conf.slew_rate]);
if (conf->schmitt_trigger_disabled) {
if (conf.schmitt_trigger_disabled) {
print_str(", Schmitt trigger disabled");
}
}

View File

@ -45,24 +45,24 @@ static inline void print_str(const char *str)
}
#endif
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_KEEP) {
if (conf.pull == GPIO_PULL_KEEP) {
return -ENOTSUP;
}
uint32_t pin_cnf = (unsigned)conf->pull << GPIO_PIN_CNF_PULL_Pos;
switch (conf->state) {
uint32_t pin_cnf = (unsigned)conf.pull << GPIO_PIN_CNF_PULL_Pos;
switch (conf.state) {
case GPIO_OUTPUT_PUSH_PULL:
/* INPUT bit needs to be *CLEARED* in input mode, so set to disconnect input buffer */
pin_cnf |= GPIO_PIN_CNF_DIR_Msk | GPIO_PIN_CNF_INPUT_Msk;
if (conf->drive_strength) {
if (conf.drive_strength) {
pin_cnf |= GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos;
}
break;
case GPIO_OUTPUT_OPEN_DRAIN:
pin_cnf |= GPIO_PIN_CNF_DIR_Msk;
if (conf->drive_strength) {
if (conf.drive_strength) {
pin_cnf |= GPIO_PIN_CNF_DRIVE_H0D1 << GPIO_PIN_CNF_DRIVE_Pos;
}
else {
@ -71,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:
pin_cnf |= GPIO_PIN_CNF_DIR_Msk;
if (conf->drive_strength) {
if (conf.drive_strength) {
pin_cnf |= GPIO_PIN_CNF_DRIVE_D0H1 << GPIO_PIN_CNF_DRIVE_Pos;
}
else {
@ -87,8 +87,8 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
break;
}
if (conf->state != GPIO_OUTPUT_PUSH_PULL) {
switch (conf->pull) {
if (conf.state != GPIO_OUTPUT_PUSH_PULL) {
switch (conf.pull) {
default:
case GPIO_FLOATING:
break;
@ -102,7 +102,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf)
}
NRF_GPIO_Type *p = (NRF_GPIO_Type *)port;
if (conf->initial_value) {
if (conf.initial_value) {
p->OUTSET = 1UL << pin;
}
else {
@ -113,18 +113,11 @@ 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)
{
assert((dest != NULL)
&& (NULL == gpio_port_unpack_addr(port))
&& (pin < 32));
memset(dest, 0, sizeof(*dest));
/* Searching "Schmitt" in
* https://infocenter.nordicsemi.com/pdf/nRF52840_OPS_v0.5.pdf yields
* no matches. Assuming Schmitt trigger cannot be disabled for the
* nRF5x MCU.
*/
dest->state = GPIO_INPUT;
gpio_conf_t result = { 0 };
assert((NULL == gpio_port_unpack_addr(port)) && (pin < 32));
result.state = GPIO_INPUT;
NRF_GPIO_Type *p = (NRF_GPIO_Type *)port;
uint32_t cnf = p->PIN_CNF[pin];
@ -142,38 +135,38 @@ void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin)
case GPIO_PIN_CNF_DRIVE_S0S1:
/* standard drive 0, standard drive 1
* --> push pull with weak drive */
dest->state = GPIO_OUTPUT_PUSH_PULL;
dest->drive_strength = GPIO_DRIVE_WEAK;
result.state = GPIO_OUTPUT_PUSH_PULL;
result.drive_strength = GPIO_DRIVE_WEAK;
break;
case GPIO_PIN_CNF_DRIVE_H0H1:
/* high drive 0, high drive 1
* --> push pull with high drive */
dest->state = GPIO_OUTPUT_PUSH_PULL;
dest->drive_strength = GPIO_DRIVE_STRONG;
result.state = GPIO_OUTPUT_PUSH_PULL;
result.drive_strength = GPIO_DRIVE_STRONG;
break;
case GPIO_PIN_CNF_DRIVE_S0D1:
/* standard drive 0, disconnect at 1
* --> open drain with weak drive */
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
dest->drive_strength = GPIO_DRIVE_WEAK;
result.state = GPIO_OUTPUT_OPEN_DRAIN;
result.drive_strength = GPIO_DRIVE_WEAK;
break;
case GPIO_PIN_CNF_DRIVE_H0D1:
/* high drive 0, disconnect at 1
* --> open drain with strong drive */
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
dest->drive_strength = GPIO_DRIVE_STRONG;
result.state = GPIO_OUTPUT_OPEN_DRAIN;
result.drive_strength = GPIO_DRIVE_STRONG;
break;
case GPIO_PIN_CNF_DRIVE_D0S1:
/* disconnect at 0, standard drive 1
* --> open emitter with weak drive */
dest->state = GPIO_OUTPUT_OPEN_SOURCE;
dest->drive_strength = GPIO_DRIVE_WEAK;
result.state = GPIO_OUTPUT_OPEN_SOURCE;
result.drive_strength = GPIO_DRIVE_WEAK;
break;
case GPIO_PIN_CNF_DRIVE_D0H1:
/* disconnect at 0, high drive 1
* --> open emitter with strong drive */
dest->state = GPIO_OUTPUT_OPEN_SOURCE;
dest->drive_strength = GPIO_DRIVE_STRONG;
result.state = GPIO_OUTPUT_OPEN_SOURCE;
result.drive_strength = GPIO_DRIVE_STRONG;
break;
}
}
@ -182,31 +175,33 @@ void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin)
/* input buffer is disconnected and pin is not in output mode
* --> GPIO pin is off
*/
dest->state = GPIO_DISCONNECT;
result.state = GPIO_DISCONNECT;
}
}
switch ((cnf & GPIO_PIN_CNF_PULL_Msk) >> GPIO_PIN_CNF_PULL_Pos) {
case GPIO_PIN_CNF_PULL_Pullup:
dest->pull = GPIO_PULL_UP;
result.pull = GPIO_PULL_UP;
break;
case GPIO_PIN_CNF_PULL_Pulldown:
dest->pull = GPIO_PULL_DOWN;
result.pull = GPIO_PULL_DOWN;
break;
default:
dest->pull = GPIO_FLOATING;
result.pull = GPIO_FLOATING;
break;
}
if (dest->state == GPIO_INPUT) {
dest->initial_value = (gpio_ll_read(port) >> pin) & 1UL;
if (result.state == GPIO_INPUT) {
result.initial_value = (gpio_ll_read(port) >> pin) & 1UL;
}
else {
dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
result.initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
}
return result;
}
void gpio_ll_print_conf(const gpio_conf_t *conf)
void gpio_ll_print_conf(gpio_conf_t conf)
{
static const char *drive_strs[] = {
[GPIO_DRIVE_WEAK] = "weak",
@ -215,5 +210,5 @@ void gpio_ll_print_conf(const gpio_conf_t *conf)
gpio_ll_print_conf_common(conf);
print_str(", drive: ");
print_str(drive_strs[conf->drive_strength]);
print_str(drive_strs[conf.drive_strength]);
}

View File

@ -24,7 +24,6 @@
#include <errno.h>
#include <string.h>
#include "bitarithm.h"
#include "board.h"
#include "iolist.h"
#include "macros/utils.h"
@ -33,7 +32,6 @@
#include "net/ethernet.h"
#include "net/eui_provider.h"
#include "net/netdev/eth.h"
#include "periph/gpio.h"
#include "periph/gpio_ll.h"
#include "time_units.h"
@ -487,10 +485,10 @@ static int stm32_eth_init(netdev_t *netdev)
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_init(GPIO_PORT(STM32_ETH_TRACING_TX_PORT_NUM),
STM32_ETH_TRACING_TX_PIN_NUM,
&gpio_ll_out);
gpio_ll_out);
gpio_ll_init(GPIO_PORT(STM32_ETH_TRACING_RX_PORT_NUM),
STM32_ETH_TRACING_RX_PIN_NUM,
&gpio_ll_out);
gpio_ll_out);
}
if (IS_USED(MODULE_STM32_ETH_LINK_UP)) {
_link_status_timer.callback = _timer_cb;

View File

@ -95,7 +95,7 @@ void stm32_eth_common_init(void)
if (IS_USED(MODULE_STM32_ETH_TRACING)) {
gpio_ll_init(GPIO_PORT(STM32_ETH_TRACING_IRQ_PORT_NUM),
STM32_ETH_TRACING_IRQ_PIN_NUM,
&gpio_ll_out);
gpio_ll_out);
}
if (IS_USED(MODULE_PERIPH_ETH) || IS_USED(MODULE_PERIPH_PTP_TIMER)) {

View File

@ -29,10 +29,8 @@
*/
#include <errno.h>
#include <string.h>
#include "cpu.h"
#include "bitarithm.h"
#include "periph/gpio_ll.h"
#ifdef MODULE_FMT
@ -177,7 +175,7 @@ static gpio_slew_t _get_slew_rate(gpio_port_t port, uint8_t pin)
#ifdef GPIO_CRL_MODE
static void _set_legacy_f1_config(gpio_port_t port, uint8_t pin,
const gpio_conf_t *conf)
gpio_conf_t conf)
{
/* STM32F1 style config register mix output mode and slew rate into the
* same field. This look up table can be used to look up the correct
@ -196,11 +194,11 @@ static void _set_legacy_f1_config(gpio_port_t port, uint8_t pin,
bool high_reg = pin > 7;
uint32_t control = high_reg ? p->CRH : p -> CRL;
assert((unsigned)conf->slew_rate < ARRAY_SIZE(output_mode_by_slew_rate));
assert((unsigned)conf.slew_rate < ARRAY_SIZE(output_mode_by_slew_rate));
/* prepare bis in cnf and mode fields for given pin */
uint32_t cnf_mode = 0;
switch (conf->state) {
switch (conf.state) {
default:
case GPIO_DISCONNECT:
/* Keeping GPIO in analog mode is said to reduce power consumption.
@ -209,7 +207,7 @@ static void _set_legacy_f1_config(gpio_port_t port, uint8_t pin,
cnf_mode = GPIO_CRL_MODE0_INPUT | GPIO_CRL_CNF0_INPUT_ANALOG;
break;
case GPIO_INPUT:
switch (conf->pull) {
switch (conf.pull) {
default:
case GPIO_FLOATING:
cnf_mode = GPIO_CRL_MODE0_INPUT | GPIO_CRL_CNF0_INPUT_FLOATING;
@ -231,11 +229,11 @@ static void _set_legacy_f1_config(gpio_port_t port, uint8_t pin,
break;
case GPIO_OUTPUT_PUSH_PULL:
cnf_mode = GPIO_CRL_CNF0_OUTPUT_PUSH_PULL
| output_mode_by_slew_rate[conf->slew_rate];
| output_mode_by_slew_rate[conf.slew_rate];
break;
case GPIO_OUTPUT_OPEN_DRAIN:
cnf_mode = GPIO_CRL_CNF0_OUTPUT_OPEN_DRAIN
| output_mode_by_slew_rate[conf->slew_rate];
| output_mode_by_slew_rate[conf.slew_rate];
}
/* clear old values of cnf and mode fields in config reg */
@ -250,9 +248,9 @@ static void _set_legacy_f1_config(gpio_port_t port, uint8_t pin,
p->CRL = control;
}
}
static void _get_legacy_f1_config(gpio_conf_t *dest, gpio_port_t port,
uint8_t pin)
static gpio_conf_t _get_legacy_f1_config(gpio_port_t port, uint8_t pin)
{
gpio_conf_t result = { 0 };
GPIO_TypeDef *p = (void *)port;
unsigned offset = (pin & 0x7U) << 2;
bool high_reg = pin > 7;
@ -267,62 +265,64 @@ static void _get_legacy_f1_config(gpio_conf_t *dest, gpio_port_t port,
switch (cnf) {
default:
case GPIO_CRL_CNF0_INPUT_ANALOG:
dest->state = GPIO_DISCONNECT;
result.state = GPIO_DISCONNECT;
break;
case GPIO_CRL_CNF0_INPUT_FLOATING:
dest->state = GPIO_INPUT;
result.state = GPIO_INPUT;
break;
case GPIO_CRL_CNF0_INPUT_PULL:
dest->state = GPIO_INPUT;
dest->pull = GPIO_PULL_DOWN;
result.state = GPIO_INPUT;
result.pull = GPIO_PULL_DOWN;
if (p->ODR & (1U << pin)) {
dest->pull = GPIO_PULL_UP;
result.pull = GPIO_PULL_UP;
}
}
return;
return result;
case GPIO_CRL_MODE0_OUTPUT_2MHZ:
dest->slew_rate = GPIO_SLEW_SLOWEST;
result.slew_rate = GPIO_SLEW_SLOWEST;
break;
case GPIO_CRL_MODE0_OUTPUT_10MHZ:
dest->slew_rate = GPIO_SLEW_FAST;
result.slew_rate = GPIO_SLEW_FAST;
break;
case GPIO_CRL_MODE0_OUTPUT_50MHZ:
dest->slew_rate = GPIO_SLEW_FASTEST;
result.slew_rate = GPIO_SLEW_FASTEST;
break;
}
switch (cnf) {
case GPIO_CRL_CNF0_OUTPUT_PUSH_PULL:
dest->state = GPIO_OUTPUT_PUSH_PULL;
result.state = GPIO_OUTPUT_PUSH_PULL;
break;
case GPIO_CRL_CNF0_OUTPUT_OPEN_DRAIN:
dest->state = GPIO_OUTPUT_OPEN_DRAIN;
result.state = GPIO_OUTPUT_OPEN_DRAIN;
break;
default:
case GPIO_CRL_CNF0_AF_PUSH_PULL:
case GPIO_CRL_CNF0_AF_OPEN_DRAIN:
dest->state = GPIO_USED_BY_PERIPHERAL;
result.state = GPIO_USED_BY_PERIPHERAL;
}
return result;
}
#endif
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_KEEP) || (conf->state == GPIO_OUTPUT_OPEN_SOURCE)) {
if ((conf.pull == GPIO_PULL_KEEP) || (conf.state == GPIO_OUTPUT_OPEN_SOURCE)) {
return -ENOTSUP;
}
#ifndef GPIO_PUPDR_PUPDR0
/* without dedicated pull up / pull down register, pull resistors can only
* be used with input pins */
if ((conf->state == GPIO_OUTPUT_OPEN_DRAIN) && (conf->pull != GPIO_FLOATING)) {
if ((conf.state == GPIO_OUTPUT_OPEN_DRAIN) && (conf.pull != GPIO_FLOATING)) {
return -ENOTSUP;
}
#endif
unsigned state = irq_disable();
_init_clock(port);
if (conf->initial_value) {
if (conf.initial_value) {
gpio_ll_set(port, 1UL << pin);
}
else {
@ -333,40 +333,41 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const 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_pull_config(port, pin, conf->pull);
_set_slew_rate(port, pin, conf->slew_rate);
_set_dir(port, pin, conf->state < GPIO_INPUT);
_set_output_type(port, pin, conf.state == GPIO_OUTPUT_OPEN_DRAIN);
_set_pull_config(port, pin, conf.pull);
_set_slew_rate(port, pin, conf.slew_rate);
_set_dir(port, pin, conf.state < GPIO_INPUT);
#endif
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);
gpio_conf_t result = { 0 };
unsigned state = irq_disable();
memset(dest, 0, sizeof(*dest));
#ifdef GPIO_CRL_MODE
/* old STM32F1 style GPIO configuration register layout */
_get_legacy_f1_config(dest, port, pin);
result = _get_legacy_f1_config(port, pin);
#else
/* modern STM32 style GPIO configuration register layout */
dest->state = _get_state(port, pin);
dest->pull = _get_pull_config(port, pin);
dest->slew_rate = _get_slew_rate(port, pin);
result.state = _get_state(port, pin);
result.pull = _get_pull_config(port, pin);
result.slew_rate = _get_slew_rate(port, pin);
#endif
if (dest->state == GPIO_INPUT) {
dest->initial_value = (gpio_ll_read(port) >> pin) & 1UL;
if (result.state == GPIO_INPUT) {
result.initial_value = (gpio_ll_read(port) >> pin) & 1UL;
}
else {
dest->initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
result.initial_value = (gpio_ll_read_output(port) >> pin) & 1UL;
}
irq_restore(state);
return result;
}
void gpio_ll_print_conf(const gpio_conf_t *conf)
void gpio_ll_print_conf(gpio_conf_t conf)
{
static const char *slew_strs[] = {
[GPIO_SLEW_SLOWEST] = "slowest",
@ -384,9 +385,9 @@ void gpio_ll_print_conf(const gpio_conf_t *conf)
gpio_ll_print_conf_common(conf);
print_str(", slew: ");
print_str(slew_strs[conf->slew_rate]);
print_str(slew_strs[conf.slew_rate]);
if (conf->schmitt_trigger_disabled) {
if (conf.schmitt_trigger_disabled) {
print_str(", Schmitt trigger disabled");
}
}

View File

@ -364,22 +364,51 @@ typedef union gpio_conf_minimal gpio_conf_t;
typedef /* implementation specific */ gpio_conf_t;
#endif
#ifndef __cplusplus
/**
* @name Commonly used GPIO LL configuration presets
*
* @warning These are not available in C++
*
* C++ requires initializers to be provided in declaration order and contain
* explicit initialization for each and every field. However, the actual
* layout and the number of members of `gpio_conf_t` depends on the
* implementation, so that implementations can expose advanced features such
* as pull strength, driver strength, skew rate, mux settings, etc. The
* API mandates that those extra fields will have a sane default value when
* implicitly initialized with 0, as done here in C.
*
* This doesn't work in C++, unless multiplying the maintenance burden by
* the number of implementations by having each implementation provide this
* by hand. This is not acceptable.
*
* @{
*/
/**
* @brief A standard configuration for a generic floating input pin
*/
extern const gpio_conf_t gpio_ll_in;
static const gpio_conf_t gpio_ll_in = {
.state = GPIO_INPUT,
.pull = GPIO_FLOATING,
};
/**
* @brief A standard configuration for a generic input pin with pull down
* resistor
*/
extern const gpio_conf_t gpio_ll_in_pd;
static const gpio_conf_t gpio_ll_in_pd = {
.state = GPIO_INPUT,
.pull = GPIO_PULL_DOWN,
};
/**
* @brief A standard configuration for a generic input pin with pull up
* resistor
*/
extern const gpio_conf_t gpio_ll_in_pu;
static const gpio_conf_t gpio_ll_in_pu = {
.state = GPIO_INPUT,
.pull = GPIO_PULL_UP,
};
/**
* @brief A standard configuration for a generic input pin with pull
@ -387,15 +416,24 @@ extern const gpio_conf_t gpio_ll_in_pu;
*
* This means, when the input reaches a 0, a pull down resistor is applied. If
* input reaches 1, a pull up is applied instead.
*
* @note This is a rather uncommon feature. MCUs that support this are
* RP2040.
*/
extern const gpio_conf_t gpio_ll_in_pk;
static const gpio_conf_t gpio_ll_in_pk = {
.state = GPIO_INPUT,
.pull = GPIO_PULL_KEEP,
};
/**
* @brief A standard configuration for a generic push-pull output pin
*
* @note The pin will have an initial value of 0.
*/
extern const gpio_conf_t gpio_ll_out;
static const gpio_conf_t gpio_ll_out = {
.state = GPIO_OUTPUT_PUSH_PULL,
.initial_value = false,
};
/**
* @brief A standard configuration for a generic floating open drain output
@ -403,7 +441,11 @@ extern const gpio_conf_t gpio_ll_out;
* @note The pin will have an initial value of 1 (which in absence of an
* external pull up resistor will be high impedance).
*/
extern const gpio_conf_t gpio_ll_od;
static const gpio_conf_t gpio_ll_od = {
.state = GPIO_OUTPUT_OPEN_DRAIN,
.pull = GPIO_FLOATING,
.initial_value = true,
};
/**
* @brief A standard configuration for a generic open drain output with pull
@ -412,7 +454,13 @@ extern const gpio_conf_t gpio_ll_od;
* @note The pin will have an initial value of 1 (so that the pull up will
* pill the line high).
*/
extern const gpio_conf_t gpio_ll_od_pu;
static const gpio_conf_t gpio_ll_od_pu = {
.state = GPIO_OUTPUT_OPEN_DRAIN,
.pull = GPIO_PULL_UP,
.initial_value = true,
};
/** @} */
#endif
/**
* @brief Check if the given number is a valid argument for @ref GPIO_PORT
@ -460,14 +508,14 @@ static inline bool is_gpio_port_num_valid(uint_fast8_t num);
* different pins on the same port is supported. The underlying
* implementation might perform locking where needed.
*/
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);
/**
* @brief Retrieve the current configuration of a GPIO pin
*
* @param[out] dest Write the current config of the given GPIO here
* @param[in] port GPIO port the pin to query is located at
* @param[in] pin Number of the pin to query within @p port
* @return The current config of the given GPIO here
*
* @pre @p port and @p pin refer to an existing GPIO pin and @p dest can
* be written to. Expect blowing assertions otherwise.
@ -476,7 +524,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, const gpio_conf_t *conf);
* value of the pin, so that no shadow log of the initial value is
* needed to consult.
*/
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);
/**
* @brief INTERNAL, use @ref gpio_ll_print_conf instead
@ -486,13 +534,13 @@ void gpio_ll_query_conf(gpio_conf_t *dest, gpio_port_t port, uint8_t pin);
* more members overwrite @ref gpio_ll_print_conf and call this function to
* print the common members
*/
void gpio_ll_print_conf_common(const gpio_conf_t *conf);
void gpio_ll_print_conf_common(const gpio_conf_t conf);
/**
* @brief Utility function to print a given GPIO configuration to stdio
* @param[in] conf Configuration to print
*/
void gpio_ll_print_conf(const gpio_conf_t *conf);
void gpio_ll_print_conf(const gpio_conf_t conf);
/**
* @brief Get the current input value of all GPIO pins of the given port as

View File

@ -6,8 +6,6 @@
* directory for more details.
*/
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include "periph/gpio_ll.h"
@ -29,50 +27,12 @@ static inline void print_str(const char *str)
}
#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)
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) {
switch (conf.state) {
case GPIO_OUTPUT_PUSH_PULL:
print_str("out-pp");
break;
@ -93,9 +53,9 @@ void gpio_ll_print_conf_common(const gpio_conf_t *conf)
break;
}
if (conf->state != GPIO_OUTPUT_PUSH_PULL) {
if (conf.state != GPIO_OUTPUT_PUSH_PULL) {
print_str(", pull: ");
switch (conf->pull) {
switch (conf.pull) {
default:
case GPIO_FLOATING:
print_str("none");
@ -113,7 +73,7 @@ void gpio_ll_print_conf_common(const gpio_conf_t *conf)
}
print_str(", value: ");
print_str(off_on[conf->initial_value]);
print_str(off_on[conf.initial_value]);
}
/* implement gpio_ll_print_conf as weak alias symbol for
@ -121,4 +81,4 @@ void gpio_ll_print_conf_common(const gpio_conf_t *conf)
* 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);
void gpio_ll_print_conf(gpio_conf_t conf);

View File

@ -143,7 +143,7 @@ int ws281x_init(ws281x_t *dev, const ws281x_params_t *params)
gpio_port_t port = gpio_get_port(dev->params.pin);
uint8_t pin = gpio_get_pin_num(dev->params.pin);
err = gpio_ll_init(port, pin, &gpio_ll_out);
err = gpio_ll_init(port, pin, gpio_ll_out);
DEBUG("Initializing port %x pin %d (originally %x): %d\n",
port, pin, params->pin, err);
if (err != 0) {

View File

@ -18,17 +18,13 @@
* @}
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mutex.h"
#include "periph/gpio.h"
#include "periph/gpio_ll.h"
#include "test_utils/expect.h"
#include "time_units.h"
#include "ztimer.h"
#include "timex.h"
#ifndef COMPENSATE_OVERHEAD
#define COMPENSATE_OVERHEAD 1
@ -158,8 +154,8 @@ int main(void)
gpio_conf_t conf = {
.state = GPIO_OUTPUT_PUSH_PULL,
};
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, &conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, conf));
uint32_t start = ztimer_now(ZTIMER_USEC);
for (uint_fast16_t i = loops; i > 0; i--) {
@ -211,8 +207,8 @@ int main(void)
gpio_conf_t conf = {
.state = GPIO_OUTPUT_PUSH_PULL,
};
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, &conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, conf));
uint32_t start = ztimer_now(ZTIMER_USEC);
for (uint_fast16_t i = loops; i > 0; i--) {
@ -264,8 +260,8 @@ int main(void)
gpio_conf_t conf = {
.state = GPIO_OUTPUT_PUSH_PULL,
};
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, &conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, conf));
uword_t both_high = gpio_ll_prepare_write(port_out, mask_both,
mask_both);

View File

@ -119,7 +119,7 @@ static void test_gpio_port_pack(void)
puts_optional("All OK");
}
static void print_conf(gpio_conf_t *conf)
static void print_conf(gpio_conf_t conf)
{
gpio_ll_print_conf(conf);
puts("");
@ -138,43 +138,39 @@ static void test_gpio_ll_init(void)
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));
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]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
expect((conf.state == GPIO_INPUT) && (conf.pull == GPIO_PULL_UP));
}
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pd));
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]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
expect((conf.state == GPIO_INPUT) && (conf.pull == GPIO_PULL_DOWN));
}
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pk));
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]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
expect((conf.state == GPIO_INPUT) && (conf.pull == GPIO_PULL_KEEP));
}
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in));
printf_optional("Support for floating input (no pull resistors): %s\n",
noyes[is_supported]);
{
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
expect((conf.state == GPIO_INPUT) && (conf.pull == GPIO_FLOATING));
}
/* Support for floating inputs is mandatory */
@ -186,29 +182,28 @@ static void test_gpio_ll_init(void)
.state = GPIO_OUTPUT_PUSH_PULL,
.initial_value = false,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (push-pull) with initial value of "
"LOW: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
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);
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = !(gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
printf_optional("Output is indeed LOW: %s\n", noyes[is_supported]);
expect(is_supported);
gpio_ll_set(port_out, (1ULL<< PIN_OUT_0));
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
print_conf(conf);
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = (gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
printf_optional("Output can be pushed HIGH: %s\n", noyes[is_supported]);
expect(is_supported);
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
expect((conf.state == GPIO_OUTPUT_PUSH_PULL) && conf.initial_value);
}
@ -217,16 +212,15 @@ static void test_gpio_ll_init(void)
.state = GPIO_OUTPUT_PUSH_PULL,
.initial_value = true,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (push-pull) with initial value of "
"HIGH: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
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);
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = (gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
@ -240,16 +234,15 @@ static void test_gpio_ll_init(void)
.initial_value = false,
.pull = GPIO_PULL_UP
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open drain with pull up) with initial "
"value of LOW: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
print_conf(conf);
expect((conf.state == GPIO_OUTPUT_OPEN_DRAIN) && !conf.initial_value
&& (conf.pull == GPIO_PULL_UP));
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
@ -264,16 +257,15 @@ static void test_gpio_ll_init(void)
.initial_value = true,
.pull = GPIO_PULL_UP
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open drain with pull up) with initial "
"value of HIGH: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
print_conf(conf);
expect((conf.state == GPIO_OUTPUT_OPEN_DRAIN) && conf.initial_value
&& (conf.pull == GPIO_PULL_UP));
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
@ -288,16 +280,15 @@ static void test_gpio_ll_init(void)
.initial_value = false,
.pull = GPIO_FLOATING,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open drain) with initial value of "
"LOW: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
print_conf(conf);
expect((conf.state == GPIO_OUTPUT_OPEN_DRAIN) && !conf.initial_value
&& (conf.pull == GPIO_FLOATING));
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
@ -312,23 +303,21 @@ static void test_gpio_ll_init(void)
.initial_value = true,
.pull = GPIO_FLOATING,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open drain) with initial value of "
"HIGH: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
print_conf(conf);
expect((conf.state == GPIO_OUTPUT_OPEN_DRAIN) && conf.initial_value
&& (conf.pull == GPIO_FLOATING));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pd));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pd));
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = !(gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
printf_optional("Output can indeed be pulled LOW: %s\n",
@ -339,11 +328,10 @@ static void test_gpio_ll_init(void)
puts_optional("WARN: Cannot enable pull down of PIN_IN_0 to verify "
"correct Open Drain behavior");
}
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pu));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pu));
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = (gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
printf_optional("Output can indeed be pulled HIGH: %s\n",
@ -362,23 +350,21 @@ static void test_gpio_ll_init(void)
.initial_value = false,
.pull = GPIO_FLOATING,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open source) with initial value of "
"LOW: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
print_conf(conf);
expect((conf.state == GPIO_OUTPUT_OPEN_SOURCE) && !conf.initial_value
&& (conf.pull == GPIO_FLOATING));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pd));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pd));
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = !(gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
printf_optional("Output can indeed be pulled LOW: %s\n",
@ -389,11 +375,10 @@ static void test_gpio_ll_init(void)
puts_optional("WARN: Cannot enable pull down of PIN_IN_0 to verify "
"correct Open Source behavior");
}
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pu));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pu));
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_in, PIN_IN_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_in, PIN_IN_0);
print_conf(conf);
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = (gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
printf_optional("Output can indeed be pulled HIGH: %s\n",
@ -406,7 +391,7 @@ static void test_gpio_ll_init(void)
}
}
expect(0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in));
expect(0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in));
{
gpio_conf_t conf = {
@ -414,16 +399,15 @@ static void test_gpio_ll_init(void)
.initial_value = true,
.pull = GPIO_FLOATING,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open source) with initial value of "
"HIGH: %s\n",
noyes[is_supported]);
if (is_supported) {
gpio_conf_t conf;
gpio_ll_query_conf(&conf, port_out, PIN_OUT_0);
print_conf(&conf);
gpio_conf_t conf = gpio_ll_query_conf(port_out, PIN_OUT_0);
print_conf(conf);
expect((conf.state == GPIO_OUTPUT_OPEN_SOURCE) && conf.initial_value
&& (conf.pull == GPIO_FLOATING));
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
@ -438,7 +422,7 @@ static void test_gpio_ll_init(void)
.initial_value = true,
.pull = GPIO_PULL_DOWN,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open source with pull up) with initial "
"value of HIGH: %s\n",
@ -457,7 +441,7 @@ static void test_gpio_ll_init(void)
.initial_value = false,
.pull = GPIO_PULL_DOWN,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for output (open source with pull up) with initial "
"value of LOW: %s\n",
@ -474,13 +458,13 @@ static void test_gpio_ll_init(void)
gpio_conf_t conf = {
.state = GPIO_DISCONNECT,
};
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, &conf));
is_supported = (0 == gpio_ll_init(port_out, PIN_OUT_0, conf));
}
printf_optional("Support for disconnecting GPIO: %s\n", noyes[is_supported]);
/* This is mandatory */
expect(is_supported);
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pd));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pd));
if (is_supported) {
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = !(gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
@ -492,7 +476,7 @@ static void test_gpio_ll_init(void)
puts_optional("WARN: Cannot enable pull down of PIN_IN_0 to verify "
"correct disabled behavior");
}
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in_pu));
is_supported = (0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in_pu));
if (is_supported) {
ztimer_sleep(ZTIMER_USEC, US_PER_MS);
is_supported = (gpio_ll_read(port_in) & (1ULL << PIN_IN_0));
@ -512,10 +496,10 @@ static void test_input_output(void)
"Testing Reading/Writing GPIO Ports\n"
"==================================\n");
expect(0 == gpio_ll_init(port_in, PIN_IN_0, &gpio_ll_in));
expect(0 == gpio_ll_init(port_in, PIN_IN_1, &gpio_ll_in));
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, &gpio_ll_out));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, &gpio_ll_out));
expect(0 == gpio_ll_init(port_in, PIN_IN_0, gpio_ll_in));
expect(0 == gpio_ll_init(port_in, PIN_IN_1, gpio_ll_in));
expect(0 == gpio_ll_init(port_out, PIN_OUT_0, gpio_ll_out));
expect(0 == gpio_ll_init(port_out, PIN_OUT_1, gpio_ll_out));
uword_t mask_in_0 = (1UL << PIN_IN_0);
uword_t mask_in_1 = (1UL << PIN_IN_1);
@ -793,8 +777,8 @@ static void test_irq(void)
"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();