diff --git a/Documentation/components/drivers/character/gpio.rst b/Documentation/components/drivers/character/gpio.rst index 1728b0f378b..fe3bf735ce4 100644 --- a/Documentation/components/drivers/character/gpio.rst +++ b/Documentation/components/drivers/character/gpio.rst @@ -44,6 +44,8 @@ are supported: * :c:macro:`GPIOC_REGISTER` * :c:macro:`GPIOC_UNREGISTER` * :c:macro:`GPIOC_SETPINTYPE` + * :c:macro:`GPIOC_SETDEBOUNCE` + * :c:macro:`GPIOC_IRQ_SETMASK` .. c:macro:: GPIOC_WRITE @@ -104,8 +106,8 @@ is a pointer to an instance of type :c:enum:`gpio_pintype_e`. The ``GPIOC_REGISTER`` command registers a pin to receive a signal whenever there is an interrupt received on an input GPIO pin. This feature, of course, -depends upon interript GPIO support in the platform specific code. Please -refer to the documentation describing your target platform for futher +depends upon interrupt GPIO support in the platform specific code. Please +refer to the documentation describing your target platform for further information. The argument is the pointer to :c:type:`sigevent` value, a signal to be generated when the interrupt occurs. @@ -131,6 +133,32 @@ The ``GPIOC_SETPINTYPE`` command can be used to change the GPIO pin type (from input pin to output pin, changing interrupt edges and similar). The types to set are listed in :c:enum:`gpio_pintype_e`. +.. c:macro:: GPIOC_SETDEBOUNCE + +The ``GPIOC_SETDEBOUNCE`` command sets the debounce time for a GPIO input pin. +The argument is a pointer to an integer value, which specifies the debounce time in milliseconds. +This helps to filter out spurious transitions (noise) on the input pin. + +Typical use case: + +.. code-block:: c + + int debounce_ms = 10; + int ret = ioctl(fd, GPIOC_SETDEBOUNCE, (unsigned long)(uintptr_t)&debounce_ms); + +.. c:macro:: GPIOC_IRQ_SETMASK + +The ``GPIOC_IRQ_SETMASK`` command sets the interrupt mask for a GPIO pin. +The argument is a pointer to an integer value, which specifies the mask to enable or disable specific interrupt types (such as rising/falling edge, level, etc). +The exact meaning of the mask depends on the platform implementation. + +Typical use case: + +.. code-block:: c + + int irq_mask = /* platform-specific mask value */; + int ret = ioctl(fd, GPIOC_IRQ_SETMASK, (unsigned long)(uintptr_t)&irq_mask); + Application Example ~~~~~~~~~~~~~~~~~~~ diff --git a/drivers/ioexpander/gpio.c b/drivers/ioexpander/gpio.c index 1549d7d4817..522c28c2866 100644 --- a/drivers/ioexpander/gpio.c +++ b/drivers/ioexpander/gpio.c @@ -576,6 +576,34 @@ static int gpio_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } break; + /* Command: GPIOC_SETDEBOUNCE + * Description: Set the GPIO pin debounce duration. + * Argument: The duration of the channel debounce, uint is ns. + */ + + case GPIOC_SETDEBOUNCE: + { + DEBUGASSERT(dev->gp_ops->go_setdebounce != NULL); + ret = dev->gp_ops->go_setdebounce(dev, arg); + break; + } + + /* Command: GPIOC_SETMASK + * Description: Mask or unmask the GPIO interrupt without disabling it. + * When masked, the interrupt is suppressed but the + * interrupt source remains enabled. + * Argument: true to mask the interrupt; + * false to unmask the interrupt. + */ + + case GPIOC_IRQ_SETMASK: + { + bool mask = (bool)arg; + DEBUGASSERT(dev->gp_ops->go_setmask != NULL); + ret = dev->gp_ops->go_setmask(dev, mask); + break; + } + /* Unrecognized command */ default: diff --git a/drivers/ioexpander/gpio_lower_half.c b/drivers/ioexpander/gpio_lower_half.c index 7cf1ab6868c..28c1ebcd04e 100644 --- a/drivers/ioexpander/gpio_lower_half.c +++ b/drivers/ioexpander/gpio_lower_half.c @@ -79,6 +79,10 @@ static int gplh_enable(FAR struct gpio_dev_s *gpio, bool enable); #endif static int gplh_setpintype(FAR struct gpio_dev_s *gpio, enum gpio_pintype_e pintype); +static int gplh_setdebounce(FAR struct gpio_dev_s *gpio, + unsigned long duration); +static int gplh_setmask(FAR struct gpio_dev_s *gpio, + bool mask); /**************************************************************************** * Private Data @@ -98,6 +102,8 @@ static const struct gpio_operations_s g_gplh_ops = NULL, /* enable */ #endif gplh_setpintype, + gplh_setdebounce, + gplh_setmask, }; /* Identifies the type of the GPIO pin */ @@ -395,6 +401,43 @@ static int gplh_setpintype(FAR struct gpio_dev_s *gpio, return OK; } +/**************************************************************************** + * Name: gplh_setdebounce + * + * Description: + * Set I/O expander debounce duration, unit is ns. + * + ****************************************************************************/ + +static int gplh_setdebounce(FAR struct gpio_dev_s *gpio, + unsigned long duration) +{ + FAR struct gplh_dev_s *priv = (FAR struct gplh_dev_s *)gpio; + FAR struct ioexpander_dev_s *ioe = priv->ioe; + uint8_t pin = priv->pin; + IOEXP_SETOPTION(ioe, pin, IOEXPANDER_OPTION_SETDEBOUNCE, + (FAR void *)duration); + return OK; +} + +/**************************************************************************** + * Name: gplh_setmask + * + * Description: + * Set I/O expander whether to enable interrupt mask + * + ****************************************************************************/ + +static int gplh_setmask(FAR struct gpio_dev_s *gpio, + bool mask) +{ + FAR struct gplh_dev_s *priv = (FAR struct gplh_dev_s *)gpio; + FAR struct ioexpander_dev_s *ioe = priv->ioe; + uint8_t pin = priv->pin; + IOEXP_SETOPTION(ioe, pin, IOEXPANDER_OPTION_SETMASK, (FAR void *)mask); + return OK; +} + /**************************************************************************** * Name: gpio_lower_half_internal * diff --git a/include/nuttx/ioexpander/gpio.h b/include/nuttx/ioexpander/gpio.h index 2b8bea79284..cd85ae888bd 100644 --- a/include/nuttx/ioexpander/gpio.h +++ b/include/nuttx/ioexpander/gpio.h @@ -70,14 +70,26 @@ * Description: Set the GPIO pin type. * Argument: The enum gpio_pintype_e type. * + * Command: GPIOC_SETDEBOUNCE + * Description: Set the channel debounce duration + * Argument: The duration of the channel debounce, unit is ns. + + * Command: GPIOC_IRQ_SETMASK + * Description: Mask or unmask the GPIO interrupt without disabling it. + * When masked, the interrupt is suppressed but the + * interrupt source remains enabled. + * Argument: true to mask the interrupt; + * false to unmask the interrupt. */ -#define GPIOC_WRITE _GPIOC(1) -#define GPIOC_READ _GPIOC(2) -#define GPIOC_PINTYPE _GPIOC(3) -#define GPIOC_REGISTER _GPIOC(4) -#define GPIOC_UNREGISTER _GPIOC(5) -#define GPIOC_SETPINTYPE _GPIOC(6) +#define GPIOC_WRITE _GPIOC(1) +#define GPIOC_READ _GPIOC(2) +#define GPIOC_PINTYPE _GPIOC(3) +#define GPIOC_REGISTER _GPIOC(4) +#define GPIOC_UNREGISTER _GPIOC(5) +#define GPIOC_SETPINTYPE _GPIOC(6) +#define GPIOC_SETDEBOUNCE _GPIOC(7) +#define GPIOC_IRQ_SETMASK _GPIOC(8) /**************************************************************************** * Public Types @@ -125,6 +137,8 @@ typedef CODE int (*pin_interrupt_t)(FAR struct gpio_dev_s *dev, uint8_t pin); * - go_attach and go_enable. Required only for the GPIO_INTERRUPT_PIN pin * type. Unused for other pin types, may be NULL. * - go_setpintype. Required for all pin types. + * - go_setdebounce. Required for all pin types. + * - go_setmask. Required only for the GPIO_INTERRUPT_PIN pin */ struct gpio_dev_s; @@ -139,6 +153,9 @@ struct gpio_operations_s CODE int (*go_enable)(FAR struct gpio_dev_s *dev, bool enable); CODE int (*go_setpintype)(FAR struct gpio_dev_s *dev, enum gpio_pintype_e pintype); + CODE int (*go_setdebounce)(FAR struct gpio_dev_s *gpio, + unsigned long duration); + CODE int (*go_setmask)(FAR struct gpio_dev_s *dev, bool enable); }; /* Signal information */ diff --git a/include/nuttx/ioexpander/ioexpander.h b/include/nuttx/ioexpander/ioexpander.h index 48bbcc666c3..b2df1e4b31f 100644 --- a/include/nuttx/ioexpander/ioexpander.h +++ b/include/nuttx/ioexpander/ioexpander.h @@ -82,6 +82,8 @@ #define IOEXPANDER_OPTION_WAKEUPCFG 5 /* Configure interrupt for a pin to wake up the Soc */ #define IOEXPANDER_WAKEUP_DISABLE 0 /* Do not cfg the pin as wake up source */ #define IOEXPANDER_WAKEUP_ENABLE 1 /* Cfg the pin as wake up source */ +#define IOEXPANDER_OPTION_SETDEBOUNCE 6 /* Configure debounce duration */ +#define IOEXPANDER_OPTION_SETMASK 7 /* Mask the interrupter */ /* Access macros ************************************************************/