This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 2e57ed24a7 boards/arm/stm32f401rc-rs485: Add support to GPIO
2e57ed24a7 is described below

commit 2e57ed24a7115e5e776c41ec988874567499106d
Author: Rodrigo Sim <rcsi...@gmail.com>
AuthorDate: Fri Feb 14 15:13:47 2025 -0300

    boards/arm/stm32f401rc-rs485: Add support to GPIO
    
    This commit adds support to GPIO Subsystem for STM32F401RC RS485 board.
    
    Signed-off-by: Rodrigo Sim <rcsi...@gmail.com>
---
 .../arm/stm32/stm32f401rc-rs485/src/CMakeLists.txt |   4 +
 boards/arm/stm32/stm32f401rc-rs485/src/Make.defs   |   4 +
 .../stm32/stm32f401rc-rs485/src/stm32_bringup.c    |  10 +
 .../arm/stm32/stm32f401rc-rs485/src/stm32_gpio.c   | 343 +++++++++++++++++++++
 .../stm32f401rc-rs485/src/stm32f401rc-rs485.h      |  28 ++
 5 files changed, 389 insertions(+)

diff --git a/boards/arm/stm32/stm32f401rc-rs485/src/CMakeLists.txt 
b/boards/arm/stm32/stm32f401rc-rs485/src/CMakeLists.txt
index 95ba56f100..1dc545f551 100644
--- a/boards/arm/stm32/stm32f401rc-rs485/src/CMakeLists.txt
+++ b/boards/arm/stm32/stm32f401rc-rs485/src/CMakeLists.txt
@@ -65,6 +65,10 @@ if(CONFIG_USBMSC)
   list(APPEND SRCS stm32_usbmsc.c)
 endif()
 
+if(CONFIG_DEV_GPIO)
+  list(APPEND SRCS stm32_gpio.c)
+endif()
+
 target_sources(board PRIVATE ${SRCS})
 
 if(CONFIG_ARCH_CHIP_STM32F401RC)
diff --git a/boards/arm/stm32/stm32f401rc-rs485/src/Make.defs 
b/boards/arm/stm32/stm32f401rc-rs485/src/Make.defs
index 50ab449ada..24b7f5c91b 100644
--- a/boards/arm/stm32/stm32f401rc-rs485/src/Make.defs
+++ b/boards/arm/stm32/stm32f401rc-rs485/src/Make.defs
@@ -73,6 +73,10 @@ ifeq ($(CONFIG_USBMSC),y)
 CSRCS += stm32_usbmsc.c
 endif
 
+ifeq ($(CONFIG_DEV_GPIO),y)
+CSRCS += stm32_gpio.c
+endif
+
 DEPPATH += --dep-path board
 VPATH += :board
 CFLAGS += 
${INCDIR_PREFIX}$(TOPDIR)$(DELIM)arch$(DELIM)$(CONFIG_ARCH)$(DELIM)src$(DELIM)board$(DELIM)board
diff --git a/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c 
b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c
index 001d37e550..e3c1148cdc 100644
--- a/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c
+++ b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_bringup.c
@@ -344,5 +344,15 @@ int stm32_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_DEV_GPIO
+  /* Initialize GPIO driver */
+
+  ret = stm32_gpio_initialize();
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "ERROR: stm32_gpio_initialize() failed: %d\n", ret);
+    }
+#endif
+
   return ret;
 }
diff --git a/boards/arm/stm32/stm32f401rc-rs485/src/stm32_gpio.c 
b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_gpio.c
new file mode 100644
index 0000000000..a34eedd582
--- /dev/null
+++ b/boards/arm/stm32/stm32f401rc-rs485/src/stm32_gpio.c
@@ -0,0 +1,343 @@
+/****************************************************************************
+ * boards/arm/stm32/stm32f401rc-rs485/src/stm32_gpio.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 <stdbool.h>
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/clock.h>
+#include <nuttx/wdog.h>
+#include <nuttx/ioexpander/gpio.h>
+
+#include <arch/board/board.h>
+
+#include "chip.h"
+#include "stm32.h"
+#include "stm32f401rc-rs485.h"
+
+#if defined(CONFIG_DEV_GPIO) && !defined(CONFIG_GPIO_LOWER_HALF)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct stm32gpio_dev_s
+{
+  struct gpio_dev_s gpio;
+  uint8_t id;
+};
+
+struct stm32gpint_dev_s
+{
+  struct stm32gpio_dev_s stm32gpio;
+  pin_interrupt_t callback;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+#if BOARD_NGPIOIN > 0
+static int gpin_read(struct gpio_dev_s *dev, bool *value);
+#endif
+#if BOARD_NGPIOOUT > 0
+static int gpout_read(struct gpio_dev_s *dev, bool *value);
+static int gpout_write(struct gpio_dev_s *dev, bool value);
+#endif
+#if BOARD_NGPIOINT > 0
+static int gpint_read(struct gpio_dev_s *dev, bool *value);
+static int gpint_attach(struct gpio_dev_s *dev,
+                        pin_interrupt_t callback);
+static int gpint_enable(struct gpio_dev_s *dev, bool enable);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#if BOARD_NGPIOIN > 0
+static const struct gpio_operations_s gpin_ops =
+{
+  .go_read   = gpin_read,
+  .go_write  = NULL,
+  .go_attach = NULL,
+  .go_enable = NULL,
+};
+#endif
+
+#if BOARD_NGPIOOUT > 0
+static const struct gpio_operations_s gpout_ops =
+{
+  .go_read   = gpout_read,
+  .go_write  = gpout_write,
+  .go_attach = NULL,
+  .go_enable = NULL,
+};
+#endif
+
+#if BOARD_NGPIOINT > 0
+static const struct gpio_operations_s gpint_ops =
+{
+  .go_read   = gpint_read,
+  .go_write  = NULL,
+  .go_attach = gpint_attach,
+  .go_enable = gpint_enable,
+};
+#endif
+
+#if BOARD_NGPIOIN > 0
+/* This array maps the GPIO pins used as INPUT */
+
+static const uint32_t g_gpioinputs[BOARD_NGPIOIN] =
+{
+  GPIO_IN1,
+};
+
+static struct stm32gpio_dev_s g_gpin[BOARD_NGPIOIN];
+#endif
+
+#if BOARD_NGPIOOUT
+/* This array maps the GPIO pins used as OUTPUT */
+
+static const uint32_t g_gpiooutputs[BOARD_NGPIOOUT] =
+{
+  GPIO_OUT1,
+};
+
+static struct stm32gpio_dev_s g_gpout[BOARD_NGPIOOUT];
+#endif
+
+#if BOARD_NGPIOINT > 0
+/* This array maps the GPIO pins used as INTERRUPT INPUTS */
+
+static const uint32_t g_gpiointinputs[BOARD_NGPIOINT] =
+{
+  GPIO_INT1,
+};
+
+static struct stm32gpint_dev_s g_gpint[BOARD_NGPIOINT];
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#if BOARD_NGPIOINT > 0
+static int stm32gpio_interrupt(int irq, void *context, void *arg)
+{
+  struct stm32gpint_dev_s *stm32gpint =
+                        (struct stm32gpint_dev_s *)arg;
+
+  DEBUGASSERT(stm32gpint != NULL && stm32gpint->callback != NULL);
+  gpioinfo("Interrupt! callback=%p\n", stm32gpint->callback);
+
+  stm32gpint->callback(&stm32gpint->stm32gpio.gpio,
+                       stm32gpint->stm32gpio.id);
+  return OK;
+}
+#endif
+
+#if BOARD_NGPIOIN > 0
+static int gpin_read(struct gpio_dev_s *dev, bool *value)
+{
+  struct stm32gpio_dev_s *stm32gpio =
+                        (struct stm32gpio_dev_s *)dev;
+
+  DEBUGASSERT(stm32gpio != NULL && value != NULL);
+  DEBUGASSERT(stm32gpio->id < BOARD_NGPIOIN);
+  gpioinfo("Reading...\n");
+
+  *value = stm32_gpioread(g_gpioinputs[stm32gpio->id]);
+  return OK;
+}
+#endif
+
+#if BOARD_NGPIOOUT > 0
+static int gpout_read(struct gpio_dev_s *dev, bool *value)
+{
+  struct stm32gpio_dev_s *stm32gpio =
+                        (struct stm32gpio_dev_s *)dev;
+
+  DEBUGASSERT(stm32gpio != NULL && value != NULL);
+  DEBUGASSERT(stm32gpio->id < BOARD_NGPIOOUT);
+  gpioinfo("Reading...\n");
+
+  *value = stm32_gpioread(g_gpiooutputs[stm32gpio->id]);
+  return OK;
+}
+
+static int gpout_write(struct gpio_dev_s *dev, bool value)
+{
+  struct stm32gpio_dev_s *stm32gpio =
+                             (struct stm32gpio_dev_s *)dev;
+
+  DEBUGASSERT(stm32gpio != NULL);
+  DEBUGASSERT(stm32gpio->id < BOARD_NGPIOOUT);
+  gpioinfo("Writing %d\n", (int)value);
+
+  stm32_gpiowrite(g_gpiooutputs[stm32gpio->id], value);
+  return OK;
+}
+#endif
+
+#if BOARD_NGPIOINT > 0
+static int gpint_read(struct gpio_dev_s *dev, bool *value)
+{
+  struct stm32gpint_dev_s *stm32gpint =
+                              (struct stm32gpint_dev_s *)dev;
+
+  DEBUGASSERT(stm32gpint != NULL && value != NULL);
+  DEBUGASSERT(stm32gpint->stm32gpio.id < BOARD_NGPIOINT);
+  gpioinfo("Reading int pin...\n");
+
+  *value = stm32_gpioread(g_gpiointinputs[stm32gpint->stm32gpio.id]);
+  return OK;
+}
+
+static int gpint_attach(struct gpio_dev_s *dev,
+                        pin_interrupt_t callback)
+{
+  struct stm32gpint_dev_s *stm32gpint =
+                             (struct stm32gpint_dev_s *)dev;
+
+  gpioinfo("Attaching the callback\n");
+
+  /* Make sure the interrupt is disabled */
+
+  stm32_gpiosetevent(g_gpiointinputs[stm32gpint->stm32gpio.id], false,
+                     false, false, NULL, NULL);
+
+  gpioinfo("Attach %p\n", callback);
+  stm32gpint->callback = callback;
+  return OK;
+}
+
+static int gpint_enable(struct gpio_dev_s *dev, bool enable)
+{
+  struct stm32gpint_dev_s *stm32gpint =
+                              (struct stm32gpint_dev_s *)dev;
+
+  if (enable)
+    {
+      if (stm32gpint->callback != NULL)
+        {
+          gpioinfo("Enabling the interrupt\n");
+
+          /* Configure the interrupt for rising edge */
+
+          stm32_gpiosetevent(g_gpiointinputs[stm32gpint->stm32gpio.id],
+                             true, false, false, stm32gpio_interrupt,
+                             &g_gpint[stm32gpint->stm32gpio.id]);
+        }
+    }
+  else
+    {
+      gpioinfo("Disable the interrupt\n");
+      stm32_gpiosetevent(g_gpiointinputs[stm32gpint->stm32gpio.id],
+                         false, false, false, NULL, NULL);
+    }
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: stm32_gpio_initialize
+ *
+ * Description:
+ *   Initialize GPIO drivers for use with /apps/examples/gpio
+ *
+ ****************************************************************************/
+
+int stm32_gpio_initialize(void)
+{
+  int i;
+  int pincount = 0;
+
+#if BOARD_NGPIOIN > 0
+  for (i = 0; i < BOARD_NGPIOIN; i++)
+    {
+      /* Setup and register the GPIO pin */
+
+      g_gpin[i].gpio.gp_pintype = GPIO_INPUT_PIN;
+      g_gpin[i].gpio.gp_ops     = &gpin_ops;
+      g_gpin[i].id              = i;
+      gpio_pin_register(&g_gpin[i].gpio, pincount);
+
+      /* Configure the pin that will be used as input */
+
+      stm32_configgpio(g_gpioinputs[i]);
+
+      pincount++;
+    }
+#endif
+
+#if BOARD_NGPIOOUT > 0
+  for (i = 0; i < BOARD_NGPIOOUT; i++)
+    {
+      /* Setup and register the GPIO pin */
+
+      g_gpout[i].gpio.gp_pintype = GPIO_OUTPUT_PIN;
+      g_gpout[i].gpio.gp_ops     = &gpout_ops;
+      g_gpout[i].id              = i;
+      gpio_pin_register(&g_gpout[i].gpio, pincount);
+
+      /* Configure the pin that will be used as output */
+
+      stm32_gpiowrite(g_gpiooutputs[i], 0);
+      stm32_configgpio(g_gpiooutputs[i]);
+
+      pincount++;
+    }
+#endif
+
+#if BOARD_NGPIOINT > 0
+  for (i = 0; i < BOARD_NGPIOINT; i++)
+    {
+      /* Setup and register the GPIO pin */
+
+      g_gpint[i].stm32gpio.gpio.gp_pintype = GPIO_INTERRUPT_PIN;
+      g_gpint[i].stm32gpio.gpio.gp_ops     = &gpint_ops;
+      g_gpint[i].stm32gpio.id              = i;
+      gpio_pin_register(&g_gpint[i].stm32gpio.gpio, pincount);
+
+      /* Configure the pin that will be used as interrupt input */
+
+      stm32_configgpio(g_gpiointinputs[i]);
+
+      pincount++;
+    }
+#endif
+
+  return 0;
+}
+#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */
diff --git a/boards/arm/stm32/stm32f401rc-rs485/src/stm32f401rc-rs485.h 
b/boards/arm/stm32/stm32f401rc-rs485/src/stm32f401rc-rs485.h
index e4aa2438dc..1a2da26368 100644
--- a/boards/arm/stm32/stm32f401rc-rs485/src/stm32f401rc-rs485.h
+++ b/boards/arm/stm32/stm32f401rc-rs485/src/stm32f401rc-rs485.h
@@ -146,6 +146,19 @@
 
 #define STM32F401RCRS485_QETIMER 3
 
+/* GPIO pins used by the GPIO Subsystem */
+
+#define BOARD_NGPIOIN     1 /* Amount of GPIO Input pins */
+#define BOARD_NGPIOOUT    1 /* Amount of GPIO Output pins */
+#define BOARD_NGPIOINT    1 /* Amount of GPIO Input w/ Interruption pins */
+
+#define GPIO_IN1          (GPIO_INPUT | GPIO_PULLDOWN | GPIO_SPEED_2MHz | \
+                           GPIO_PORTC | GPIO_PIN4)
+#define GPIO_OUT1         (GPIO_OUTPUT | GPIO_PUSHPULL | GPIO_SPEED_2MHz | \
+                           GPIO_OUTPUT_SET | GPIO_PORTB | GPIO_PIN0)
+#define GPIO_INT1         (GPIO_INPUT | GPIO_PULLDOWN | GPIO_SPEED_2MHz | \
+                           GPIO_PORTC | GPIO_PIN4)
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
@@ -265,6 +278,21 @@ struct i2c_master_s *stm32_i2cbus_initialize(int port);
 
 int stm32_at24_init(char *path);
 
+/****************************************************************************
+ * Name: stm32_gpio_initialize
+ *
+ * Description:
+ *   Initialize GPIO drivers for use with /apps/examples/gpio
+ *
+ * Return Value:
+ *   OK on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEV_GPIO
+int stm32_gpio_initialize(void);
+#endif
+
 /****************************************************************************
  * Name: stm32_adc_setup
  *

Reply via email to