From bf76231f3c74e73f077caa13773b93e99ed6ccac Mon Sep 17 00:00:00 2001 From: Kerogit Date: Tue, 15 Apr 2025 01:00:08 +0200 Subject: [PATCH] boards/avr/avrdx/breadxavr: support for buttons handled by input driver This patch registers board buttons in input driver as /dev/buttons and provides functions required by the driver --- .../platforms/avr/avrdx/gpio_intr_mux.rst | 8 +- Documentation/platforms/avr/avrdx/index.rst | 13 ++ arch/avr/src/avrdx/iodefs/avr128da28.h | 2 + boards/Kconfig | 2 + boards/avr/avrdx/breadxavr/Kconfig | 12 ++ .../avrdx/breadxavr/configs/hello/defconfig | 3 + boards/avr/avrdx/breadxavr/include/board.h | 15 ++ boards/avr/avrdx/breadxavr/src/Makefile | 8 + .../avr/avrdx/breadxavr/src/avrdx_buttons.c | 185 ++++++++++++++++++ boards/avr/avrdx/breadxavr/src/avrdx_init.c | 91 +++++++++ 10 files changed, 336 insertions(+), 3 deletions(-) create mode 100644 boards/avr/avrdx/breadxavr/src/avrdx_buttons.c create mode 100644 boards/avr/avrdx/breadxavr/src/avrdx_init.c diff --git a/Documentation/platforms/avr/avrdx/gpio_intr_mux.rst b/Documentation/platforms/avr/avrdx/gpio_intr_mux.rst index 9c73a4d454f..d7114df8500 100644 --- a/Documentation/platforms/avr/avrdx/gpio_intr_mux.rst +++ b/Documentation/platforms/avr/avrdx/gpio_intr_mux.rst @@ -5,7 +5,7 @@ GPIO interrupt multiplexer AVR DA/DB family chips have single interrupt vector for all changes on an I/O port. This poses problem when multiple drivers want to claim the same interrupt (might happen for example with button and discrete -joystick drivers suing pins on the same port.) +joystick drivers using pins on the same port.) The I/O multiplexer solves it by providing interface similar to irq_attach. However, it allows registration of multiple handlers @@ -16,7 +16,8 @@ which pins should be serviced by each handler. Configuration ============= -The GPIO interrupt multiplexer is enabled in :menuselection:`System Type --> GPIO ISR Multiplexer`. All basic initialization is done automatically. +The GPIO interrupt multiplexer is enabled in :menuselection:`System Type --> GPIO ISR Multiplexer`. +All basic initialization is done automatically. Usage ===== @@ -24,7 +25,8 @@ Usage Taking button input driver as an example, this driver requires that the board provides ``board_button_irq`` method which enables and disables servicing interrupts for given button. Other than ID of the button to be configured, -interrupt handler (function pointer) and opaque argument (void pointer) are provided. +interrupt handler (function pointer) and opaque argument (void pointer) +parameters are provided. Instead of calling ``irq_attach`` directly, this function may call ``avrdx_irq_attach_gpio_mux``. Handler and argument are among parameters diff --git a/Documentation/platforms/avr/avrdx/index.rst b/Documentation/platforms/avr/avrdx/index.rst index 8da4a75cd85..6e067097de4 100644 --- a/Documentation/platforms/avr/avrdx/index.rst +++ b/Documentation/platforms/avr/avrdx/index.rst @@ -33,9 +33,22 @@ The following list indicates peripherals supported in NuttX: ========== ================ Peripheral Notes ========== ================ +GPIO In board code UART See below ========== ================ +GPIO +---- + +For the most part, there is no need for any specific support for GPIO +in architecture code. For example, NuttX button input driver should only +need functions defined in the board code to work. + +The architecture code provides means to share single interrupt vector +if the board needs to have multiple peripherals connected to a single +I/O port. See gpio_intr_mux.rst for details and breadxavr board +for example usage. + UART ---- diff --git a/arch/avr/src/avrdx/iodefs/avr128da28.h b/arch/avr/src/avrdx/iodefs/avr128da28.h index 2e63aa0abec..53b0a7fc376 100644 --- a/arch/avr/src/avrdx/iodefs/avr128da28.h +++ b/arch/avr/src/avrdx/iodefs/avr128da28.h @@ -41,6 +41,8 @@ #define PORT_ISC_GM ( PORT_ISC_0_bm | PORT_ISC_1_bm | PORT_ISC_2_bm ) +#define PORT_ISC_BOTHEDGES_GC ( PORT_ISC_0_bm ) + /* CLKCTRL.MCLKCTRLB */ #define CLKCTRL_PDIV_GM ( CLKCTRL_PDIV_0_bm | CLKCTRL_PDIV_1_bm | \ diff --git a/boards/Kconfig b/boards/Kconfig index 781ef7d5eaa..1406a24fe4c 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -84,6 +84,8 @@ config ARCH_BOARD_AVRDX_BREADXAVR bool "AVR Dx chip on breadboard" depends on ARCH_CHIP_AVRDX select ARCH_HAVE_LEDS + select ARCH_HAVE_BUTTONS + select ARCH_HAVE_IRQBUTTONS ---help--- This is a board used to make something use an AVRnDx core so it can be developed and tested. diff --git a/boards/avr/avrdx/breadxavr/Kconfig b/boards/avr/avrdx/breadxavr/Kconfig index f72f3c094ce..468cc79eb93 100644 --- a/boards/avr/avrdx/breadxavr/Kconfig +++ b/boards/avr/avrdx/breadxavr/Kconfig @@ -2,3 +2,15 @@ # For a description of the syntax of this configuration file, # see the file kconfig-language.txt in the NuttX tools repository. # + +if ARCH_BOARD_AVRDX_BREADXAVR + +config BREADXAVR_BUTTONS_DRIVER + bool "Enable button input driver for GPIO pins" + depends on (INPUT_BUTTONS && INPUT_BUTTONS_LOWER && BOARD_EARLY_INITIALIZE) + default n + ---help--- + If set, button driver registered as /dev/buttons + for PORT A and PORT C (pins 2 and 3 for both ports.) + +endif diff --git a/boards/avr/avrdx/breadxavr/configs/hello/defconfig b/boards/avr/avrdx/breadxavr/configs/hello/defconfig index 5d6961e9f28..579f6a6184a 100644 --- a/boards/avr/avrdx/breadxavr/configs/hello/defconfig +++ b/boards/avr/avrdx/breadxavr/configs/hello/defconfig @@ -37,3 +37,6 @@ CONFIG_START_MONTH=6 CONFIG_START_YEAR=2011 CONFIG_STDIO_BUFFER_SIZE=0 CONFIG_TASK_NAME_SIZE=0 +CONFIG_INPUT_BUTTONS=y +CONFIG_INPUT_BUTTONS_LOWER=y +CONFIG_BOARD_EARLY_INITIALIZE=y diff --git a/boards/avr/avrdx/breadxavr/include/board.h b/boards/avr/avrdx/breadxavr/include/board.h index 6a500b89062..5bac0222fc5 100644 --- a/boards/avr/avrdx/breadxavr/include/board.h +++ b/boards/avr/avrdx/breadxavr/include/board.h @@ -57,6 +57,21 @@ #define LED_ASSERTION 6 #define LED_PANIC 7 +/* Button definitions + * + * The breadboard has 4 buttons connected to port A pins 2, 3 and port C + * pins 2, 3 + */ + +enum breadboard_buttons_e +{ + BBRD_BUTTON_1 = 0, + BBRD_BUTTON_2 = 1, + BBRD_BUTTON_3 = 2, + BBRD_BUTTON_4 = 3, + BBRD_NUM_BUTTONS +}; + /**************************************************************************** * Public Types ****************************************************************************/ diff --git a/boards/avr/avrdx/breadxavr/src/Makefile b/boards/avr/avrdx/breadxavr/src/Makefile index 38f01daa8a7..f5ef01580aa 100644 --- a/boards/avr/avrdx/breadxavr/src/Makefile +++ b/boards/avr/avrdx/breadxavr/src/Makefile @@ -28,4 +28,12 @@ ifeq ($(CONFIG_ARCH_LEDS),y) CSRCS += avr_leds.c endif +ifeq ($(CONFIG_BOARD_EARLY_INITIALIZE),y) +CSRCS += avrdx_init.c +endif + +ifeq ($(CONFIG_BREADXAVR_BUTTONS_DRIVER),y) +CSRCS += avrdx_buttons.c +endif + include $(TOPDIR)/boards/Board.mk diff --git a/boards/avr/avrdx/breadxavr/src/avrdx_buttons.c b/boards/avr/avrdx/breadxavr/src/avrdx_buttons.c new file mode 100644 index 00000000000..87568a8f9ca --- /dev/null +++ b/boards/avr/avrdx/breadxavr/src/avrdx_buttons.c @@ -0,0 +1,185 @@ +/**************************************************************************** + * boards/avr/avrdx/breadxavr/src/avrdx_buttons.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include + +#include + +#include "avrdx_gpio.h" +#include "avrdx_iodefs.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef CONFIG_BOARD_EARLY_INITIALIZE +# error Button code must be initialized in board_early_initialize +#endif + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_initialize + * + * Description: + * Function called by the button lower half OS driver code in response + * to call of board_early_initialize() (see in avrdx_init.c.) It initializes + * button resources, making everything ready so board_buttons() and/or + * board_button_irq functions may be called. + * + ****************************************************************************/ + +uint32_t board_button_initialize(void) +{ + /* Button driver expects logical value of 1 when button is pressed, + * need to invert the input. + */ + + PORTA.PIN2CTRL |= (PORT_PULLUPEN_bm | PORT_INVEN_bm); + PORTA.PIN3CTRL |= (PORT_PULLUPEN_bm | PORT_INVEN_bm); + PORTC.PIN2CTRL |= (PORT_PULLUPEN_bm | PORT_INVEN_bm); + PORTC.PIN3CTRL |= (PORT_PULLUPEN_bm | PORT_INVEN_bm); + + return BBRD_NUM_BUTTONS; +} + +/**************************************************************************** + * Name: board_buttons + * + * Description: + * Reader function called by button_lower.c (button driver lower half). + * + * Returned Value: + * Button states returned in integer variable as a bit field. + * + ****************************************************************************/ + +uint32_t board_buttons(void) +{ + uint8_t ret; + uint8_t temp; + + /* Making nxstyle happy by using this temporary variable. + * Comment must not be on the same line either. + */ + + temp = PIN2_bm | PIN3_bm; + ret = (VPORTA.IN & (temp)) >> 2; + ret |= (VPORTC.IN & (PIN2_bm | PIN3_bm)); + + return ret; +} + +/**************************************************************************** + * Name: board_button_irq + * + * Description: + * Setter function called by button_lower.c (button driver lower half). + * + * Input parameters: + * Button ID - numeric value, board code knows what hardware it maps to + * IRQ handler. Handler to be called to service pin interrupt. If set + * to NULL, then the interrupt handling is to be disabled + * Opaque argument arg passed to the handler. Currently always NULL. + * + * Returned Value: + * Value returned by the ISR multiplexer. + * + ****************************************************************************/ + +int board_button_irq(int id, xcpt_t irqhandler, FAR void *arg) +{ + int ret; + uint8_t pin_select; + uint8_t port_idx; + + /* Pins 2 and 3 on both ports, can use a bit of a trick */ + + pin_select = 0x04; + pin_select <<= (id & 1); + + if (id < 2) + { + port_idx = AVRDX_GPIO_PORTA_IDX; + } + else + { + port_idx = AVRDX_GPIO_PORTC_IDX; + } + + if (irqhandler) + { + /* Note that if we wanted only a specific edge, ie. if the button + * driver lower half supported only one type of event (press/release), + * the ISC variable must be inverted because we are inverting + * the input + */ + + ret = avrdx_irq_attach_gpio_mux(\ + port_idx, + pin_select, + irqhandler, + arg, + PORT_ISC_BOTHEDGES_GC + ); + } + else + { + ret = avrdx_irq_detach_gpio_mux(\ + port_idx, + pin_select, + true + ); + } + + return ret; +} diff --git a/boards/avr/avrdx/breadxavr/src/avrdx_init.c b/boards/avr/avrdx/breadxavr/src/avrdx_init.c new file mode 100644 index 00000000000..6e09599e38f --- /dev/null +++ b/boards/avr/avrdx/breadxavr/src/avrdx_init.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * boards/avr/avrdx/breadxavr/src/avrdx_init.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#ifdef CONFIG_BREADXAVR_BUTTONS_DRIVER +# include +#endif + +#include + +#include "avrdx_gpio.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_early_initialize + * + * Description: + * Function called by the OS when BOARD_EARLY_INITIALIZE is set. + * Called after up_initialize, OS has been initialized at this point + * and it is okay to initialize drivers. No waiting for events though. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_EARLY_INITIALIZE +void board_early_initialize(void) +{ + int ret = OK; + +# ifdef CONFIG_BREADXAVR_BUTTONS_DRIVER + ret = btn_lower_initialize("/dev/buttons"); + if (ret != OK) + { + return; + } +# endif +} + +#endif /* CONFIG_BOARD_EARLY_INITIALIZE */