From 3bfabb4a6cf66b948230036273b104edd0798323 Mon Sep 17 00:00:00 2001 From: Gilles DOFFE Date: Wed, 24 Jan 2024 13:13:31 +0100 Subject: [PATCH 1/4] cpu/native/periph/qdec: remove useless loop Signed-off-by: Gilles DOFFE --- cpu/native/periph/qdec.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cpu/native/periph/qdec.c b/cpu/native/periph/qdec.c index c735d60cc5..c3a3b8aa91 100644 --- a/cpu/native/periph/qdec.c +++ b/cpu/native/periph/qdec.c @@ -71,9 +71,7 @@ int32_t qdec_init(qdec_t qdec, qdec_mode_t mode, qdec_cb_t cb, void *arg) } /* Initialize qdec channels */ - for (uint8_t i = 0; i < QDEC_NUMOF; i++) { - qdecs[qdec] = 0; - } + qdecs[qdec] = 0; /* Reset counter and start qdec */ qdec_start(qdec); From 5b4c8fe92d1d5c421fb4f5380876191b2cef7277 Mon Sep 17 00:00:00 2001 From: Gilles DOFFE Date: Wed, 24 Jan 2024 13:13:31 +0100 Subject: [PATCH 2/4] cpu/native: return 0 for all gpio_init*() calls If the gpio is initialized as an input or interruptable pin, the gpio_mock driver returns -1 leading to failed initialization. However that is not because nothing can change the GPIO state that it has to be an error. Return 0 in all cases. Signed-off-by: Gilles DOFFE --- cpu/native/periph/gpio_mock.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/cpu/native/periph/gpio_mock.c b/cpu/native/periph/gpio_mock.c index 3b1bb02445..e434c2017f 100644 --- a/cpu/native/periph/gpio_mock.c +++ b/cpu/native/periph/gpio_mock.c @@ -20,13 +20,10 @@ #include "periph/gpio.h" int gpio_init(gpio_t pin, gpio_mode_t mode) { - (void) pin; - (void) mode; + (void) pin; + (void) mode; - if (mode >= GPIO_OUT) return 0; - else - return -1; } int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, @@ -38,7 +35,7 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, (void) cb; (void) arg; - return -1; + return 0; } void gpio_irq_enable(gpio_t pin) From 24d9657b403bc5dd9062407f1b2a32f855934f55 Mon Sep 17 00:00:00 2001 From: Gilles DOFFE Date: Thu, 25 Jan 2024 01:57:48 +0100 Subject: [PATCH 3/4] cpu/native: mark gpio_mock function as weak This allows developpers to override gpio behavior into their applications. Signed-off-by: Gilles DOFFE --- cpu/native/periph/gpio_mock.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpu/native/periph/gpio_mock.c b/cpu/native/periph/gpio_mock.c index e434c2017f..e2accd2b51 100644 --- a/cpu/native/periph/gpio_mock.c +++ b/cpu/native/periph/gpio_mock.c @@ -19,14 +19,14 @@ #include "periph/gpio.h" -int gpio_init(gpio_t pin, gpio_mode_t mode) { +__attribute__((weak)) int gpio_init(gpio_t pin, gpio_mode_t mode) { (void) pin; (void) mode; return 0; } -int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, +__attribute__((weak)) int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg) { (void) pin; @@ -38,35 +38,35 @@ int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, return 0; } -void gpio_irq_enable(gpio_t pin) +__attribute__((weak)) void gpio_irq_enable(gpio_t pin) { (void) pin; } -void gpio_irq_disable(gpio_t pin) +__attribute__((weak)) void gpio_irq_disable(gpio_t pin) { (void) pin; } -int gpio_read(gpio_t pin) { +__attribute__((weak)) int gpio_read(gpio_t pin) { (void) pin; return 0; } -void gpio_set(gpio_t pin) { +__attribute__((weak)) void gpio_set(gpio_t pin) { (void) pin; } -void gpio_clear(gpio_t pin) { +__attribute__((weak)) void gpio_clear(gpio_t pin) { (void) pin; } -void gpio_toggle(gpio_t pin) { +__attribute__((weak)) void gpio_toggle(gpio_t pin) { (void) pin; } -void gpio_write(gpio_t pin, int value) { +__attribute__((weak)) void gpio_write(gpio_t pin, int value) { (void) pin; (void) value; } From ebf95d2545499004172607bdb09082d29752805f Mon Sep 17 00:00:00 2001 From: Gilles DOFFE Date: Tue, 27 Feb 2024 00:16:20 +0100 Subject: [PATCH 4/4] cpu/native: enhance GPIO mocking with 2D array representation This commit introduces a more robust GPIO mocking mechanism by utilizing a 2-dimensional array. Each element of the array holds a gpio_mock_t structure describing a pin's attributes such as value, mode, flank, interruption callback, and callback argument. This enhancement allows for the arbitrary simulation of GPIOs across various microcontroller architectures using the current API, while maintaining consistency through the use of the GPIO_PIN macro. Additionally, it should be noted that only the maximum number of ports and maximum number of pins can be altered according to the context. The implemented API in gpio_mock.c remains rudimentary, providing no validation but fulfilling the required functions. However, it remains customizable as all its functions are marked as weak. Signed-off-by: Gilles DOFFE --- cpu/native/include/periph_cpu.h | 46 +++++++++++++++++++++++++++++ cpu/native/periph/gpio_mock.c | 51 +++++++++++++++++++++++++-------- 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/cpu/native/include/periph_cpu.h b/cpu/native/include/periph_cpu.h index 668c877aee..94d70693eb 100644 --- a/cpu/native/include/periph_cpu.h +++ b/cpu/native/include/periph_cpu.h @@ -96,6 +96,52 @@ typedef enum { } gpio_flank_t; /** @} */ +#elif defined(MODULE_PERIPH_GPIO_MOCK) + +/** + * @brief Mocked GPIO + * + * Mocked GPIO representation for simulation. + * @{ + */ +typedef struct { + int value; /**< current value */ + int mode; /**< current mode */ + int flank; /**< flank to trigger interrupts */ + void (*cb)(void *arg); /**< ISR */ + void *arg; /**< ISR arg */ +} gpio_mock_t; +/** @} */ + +#define GPIO_UNDEF 0 + +#ifndef GPIO_PORT_MAX +#define GPIO_PORT_MAX (16) +#endif + +#ifndef GPIO_PIN_MAX +#define GPIO_PIN_MAX (32) +#endif + +/** + * @brief Mocked GPIO array + */ +extern gpio_mock_t gpio_mock[GPIO_PORT_MAX][GPIO_PIN_MAX]; + +#define HAVE_GPIO_T +/** + * @brief Pointer on a mocked GPIO + */ +typedef gpio_mock_t* gpio_t; + +/** + * @brief Define a custom GPIO_PIN macro for native mocked GPIO framework. + * Get the mocked GPIO object from mocked GPIO array. + */ +#define GPIO_PIN(port, pin) \ + (((port >= 0) && (pin >= 0) && (port < GPIO_PORT_MAX) && (pin < GPIO_PIN_MAX)) \ + ? &gpio_mock[port][pin] \ + : GPIO_UNDEF) #endif /* MODULE_PERIPH_GPIO_LINUX | DOXYGEN */ diff --git a/cpu/native/periph/gpio_mock.c b/cpu/native/periph/gpio_mock.c index e2accd2b51..3e75755eea 100644 --- a/cpu/native/periph/gpio_mock.c +++ b/cpu/native/periph/gpio_mock.c @@ -19,23 +19,41 @@ #include "periph/gpio.h" +/** + * @brief Mocked GPIO array + */ +gpio_mock_t gpio_mock[GPIO_PORT_MAX][GPIO_PIN_MAX]; + __attribute__((weak)) int gpio_init(gpio_t pin, gpio_mode_t mode) { (void) pin; (void) mode; - return 0; + if (pin) { + pin->mode = mode; + pin->value = 0; + return 0; + } + + return -1; } __attribute__((weak)) int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, gpio_cb_t cb, void *arg) { - (void) pin; - (void) mode; - (void) flank; (void) cb; (void) arg; - return 0; + if (pin) { + pin->mode = mode; + pin->flank = flank; + pin->value = 0; + pin->cb = cb; + pin->arg = arg; + + return 0; + } + + return -1; } __attribute__((weak)) void gpio_irq_enable(gpio_t pin) @@ -49,26 +67,35 @@ __attribute__((weak)) void gpio_irq_disable(gpio_t pin) } __attribute__((weak)) int gpio_read(gpio_t pin) { - (void) pin; + if (pin) { + return pin->value; + } - return 0; + return -1; } __attribute__((weak)) void gpio_set(gpio_t pin) { - (void) pin; + if (pin) { + pin->value = 1; + } } __attribute__((weak)) void gpio_clear(gpio_t pin) { - (void) pin; + if (pin) { + pin->value = 0; + } } __attribute__((weak)) void gpio_toggle(gpio_t pin) { - (void) pin; + if (pin) { + pin->value ^= 1; + } } __attribute__((weak)) void gpio_write(gpio_t pin, int value) { - (void) pin; - (void) value; + if (pin) { + pin->value = value; + } } /** @} */