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
This commit is contained in:
Kerogit 2025-04-15 01:00:08 +02:00 committed by Xiang Xiao
parent 065910c7d3
commit bf76231f3c
10 changed files with 336 additions and 3 deletions

View file

@ -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

View file

@ -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
----

View file

@ -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 | \

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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
****************************************************************************/

View file

@ -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

View file

@ -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 <nuttx/config.h>
#include <nuttx/irq.h>
#include <arch/board/board.h>
#include <nuttx/input/buttons.h>
#include <avr/io.h>
#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;
}

View file

@ -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 <nuttx/config.h>
#include <nuttx/irq.h>
#include <arch/board/board.h>
#ifdef CONFIG_BREADXAVR_BUTTONS_DRIVER
# include <nuttx/input/buttons.h>
#endif
#include <avr/io.h>
#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 */