From 8db01ab9a09a7d3128f6b01e696e47ef06af5196 Mon Sep 17 00:00:00 2001 From: Francois Berder <18538310+francois-berder@users.noreply.github.com> Date: Sun, 5 Apr 2020 14:54:07 +0100 Subject: [PATCH 1/5] cpu: mips_pic32_common: Implement GPIO IRQ Signed-off-by: Francois Berder <18538310+francois-berder@users.noreply.github.com> --- cpu/mips_pic32_common/Makefile.features | 1 + cpu/mips_pic32_common/periph/gpio.c | 191 ++++++++++++++++++++++++ 2 files changed, 192 insertions(+) diff --git a/cpu/mips_pic32_common/Makefile.features b/cpu/mips_pic32_common/Makefile.features index f5a08b684f..95e072df63 100644 --- a/cpu/mips_pic32_common/Makefile.features +++ b/cpu/mips_pic32_common/Makefile.features @@ -1,3 +1,4 @@ FEATURES_PROVIDED += periph_cpuid +FEATURES_PROVIDED += periph_gpio periph_gpio_irq -include $(RIOTCPU)/mips32r2_common/Makefile.features diff --git a/cpu/mips_pic32_common/periph/gpio.c b/cpu/mips_pic32_common/periph/gpio.c index 5f6fa6ea51..8be48f6ccf 100644 --- a/cpu/mips_pic32_common/periph/gpio.c +++ b/cpu/mips_pic32_common/periph/gpio.c @@ -20,6 +20,7 @@ */ #include "cpu.h" +#include "eic.h" #include "periph/gpio.h" #include "periph_conf.h" @@ -37,6 +38,14 @@ #define ANSELxCLR(P) ((P)[0x04/0x4]) #define TRISxCLR(P) ((P)[0x14/0x4]) #define TRISxSET(P) ((P)[0x18/0x4]) +#define CNENxCLR(P) ((P)[0x84/0x4]) +#define CNENxSET(P) ((P)[0x88/0x4]) +#define CNNExCLR(P) ((P)[0xA4/0x4]) +#define CNNExSET(P) ((P)[0xA8/0x4]) +#define CNSTATx(P) ((P)[0x90/0x4]) +#define CNCONxCLR(P) ((P)[0x74/0x4]) +#define CNCONxSET(P) ((P)[0x78/0x4]) +#define CNFx(P) ((P)[0xB0/0x4]) /** * @brief Extract the port base address from the given pin identifier @@ -65,6 +74,117 @@ static inline int _pin_num(gpio_t pin) return (pin & 0x0f); } +#ifdef MODULE_PERIPH_GPIO_IRQ +/** + * @brief The PIC32 family has 7 I/O ports and 16 I/O per port + */ +#define PORT_NUMOF (7U) +#define GPIO_NUMOF (16U) + +static gpio_flank_t isr_flank[PORT_NUMOF][GPIO_NUMOF]; +static gpio_isr_ctx_t isr_ctx[PORT_NUMOF][GPIO_NUMOF]; + +#if defined(CPU_FAM_PIC32MX) +static void isr_handler(uint32_t port_addr) +{ + uint32_t cnstat = CNSTATx(_port(port_addr)); + + cnstat &= (1 << GPIO_NUMOF) - 1; + while (cnstat) { + /* we want the position of the first one bit, so N_bits - (N_zeros + 1) */ + int pin = 32 - __builtin_clz(cnstat) - 1; + uint32_t port = PORTx(_port(port_addr)); + + cnstat &= ~(1 << pin); + if (isr_flank[_port_num(port_addr)][pin] == GPIO_BOTH + || (isr_flank[_port_num(port_addr)][pin] == GPIO_RISING && (port & (1U << pin))) + || (isr_flank[_port_num(port_addr)][pin] == GPIO_FALLING && !(port & (1U << pin)))) + isr_ctx[_port_num(port_addr)][pin].cb(isr_ctx[_port_num(port_addr)][pin].arg); + } +} + +static void cn_isr(void) +{ +#ifdef _PORTA_BASE_ADDRESS + isr_handler(_PORTA_BASE_ADDRESS); +#endif +#ifdef _PORTB_BASE_ADDRESS + isr_handler(_PORTB_BASE_ADDRESS); +#endif +#ifdef _PORTC_BASE_ADDRESS + isr_handler(_PORTC_BASE_ADDRESS); +#endif +#ifdef _PORTD_BASE_ADDRESS + isr_handler(_PORTD_BASE_ADDRESS); +#endif +#ifdef _PORTE_BASE_ADDRESS + isr_handler(_PORTE_BASE_ADDRESS); +#endif +#ifdef _PORTF_BASE_ADDRESS + isr_handler(_PORTF_BASE_ADDRESS); +#endif +#ifdef _PORTG_BASE_ADDRESS + isr_handler(_PORTG_BASE_ADDRESS); +#endif + + mips32r2_isr_end(); +} +#elif defined(CPU_FAM_PIC32MZ) +static void isr_handler(uint32_t port_addr) +{ + while (CNFx(_port(port_addr))) { + /* we want the position of the first one bit, so N_bits - (N_zeros + 1) */ + int pin = 32 - __builtin_clz(CNFx(_port(port_addr))) - 1; + + isr_ctx[_port_num(port_addr)][pin].cb(isr_ctx[_port_num(port_addr)][pin].arg); + CNFx(_port(port_addr)) &= ~(1U << pin); + } +} + +static void cn_porta_isr(void) +{ + isr_handler(_PORTA_BASE_ADDRESS); + mips32r2_isr_end(); +} + +static void cn_portb_isr(void) +{ + isr_handler(_PORTB_BASE_ADDRESS); + mips32r2_isr_end(); +} + +static void cn_portc_isr(void) +{ + isr_handler(_PORTC_BASE_ADDRESS); + mips32r2_isr_end(); +} + +static void cn_portd_isr(void) +{ + isr_handler(_PORTD_BASE_ADDRESS); + mips32r2_isr_end(); +} + +static void cn_porte_isr(void) +{ + isr_handler(_PORTE_BASE_ADDRESS); + mips32r2_isr_end(); +} + +static void cn_portf_isr(void) +{ + isr_handler(_PORTF_BASE_ADDRESS); + mips32r2_isr_end(); +} + +static void cn_portg_isr(void) +{ + isr_handler(_PORTG_BASE_ADDRESS); + mips32r2_isr_end(); +} +#endif +#endif /* MODULE_PERIPH_GPIO_IRQ */ + int gpio_init(gpio_t pin, gpio_mode_t mode) { volatile unsigned int * port = _port(pin); @@ -141,3 +261,74 @@ void gpio_write(gpio_t pin, int value) else gpio_clear(pin); } + +#ifdef MODULE_PERIPH_GPIO_IRQ +int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank, + gpio_cb_t cb, void *arg) +{ + int pin_num = _pin_num(pin); + int port_num = _port_num(pin); + + /* set callback */ + isr_ctx[port_num][pin_num].cb = cb; + isr_ctx[port_num][pin_num].arg = arg; + isr_flank[port_num][pin_num] = flank; + + /* initialize pin as input */ + gpio_init(pin, mode); + +#if defined(CPU_FAM_PIC32MX) + set_external_isr_cb(_CHANGE_NOTICE_VECTOR, cn_isr); + eic_configure_priority(_CHANGE_NOTICE_VECTOR, 1, 0); + eic_enable(_CHANGE_NOTICE_A_IRQ + port_num); +#elif defined(CPU_FAM_PIC32MZ) + switch (port_num) { + case PORT_A: set_external_isr_cb(_CHANGE_NOTICE_A_VECTOR, cn_porta_isr); break; + case PORT_B: set_external_isr_cb(_CHANGE_NOTICE_B_VECTOR, cn_portb_isr); break; + case PORT_C: set_external_isr_cb(_CHANGE_NOTICE_C_VECTOR, cn_portc_isr); break; + case PORT_D: set_external_isr_cb(_CHANGE_NOTICE_D_VECTOR, cn_portd_isr); break; + case PORT_E: set_external_isr_cb(_CHANGE_NOTICE_E_VECTOR, cn_porte_isr); break; + case PORT_F: set_external_isr_cb(_CHANGE_NOTICE_F_VECTOR, cn_portf_isr); break; + case PORT_G: set_external_isr_cb(_CHANGE_NOTICE_G_VECTOR, cn_portg_isr); break; + } + eic_configure_priority(_CHANGE_NOTICE_A_VECTOR + port_num, 1, 0); + eic_enable(_CHANGE_NOTICE_A_VECTOR + port_num); + CNCONxSET(_port(pin)) = _CNCONB_EDGEDETECT_MASK; +#endif + CNCONxSET(_port(pin)) = _CNCONB_ON_MASK; + gpio_irq_enable(pin); + + return 0; +} + +void gpio_irq_enable(gpio_t pin) +{ +#if defined(CPU_FAM_PIC32MX) + CNENxSET(_port(pin)) = 1U << _pin_num(pin); +#elif defined(CPU_FAM_PIC32MZ) + switch (isr_flank[_port_num(pin)][_pin_num(pin)]) { + case GPIO_RISING: + CNENxSET(_port(pin)) = 1U << _pin_num(pin); + CNNExCLR(_port(pin)) = 1U << _pin_num(pin); + break; + case GPIO_FALLING: + CNENxCLR(_port(pin)) = 1U << _pin_num(pin); + CNNExSET(_port(pin)) = 1U << _pin_num(pin); + break; + case GPIO_BOTH: + CNENxSET(_port(pin)) = 1U << _pin_num(pin); + CNNExSET(_port(pin)) = 1U << _pin_num(pin); + break; + } +#endif +} + +void gpio_irq_disable(gpio_t pin) +{ + CNENxCLR(_port(pin)) = 1U << _pin_num(pin); +#if defined(CPU_FAM_PIC32Mz) + CNNExCLR(_port(pin)) = 1U << _pin_num(pin); +#endif +} + +#endif /* MODULE_PERIPH_GPIO_IRQ */ From d70f0cab513f5dfebd2577bad4ac11ac402db26b Mon Sep 17 00:00:00 2001 From: Francois Berder <18538310+francois-berder@users.noreply.github.com> Date: Fri, 3 Apr 2020 18:59:35 +0100 Subject: [PATCH 2/5] boards: pic32-wifire: Define buttons configuration Signed-off-by: Francois Berder <18538310+francois-berder@users.noreply.github.com> --- boards/pic32-wifire/Makefile.features | 1 - boards/pic32-wifire/include/board.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/boards/pic32-wifire/Makefile.features b/boards/pic32-wifire/Makefile.features index 051b80b1dc..1731bd2ac7 100644 --- a/boards/pic32-wifire/Makefile.features +++ b/boards/pic32-wifire/Makefile.features @@ -2,6 +2,5 @@ CPU = mips_pic32mz CPU_MODEL = p32mz2048efg100 # Put defined MCU peripherals here (in alphabetical order) -FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/pic32-wifire/include/board.h b/boards/pic32-wifire/include/board.h index 986e4e1c10..ce8c33477f 100644 --- a/boards/pic32-wifire/include/board.h +++ b/boards/pic32-wifire/include/board.h @@ -69,6 +69,17 @@ extern "C" { #define LED4_TOGGLE (LATGINV = LED4_MASK) /** @} */ +/** + * @name Button pin configuration + * @{ + */ +#define BTN0_PIN GPIO_PIN(PORT_A, 5) +#define BTN0_MODE GPIO_IN + +#define BTN1_PIN GPIO_PIN(PORT_A, 4) +#define BTN1_MODE GPIO_IN +/** @} */ + /** * @brief Board level initialization */ From 42f5363ef07de46c152bea8aa9069807fd4ebdc7 Mon Sep 17 00:00:00 2001 From: Francois Berder <18538310+francois-berder@users.noreply.github.com> Date: Fri, 3 Apr 2020 19:02:27 +0100 Subject: [PATCH 3/5] boards: pic32-wifire: Update GPIO SAUL configuration for buttons Signed-off-by: Francois Berder <18538310+francois-berder@users.noreply.github.com> --- boards/pic32-wifire/include/gpio_params.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boards/pic32-wifire/include/gpio_params.h b/boards/pic32-wifire/include/gpio_params.h index 1a30aa0eb1..e04df2cd8a 100644 --- a/boards/pic32-wifire/include/gpio_params.h +++ b/boards/pic32-wifire/include/gpio_params.h @@ -51,6 +51,16 @@ static const saul_gpio_params_t saul_gpio_params[] = .pin = LED4_PIN, .mode = GPIO_OUT, }, + { + .name = "BTN1", + .pin = BTN0_PIN, + .mode = BTN0_MODE, + }, + { + .name = "BTN2", + .pin = BTN1_PIN, + .mode = BTN1_MODE, + }, }; #ifdef __cplusplus From fb610ba7cb5da060d943dd09b2e0499d4436a201 Mon Sep 17 00:00:00 2001 From: Francois Berder <18538310+francois-berder@users.noreply.github.com> Date: Fri, 3 Apr 2020 19:04:55 +0100 Subject: [PATCH 4/5] boards: 6lowpan-clicker: Add button pin configuration Signed-off-by: Francois Berder <18538310+francois-berder@users.noreply.github.com> --- boards/6lowpan-clicker/Makefile.features | 1 - boards/6lowpan-clicker/include/board.h | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/boards/6lowpan-clicker/Makefile.features b/boards/6lowpan-clicker/Makefile.features index c10c2eb5ba..b820d6d873 100644 --- a/boards/6lowpan-clicker/Makefile.features +++ b/boards/6lowpan-clicker/Makefile.features @@ -2,6 +2,5 @@ CPU = mips_pic32mx CPU_MODEL = p32mx470f512h # Put defined MCU peripherals here (in alphabetical order) -FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/6lowpan-clicker/include/board.h b/boards/6lowpan-clicker/include/board.h index 5fe1a32027..11f0e19243 100644 --- a/boards/6lowpan-clicker/include/board.h +++ b/boards/6lowpan-clicker/include/board.h @@ -58,6 +58,17 @@ extern "C" { #define LED2_TOGGLE (LATBINV = LED2_MASK) /** @} */ +/** + * @name Button pin configuration + * @{ + */ +#define BTN0_PIN GPIO_PIN(PORT_E, 7) +#define BTN0_MODE GPIO_IN + +#define BTN1_PIN GPIO_PIN(PORT_B, 0) +#define BTN1_MODE GPIO_IN +/** @} */ + /** * @brief Board level initialization */ From 937a30eca7aff4dd4c196aeddde25afa519cb4a8 Mon Sep 17 00:00:00 2001 From: Francois Berder <18538310+francois-berder@users.noreply.github.com> Date: Fri, 3 Apr 2020 19:05:34 +0100 Subject: [PATCH 5/5] boards: 6lowpan-clicker: Update GPIO SAUL configuration for buttons Signed-off-by: Francois Berder <18538310+francois-berder@users.noreply.github.com> --- boards/6lowpan-clicker/include/gpio_params.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/boards/6lowpan-clicker/include/gpio_params.h b/boards/6lowpan-clicker/include/gpio_params.h index 0fae7ac913..484d9fec9c 100644 --- a/boards/6lowpan-clicker/include/gpio_params.h +++ b/boards/6lowpan-clicker/include/gpio_params.h @@ -41,6 +41,16 @@ static const saul_gpio_params_t saul_gpio_params[] = .pin = LED2_PIN, .mode = GPIO_OUT, }, + { + .name = "T1", + .pin = BTN0_PIN, + .mode = BTN0_MODE, + }, + { + .name = "T2", + .pin = BTN1_PIN, + .mode = BTN1_MODE, + }, }; #ifdef __cplusplus