mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
drivers/periph_gpio_ll: change API to access GPIO ports
The API was based on the assumption that GPIO ports are mapped in memory sanely, so that a `GPIO_PORT(num)` macro would work allow for constant folding when `num` is known and still be efficient when it is not. Some MCUs, however, will need a look up tables to efficiently translate GPIO port numbers to the port's base address. This will prevent the use of such a `GPIO_PORT(num)` macro in constant initializers. As a result, we rather provide `GPIO_PORT_0`, `GPIO_PORT_1`, etc. macros for each GPIO port present (regardless of MCU naming scheme), as well as `GPIO_PORT_A`, `GPIO_PORT_B`, etc. macros if (and only if) the MCU port naming scheme uses letters rather than numbers. These can be defined as macros to the peripheral base address even when those are randomly mapped into the address space. In addition, a C function `gpio_port()` replaces the role of the `GPIO_PORT()` and `gpio_port_num()` the `GPIO_PORT_NUM()` macro. Those functions will still be implemented as efficient as possible and will allow constant folding where it was formerly possible. Hence, there is no downside for MCUs with sane peripheral memory mapping, but it is highly beneficial for the crazy ones. There are also two benefits for the non-crazy MCUs: 1. We can now test for valid port numbers with `#ifdef GPIO_PORT_<NUM>` - This directly benefits the test in `tests/periph/gpio_ll`, which can now provide a valid GPIO port for each and every board - Writing to invalid memory mapped I/O addresses was treated as triggering undefined behavior by the compiler and used as a optimization opportunity 2. We can now detect at compile time if the naming scheme of the MCU uses letters or numbers, and produce more user friendly output. - This is directly applied in the test app
This commit is contained in:
parent
687a30af33
commit
36e8526046
@ -23,7 +23,8 @@
|
|||||||
#ifndef STM32_LEDS_H
|
#ifndef STM32_LEDS_H
|
||||||
#define 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 "gpio_ll_arch.h"
|
||||||
#include "kernel_defines.h"
|
#include "kernel_defines.h"
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ extern "C" {
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
#if defined(LED0_PORT_NUM) && defined (LED0_PIN_NUM)
|
#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_PIN GPIO_PIN(LED0_PORT_NUM, LED0_PIN_NUM)
|
||||||
# define LED0_MASK (1 << LED0_PIN_NUM)
|
# define LED0_MASK (1 << LED0_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED0_IS_INVERTED)
|
# if IS_ACTIVE(LED0_IS_INVERTED)
|
||||||
@ -50,7 +51,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LED1_PORT_NUM) && defined (LED1_PIN_NUM)
|
#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_PIN GPIO_PIN(LED1_PORT_NUM, LED1_PIN_NUM)
|
||||||
# define LED1_MASK (1 << LED1_PIN_NUM)
|
# define LED1_MASK (1 << LED1_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED1_IS_INVERTED)
|
# if IS_ACTIVE(LED1_IS_INVERTED)
|
||||||
@ -64,7 +65,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LED2_PORT_NUM) && defined (LED2_PIN_NUM)
|
#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_PIN GPIO_PIN(LED2_PORT_NUM, LED2_PIN_NUM)
|
||||||
# define LED2_MASK (1 << LED2_PIN_NUM)
|
# define LED2_MASK (1 << LED2_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED2_IS_INVERTED)
|
# if IS_ACTIVE(LED2_IS_INVERTED)
|
||||||
@ -78,7 +79,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LED3_PORT_NUM) && defined (LED3_PIN_NUM)
|
#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_PIN GPIO_PIN(LED3_PORT_NUM, LED3_PIN_NUM)
|
||||||
# define LED3_MASK (1 << LED3_PIN_NUM)
|
# define LED3_MASK (1 << LED3_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED3_IS_INVERTED)
|
# if IS_ACTIVE(LED3_IS_INVERTED)
|
||||||
@ -92,7 +93,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LED4_PORT_NUM) && defined (LED4_PIN_NUM)
|
#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_PIN GPIO_PIN(LED4_PORT_NUM, LED4_PIN_NUM)
|
||||||
# define LED4_MASK (1 << LED4_PIN_NUM)
|
# define LED4_MASK (1 << LED4_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED4_IS_INVERTED)
|
# if IS_ACTIVE(LED4_IS_INVERTED)
|
||||||
@ -106,7 +107,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LED5_PORT_NUM) && defined (LED5_PIN_NUM)
|
#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_PIN GPIO_PIN(LED5_PORT_NUM, LED5_PIN_NUM)
|
||||||
# define LED5_MASK (1 << LED5_PIN_NUM)
|
# define LED5_MASK (1 << LED5_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED5_IS_INVERTED)
|
# if IS_ACTIVE(LED5_IS_INVERTED)
|
||||||
@ -120,7 +121,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LED6_PORT_NUM) && defined (LED6_PIN_NUM)
|
#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_PIN GPIO_PIN(LED6_PORT_NUM, LED6_PIN_NUM)
|
||||||
# define LED6_MASK (1 << LED6_PIN_NUM)
|
# define LED6_MASK (1 << LED6_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED6_IS_INVERTED)
|
# if IS_ACTIVE(LED6_IS_INVERTED)
|
||||||
@ -134,7 +135,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LED7_PORT_NUM) && defined (LED7_PIN_NUM)
|
#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_PIN GPIO_PIN(LED7_PORT_NUM, LED7_PIN_NUM)
|
||||||
# define LED7_MASK (1 << LED7_PIN_NUM)
|
# define LED7_MASK (1 << LED7_PIN_NUM)
|
||||||
# if IS_ACTIVE(LED7_IS_INVERTED)
|
# if IS_ACTIVE(LED7_IS_INVERTED)
|
||||||
|
@ -57,20 +57,86 @@ extern "C" {
|
|||||||
* whenever the port number is known at compile time.
|
* whenever the port number is known at compile time.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef PORTH
|
#define GPIO_PORT_NUMBERING_ALPHABETIC 1
|
||||||
#define GPIO_PORT(num) \
|
|
||||||
((num >= PORT_H) ? \
|
#ifdef PINA
|
||||||
(ATMEGA_GPIO_BASE_H + ((num) - PORT_H) * ATMEGA_GPIO_SIZE) : \
|
/* We sadly cannot use PINA, as PINA is technically (in terms of C spec lingo)
|
||||||
(ATMEGA_GPIO_BASE_A + (num) * ATMEGA_GPIO_SIZE))
|
* not constant and would trigger:
|
||||||
#define GPIO_PORT_NUM(port) \
|
* initializer element is not constant
|
||||||
(((port) >= ATMEGA_GPIO_BASE_H) ? \
|
* Hence, the defines are a bit more involved to yield proper constants
|
||||||
(((port) - ATMEGA_GPIO_BASE_H) / ATMEGA_GPIO_SIZE + PORT_H) : \
|
* suitable for initializers.
|
||||||
(((port) - ATMEGA_GPIO_BASE_A) / ATMEGA_GPIO_SIZE))
|
*/
|
||||||
#else
|
# define GPIO_PORT_0 (ATMEGA_GPIO_BASE_A)
|
||||||
#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)
|
|
||||||
#endif
|
#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)
|
static inline uword_t gpio_ll_read(gpio_port_t port)
|
||||||
{
|
{
|
||||||
atmega_gpio_port_t *p = (void *)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)
|
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)
|
static inline uint8_t gpio_get_pin_num(gpio_t pin)
|
||||||
|
@ -73,16 +73,16 @@ typedef uint8_t gpio_t;
|
|||||||
#ifdef GPIO_PORT_DESCENDENT
|
#ifdef GPIO_PORT_DESCENDENT
|
||||||
#ifdef _AVR_ATTINY1634_H_INCLUDED
|
#ifdef _AVR_ATTINY1634_H_INCLUDED
|
||||||
/* the only one that requires particular treatment! */
|
/* the only one that requires particular treatment! */
|
||||||
#define ATMEGA_GPIO_BASE_A (0x2F)
|
#define ATMEGA_GPIO_BASE_A 0x2F
|
||||||
#else
|
#else
|
||||||
/* all other port descendent, including :
|
/* all other port descendent, including :
|
||||||
- _AVR_IO8534_ (only have port A but with 0x1B address) ;
|
- _AVR_IO8534_ (only have port A but with 0x1B address) ;
|
||||||
- _AVR_IOAT94K_H_ (only have ports D and E) ;
|
- _AVR_IOAT94K_H_ (only have ports D and E) ;
|
||||||
- _AVR_IOTN28_H_ (only have ports A and D). */
|
- _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 */
|
#endif /* _AVR_ATTINY1634_H_INCLUDED */
|
||||||
#else /* !GPIO_PORT_DESCENDENT */
|
#else /* !GPIO_PORT_DESCENDENT */
|
||||||
#define ATMEGA_GPIO_BASE_A (0x20)
|
#define ATMEGA_GPIO_BASE_A 0x20
|
||||||
#endif /* GPIO_PORT_DESCENDENT */
|
#endif /* GPIO_PORT_DESCENDENT */
|
||||||
/**
|
/**
|
||||||
* @brief Base of the GPIO port G register as memory address
|
* @brief Base of the GPIO port G register as memory address
|
||||||
|
@ -62,7 +62,7 @@ static void clear_pending_irqs(uint8_t exti)
|
|||||||
|
|
||||||
void gpio_ll_irq_mask(gpio_port_t port, uint8_t pin)
|
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)
|
#if defined(EIMSK)
|
||||||
EIMSK &= ~(1 << exti);
|
EIMSK &= ~(1 << exti);
|
||||||
#elif defined(GICR)
|
#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)
|
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)
|
#if defined(EIMSK)
|
||||||
EIMSK |= 1 << exti;
|
EIMSK |= 1 << exti;
|
||||||
#elif defined(GICR)
|
#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)
|
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);
|
clear_pending_irqs(exti);
|
||||||
#if defined(EIMSK)
|
#if defined(EIMSK)
|
||||||
EIMSK |= 1 << exti;
|
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,
|
int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig,
|
||||||
gpio_ll_cb_t cb, void *arg)
|
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);
|
assert((trig != GPIO_TRIGGER_LEVEL_HIGH) && cb);
|
||||||
if (!atmega_has_pin_exti(port_num, pin)) {
|
if (!atmega_has_pin_exti(port_num, pin)) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
@ -48,12 +48,63 @@ extern "C" {
|
|||||||
|
|
||||||
#ifndef DOXYGEN /* hide implementation specific details from Doxygen */
|
#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
|
/* We could do
|
||||||
*
|
*
|
||||||
#define GPIO_PORT(num) (GPIO->P[num])
|
* static inline gpio_port_t gpio_port(uword_t num)
|
||||||
#define GPIO_PORT_NUM(port) ((port - &GPIO->P))
|
* {
|
||||||
|
* 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
|
* for some EFM32 families to
|
||||||
*
|
*
|
||||||
#if defined(_GPIO_P_DOUTSET_MASK)
|
#if defined(_GPIO_P_DOUTSET_MASK)
|
||||||
@ -78,9 +129,15 @@ extern "C" {
|
|||||||
* an implementation for other EFM32 families. For the time being, the
|
* an implementation for other EFM32 families. For the time being, the
|
||||||
* suboptimal-but-works-for-all version is the best we have.
|
* 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)
|
static inline uword_t gpio_port_num(gpio_port_t port)
|
||||||
#define GPIO_PORT_NUM(port) (port)
|
{
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
static inline uword_t gpio_ll_read(gpio_port_t port)
|
static inline uword_t gpio_ll_read(gpio_port_t port)
|
||||||
{
|
{
|
||||||
|
@ -32,12 +32,19 @@ extern "C" {
|
|||||||
|
|
||||||
#ifndef DOXYGEN /* hide implementation specific details from Doxygen */
|
#ifndef DOXYGEN /* hide implementation specific details from Doxygen */
|
||||||
|
|
||||||
#define GPIO_PORT(num) (num)
|
static inline gpio_port_t gpio_port(uword_t num)
|
||||||
#if GPIO_PORT_NUMOF > 1
|
{
|
||||||
# define GPIO_PORT_NUM(port) (port)
|
return num;
|
||||||
#else
|
}
|
||||||
# define GPIO_PORT_NUM(port) 0
|
|
||||||
#endif
|
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)
|
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;
|
volatile uword_t *in = (uint32_t *)GPIO_IN_REG;
|
||||||
/* return 0 for unconfigured pins, the current level at the pin otherwise */
|
/* return 0 for unconfigured pins, the current level at the pin otherwise */
|
||||||
#if GPIO_PORT_NUM > 1
|
#if GPIO_PORT_NUM > 1
|
||||||
if (GPIO_PORT_NUM(port) != 0) {
|
if (gpio_port_num(port) != 0) {
|
||||||
in = (uint32_t *)GPIO_IN1_REG;
|
in = (uint32_t *)GPIO_IN1_REG;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -58,7 +65,7 @@ static inline uword_t gpio_ll_read_output(gpio_port_t port)
|
|||||||
static_assert(GPIO_PORT_NUMOF < 3);
|
static_assert(GPIO_PORT_NUMOF < 3);
|
||||||
volatile uword_t *out = (uint32_t *)GPIO_OUT_REG;
|
volatile uword_t *out = (uint32_t *)GPIO_OUT_REG;
|
||||||
#if GPIO_PORT_NUM > 1
|
#if GPIO_PORT_NUM > 1
|
||||||
if (GPIO_PORT_NUM(port) != 0) {
|
if (gpio_port_num(port) != 0) {
|
||||||
out = (uint32_t *)GPIO_OUT1_REG;
|
out = (uint32_t *)GPIO_OUT1_REG;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -70,7 +77,7 @@ static inline void gpio_ll_set(gpio_port_t port, uword_t mask)
|
|||||||
{
|
{
|
||||||
static_assert(GPIO_PORT_NUMOF < 3);
|
static_assert(GPIO_PORT_NUMOF < 3);
|
||||||
volatile uword_t *out_w1ts = (uint32_t *)GPIO_OUT_W1TS_REG;
|
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
|
#if GPIO_PORT_NUM > 1
|
||||||
out_w1ts = (uint32_t)GPIO_OUT1_W1TS;
|
out_w1ts = (uint32_t)GPIO_OUT1_W1TS;
|
||||||
#endif
|
#endif
|
||||||
@ -83,7 +90,7 @@ static inline void gpio_ll_clear(gpio_port_t port, uword_t mask)
|
|||||||
{
|
{
|
||||||
static_assert(GPIO_PORT_NUMOF < 3);
|
static_assert(GPIO_PORT_NUMOF < 3);
|
||||||
volatile uword_t *out_w1tc = (uint32_t *)GPIO_OUT_W1TC_REG;
|
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
|
#if GPIO_PORT_NUM > 1
|
||||||
out_w1tc = (uint32_t)GPIO_OUT1_W1TC;
|
out_w1tc = (uint32_t)GPIO_OUT1_W1TC;
|
||||||
#endif
|
#endif
|
||||||
@ -97,7 +104,7 @@ static inline void gpio_ll_toggle(gpio_port_t port, uword_t mask)
|
|||||||
static_assert(GPIO_PORT_NUMOF < 3);
|
static_assert(GPIO_PORT_NUMOF < 3);
|
||||||
volatile uword_t *out = (uint32_t *)GPIO_OUT_REG;
|
volatile uword_t *out = (uint32_t *)GPIO_OUT_REG;
|
||||||
#if GPIO_PORT_NUM > 1
|
#if GPIO_PORT_NUM > 1
|
||||||
if (GPIO_PORT_NUM(port) != 0) {
|
if (gpio_port_num(port) != 0) {
|
||||||
out = (uint32_t *)GPIO_OUT1_REG;
|
out = (uint32_t *)GPIO_OUT1_REG;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -111,7 +118,7 @@ static inline void gpio_ll_write(gpio_port_t port, uword_t value)
|
|||||||
static_assert(GPIO_PORT_NUMOF < 3);
|
static_assert(GPIO_PORT_NUMOF < 3);
|
||||||
volatile uword_t *out = (uint32_t *)GPIO_OUT_REG;
|
volatile uword_t *out = (uint32_t *)GPIO_OUT_REG;
|
||||||
#if GPIO_PORT_NUM > 1
|
#if GPIO_PORT_NUM > 1
|
||||||
if (GPIO_PORT_NUM(port) != 0) {
|
if (gpio_port_num(port) != 0) {
|
||||||
out = (uint32_t *)GPIO_OUT1_REG;
|
out = (uint32_t *)GPIO_OUT1_REG;
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
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)
|
static inline uint8_t gpio_get_pin_num(gpio_t pin)
|
||||||
|
@ -151,8 +151,8 @@ typedef enum {
|
|||||||
#if SOC_GPIO_PIN_COUNT > 32
|
#if SOC_GPIO_PIN_COUNT > 32
|
||||||
|
|
||||||
#define GPIO_PORT_NUMOF 2
|
#define GPIO_PORT_NUMOF 2
|
||||||
#define GPIO_PORT_0 GPIO_PORT(0)
|
#define GPIO_PORT_0 0
|
||||||
#define GPIO_PORT_1 GPIO_PORT(1)
|
#define GPIO_PORT_1 1
|
||||||
#define GPIO_PORT_0_PIN_NUMOF (32)
|
#define GPIO_PORT_0_PIN_NUMOF (32)
|
||||||
#define GPIO_PORT_1_PIN_NUMOF (SOC_GPIO_PIN_COUNT - 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 \
|
#define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF \
|
||||||
@ -160,7 +160,7 @@ typedef enum {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
#define GPIO_PORT_NUMOF 1
|
#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_0_PIN_NUMOF (SOC_GPIO_PIN_COUNT)
|
||||||
#define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF : 0)
|
#define GPIO_PORT_PIN_NUMOF(p) ((p == GPIO_PORT_0) ? GPIO_PORT_0_PIN_NUMOF : 0)
|
||||||
|
|
||||||
|
@ -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(is_gpio_port_num_valid(port));
|
||||||
assert(pin < GPIO_PORT_PIN_NUMOF(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 = {
|
gpio_config_t cfg = {
|
||||||
.pin_bit_mask = (1ULL << gpio),
|
.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();
|
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) {
|
if (result.state == GPIO_INPUT) {
|
||||||
result.initial_value = (gpio_ll_read(port) >> pin) & 1UL;
|
result.initial_value = (gpio_ll_read(port) >> pin) & 1UL;
|
||||||
}
|
}
|
||||||
|
@ -61,10 +61,10 @@ int gpio_ll_irq(gpio_port_t port, uint8_t pin, gpio_irq_trig_t trig,
|
|||||||
|
|
||||||
unsigned state = irq_disable();
|
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",
|
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 */
|
/* install GPIO ISR of ESP-IDF if not yet done */
|
||||||
if (!gpio_isr_service_installed &&
|
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)
|
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",
|
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) {
|
if (esp_idf_gpio_intr_disable(gpio) == ESP_OK) {
|
||||||
gpio_int_enabled_table[gpio] = false;
|
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)
|
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",
|
DEBUG("%s gpio=%u port=%u pin=%u\n",
|
||||||
__func__, gpio, port, pin);
|
__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)
|
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",
|
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;
|
volatile uint32_t *status_w1tc = (uint32_t *)GPIO_STATUS_W1TC_REG;
|
||||||
#if GPIO_PORT_NUMOF > 1
|
#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;
|
status_w1tc = (uint32_t *)GPIO_STATUS1_W1TC_REG;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#define GPIO_LL_ARCH_H
|
#define GPIO_LL_ARCH_H
|
||||||
|
|
||||||
#include "architecture.h"
|
#include "architecture.h"
|
||||||
#include "periph/gpio_ll.h"
|
|
||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -35,15 +34,69 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define GPIO_PORT_NUMOF 5
|
#define GPIO_PORT_NUMOF 5
|
||||||
|
|
||||||
/**
|
#define GPIO_PORT_NUMBERING_ALPHABETIC 1
|
||||||
* @brief Get a GPIO port by number
|
|
||||||
*/
|
|
||||||
#define GPIO_PORT(num) (GPIOA_BASE + ((num) << 10))
|
|
||||||
|
|
||||||
/**
|
#ifdef GPIOA_BASE
|
||||||
* @brief Get a GPIO port number by gpio_t value
|
# define GPIO_PORT_0 GPIOA_BASE
|
||||||
*/
|
#endif
|
||||||
#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)
|
static inline uword_t gpio_ll_read(gpio_port_t port)
|
||||||
{
|
{
|
||||||
|
@ -48,7 +48,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
|
|||||||
|
|
||||||
unsigned state = irq_disable();
|
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
|
volatile uint32_t *ctrl = (pin < 8) ? &((GPIO_Type *)port)->CTL0
|
||||||
: &((GPIO_Type *)port)->CTL1;
|
: &((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) {
|
switch (conf.state) {
|
||||||
case GPIO_DISCONNECT:
|
case GPIO_DISCONNECT:
|
||||||
pin_used[GPIO_PORT_NUM(port)] &= ~(1 << pin);
|
pin_used[gpio_port_num(port)] &= ~(1 << pin);
|
||||||
if (pin_used[GPIO_PORT_NUM(port)] == 0) {
|
if (pin_used[gpio_port_num(port)] == 0) {
|
||||||
periph_clk_dis(APB2, (RCU_APB2EN_PAEN_Msk << GPIO_PORT_NUM(port)));
|
periph_clk_dis(APB2, (RCU_APB2EN_PAEN_Msk << gpio_port_num(port)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GPIO_INPUT:
|
case GPIO_INPUT:
|
||||||
pin_used[GPIO_PORT_NUM(port)] |= 1 << pin;
|
pin_used[gpio_port_num(port)] |= 1 << pin;
|
||||||
if (conf.pull == GPIO_FLOATING) {
|
if (conf.pull == GPIO_FLOATING) {
|
||||||
*ctrl |= 0x1 << (pos + 2);
|
*ctrl |= 0x1 << (pos + 2);
|
||||||
}
|
}
|
||||||
@ -82,7 +82,7 @@ int gpio_ll_init(gpio_port_t port, uint8_t pin, gpio_conf_t conf)
|
|||||||
break;
|
break;
|
||||||
case GPIO_OUTPUT_PUSH_PULL:
|
case GPIO_OUTPUT_PUSH_PULL:
|
||||||
case GPIO_OUTPUT_OPEN_DRAIN:
|
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.slew_rate + 1) << pos;
|
||||||
*ctrl |= (conf.state == GPIO_OUTPUT_OPEN_DRAIN ? 0x1 : 0x0) << (pos + 2);
|
*ctrl |= (conf.state == GPIO_OUTPUT_OPEN_DRAIN ? 0x1 : 0x0) << (pos + 2);
|
||||||
if (conf.initial_value) {
|
if (conf.initial_value) {
|
||||||
|
@ -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)
|
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();
|
unsigned irq_state = irq_disable();
|
||||||
int port_num = GPIO_PORT_NUM(port);
|
int port_num = gpio_port_num(port);
|
||||||
|
|
||||||
/* set callback */
|
/* set callback */
|
||||||
_exti_ctx[pin].cb = cb;
|
_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)) {
|
if ((_h_level_triggered & pin_mask) || (_l_level_triggered & pin_mask)) {
|
||||||
/* determine the port of triggered interrupt */
|
/* determine the port of triggered interrupt */
|
||||||
volatile uint32_t *afio_exti_ss = &AFIO->EXTISS0 + (pin >> 2);
|
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 */
|
/* trigger software interrupt if the pin has the according level */
|
||||||
uint32_t level = gpio_ll_read(port) & pin_mask;
|
uint32_t level = gpio_ll_read(port) & pin_mask;
|
||||||
|
@ -51,16 +51,37 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CPU_FAM_NRF51)
|
#if defined(CPU_FAM_NRF51)
|
||||||
#define GPIO_PORT(num) ((gpio_port_t)NRF_GPIO)
|
# define GPIO_PORT_0 ((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)
|
|
||||||
#else
|
#else
|
||||||
#define GPIO_PORT(num) ((gpio_port_t)NRF_P0)
|
# if defined(NRF_P1)
|
||||||
#define GPIO_PORT_NUM(port) 0
|
# define GPIO_PORT_1 ((gpio_port_t)NRF_P1)
|
||||||
|
# endif
|
||||||
|
# define GPIO_PORT_0 ((gpio_port_t)NRF_P0)
|
||||||
#endif
|
#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)
|
static inline uword_t gpio_ll_read(gpio_port_t port)
|
||||||
{
|
{
|
||||||
NRF_GPIO_Type *p = (NRF_GPIO_Type *)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)
|
static inline gpio_port_t gpio_get_port(gpio_t pin)
|
||||||
{
|
{
|
||||||
#if defined(NRF_P1)
|
#if defined(NRF_P1)
|
||||||
return GPIO_PORT(pin >> 5);
|
return gpio_port(pin >> 5);
|
||||||
#else
|
#else
|
||||||
(void)pin;
|
(void)pin;
|
||||||
return GPIO_PORT(0);
|
return GPIO_PORT_0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 */
|
/* param port is not used on nRF5x variants with only one GPIO port */
|
||||||
(void)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);
|
uint8_t channel = get_channel_for_pin(port_num, pin);
|
||||||
assert((trig != GPIO_TRIGGER_LEVEL_HIGH) && (trig != GPIO_TRIGGER_LEVEL_LOW));
|
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 */
|
/* param port is not used on nRF5x variants with only one GPIO port */
|
||||||
(void)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);
|
unsigned channel = get_channel_of_pin(port_num, pin);
|
||||||
assert(channel != GPIOTE_CHAN_NUMOF);
|
assert(channel != GPIOTE_CHAN_NUMOF);
|
||||||
if (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 */
|
/* param port is not used on nRF5x variants with only one GPIO port */
|
||||||
(void)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);
|
unsigned channel = get_channel_of_pin(port_num, pin);
|
||||||
assert(channel != GPIOTE_CHAN_NUMOF);
|
assert(channel != GPIOTE_CHAN_NUMOF);
|
||||||
if (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 */
|
/* param port is not used on nRF5x variants with only one GPIO port */
|
||||||
(void)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);
|
unsigned channel = get_channel_of_pin(port_num, pin);
|
||||||
assert(channel != GPIOTE_CHAN_NUMOF);
|
assert(channel != GPIOTE_CHAN_NUMOF);
|
||||||
if (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 */
|
/* param port is not used on nRF5x variants with only one GPIO port */
|
||||||
(void)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);
|
unsigned channel = get_channel_of_pin(port_num, pin);
|
||||||
assert(channel != GPIOTE_CHAN_NUMOF);
|
assert(channel != GPIOTE_CHAN_NUMOF);
|
||||||
if (channel != GPIOTE_CHAN_NUMOF) {
|
if (channel != GPIOTE_CHAN_NUMOF) {
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#define GPIO_LL_ARCH_H
|
#define GPIO_LL_ARCH_H
|
||||||
|
|
||||||
#include "architecture.h"
|
#include "architecture.h"
|
||||||
#include "periph/gpio_ll.h"
|
|
||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -48,6 +47,36 @@ extern "C" {
|
|||||||
# define GPIO_IOBUS_BASE GPIO_APB_BASE /* no IOBUS present, fall back to APB */
|
# define GPIO_IOBUS_BASE GPIO_APB_BASE /* no IOBUS present, fall back to APB */
|
||||||
#endif
|
#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
|
* @brief Get a GPIO port by number
|
||||||
*/
|
*/
|
||||||
@ -59,6 +88,16 @@ extern "C" {
|
|||||||
#define GPIO_PORT_NUM(port) \
|
#define GPIO_PORT_NUM(port) \
|
||||||
(((port) - (uintptr_t)&GPIO_IOBUS_BASE->Group[0]) / sizeof(GPIO_IOBUS_BASE->Group[0]))
|
(((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)
|
static inline PortGroup *sam0_gpio_iobus2ap(PortGroup *iobus)
|
||||||
{
|
{
|
||||||
const uintptr_t iobus_base = (uintptr_t)GPIO_IOBUS_BASE;
|
const uintptr_t iobus_base = (uintptr_t)GPIO_IOBUS_BASE;
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#define GPIO_LL_ARCH_H
|
#define GPIO_LL_ARCH_H
|
||||||
|
|
||||||
#include "architecture.h"
|
#include "architecture.h"
|
||||||
#include "periph/gpio_ll.h"
|
|
||||||
#include "periph_cpu.h"
|
#include "periph_cpu.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -32,24 +31,70 @@ extern "C" {
|
|||||||
|
|
||||||
#ifndef DOXYGEN /* hide implementation specific details from Doxygen */
|
#ifndef DOXYGEN /* hide implementation specific details from Doxygen */
|
||||||
|
|
||||||
/**
|
#define GPIO_PORT_NUMBERING_ALPHABETIC 1
|
||||||
* @brief Get a GPIO port by number
|
|
||||||
*/
|
#ifdef GPIOA_BASE
|
||||||
#if defined(CPU_FAM_STM32MP1)
|
# define GPIO_PORT_0 GPIOA_BASE
|
||||||
#define GPIO_PORT(num) (GPIOA_BASE + ((num) << 12))
|
|
||||||
#else
|
|
||||||
#define GPIO_PORT(num) (GPIOA_BASE + ((num) << 10))
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
#ifdef GPIOB_BASE
|
||||||
* @brief Get a GPIO port number by gpio_t value
|
# define GPIO_PORT_1 GPIOB_BASE
|
||||||
*/
|
|
||||||
#if defined(CPU_FAM_STM32MP1)
|
|
||||||
#define GPIO_PORT_NUM(port) (((port) - GPIOA_BASE) >> 12)
|
|
||||||
#else
|
|
||||||
#define GPIO_PORT_NUM(port) (((port) - GPIOA_BASE) >> 10)
|
|
||||||
#endif
|
#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)
|
static inline uword_t gpio_ll_read(gpio_port_t port)
|
||||||
{
|
{
|
||||||
GPIO_TypeDef *p = (GPIO_TypeDef *)port;
|
GPIO_TypeDef *p = (GPIO_TypeDef *)port;
|
||||||
|
@ -95,7 +95,7 @@ static inline void print_str(const char *str)
|
|||||||
|
|
||||||
static void _init_clock(gpio_port_t port)
|
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
|
#ifdef PORTG_REQUIRES_EXTERNAL_POWER
|
||||||
if (port == (uintptr_t)GPIOG) {
|
if (port == (uintptr_t)GPIOG) {
|
||||||
/* Port G requires external power supply */
|
/* Port G requires external power supply */
|
||||||
|
@ -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)
|
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();
|
unsigned irq_state = irq_disable();
|
||||||
int port_num = GPIO_PORT_NUM(port);
|
int port_num = gpio_port_num(port);
|
||||||
|
|
||||||
/* set callback */
|
/* set callback */
|
||||||
isr_ctx[pin].cb = cb;
|
isr_ctx[pin].cb = cb;
|
||||||
@ -297,7 +297,7 @@ void isr_exti(void)
|
|||||||
if (level_triggered & (1UL << pin)) {
|
if (level_triggered & (1UL << pin)) {
|
||||||
/* Trading a couple of CPU cycles to not having to store port connected to EXTI in RAM.
|
/* 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. */
|
* 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 actual_level = gpio_ll_read(port) & (1UL << pin);
|
||||||
uint32_t trigger_level = EXTI_REG_RTSR & (1UL << pin);
|
uint32_t trigger_level = EXTI_REG_RTSR & (1UL << pin);
|
||||||
if (actual_level == trigger_level) {
|
if (actual_level == trigger_level) {
|
||||||
|
@ -93,38 +93,63 @@ typedef uintptr_t gpio_port_t;
|
|||||||
#define GPIO_PORT_UNDEF UINTPTR_MAX
|
#define GPIO_PORT_UNDEF UINTPTR_MAX
|
||||||
#endif
|
#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
|
* @note You can use both @ref GPIO_PORT_A and @ref GPIO_PORT_0 to refer
|
||||||
* suitable for a constant initializer.
|
* 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
|
||||||
* Typically this will be something like `(GPIO_BASE_ADDR + num * sizeof(struct
|
* e.g. for pretty-printing.
|
||||||
* vendor_gpio_reg))`
|
|
||||||
*/
|
*/
|
||||||
#define GPIO_PORT(num) implementation_specific
|
# define GPIO_PORT_NUMBERING_ALPHABETIC implementation_specific
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef DOXYGEN
|
#ifdef DOXYGEN
|
||||||
/**
|
/**
|
||||||
* @brief Get the number of the GPIO port belonging to the given @ref
|
* @brief Get the @ref gpio_port_t value of the port labeled 0.
|
||||||
* gpio_port_t value
|
|
||||||
*
|
*
|
||||||
* @note If @p port is a compile time constant, this is guaranteed to be
|
* @note For MCUs that use letters instead of numbers, this will be an alias
|
||||||
* suitable for a constant initializer.
|
* for @ref GPIO_PORT_A
|
||||||
*
|
* @note Some MCUs will not start with Port 0 / Port A, but rather with
|
||||||
* @pre @p port is the return value of @ref GPIO_PORT
|
* Port 1 (e.g. MSP430) or Port B (e.g. ATmega328P). It will be
|
||||||
*
|
* undefined when unavailable
|
||||||
* For every supported port number *n* the following `assert()` must not blow
|
* @note There will also be `GPIO_PORT_1`, `GPIO_PORT_2`, etc. when there
|
||||||
* up:
|
* are corresponding GPIO ports in hardware.
|
||||||
*
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
|
|
||||||
* assert(n == GPIO_PORT_NUM(GPIO_PORT(n)));
|
|
||||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
*/
|
*/
|
||||||
#define GPIO_PORT_NUM(port) implementation_specific
|
#define GPIO_PORT_0 implementation_specific
|
||||||
#endif
|
|
||||||
|
/**
|
||||||
|
* @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)
|
#if !defined(HAVE_GPIO_STATE_T) || defined(DOXYGEN)
|
||||||
/**
|
/**
|
||||||
@ -490,7 +515,7 @@ static const gpio_conf_t gpio_ll_od_pu = {
|
|||||||
#endif
|
#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
|
* @param[in] num port number to check
|
||||||
* @retval true the MCU used has a GPIO port with that number
|
* @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 */
|
* to be provided */
|
||||||
#include "gpio_ll_arch.h" /* IWYU pragma: export */
|
#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 */
|
#endif /* PERIPH_GPIO_LL_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
@ -9,7 +9,7 @@ BOARD ?= nucleo-f767zi
|
|||||||
#
|
#
|
||||||
# Beware: If other pins on the output port are configured as output GPIOs, they
|
# Beware: If other pins on the output port are configured as output GPIOs, they
|
||||||
# might be written to during this test.
|
# might be written to during this test.
|
||||||
PORT_OUT ?= 0
|
#PORT_OUT := 0
|
||||||
PIN_OUT_0 ?= 0
|
PIN_OUT_0 ?= 0
|
||||||
PIN_OUT_1 ?= 1
|
PIN_OUT_1 ?= 1
|
||||||
|
|
||||||
@ -36,7 +36,10 @@ endif
|
|||||||
|
|
||||||
COMPENSATE_OVERHEAD ?= 1
|
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_0=$(PIN_OUT_0)
|
||||||
CFLAGS += -DPIN_OUT_1=$(PIN_OUT_1)
|
CFLAGS += -DPIN_OUT_1=$(PIN_OUT_1)
|
||||||
CFLAGS += -DCOMPENSATE_OVERHEAD=$(COMPENSATE_OVERHEAD)
|
CFLAGS += -DCOMPENSATE_OVERHEAD=$(COMPENSATE_OVERHEAD)
|
||||||
|
@ -30,7 +30,20 @@
|
|||||||
#define COMPENSATE_OVERHEAD 1
|
#define COMPENSATE_OVERHEAD 1
|
||||||
#endif
|
#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,
|
static void print_summary_compensated(uint_fast16_t loops, uint32_t duration,
|
||||||
uint32_t duration_uncompensated)
|
uint32_t duration_uncompensated)
|
||||||
@ -124,8 +137,8 @@ int main(void)
|
|||||||
puts("\n"
|
puts("\n"
|
||||||
"periph/gpio: Using 2x gpio_set() and 2x gpio_clear()\n"
|
"periph/gpio: Using 2x gpio_set() and 2x gpio_clear()\n"
|
||||||
"---------------------------------------------------");
|
"---------------------------------------------------");
|
||||||
gpio_t p0 = GPIO_PIN(PORT_OUT, PIN_OUT_0);
|
gpio_t p0 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_0);
|
||||||
gpio_t p1 = GPIO_PIN(PORT_OUT, PIN_OUT_1);
|
gpio_t p1 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_1);
|
||||||
gpio_init(p0, GPIO_OUT);
|
gpio_init(p0, GPIO_OUT);
|
||||||
gpio_init(p1, GPIO_OUT);
|
gpio_init(p1, GPIO_OUT);
|
||||||
|
|
||||||
@ -177,8 +190,8 @@ int main(void)
|
|||||||
puts("\n"
|
puts("\n"
|
||||||
"periph/gpio: Using 4x gpio_toggle()\n"
|
"periph/gpio: Using 4x gpio_toggle()\n"
|
||||||
"-----------------------------------");
|
"-----------------------------------");
|
||||||
gpio_t p0 = GPIO_PIN(PORT_OUT, PIN_OUT_0);
|
gpio_t p0 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_0);
|
||||||
gpio_t p1 = GPIO_PIN(PORT_OUT, PIN_OUT_1);
|
gpio_t p1 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_1);
|
||||||
gpio_init(p0, GPIO_OUT);
|
gpio_init(p0, GPIO_OUT);
|
||||||
gpio_init(p1, GPIO_OUT);
|
gpio_init(p1, GPIO_OUT);
|
||||||
|
|
||||||
@ -230,8 +243,8 @@ int main(void)
|
|||||||
puts("\n"
|
puts("\n"
|
||||||
"periph/gpio: Using 4x gpio_write()\n"
|
"periph/gpio: Using 4x gpio_write()\n"
|
||||||
"----------------------------------");
|
"----------------------------------");
|
||||||
gpio_t p0 = GPIO_PIN(PORT_OUT, PIN_OUT_0);
|
gpio_t p0 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_0);
|
||||||
gpio_t p1 = GPIO_PIN(PORT_OUT, PIN_OUT_1);
|
gpio_t p1 = GPIO_PIN(PORT_OUT_NUM, PIN_OUT_1);
|
||||||
gpio_init(p0, GPIO_OUT);
|
gpio_init(p0, GPIO_OUT);
|
||||||
gpio_init(p1, GPIO_OUT);
|
gpio_init(p1, GPIO_OUT);
|
||||||
|
|
||||||
|
@ -9,8 +9,8 @@ BOARD ?= nucleo-f767zi
|
|||||||
# pins *must* be on the same port, respectively. Connect the first input to the
|
# 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
|
# first output pin and the second input pin to the second output pin, e.g. using
|
||||||
# jumper wires.
|
# jumper wires.
|
||||||
PORT_IN ?= 1
|
PORT_IN ?=
|
||||||
PORT_OUT ?= 1
|
PORT_OUT ?=
|
||||||
PIN_IN_0 ?= 0
|
PIN_IN_0 ?= 0
|
||||||
PIN_IN_1 ?= 1
|
PIN_IN_1 ?= 1
|
||||||
PIN_OUT_0 ?= 2
|
PIN_OUT_0 ?= 2
|
||||||
@ -38,8 +38,14 @@ USEMODULE += ztimer_usec
|
|||||||
|
|
||||||
include $(RIOTBASE)/Makefile.include
|
include $(RIOTBASE)/Makefile.include
|
||||||
|
|
||||||
CFLAGS += -DPORT_OUT=$(PORT_OUT)
|
ifneq (,$(PORT_OUT))
|
||||||
CFLAGS += -DPORT_IN=$(PORT_IN)
|
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_0=$(PIN_IN_0)
|
||||||
CFLAGS += -DPIN_IN_1=$(PIN_IN_1)
|
CFLAGS += -DPIN_IN_1=$(PIN_IN_1)
|
||||||
CFLAGS += -DPIN_OUT_0=$(PIN_OUT_0)
|
CFLAGS += -DPIN_OUT_0=$(PIN_OUT_0)
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
BOARD_INSUFFICIENT_MEMORY := \
|
BOARD_INSUFFICIENT_MEMORY := \
|
||||||
atmega8 \
|
atmega8 \
|
||||||
|
samd10-xmini \
|
||||||
#
|
#
|
||||||
|
@ -36,9 +36,33 @@
|
|||||||
#define LOW_ROM 0
|
#define LOW_ROM 0
|
||||||
#endif
|
#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 const char *noyes[] = { "no", "yes" };
|
||||||
static gpio_port_t port_out = GPIO_PORT(PORT_OUT);
|
static gpio_port_t port_out = PORT_OUT;
|
||||||
static gpio_port_t port_in = GPIO_PORT(PORT_IN);
|
static gpio_port_t port_in = PORT_IN;
|
||||||
|
|
||||||
static const uint64_t mutex_timeout = US_PER_MS;
|
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,
|
static void print_cabling(unsigned port1, unsigned pin1,
|
||||||
unsigned port2, unsigned pin2)
|
unsigned port2, unsigned pin2)
|
||||||
{
|
{
|
||||||
printf(" P%u.%u (P%c%u) -- P%u.%u (P%c%u)\n",
|
if (GPIO_PORT_NUMBERING_ALPHABETIC) {
|
||||||
port1, pin1, 'A' + (char)port1, pin1,
|
/* alphabetic naming scheme */
|
||||||
port2, pin2, 'A' + (char)port2, pin2);
|
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)
|
static void print_details(void)
|
||||||
@ -86,8 +116,8 @@ static void print_details(void)
|
|||||||
"========================\n"
|
"========================\n"
|
||||||
"Cabling:\n"
|
"Cabling:\n"
|
||||||
"(INPUT -- OUTPUT)");
|
"(INPUT -- OUTPUT)");
|
||||||
print_cabling(PORT_IN, PIN_IN_0, PORT_OUT, PIN_OUT_0);
|
print_cabling(PORT_IN_NUM, PIN_IN_0, PORT_OUT_NUM, PIN_OUT_0);
|
||||||
print_cabling(PORT_IN, PIN_IN_1, PORT_OUT, PIN_OUT_1);
|
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 pull resistor values supported: %u\n", GPIO_PULL_NUMOF);
|
||||||
printf("Number of drive strengths supported: %u\n", GPIO_DRIVE_NUMOF);
|
printf("Number of drive strengths supported: %u\n", GPIO_DRIVE_NUMOF);
|
||||||
printf("Number of slew rates supported: %u\n", GPIO_SLEW_NUMOF);
|
printf("Number of slew rates supported: %u\n", GPIO_SLEW_NUMOF);
|
||||||
@ -486,8 +516,8 @@ static void test_gpio_ll_init(void)
|
|||||||
"\n"
|
"\n"
|
||||||
"Testing is_gpio_port_num_valid() is true for PORT_OUT and "
|
"Testing is_gpio_port_num_valid() is true for PORT_OUT and "
|
||||||
"PORT_IN:");
|
"PORT_IN:");
|
||||||
expect(is_gpio_port_num_valid(PORT_IN));
|
expect(is_gpio_port_num_valid(PORT_IN_NUM));
|
||||||
expect(is_gpio_port_num_valid(PORT_OUT));
|
expect(is_gpio_port_num_valid(PORT_OUT_NUM));
|
||||||
|
|
||||||
/* first, iterate through input configurations and test them one by one */
|
/* first, iterate through input configurations and test them one by one */
|
||||||
test_gpio_ll_init_input_configs();
|
test_gpio_ll_init_input_configs();
|
||||||
|
Loading…
Reference in New Issue
Block a user