diff --git a/boards/common/stm32/include/stm32_leds.h b/boards/common/stm32/include/stm32_leds.h index ce8ff6b84e..9c243d178b 100644 --- a/boards/common/stm32/include/stm32_leds.h +++ b/boards/common/stm32/include/stm32_leds.h @@ -23,7 +23,8 @@ #ifndef STM32_LEDS_H #define STM32_LEDS_H -/* GPIO_PORT() macro. This define even works when GPIO LL is not in used */ +/* Using gpio_ll_arch for the gpio_port() function. This even works when + * GPIO LL is not in used */ #include "gpio_ll_arch.h" #include "kernel_defines.h" @@ -36,7 +37,7 @@ extern "C" { * @{ */ #if defined(LED0_PORT_NUM) && defined (LED0_PIN_NUM) -# define LED0_PORT ((GPIO_TypeDef *)GPIO_PORT(LED0_PORT_NUM)) +# define LED0_PORT ((GPIO_TypeDef *)gpio_port(LED0_PORT_NUM)) # define LED0_PIN GPIO_PIN(LED0_PORT_NUM, LED0_PIN_NUM) # define LED0_MASK (1 << LED0_PIN_NUM) # if IS_ACTIVE(LED0_IS_INVERTED) @@ -50,7 +51,7 @@ extern "C" { #endif #if defined(LED1_PORT_NUM) && defined (LED1_PIN_NUM) -# define LED1_PORT ((GPIO_TypeDef *)GPIO_PORT(LED1_PORT_NUM)) +# define LED1_PORT ((GPIO_TypeDef *)gpio_port(LED1_PORT_NUM)) # define LED1_PIN GPIO_PIN(LED1_PORT_NUM, LED1_PIN_NUM) # define LED1_MASK (1 << LED1_PIN_NUM) # if IS_ACTIVE(LED1_IS_INVERTED) @@ -64,7 +65,7 @@ extern "C" { #endif #if defined(LED2_PORT_NUM) && defined (LED2_PIN_NUM) -# define LED2_PORT ((GPIO_TypeDef *)GPIO_PORT(LED2_PORT_NUM)) +# define LED2_PORT ((GPIO_TypeDef *)gpio_port(LED2_PORT_NUM)) # define LED2_PIN GPIO_PIN(LED2_PORT_NUM, LED2_PIN_NUM) # define LED2_MASK (1 << LED2_PIN_NUM) # if IS_ACTIVE(LED2_IS_INVERTED) @@ -78,7 +79,7 @@ extern "C" { #endif #if defined(LED3_PORT_NUM) && defined (LED3_PIN_NUM) -# define LED3_PORT ((GPIO_TypeDef *)GPIO_PORT(LED3_PORT_NUM)) +# define LED3_PORT ((GPIO_TypeDef *)gpio_port(LED3_PORT_NUM)) # define LED3_PIN GPIO_PIN(LED3_PORT_NUM, LED3_PIN_NUM) # define LED3_MASK (1 << LED3_PIN_NUM) # if IS_ACTIVE(LED3_IS_INVERTED) @@ -92,7 +93,7 @@ extern "C" { #endif #if defined(LED4_PORT_NUM) && defined (LED4_PIN_NUM) -# define LED4_PORT ((GPIO_TypeDef *)GPIO_PORT(LED4_PORT_NUM)) +# define LED4_PORT ((GPIO_TypeDef *)gpio_port(LED4_PORT_NUM)) # define LED4_PIN GPIO_PIN(LED4_PORT_NUM, LED4_PIN_NUM) # define LED4_MASK (1 << LED4_PIN_NUM) # if IS_ACTIVE(LED4_IS_INVERTED) @@ -106,7 +107,7 @@ extern "C" { #endif #if defined(LED5_PORT_NUM) && defined (LED5_PIN_NUM) -# define LED5_PORT ((GPIO_TypeDef *)GPIO_PORT(LED5_PORT_NUM)) +# define LED5_PORT ((GPIO_TypeDef *)gpio_port(LED5_PORT_NUM)) # define LED5_PIN GPIO_PIN(LED5_PORT_NUM, LED5_PIN_NUM) # define LED5_MASK (1 << LED5_PIN_NUM) # if IS_ACTIVE(LED5_IS_INVERTED) @@ -120,7 +121,7 @@ extern "C" { #endif #if defined(LED6_PORT_NUM) && defined (LED6_PIN_NUM) -# define LED6_PORT ((GPIO_TypeDef *)GPIO_PORT(LED6_PORT_NUM)) +# define LED6_PORT ((GPIO_TypeDef *)gpio_port(LED6_PORT_NUM)) # define LED6_PIN GPIO_PIN(LED6_PORT_NUM, LED6_PIN_NUM) # define LED6_MASK (1 << LED6_PIN_NUM) # if IS_ACTIVE(LED6_IS_INVERTED) @@ -134,7 +135,7 @@ extern "C" { #endif #if defined(LED7_PORT_NUM) && defined (LED7_PIN_NUM) -# define LED7_PORT ((GPIO_TypeDef *)GPIO_PORT(LED7_PORT_NUM)) +# define LED7_PORT ((GPIO_TypeDef *)gpio_port(LED7_PORT_NUM)) # define LED7_PIN GPIO_PIN(LED7_PORT_NUM, LED7_PIN_NUM) # define LED7_MASK (1 << LED7_PIN_NUM) # if IS_ACTIVE(LED7_IS_INVERTED) diff --git a/cpu/atmega_common/include/gpio_ll_arch.h b/cpu/atmega_common/include/gpio_ll_arch.h index 9f8cdf1a4f..8f745b1fc8 100644 --- a/cpu/atmega_common/include/gpio_ll_arch.h +++ b/cpu/atmega_common/include/gpio_ll_arch.h @@ -57,20 +57,86 @@ extern "C" { * whenever the port number is known at compile time. */ -#ifdef PORTH -#define GPIO_PORT(num) \ - ((num >= PORT_H) ? \ - (ATMEGA_GPIO_BASE_H + ((num) - PORT_H) * ATMEGA_GPIO_SIZE) : \ - (ATMEGA_GPIO_BASE_A + (num) * ATMEGA_GPIO_SIZE)) -#define GPIO_PORT_NUM(port) \ - (((port) >= ATMEGA_GPIO_BASE_H) ? \ - (((port) - ATMEGA_GPIO_BASE_H) / ATMEGA_GPIO_SIZE + PORT_H) : \ - (((port) - ATMEGA_GPIO_BASE_A) / ATMEGA_GPIO_SIZE)) -#else -#define GPIO_PORT(num) (ATMEGA_GPIO_BASE_A + (num) * ATMEGA_GPIO_SIZE) -#define GPIO_PORT_NUM(port) (((port) - ATMEGA_GPIO_BASE_A) / ATMEGA_GPIO_SIZE) +#define GPIO_PORT_NUMBERING_ALPHABETIC 1 + +#ifdef PINA +/* We sadly cannot use PINA, as PINA is technically (in terms of C spec lingo) + * not constant and would trigger: + * initializer element is not constant + * Hence, the defines are a bit more involved to yield proper constants + * suitable for initializers. + */ +# define GPIO_PORT_0 (ATMEGA_GPIO_BASE_A) #endif +#ifdef PINB +# define GPIO_PORT_1 (ATMEGA_GPIO_BASE_A + 1 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PINC +# define GPIO_PORT_2 (ATMEGA_GPIO_BASE_A + 2 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PIND +# define GPIO_PORT_3 (ATMEGA_GPIO_BASE_A + 3 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PINE +# define GPIO_PORT_4 (ATMEGA_GPIO_BASE_A + 4 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PINF +# define GPIO_PORT_5 (ATMEGA_GPIO_BASE_A + 5 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PING +# define GPIO_PORT_6 (ATMEGA_GPIO_BASE_A + 6 * ATMEGA_GPIO_SIZE) +#endif + +/* There is a larger gap between PING and PINH to allow other peripherals to + * also be mapped into the fast I/O memory area. */ +#ifdef PINH +# define GPIO_PORT_7 (ATMEGA_GPIO_BASE_H) +#endif + +#ifdef PINI +# define GPIO_PORT_8 (ATMEGA_GPIO_BASE_H + 1 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PINJ +# define GPIO_PORT_9 (ATMEGA_GPIO_BASE_H + 2 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PINK +# define GPIO_PORT_10 (ATMEGA_GPIO_BASE_H + 3 * ATMEGA_GPIO_SIZE) +#endif + +#ifdef PINL +# define GPIO_PORT_11 (ATMEGA_GPIO_BASE_H + 4 * ATMEGA_GPIO_SIZE) +#endif + +static inline gpio_port_t gpio_port(uword_t num) +{ +#ifdef PINH + if (num >= PORT_H) { + return ATMEGA_GPIO_BASE_H + ((num - PORT_H) * ATMEGA_GPIO_SIZE); + } +#endif + + return ATMEGA_GPIO_BASE_A + (num * ATMEGA_GPIO_SIZE); +} + +static inline uword_t gpio_port_num(gpio_port_t port) +{ +#ifdef PINH + if ((port) >= ATMEGA_GPIO_BASE_H) { + return (port - ATMEGA_GPIO_BASE_H) / ATMEGA_GPIO_SIZE + PORT_H; + } +#endif + + return (port - ATMEGA_GPIO_BASE_A) / ATMEGA_GPIO_SIZE; +} + static inline uword_t gpio_ll_read(gpio_port_t port) { atmega_gpio_port_t *p = (void *)port; @@ -158,7 +224,7 @@ static inline void gpio_ll_write(gpio_port_t port, uword_t value) static inline gpio_port_t gpio_get_port(gpio_t pin) { - return GPIO_PORT(pin >> 4); + return gpio_port(pin >> 4); } static inline uint8_t gpio_get_pin_num(gpio_t pin) diff --git a/cpu/atmega_common/include/periph_cpu_common.h b/cpu/atmega_common/include/periph_cpu_common.h index 3b5a5756b9..48e6c72f5d 100644 --- a/cpu/atmega_common/include/periph_cpu_common.h +++ b/cpu/atmega_common/include/periph_cpu_common.h @@ -73,16 +73,16 @@ typedef uint8_t gpio_t; #ifdef GPIO_PORT_DESCENDENT #ifdef _AVR_ATTINY1634_H_INCLUDED /* the only one that requires particular treatment! */ -#define ATMEGA_GPIO_BASE_A (0x2F) +#define ATMEGA_GPIO_BASE_A 0x2F #else /* all other port descendent, including : - _AVR_IO8534_ (only have port A but with 0x1B address) ; - _AVR_IOAT94K_H_ (only have ports D and E) ; - _AVR_IOTN28_H_ (only have ports A and D). */ -#define ATMEGA_GPIO_BASE_A (0x39) +#define ATMEGA_GPIO_BASE_A 0x39 #endif /* _AVR_ATTINY1634_H_INCLUDED */ #else /* !GPIO_PORT_DESCENDENT */ -#define ATMEGA_GPIO_BASE_A (0x20) +#define ATMEGA_GPIO_BASE_A 0x20 #endif /* GPIO_PORT_DESCENDENT */ /** * @brief Base of the GPIO port G register as memory address diff --git a/cpu/atmega_common/periph/gpio_ll_irq.c b/cpu/atmega_common/periph/gpio_ll_irq.c index dd073b1076..8f13f1291c 100644 --- a/cpu/atmega_common/periph/gpio_ll_irq.c +++ b/cpu/atmega_common/periph/gpio_ll_irq.c @@ -62,7 +62,7 @@ static void clear_pending_irqs(uint8_t exti) void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin) { - uint8_t exti = atmega_pin2exti(GPIO_PORT_NUM(port), pin); + uint8_t exti = atmega_pin2exti(gpio_port_num(port), pin); #if defined(EIMSK) EIMSK &= ~(1 << exti); #elif defined(GICR) @@ -72,7 +72,7 @@ void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin) void gpio_ll_irq_unmask(gpio_port_t port, uint8_t pin) { - uint8_t exti = atmega_pin2exti(GPIO_PORT_NUM(port), pin); + uint8_t exti = atmega_pin2exti(gpio_port_num(port), pin); #if defined(EIMSK) EIMSK |= 1 << exti; #elif defined(GICR) @@ -82,7 +82,7 @@ void gpio_ll_irq_unmask(gpio_port_t port, uint8_t pin) void gpio_ll_irq_unmask_and_clear(gpio_port_t port, uint8_t pin) { - uint8_t exti = atmega_pin2exti(GPIO_PORT_NUM(port), pin); + uint8_t exti = atmega_pin2exti(gpio_port_num(port), pin); clear_pending_irqs(exti); #if defined(EIMSK) EIMSK |= 1 << exti; @@ -118,7 +118,7 @@ static void set_trigger(uint8_t exti, gpio_irq_trig_t trig) int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig, gpio_ll_cb_t cb, void *arg) { - int port_num = GPIO_PORT_NUM(port); + int port_num = gpio_port_num(port); assert((trig != GPIO_TRIGGER_LEVEL_HIGH) && cb); if (!atmega_has_pin_exti(port_num, pin)) { return -ENOTSUP; diff --git a/cpu/efm32/include/gpio_ll_arch.h b/cpu/efm32/include/gpio_ll_arch.h index 01bb26a6e2..731ac26d15 100644 --- a/cpu/efm32/include/gpio_ll_arch.h +++ b/cpu/efm32/include/gpio_ll_arch.h @@ -48,12 +48,63 @@ extern "C" { #ifndef DOXYGEN /* hide implementation specific details from Doxygen */ +#define GPIO_PORT_NUMBERING_ALPHABETIC 1 + +/* Note: The pin count may be defined as zero to indicate the port not existing. + * Hence, don't to `#if defined(foo)` but only `#if foo` + */ +#if _GPIO_PORT_A_PIN_COUNT +# define GPIO_PORT_0 0 +#endif + +#if _GPIO_PORT_B_PIN_COUNT +# define GPIO_PORT_1 1 +#endif + +#if _GPIO_PORT_C_PIN_COUNT +# define GPIO_PORT_2 2 +#endif + +#if _GPIO_PORT_D_PIN_COUNT +# define GPIO_PORT_3 3 +#endif + +#if _GPIO_PORT_E_PIN_COUNT +# define GPIO_PORT_4 4 +#endif + +#if _GPIO_PORT_F_PIN_COUNT +# define GPIO_PORT_6 6 +#endif + +#if _GPIO_PORT_G_PIN_COUNT +# define GPIO_PORT_7 7 +#endif + +#if _GPIO_PORT_H_PIN_COUNT +# define GPIO_PORT_8 8 +#endif + +#if _GPIO_PORT_I_PIN_COUNT +# define GPIO_PORT_9 9 +#endif + +#if _GPIO_PORT_J_PIN_COUNT +# define GPIO_PORT_10 10 +#endif + +#if _GPIO_PORT_K_PIN_COUNT +# define GPIO_PORT_11 11 +#endif + /* We could do * -#define GPIO_PORT(num) (GPIO->P[num]) -#define GPIO_PORT_NUM(port) ((port - &GPIO->P)) + * static inline gpio_port_t gpio_port(uword_t num) + * { + * return GPIO->P[num]; + * } * - * which forks for some operations, but at latest when _ll_set needs to fan out + * which works for some operations, but at latest when _ll_set needs to fan out * for some EFM32 families to * #if defined(_GPIO_P_DOUTSET_MASK) @@ -78,9 +129,15 @@ extern "C" { * an implementation for other EFM32 families. For the time being, the * suboptimal-but-works-for-all version is the best we have. */ +static inline gpio_port_t gpio_port(uword_t num) +{ + return num; +} -#define GPIO_PORT(num) (num) -#define GPIO_PORT_NUM(port) (port) +static inline uword_t gpio_port_num(gpio_port_t port) +{ + return port; +} static inline uword_t gpio_ll_read(gpio_port_t port) { diff --git a/cpu/esp32/include/gpio_ll_arch.h b/cpu/esp32/include/gpio_ll_arch.h index 70ced489cd..a778a057ff 100644 --- a/cpu/esp32/include/gpio_ll_arch.h +++ b/cpu/esp32/include/gpio_ll_arch.h @@ -32,12 +32,19 @@ extern "C" { #ifndef DOXYGEN /* hide implementation specific details from Doxygen */ -#define GPIO_PORT(num) (num) -#if GPIO_PORT_NUMOF > 1 -# define GPIO_PORT_NUM(port) (port) -#else -# define GPIO_PORT_NUM(port) 0 -#endif +static inline gpio_port_t gpio_port(uword_t num) +{ + return num; +} + +static inline uword_t gpio_port_num(gpio_port_t port) +{ + if (GPIO_PORT_NUMOF == 1) { + return 0; + } + + return port; +} static inline uword_t gpio_ll_read(gpio_port_t port) { @@ -45,7 +52,7 @@ static inline uword_t gpio_ll_read(gpio_port_t port) volatile uword_t *in = (uint32_t *)GPIO_IN_REG; /* return 0 for unconfigured pins, the current level at the pin otherwise */ #if GPIO_PORT_NUM > 1 - if (GPIO_PORT_NUM(port) != 0) { + if (gpio_port_num(port) != 0) { in = (uint32_t *)GPIO_IN1_REG; } #endif @@ -58,7 +65,7 @@ static inline uword_t gpio_ll_read_output(gpio_port_t port) static_assert(GPIO_PORT_NUMOF < 3); volatile uword_t *out = (uint32_t *)GPIO_OUT_REG; #if GPIO_PORT_NUM > 1 - if (GPIO_PORT_NUM(port) != 0) { + if (gpio_port_num(port) != 0) { out = (uint32_t *)GPIO_OUT1_REG; } #endif @@ -70,7 +77,7 @@ static inline void gpio_ll_set(gpio_port_t port, uword_t mask) { static_assert(GPIO_PORT_NUMOF < 3); volatile uword_t *out_w1ts = (uint32_t *)GPIO_OUT_W1TS_REG; - if (GPIO_PORT_NUM(port) != 0) { + if (gpio_port_num(port) != 0) { #if GPIO_PORT_NUM > 1 out_w1ts = (uint32_t)GPIO_OUT1_W1TS; #endif @@ -83,7 +90,7 @@ static inline void gpio_ll_clear(gpio_port_t port, uword_t mask) { static_assert(GPIO_PORT_NUMOF < 3); volatile uword_t *out_w1tc = (uint32_t *)GPIO_OUT_W1TC_REG; - if (GPIO_PORT_NUM(port) != 0) { + if (gpio_port_num(port) != 0) { #if GPIO_PORT_NUM > 1 out_w1tc = (uint32_t)GPIO_OUT1_W1TC; #endif @@ -97,7 +104,7 @@ static inline void gpio_ll_toggle(gpio_port_t port, uword_t mask) static_assert(GPIO_PORT_NUMOF < 3); volatile uword_t *out = (uint32_t *)GPIO_OUT_REG; #if GPIO_PORT_NUM > 1 - if (GPIO_PORT_NUM(port) != 0) { + if (gpio_port_num(port) != 0) { out = (uint32_t *)GPIO_OUT1_REG; } #endif @@ -111,7 +118,7 @@ static inline void gpio_ll_write(gpio_port_t port, uword_t value) static_assert(GPIO_PORT_NUMOF < 3); volatile uword_t *out = (uint32_t *)GPIO_OUT_REG; #if GPIO_PORT_NUM > 1 - if (GPIO_PORT_NUM(port) != 0) { + if (gpio_port_num(port) != 0) { out = (uint32_t *)GPIO_OUT1_REG; } #endif @@ -120,7 +127,7 @@ static inline void gpio_ll_write(gpio_port_t port, uword_t value) static inline gpio_port_t gpio_get_port(gpio_t pin) { - return GPIO_PORT(pin >> 5); + return gpio_port(pin >> 5); } static inline uint8_t gpio_get_pin_num(gpio_t pin) diff --git a/cpu/esp32/include/periph_cpu.h b/cpu/esp32/include/periph_cpu.h index b00f0ee6d1..6bd48fd821 100644 --- a/cpu/esp32/include/periph_cpu.h +++ b/cpu/esp32/include/periph_cpu.h @@ -151,8 +151,8 @@ typedef enum { #if SOC_GPIO_PIN_COUNT > 32 #define GPIO_PORT_NUMOF 2 -#define GPIO_PORT_0 GPIO_PORT(0) -#define GPIO_PORT_1 GPIO_PORT(1) +#define GPIO_PORT_0 0 +#define GPIO_PORT_1 1 #define GPIO_PORT_0_PIN_NUMOF (32) #define GPIO_PORT_1_PIN_NUMOF (SOC_GPIO_PIN_COUNT - 32) #define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF \ @@ -160,7 +160,7 @@ typedef enum { #else #define GPIO_PORT_NUMOF 1 -#define GPIO_PORT_0 GPIO_PORT(0) +#define GPIO_PORT_0 0 #define GPIO_PORT_0_PIN_NUMOF (SOC_GPIO_PIN_COUNT) #define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF : 0) diff --git a/cpu/esp32/periph/gpio_ll.c b/cpu/esp32/periph/gpio_ll.c index 4d7cf5701f..93146c1d05 100644 --- a/cpu/esp32/periph/gpio_ll.c +++ b/cpu/esp32/periph/gpio_ll.c @@ -60,7 +60,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf) assert(is_gpio_port_num_valid(port)); assert(pin < GPIO_PORT_PIN_NUMOF(port)); - gpio_t gpio = GPIO_PIN(GPIO_PORT_NUM(port), pin); + gpio_t gpio = GPIO_PIN(gpio_port_num(port), pin); gpio_config_t cfg = { .pin_bit_mask = (1ULL << gpio), @@ -168,7 +168,7 @@ gpio_conf_t gpio_ll_query_conf(gpio_port_t port, uint8_t pin) unsigned state = irq_disable(); - result = _gpio_conf[GPIO_PIN(GPIO_PORT_NUM(port), pin)]; + result = _gpio_conf[GPIO_PIN(gpio_port_num(port), pin)]; if (result.state == GPIO_INPUT) { result.initial_value = (gpio_ll_read(port) >> pin) & 1UL; } diff --git a/cpu/esp32/periph/gpio_ll_irq.c b/cpu/esp32/periph/gpio_ll_irq.c index 492e79c099..5a47e43b93 100644 --- a/cpu/esp32/periph/gpio_ll_irq.c +++ b/cpu/esp32/periph/gpio_ll_irq.c @@ -61,10 +61,10 @@ int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig, unsigned state = irq_disable(); - gpio_t gpio = GPIO_PIN(GPIO_PORT_NUM(port), pin); + gpio_t gpio = GPIO_PIN(gpio_port_num(port), pin); DEBUG("%s gpio=%u port=%u pin=%u trig=%d cb=%p arg=%p\n", - __func__, gpio, GPIO_PORT_NUM(port), pin, trig, cb, arg); + __func__, gpio, (unsigned)gpio_port_num(port), pin, trig, cb, arg); /* install GPIO ISR of ESP-IDF if not yet done */ if (!gpio_isr_service_installed && @@ -113,10 +113,10 @@ int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig, void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin) { - gpio_t gpio = GPIO_PIN(GPIO_PORT_NUM(port), pin); + gpio_t gpio = GPIO_PIN(gpio_port_num(port), pin); DEBUG("%s gpio=%u port=%u pin=%u\n", - __func__, gpio, GPIO_PORT_NUM(port), pin); + __func__, gpio, (unsigned)gpio_port_num(port), pin); if (esp_idf_gpio_intr_disable(gpio) == ESP_OK) { gpio_int_enabled_table[gpio] = false; @@ -125,7 +125,7 @@ void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin) void gpio_ll_irq_unmask(gpio_port_t port, uint8_t pin) { - gpio_t gpio = GPIO_PIN(GPIO_PORT_NUM(port), pin); + gpio_t gpio = GPIO_PIN(gpio_port_num(port), pin); DEBUG("%s gpio=%u port=%u pin=%u\n", __func__, gpio, port, pin); @@ -137,14 +137,14 @@ void gpio_ll_irq_unmask(gpio_port_t port, uint8_t pin) void gpio_ll_irq_unmask_and_clear(gpio_port_t port, uint8_t pin) { - gpio_t gpio = GPIO_PIN(GPIO_PORT_NUM(port), pin); + gpio_t gpio = GPIO_PIN(gpio_port_num(port), pin); DEBUG("%s gpio=%u port=%u pin=%u\n", - __func__, gpio, GPIO_PORT_NUM(port), pin); + __func__, gpio, (unsigned)gpio_port_num(port), pin); volatile uint32_t *status_w1tc = (uint32_t *)GPIO_STATUS_W1TC_REG; #if GPIO_PORT_NUMOF > 1 - if (GPIO_PORT_NUM(port) != 0) { + if (gpio_port_num(port) != 0) { status_w1tc = (uint32_t *)GPIO_STATUS1_W1TC_REG; } #endif diff --git a/cpu/gd32v/include/gpio_ll_arch.h b/cpu/gd32v/include/gpio_ll_arch.h index c60379d3a0..ddc388d689 100644 --- a/cpu/gd32v/include/gpio_ll_arch.h +++ b/cpu/gd32v/include/gpio_ll_arch.h @@ -21,7 +21,6 @@ #define GPIO_LL_ARCH_H #include "architecture.h" -#include "periph/gpio_ll.h" #include "periph_cpu.h" #ifdef __cplusplus @@ -35,15 +34,69 @@ extern "C" { */ #define GPIO_PORT_NUMOF 5 -/** - * @brief Get a GPIO port by number - */ -#define GPIO_PORT(num) (GPIOA_BASE + ((num) << 10)) +#define GPIO_PORT_NUMBERING_ALPHABETIC 1 -/** - * @brief Get a GPIO port number by gpio_t value - */ -#define GPIO_PORT_NUM(port) (((port) - GPIOA_BASE) >> 10) +#ifdef GPIOA_BASE +# define GPIO_PORT_0 GPIOA_BASE +#endif + +#ifdef GPIOB_BASE +# define GPIO_PORT_1 GPIOB_BASE +#endif + +#ifdef GPIOC_BASE +# define GPIO_PORT_2 GPIOC_BASE +#endif + +#ifdef GPIOD_BASE +# define GPIO_PORT_3 GPIOD_BASE +#endif + +#ifdef GPIOE_BASE +# define GPIO_PORT_4 GPIOE_BASE +#endif + +#ifdef GPIOF_BASE +# define GPIO_PORT_5 GPIOF_BASE +#endif + +#ifdef GPIOG_BASE +# define GPIO_PORT_6 GPIOG_BASE +#endif + +#ifdef GPIOH_BASE +# define GPIO_PORT_7 GPIOH_BASE +#endif + +#ifdef GPIOI_BASE +# define GPIO_PORT_8 GPIOI_BASE +#endif + +#ifdef GPIOJ_BASE +# define GPIO_PORT_9 GPIOJ_BASE +#endif + +#ifdef GPIOK_BASE +# define GPIO_PORT_10 GPIOK_BASE +#endif + +static inline gpio_port_t gpio_port(uword_t num) +{ +#if defined(CPU_FAM_STM32MP1) + return GPIOA_BASE + (num << 12); +#else + return GPIOA_BASE + (num << 10); +#endif +} + +static inline uword_t gpio_port_num(gpio_port_t port) +{ +#if defined(CPU_FAM_STM32MP1) + return (port - GPIOA_BASE) >> 12; +#else + return (port - GPIOA_BASE) >> 10; +#endif +} static inline uword_t gpio_ll_read(gpio_port_t port) { diff --git a/cpu/gd32v/periph/gpio_ll.c b/cpu/gd32v/periph/gpio_ll.c index 72de29352b..8a59b1df64 100644 --- a/cpu/gd32v/periph/gpio_ll.c +++ b/cpu/gd32v/periph/gpio_ll.c @@ -48,7 +48,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf) unsigned state = irq_disable(); - periph_clk_en(APB2, (RCU_APB2EN_PAEN_Msk << GPIO_PORT_NUM(port))); + periph_clk_en(APB2, (RCU_APB2EN_PAEN_Msk << gpio_port_num(port))); volatile uint32_t *ctrl = (pin < 8) ? &((GPIO_Type *)port)->CTL0 : &((GPIO_Type *)port)->CTL1; @@ -60,13 +60,13 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf) switch (conf.state) { case GPIO_DISCONNECT: - 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))); + 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))); } break; case GPIO_INPUT: - pin_used[GPIO_PORT_NUM(port)] |= 1 << pin; + pin_used[gpio_port_num(port)] |= 1 << pin; if (conf.pull == GPIO_FLOATING) { *ctrl |= 0x1 << (pos + 2); } @@ -82,7 +82,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf) break; case GPIO_OUTPUT_PUSH_PULL: case GPIO_OUTPUT_OPEN_DRAIN: - pin_used[GPIO_PORT_NUM(port)] |= 1 << pin; + 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) { diff --git a/cpu/gd32v/periph/gpio_ll_irq.c b/cpu/gd32v/periph/gpio_ll_irq.c index de3ea6cbab..d4f51e2ab5 100644 --- a/cpu/gd32v/periph/gpio_ll_irq.c +++ b/cpu/gd32v/periph/gpio_ll_irq.c @@ -78,7 +78,7 @@ static void _gpio_isr(unsigned irqn); int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig, gpio_ll_cb_t cb, void *arg) { unsigned irq_state = irq_disable(); - int port_num = GPIO_PORT_NUM(port); + int port_num = gpio_port_num(port); /* set callback */ _exti_ctx[pin].cb = cb; @@ -177,7 +177,7 @@ static void _gpio_isr(unsigned irqn) if ((_h_level_triggered & pin_mask) || (_l_level_triggered & pin_mask)) { /* determine the port of triggered interrupt */ volatile uint32_t *afio_exti_ss = &AFIO->EXTISS0 + (pin >> 2); - gpio_port_t port = GPIO_PORT(((*afio_exti_ss >> ((pin & 0x03) * 4)) & 0xfUL)); + gpio_port_t port = gpio_port(((*afio_exti_ss >> ((pin & 0x03) * 4)) & 0xfUL)); /* trigger software interrupt if the pin has the according level */ uint32_t level = gpio_ll_read(port) & pin_mask; diff --git a/cpu/nrf5x_common/include/gpio_ll_arch.h b/cpu/nrf5x_common/include/gpio_ll_arch.h index 67a44d56ca..e1d13485e4 100644 --- a/cpu/nrf5x_common/include/gpio_ll_arch.h +++ b/cpu/nrf5x_common/include/gpio_ll_arch.h @@ -51,16 +51,37 @@ extern "C" { #endif #if defined(CPU_FAM_NRF51) -#define GPIO_PORT(num) ((gpio_port_t)NRF_GPIO) -#define GPIO_PORT_NUM(port) 0 -#elif defined(NRF_P1) -#define GPIO_PORT(num) ((num) ? (gpio_port_t)NRF_P1 : (gpio_port_t)NRF_P0) -#define GPIO_PORT_NUM(port) ((port == (gpio_port_t)NRF_P1) ? 1 : 0) +# define GPIO_PORT_0 ((gpio_port_t)NRF_GPIO) #else -#define GPIO_PORT(num) ((gpio_port_t)NRF_P0) -#define GPIO_PORT_NUM(port) 0 +# if defined(NRF_P1) +# define GPIO_PORT_1 ((gpio_port_t)NRF_P1) +# endif +# define GPIO_PORT_0 ((gpio_port_t)NRF_P0) #endif +static inline gpio_port_t gpio_port(uword_t num) +{ + (void)num; +#ifdef GPIO_PORT_1 + if (num == 1) { + return GPIO_PORT_1; + } +#endif + + return GPIO_PORT_0; +} + +static inline uword_t gpio_port_num(gpio_port_t port) +{ + (void)port; +#ifdef GPIO_PORT_1 + if (port == GPIO_PORT_1) { + return 1; + } +#endif + return 0; +} + static inline uword_t gpio_ll_read(gpio_port_t port) { NRF_GPIO_Type *p = (NRF_GPIO_Type *)port; @@ -102,10 +123,10 @@ static inline void gpio_ll_write(gpio_port_t port, uword_t value) static inline gpio_port_t gpio_get_port(gpio_t pin) { #if defined(NRF_P1) - return GPIO_PORT(pin >> 5); + return gpio_port(pin >> 5); #else (void)pin; - return GPIO_PORT(0); + return GPIO_PORT_0; #endif } diff --git a/cpu/nrf5x_common/periph/gpio_ll_irq.c b/cpu/nrf5x_common/periph/gpio_ll_irq.c index 68533bb663..63f7898498 100644 --- a/cpu/nrf5x_common/periph/gpio_ll_irq.c +++ b/cpu/nrf5x_common/periph/gpio_ll_irq.c @@ -128,7 +128,7 @@ int gpio_ll_irq(gpio_port_t port, uint8_t pin, { /* param port is not used on nRF5x variants with only one GPIO port */ (void)port; - uint8_t port_num = GPIO_PORT_NUM(port); + uint8_t port_num = gpio_port_num(port); uint8_t channel = get_channel_for_pin(port_num, pin); assert((trig != GPIO_TRIGGER_LEVEL_HIGH) && (trig != GPIO_TRIGGER_LEVEL_LOW)); @@ -167,7 +167,7 @@ void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin) { /* param port is not used on nRF5x variants with only one GPIO port */ (void)port; - uint8_t port_num = GPIO_PORT_NUM(port); + uint8_t port_num = gpio_port_num(port); unsigned channel = get_channel_of_pin(port_num, pin); assert(channel != GPIOTE_CHAN_NUMOF); if (channel != GPIOTE_CHAN_NUMOF) { @@ -179,7 +179,7 @@ void gpio_ll_irq_unmask(gpio_port_t port, uint8_t pin) { /* param port is not used on nRF5x variants with only one GPIO port */ (void)port; - uint8_t port_num = GPIO_PORT_NUM(port); + uint8_t port_num = gpio_port_num(port); unsigned channel = get_channel_of_pin(port_num, pin); assert(channel != GPIOTE_CHAN_NUMOF); if (channel != GPIOTE_CHAN_NUMOF) { @@ -191,7 +191,7 @@ void gpio_ll_irq_unmask_and_clear(gpio_port_t port, uint8_t pin) { /* param port is not used on nRF5x variants with only one GPIO port */ (void)port; - uint8_t port_num = GPIO_PORT_NUM(port); + uint8_t port_num = gpio_port_num(port); unsigned channel = get_channel_of_pin(port_num, pin); assert(channel != GPIOTE_CHAN_NUMOF); if (channel != GPIOTE_CHAN_NUMOF) { @@ -204,7 +204,7 @@ void gpio_ll_irq_off(gpio_port_t port, uint8_t pin) { /* param port is not used on nRF5x variants with only one GPIO port */ (void)port; - uint8_t port_num = GPIO_PORT_NUM(port); + uint8_t port_num = gpio_port_num(port); unsigned channel = get_channel_of_pin(port_num, pin); assert(channel != GPIOTE_CHAN_NUMOF); if (channel != GPIOTE_CHAN_NUMOF) { diff --git a/cpu/sam0_common/include/gpio_ll_arch.h b/cpu/sam0_common/include/gpio_ll_arch.h index 02b25c7c1e..c2fdb811b3 100644 --- a/cpu/sam0_common/include/gpio_ll_arch.h +++ b/cpu/sam0_common/include/gpio_ll_arch.h @@ -23,7 +23,6 @@ #define GPIO_LL_ARCH_H #include "architecture.h" -#include "periph/gpio_ll.h" #include "periph_cpu.h" #ifdef __cplusplus @@ -48,6 +47,36 @@ extern "C" { # define GPIO_IOBUS_BASE GPIO_APB_BASE /* no IOBUS present, fall back to APB */ #endif +#define GPIO_PORT_NUMBERING_ALPHABETIC 1 + +#if PORT_GROUPS >= 1 +# define GPIO_PORT_0 ((uintptr_t)&GPIO_IOBUS_BASE->Group[0]) +#endif +#if PORT_GROUPS >= 2 +# define GPIO_PORT_1 ((uintptr_t)&GPIO_IOBUS_BASE->Group[1]) +#endif +#if PORT_GROUPS >= 3 +# define GPIO_PORT_2 ((uintptr_t)&GPIO_IOBUS_BASE->Group[2]) +#endif +#if PORT_GROUPS >= 4 +# define GPIO_PORT_3 ((uintptr_t)&GPIO_IOBUS_BASE->Group[3]) +#endif +#if PORT_GROUPS >= 5 +# define GPIO_PORT_4 ((uintptr_t)&GPIO_IOBUS_BASE->Group[4]) +#endif +#if PORT_GROUPS >= 5 +# define GPIO_PORT_4 ((uintptr_t)&GPIO_IOBUS_BASE->Group[4]) +#endif +#if PORT_GROUPS >= 6 +# define GPIO_PORT_5 ((uintptr_t)&GPIO_IOBUS_BASE->Group[5]) +#endif +#if PORT_GROUPS >= 7 +# define GPIO_PORT_6 ((uintptr_t)&GPIO_IOBUS_BASE->Group[6]) +#endif +#if PORT_GROUPS >= 8 +# define GPIO_PORT_7 ((uintptr_t)&GPIO_IOBUS_BASE->Group[7]) +#endif + /** * @brief Get a GPIO port by number */ @@ -59,6 +88,16 @@ extern "C" { #define GPIO_PORT_NUM(port) \ (((port) - (uintptr_t)&GPIO_IOBUS_BASE->Group[0]) / sizeof(GPIO_IOBUS_BASE->Group[0])) +static inline gpio_port_t gpio_port(uword_t num) +{ + return (uintptr_t)&GPIO_IOBUS_BASE->Group[num]; +} + +static inline uword_t gpio_port_num(gpio_port_t port) +{ + return (port - (uintptr_t)&GPIO_IOBUS_BASE->Group[0]) / sizeof(GPIO_IOBUS_BASE->Group[0]); +} + static inline PortGroup *sam0_gpio_iobus2ap(PortGroup *iobus) { const uintptr_t iobus_base = (uintptr_t)GPIO_IOBUS_BASE; diff --git a/cpu/stm32/include/gpio_ll_arch.h b/cpu/stm32/include/gpio_ll_arch.h index 7653dd8d63..56f3647408 100644 --- a/cpu/stm32/include/gpio_ll_arch.h +++ b/cpu/stm32/include/gpio_ll_arch.h @@ -23,7 +23,6 @@ #define GPIO_LL_ARCH_H #include "architecture.h" -#include "periph/gpio_ll.h" #include "periph_cpu.h" #ifdef __cplusplus @@ -32,24 +31,70 @@ extern "C" { #ifndef DOXYGEN /* hide implementation specific details from Doxygen */ -/** - * @brief Get a GPIO port by number - */ -#if defined(CPU_FAM_STM32MP1) -#define GPIO_PORT(num) (GPIOA_BASE + ((num) << 12)) -#else -#define GPIO_PORT(num) (GPIOA_BASE + ((num) << 10)) +#define GPIO_PORT_NUMBERING_ALPHABETIC 1 + +#ifdef GPIOA_BASE +# define GPIO_PORT_0 GPIOA_BASE #endif -/** - * @brief Get a GPIO port number by gpio_t value - */ -#if defined(CPU_FAM_STM32MP1) -#define GPIO_PORT_NUM(port) (((port) - GPIOA_BASE) >> 12) -#else -#define GPIO_PORT_NUM(port) (((port) - GPIOA_BASE) >> 10) +#ifdef GPIOB_BASE +# define GPIO_PORT_1 GPIOB_BASE #endif +#ifdef GPIOC_BASE +# define GPIO_PORT_2 GPIOC_BASE +#endif + +#ifdef GPIOD_BASE +# define GPIO_PORT_3 GPIOD_BASE +#endif + +#ifdef GPIOE_BASE +# define GPIO_PORT_4 GPIOE_BASE +#endif + +#ifdef GPIOF_BASE +# define GPIO_PORT_5 GPIOF_BASE +#endif + +#ifdef GPIOG_BASE +# define GPIO_PORT_6 GPIOG_BASE +#endif + +#ifdef GPIOH_BASE +# define GPIO_PORT_7 GPIOH_BASE +#endif + +#ifdef GPIOI_BASE +# define GPIO_PORT_8 GPIOI_BASE +#endif + +#ifdef GPIOJ_BASE +# define GPIO_PORT_9 GPIOJ_BASE +#endif + +#ifdef GPIOK_BASE +# define GPIO_PORT_10 GPIOK_BASE +#endif + +static inline gpio_port_t gpio_port(uword_t num) +{ +#if defined(CPU_FAM_STM32MP1) + return GPIOA_BASE + (num << 12); +#else + return GPIOA_BASE + (num << 10); +#endif +} + +static inline uword_t gpio_port_num(gpio_port_t port) +{ +#if defined(CPU_FAM_STM32MP1) + return (port - GPIOA_BASE) >> 12; +#else + return (port - GPIOA_BASE) >> 10; +#endif +} + static inline uword_t gpio_ll_read(gpio_port_t port) { GPIO_TypeDef *p = (GPIO_TypeDef *)port; diff --git a/cpu/stm32/periph/gpio_ll.c b/cpu/stm32/periph/gpio_ll.c index 35e1a3597a..66a7af11f3 100644 --- a/cpu/stm32/periph/gpio_ll.c +++ b/cpu/stm32/periph/gpio_ll.c @@ -95,7 +95,7 @@ static inline void print_str(const char *str) static void _init_clock(gpio_port_t port) { - periph_clk_en(GPIO_BUS, (GPIOAEN << GPIO_PORT_NUM(port))); + periph_clk_en(GPIO_BUS, (GPIOAEN << gpio_port_num(port))); #ifdef PORTG_REQUIRES_EXTERNAL_POWER if (port == (uintptr_t)GPIOG) { /* Port G requires external power supply */ diff --git a/cpu/stm32/periph/gpio_ll_irq.c b/cpu/stm32/periph/gpio_ll_irq.c index 6196b1bb35..e7bd0ff2b6 100644 --- a/cpu/stm32/periph/gpio_ll_irq.c +++ b/cpu/stm32/periph/gpio_ll_irq.c @@ -207,7 +207,7 @@ static uint8_t get_exti_port(uint8_t exti_num) int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig, gpio_ll_cb_t cb, void *arg) { unsigned irq_state = irq_disable(); - int port_num = GPIO_PORT_NUM(port); + int port_num = gpio_port_num(port); /* set callback */ isr_ctx[pin].cb = cb; @@ -297,7 +297,7 @@ void isr_exti(void) if (level_triggered & (1UL << pin)) { /* Trading a couple of CPU cycles to not having to store port connected to EXTI in RAM. * A simple look up table would save ~6 instructions for the cost 64 bytes of RAM. */ - gpio_port_t port = GPIO_PORT(get_exti_port(pin)); + gpio_port_t port = gpio_port(get_exti_port(pin)); uint32_t actual_level = gpio_ll_read(port) & (1UL << pin); uint32_t trigger_level = EXTI_REG_RTSR & (1UL << pin); if (actual_level == trigger_level) { diff --git a/drivers/include/periph/gpio_ll.h b/drivers/include/periph/gpio_ll.h index 365c31b400..6dec66d5cc 100644 --- a/drivers/include/periph/gpio_ll.h +++ b/drivers/include/periph/gpio_ll.h @@ -93,38 +93,63 @@ typedef uintptr_t gpio_port_t; #define GPIO_PORT_UNDEF UINTPTR_MAX #endif -#ifdef DOXYGEN +#if defined(DOXYGEN) /** - * @brief Get the @ref gpio_port_t value of the port identified by @p num + * @brief Indicates whether GPIO ports are enumerated alphabetically (`1`) + * or numerically (`0`). * - * @note If @p num is a compile time constant, this is guaranteed to be - * suitable for a constant initializer. - * - * Typically this will be something like `(GPIO_BASE_ADDR + num * sizeof(struct - * vendor_gpio_reg))` + * @note You can use both @ref GPIO_PORT_A and @ref GPIO_PORT_0 to refer + * to the first GPIO port in RIOT, regardless of the naming scheme + * used by the MCU the app is compiled for. This macro is useful + * e.g. for pretty-printing. */ -#define GPIO_PORT(num) implementation_specific +# define GPIO_PORT_NUMBERING_ALPHABETIC implementation_specific #endif + #ifdef DOXYGEN /** - * @brief Get the number of the GPIO port belonging to the given @ref - * gpio_port_t value + * @brief Get the @ref gpio_port_t value of the port labeled 0. * - * @note If @p port is a compile time constant, this is guaranteed to be - * suitable for a constant initializer. - * - * @pre @p port is the return value of @ref GPIO_PORT - * - * For every supported port number *n* the following `assert()` must not blow - * up: - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c} - * assert(n == GPIO_PORT_NUM(GPIO_PORT(n))); - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * @note For MCUs that use letters instead of numbers, this will be an alias + * for @ref GPIO_PORT_A + * @note Some MCUs will not start with Port 0 / Port A, but rather with + * Port 1 (e.g. MSP430) or Port B (e.g. ATmega328P). It will be + * undefined when unavailable + * @note There will also be `GPIO_PORT_1`, `GPIO_PORT_2`, etc. when there + * are corresponding GPIO ports in hardware. */ -#define GPIO_PORT_NUM(port) implementation_specific -#endif +#define GPIO_PORT_0 implementation_specific + +/** + * @brief Get the @ref gpio_port_t value of the port number @p num + * @param[in] num The number of the port to get + * @pre @p num is a valid GPIO port number. An implementation may + * follow the "garbage in, garbage out" philosophy. + * + * @note If the MCU uses an alphabetic naming scheme, number 0 refers + * to port A. + * @warning This may involve accessing a lookup table, prefer e.g. using + * `GPIO_PORT_0` over `gpio_port(0)` if the port number is known + * at compile time. + */ +gpio_port_t gpio_port(uword_t num); + +/** + * @brief Get the number of the GPIO port @p port refers to + * @param[in] port The port to get the number of + * + * @pre @p port is a valid GPIO port. An implementation may follow the + * "garbage in, garbage out" philosophy. + * @warning This may involve iterating over a lookup table, prefer using + * e.g. `0` instead of `gpio_port_num(GPIO_PORT_0)` if the port + * number is known at compile time. + * + * In other words `n == gpio_port_num(gpio_port(n))` for every `n` that is + * a valid port number. + */ +uword_t gpio_port_num(gpio_port_t port); +#endif /* DOXYGEN */ #if !defined(HAVE_GPIO_STATE_T) || defined(DOXYGEN) /** @@ -490,7 +515,7 @@ static const gpio_conf_t gpio_ll_od_pu = { #endif /** - * @brief Check if the given number is a valid argument for @ref GPIO_PORT + * @brief Check if the given number is a valid argument for @ref gpio_port * * @param[in] num port number to check * @retval true the MCU used has a GPIO port with that number @@ -868,5 +893,111 @@ static inline void gpio_ll_switch_dir_input(gpio_port_t port, uword_t inputs) * to be provided */ #include "gpio_ll_arch.h" /* IWYU pragma: export */ +#if !defined(DOXYGEN) && !defined(GPIO_PORT_NUMBERING_ALPHABETIC) +# define GPIO_PORT_NUMBERING_ALPHABETIC 0 +#endif + +/** + * @name GPIO port aliases for alphabetic enumeration + * @{ + */ +#if defined(GPIO_PORT_0) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_0` + */ +# define GPIO_PORT_A GPIO_PORT_0 +#endif +#if defined(GPIO_PORT_1) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_1` + */ +# define GPIO_PORT_B GPIO_PORT_1 +#endif +#if defined(GPIO_PORT_2) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_2` + */ +# define GPIO_PORT_C GPIO_PORT_2 +#endif +#if defined(GPIO_PORT_3) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_3` + */ +# define GPIO_PORT_D GPIO_PORT_3 +#endif +#if defined(GPIO_PORT_4) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_4` + */ +# define GPIO_PORT_E GPIO_PORT_4 +#endif +#if defined(GPIO_PORT_5) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_5` + */ +# define GPIO_PORT_F GPIO_PORT_5 +#endif +#if defined(GPIO_PORT_6) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_6` + */ +# define GPIO_PORT_G GPIO_PORT_6 +#endif +#if defined(GPIO_PORT_7) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_7` + */ +# define GPIO_PORT_H GPIO_PORT_7 +#endif +#if defined(GPIO_PORT_8) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_8` + */ +# define GPIO_PORT_I GPIO_PORT_8 +#endif +#if defined(GPIO_PORT_9) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_9` + */ +# define GPIO_PORT_J GPIO_PORT_9 +#endif +#if defined(GPIO_PORT_10) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_10` + */ +# define GPIO_PORT_K GPIO_PORT_10 +#endif +#if defined(GPIO_PORT_11) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_11` + */ +# define GPIO_PORT_L GPIO_PORT_11 +#endif +#if defined(GPIO_PORT_12) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_12` + */ +# define GPIO_PORT_M GPIO_PORT_12 +#endif +#if defined(GPIO_PORT_13) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_13` + */ +# define GPIO_PORT_N GPIO_PORT_13 +#endif +#if defined(GPIO_PORT_14) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_14` + */ +# define GPIO_PORT_O GPIO_PORT_14 +#endif +#if defined(GPIO_PORT_15) || defined(DOXYGEN) +/** + * @brief Alias of `ref GPIO_PORT_15` + */ +# define GPIO_PORT_P GPIO_PORT_15 +#endif +/** @} */ + #endif /* PERIPH_GPIO_LL_H */ /** @} */ diff --git a/tests/bench/periph_gpio_ll/Makefile b/tests/bench/periph_gpio_ll/Makefile index 6b22fb729b..92d3780748 100644 --- a/tests/bench/periph_gpio_ll/Makefile +++ b/tests/bench/periph_gpio_ll/Makefile @@ -9,7 +9,7 @@ BOARD ?= nucleo-f767zi # # Beware: If other pins on the output port are configured as output GPIOs, they # might be written to during this test. -PORT_OUT ?= 0 +#PORT_OUT := 0 PIN_OUT_0 ?= 0 PIN_OUT_1 ?= 1 @@ -36,7 +36,10 @@ endif COMPENSATE_OVERHEAD ?= 1 -CFLAGS += -DPORT_OUT=$(PORT_OUT) +ifneq (,$(PORT_OUT)) + CFLAGS += -DPORT_OUT=GPIO_PORT_$(PORT_OUT) + CFLAGS += -DPORT_OUT_NUM=$(PORT_OUT) +endif CFLAGS += -DPIN_OUT_0=$(PIN_OUT_0) CFLAGS += -DPIN_OUT_1=$(PIN_OUT_1) CFLAGS += -DCOMPENSATE_OVERHEAD=$(COMPENSATE_OVERHEAD) diff --git a/tests/bench/periph_gpio_ll/main.c b/tests/bench/periph_gpio_ll/main.c index baf5496f73..3d93060c22 100644 --- a/tests/bench/periph_gpio_ll/main.c +++ b/tests/bench/periph_gpio_ll/main.c @@ -30,7 +30,20 @@ #define COMPENSATE_OVERHEAD 1 #endif -static gpio_port_t port_out = GPIO_PORT(PORT_OUT); +#ifndef PORT_OUT +# if defined(GPIO_PORT_0) +# define PORT_OUT GPIO_PORT_0 +# define PORT_OUT_NUM 0 +# elif defined(GPIO_PORT_1) +# define PORT_OUT GPIO_PORT_1 +# define PORT_OUT_NUM 1 +# elif defined(GPIO_PORT_2) +# define PORT_OUT GPIO_PORT_2 +# define PORT_OUT_NUM 2 +# endif +#endif + +static gpio_port_t port_out = PORT_OUT; static void print_summary_compensated(uint_fast16_t loops, uint32_t duration, uint32_t duration_uncompensated) @@ -124,8 +137,8 @@ int main(void) puts("\n" "periph/gpio: Using 2x gpio_set() and 2x gpio_clear()\n" "---------------------------------------------------"); - gpio_t p0 = GPIO_PIN(PORT_OUT, PIN_OUT_0); - gpio_t p1 = GPIO_PIN(PORT_OUT, PIN_OUT_1); + gpio_t p0 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_0); + gpio_t p1 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_1); gpio_init(p0, GPIO_OUT); gpio_init(p1, GPIO_OUT); @@ -177,8 +190,8 @@ int main(void) puts("\n" "periph/gpio: Using 4x gpio_toggle()\n" "-----------------------------------"); - gpio_t p0 = GPIO_PIN(PORT_OUT, PIN_OUT_0); - gpio_t p1 = GPIO_PIN(PORT_OUT, PIN_OUT_1); + gpio_t p0 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_0); + gpio_t p1 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_1); gpio_init(p0, GPIO_OUT); gpio_init(p1, GPIO_OUT); @@ -230,8 +243,8 @@ int main(void) puts("\n" "periph/gpio: Using 4x gpio_write()\n" "----------------------------------"); - gpio_t p0 = GPIO_PIN(PORT_OUT, PIN_OUT_0); - gpio_t p1 = GPIO_PIN(PORT_OUT, PIN_OUT_1); + gpio_t p0 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_0); + gpio_t p1 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_1); gpio_init(p0, GPIO_OUT); gpio_init(p1, GPIO_OUT); diff --git a/tests/periph/gpio_ll/Makefile b/tests/periph/gpio_ll/Makefile index d713b1082c..d38f21c4a2 100644 --- a/tests/periph/gpio_ll/Makefile +++ b/tests/periph/gpio_ll/Makefile @@ -9,8 +9,8 @@ BOARD ?= nucleo-f767zi # pins *must* be on the same port, respectively. Connect the first input to the # first output pin and the second input pin to the second output pin, e.g. using # jumper wires. -PORT_IN ?= 1 -PORT_OUT ?= 1 +PORT_IN ?= +PORT_OUT ?= PIN_IN_0 ?= 0 PIN_IN_1 ?= 1 PIN_OUT_0 ?= 2 @@ -38,8 +38,14 @@ USEMODULE += ztimer_usec include $(RIOTBASE)/Makefile.include -CFLAGS += -DPORT_OUT=$(PORT_OUT) -CFLAGS += -DPORT_IN=$(PORT_IN) +ifneq (,$(PORT_OUT)) + CFLAGS += -DPORT_OUT=GPIO_PORT_$(PORT_OUT) + CFLAGS += -DPORT_OUT_NUM=$(PORT_OUT) +endif +ifneq (,$(PORT_IN)) + CFLAGS += -DPORT_IN=GPIO_PORT_$(PORT_IN) + CFLAGS += -DPORT_IN_NUM=$(PORT_IN) +endif CFLAGS += -DPIN_IN_0=$(PIN_IN_0) CFLAGS += -DPIN_IN_1=$(PIN_IN_1) CFLAGS += -DPIN_OUT_0=$(PIN_OUT_0) diff --git a/tests/periph/gpio_ll/Makefile.ci b/tests/periph/gpio_ll/Makefile.ci index 72db76ccb5..600f7e5a21 100644 --- a/tests/periph/gpio_ll/Makefile.ci +++ b/tests/periph/gpio_ll/Makefile.ci @@ -1,3 +1,4 @@ BOARD_INSUFFICIENT_MEMORY := \ atmega8 \ + samd10-xmini \ # diff --git a/tests/periph/gpio_ll/main.c b/tests/periph/gpio_ll/main.c index d6b0603d62..bc672fa9fa 100644 --- a/tests/periph/gpio_ll/main.c +++ b/tests/periph/gpio_ll/main.c @@ -36,9 +36,33 @@ #define LOW_ROM 0 #endif +/* On e.g. ATmega328P the smallest available GPIO Port is GPIO_PORT_1 (GPIOB), + * on others (e.g. nRF51) the highest available GPIO PORT is GPIO_PORT_0. + * So we need the following dance to find a valid GPIO port to allow compile + * testing. Extend the dance as needed, when new MCUs are added */ +#if !defined(PORT_OUT) +# if defined(GPIO_PORT_0) +# define PORT_OUT GPIO_PORT_0 +# define PORT_OUT_NUM 0 +# elif defined(GPIO_PORT_1) +# define PORT_OUT GPIO_PORT_1 +# define PORT_OUT_NUM 1 +# endif +#endif + +#if !defined(PORT_IN) +# if defined(GPIO_PORT_0) +# define PORT_IN GPIO_PORT_0 +# define PORT_IN_NUM 0 +# elif defined(GPIO_PORT_1) +# define PORT_IN GPIO_PORT_1 +# define PORT_IN_NUM 1 +# endif +#endif + static const char *noyes[] = { "no", "yes" }; -static gpio_port_t port_out = GPIO_PORT(PORT_OUT); -static gpio_port_t port_in = GPIO_PORT(PORT_IN); +static gpio_port_t port_out = PORT_OUT; +static gpio_port_t port_in = PORT_IN; static const uint64_t mutex_timeout = US_PER_MS; @@ -75,9 +99,15 @@ static void expect_impl(int val, unsigned line) static void print_cabling(unsigned port1, unsigned pin1, unsigned port2, unsigned pin2) { - printf(" P%u.%u (P%c%u) -- P%u.%u (P%c%u)\n", - port1, pin1, 'A' + (char)port1, pin1, - port2, pin2, 'A' + (char)port2, pin2); + if (GPIO_PORT_NUMBERING_ALPHABETIC) { + /* alphabetic naming scheme */ + printf(" P%c%u -- P%c%u\n", 'A' + (char)port1, pin1, + 'A' + (char)port2, pin2); + } + else { + /* numeric naming scheme */ + printf(" P%u.%u -- P%u.%u\n", port1, pin1, port2, pin2); + } } static void print_details(void) @@ -86,8 +116,8 @@ static void print_details(void) "========================\n" "Cabling:\n" "(INPUT -- OUTPUT)"); - print_cabling(PORT_IN, PIN_IN_0, PORT_OUT, PIN_OUT_0); - print_cabling(PORT_IN, PIN_IN_1, PORT_OUT, PIN_OUT_1); + print_cabling(PORT_IN_NUM, PIN_IN_0, PORT_OUT_NUM, PIN_OUT_0); + print_cabling(PORT_IN_NUM, PIN_IN_1, PORT_OUT_NUM, PIN_OUT_1); printf("Number of pull resistor values supported: %u\n", GPIO_PULL_NUMOF); printf("Number of drive strengths supported: %u\n", GPIO_DRIVE_NUMOF); printf("Number of slew rates supported: %u\n", GPIO_SLEW_NUMOF); @@ -486,8 +516,8 @@ static void test_gpio_ll_init(void) "\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)); + expect(is_gpio_port_num_valid(PORT_IN_NUM)); + expect(is_gpio_port_num_valid(PORT_OUT_NUM)); /* first, iterate through input configurations and test them one by one */ test_gpio_ll_init_input_configs();