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

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

commit 5ecdf3136495c20d98e9f63dfcd5ba428a5136a4
Author: Jorge Guzman <[email protected]>
AuthorDate: Fri Jul 24 16:19:36 2026 -0300

    risc-v/gd32vw55x: fix ADC reopen and add gd32vw553k-start adc example
    
    adc_shutdown() gates the ADC clock (RCU_APB2EN.ADCEN) when the device is
    closed, but the one-shot adc_reset() that first enabled it only runs at
    registration and adc_setup() never re-enabled it. A second open() then drove
    a clock-gated peripheral whose conversions never completed, so a second run 
of
    a reader such as the adc example hung after opening the device. adc_setup()
    now re-enables the ADC clock; clock gating preserves the register
    configuration, so nothing else has to be re-programmed.
    
    Add an "adc" configuration that exercises the driver. It is the nsh base 
plus
    the ADC driver, registered as /dev/adc0 and read by the adc example. ADC
    channel 8 (ADC_IN8) is routed to PB0 on the J1 header so an analog voltage
    applied there is sampled. The board bringup samples that channel when the 
pin
    is routed, and PB0 is only claimed for the ADC when SPI is off (with SPI on 
it
    belongs to the I2C0 fallback), so the periph configuration is unaffected.
    
    The GD32VW55x ADC converts on demand rather than continuously, so the 
example
    uses the software trigger (CONFIG_EXAMPLES_ADC_SWTRIG) and is bounded to 20
    sample groups so it returns to the prompt.
    
    Signed-off-by: Jorge Guzman <[email protected]>
---
 .../gd32vw55x/boards/gd32vw553k-start/index.rst    | 27 +++++++++++
 arch/risc-v/src/gd32vw55x/gd32vw55x_adc.c          |  9 ++++
 .../gd32vw553k-start/configs/adc/defconfig         | 55 ++++++++++++++++++++++
 .../gd32vw55x/gd32vw553k-start/include/board.h     | 12 +++++
 .../gd32vw55x/gd32vw553k-start/src/gd32_bringup.c  |  6 ++-
 5 files changed, 108 insertions(+), 1 deletion(-)

diff --git 
a/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst 
b/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst
index f21730c4027..b10833d2c7d 100644
--- a/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst
+++ b/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst
@@ -300,6 +300,33 @@ on ``/mnt/sd``, so no manual ``mount`` is needed::
   GD32 on NuttX
   nsh> ls -l /mnt/sd
 
+adc
+---
+
+NSH plus the ADC driver, registered as ``/dev/adc0`` and read by the ``adc``
+example. Channel 8 (ADC_IN8) is routed to **PB0** on the J1 header, so an
+analog voltage applied there is sampled.
+
+The ADC converts on demand rather than continuously, so the example is built
+with ``CONFIG_EXAMPLES_ADC_SWTRIG``: it issues a software trigger and then
+reads a group of samples. It is bounded to 20 groups
+(``CONFIG_EXAMPLES_ADC_NSAMPLES``) so it returns to the prompt::
+
+  nsh> adc
+  adc_main: g_adcstate.count: 20
+  adc_main: Hardware initialized. Opening the ADC device: /dev/adc0
+  Sample:
+  1: channel: 8 value: 2108
+  Sample:
+  1: channel: 8 value: 2115
+  Sample:
+  1: channel: 8 value: 2112
+  ...
+
+The reported ``value`` is the 12-bit conversion (0..4095) spanning 0..3.3 V; a
+1.65 V input (half of the reference) reads about 2048, and tying PB0 to GND or
+3.3 V drives it to the rails.
+
 littlefs
 --------
 
diff --git a/arch/risc-v/src/gd32vw55x/gd32vw55x_adc.c 
b/arch/risc-v/src/gd32vw55x/gd32vw55x_adc.c
index df37f294c9d..94be2eb395a 100644
--- a/arch/risc-v/src/gd32vw55x/gd32vw55x_adc.c
+++ b/arch/risc-v/src/gd32vw55x/gd32vw55x_adc.c
@@ -419,6 +419,15 @@ static int adc_setup(struct adc_dev_s *dev)
       return ret;
     }
 
+  /* Re-enable the ADC clock.  adc_shutdown() gates it on close, and the
+   * one-shot adc_reset() that first turned it on only runs at registration;
+   * without this a second open would drive a clock-gated peripheral and its
+   * conversions would never complete.  Clock gating preserves the register
+   * configuration set up by adc_reset(), so nothing has to be re-programmed.
+   */
+
+  modifyreg32(GD32VW55X_RCU_APB2EN, 0, RCU_APB2EN_ADCEN);
+
   /* Make sure that the interrupts are disabled and power up the ADC */
 
   modifyreg32(GD32VW55X_ADC_CTL0,
diff --git a/boards/risc-v/gd32vw55x/gd32vw553k-start/configs/adc/defconfig 
b/boards/risc-v/gd32vw55x/gd32vw553k-start/configs/adc/defconfig
new file mode 100644
index 00000000000..1e703838fe8
--- /dev/null
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/configs/adc/defconfig
@@ -0,0 +1,55 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed 
.config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that 
includes your
+# modifications.
+#
+# CONFIG_ARCH_LEDS is not set
+CONFIG_ARCH="risc-v"
+CONFIG_ARCH_BOARD="gd32vw553k-start"
+CONFIG_ARCH_BOARD_GD32VW553K_START=y
+CONFIG_ARCH_CHIP="gd32vw55x"
+CONFIG_ARCH_CHIP_GD32VW553KM=y
+CONFIG_ARCH_CHIP_GD32VW55X=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_RISCV=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LOOPSPERMSEC=16000
+CONFIG_BUILTIN=y
+CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_EXAMPLES_ADC=y
+CONFIG_EXAMPLES_ADC_NSAMPLES=20
+CONFIG_EXAMPLES_ADC_SWTRIG=y
+CONFIG_EXAMPLES_HELLO=y
+CONFIG_FS_PROCFS=y
+CONFIG_GD32VW55X_ADC=y
+CONFIG_GD32VW55X_UART2=y
+CONFIG_IDLETHREAD_STACKSIZE=2048
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INIT_STACKSIZE=3072
+CONFIG_INTELHEX_BINARY=y
+CONFIG_LIBC_PERROR_STDOUT=y
+CONFIG_LIBC_STRERROR=y
+CONFIG_NFILE_DESCRIPTORS_PER_BLOCK=6
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=64
+CONFIG_NSH_READLINE=y
+CONFIG_NSH_STRERROR=y
+CONFIG_RAM_SIZE=294400
+CONFIG_RAM_START=0x20000200
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_STACK_COLORATION=y
+CONFIG_START_DAY=13
+CONFIG_START_MONTH=7
+CONFIG_START_YEAR=2026
+CONFIG_SYSTEM_NSH=y
+CONFIG_TASK_NAME_SIZE=12
+CONFIG_UART2_RXBUFSIZE=128
+CONFIG_UART2_SERIAL_CONSOLE=y
+CONFIG_UART2_TXBUFSIZE=128
diff --git a/boards/risc-v/gd32vw55x/gd32vw553k-start/include/board.h 
b/boards/risc-v/gd32vw55x/gd32vw553k-start/include/board.h
index 9f0be66d09c..1e7b41f9bf8 100644
--- a/boards/risc-v/gd32vw55x/gd32vw553k-start/include/board.h
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/include/board.h
@@ -115,6 +115,18 @@
                               GPIO_CFG_AF_1 | GPIO_CFG_PORT_A | GPIO_CFG_PIN_0)
 #endif
 
+/* ADC.  Route ADC channel 8 (ADC_IN8) to PB0 on the J1 header (datasheet
+ * Table 2-5) so an analog signal can be applied there.  When SPI is enabled
+ * PB0 is instead claimed by the I2C0 fallback (see above), so the analog pin
+ * is only routed when SPI is off.  The board bringup samples this channel
+ * when the macro is defined.
+ */
+
+#if defined(CONFIG_GD32VW55X_ADC) && !defined(CONFIG_GD32VW55X_SPI)
+#  define GPIO_ADC_IN8 (GPIO_CFG_MODE_ANALOG | GPIO_CFG_PUPD_NONE | \
+                        GPIO_CFG_PORT_B | GPIO_CFG_PIN_0)
+#endif
+
 /* LEDs *********************************************************************/
 
 /* The GD32VW553K-START has three LEDs on GPIOC, driven push-pull and
diff --git a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_bringup.c 
b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_bringup.c
index 6426b0028cf..e644af7e2a9 100644
--- a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_bringup.c
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_bringup.c
@@ -103,7 +103,11 @@ int gd32_bringup(void)
 #ifdef CONFIG_GD32VW55X_ADC
   static const uint8_t chanlist[1] =
   {
-    0
+#ifdef GPIO_ADC_IN8
+    8   /* ADC_IN8 (PB0) on J1, routed by the adc example */
+#else
+    0   /* ADC_IN0 (PA0); no analog pin routed, registers the device only */
+#endif
   };
 
   struct adc_dev_s *adc;

Reply via email to