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 bbc0bdd40cc8ec3c65ee2d364443b126d715ed22
Author: Jorge Guzman <[email protected]>
AuthorDate: Fri Jul 24 14:14:21 2026 -0300

    risc-v/gd32vw55x: add sdcard (SPI/FAT) example to gd32vw553k-start
    
    Add an "sdcard" configuration that mounts an SD card over SPI0 with a FAT
    filesystem. The board provides the SPI chip-select glue (gd32_spi0select,
    gd32_spi0status and gd32_spi0register in a new gd32_spi.c) and 
gd32_bringup()
    binds the slot with mmcsd_spislotinitialize() and mounts /dev/mmcsd0 on
    /mnt/sd.
    
    The card is wired to the J1 header: SCK PA2, MISO PA1, MOSI PA0, and a
    software chip select on PA4. CONFIG_MMCSD_MMCSUPPORT is left off (its MMC
    CMD1 probe upsets SD cards).
    
    Signed-off-by: Jorge Guzman <[email protected]>
---
 .../gd32vw55x/boards/gd32vw553k-start/index.rst    |  44 ++++++++
 .../gd32vw553k-start/configs/sdcard/defconfig      |  55 ++++++++++
 .../gd32vw55x/gd32vw553k-start/include/board.h     |   9 ++
 .../risc-v/gd32vw55x/gd32vw553k-start/src/Makefile |   4 +
 .../gd32vw55x/gd32vw553k-start/src/gd32_bringup.c  |  41 +++++++-
 .../gd32vw55x/gd32vw553k-start/src/gd32_spi.c      | 113 +++++++++++++++++++++
 .../gd32vw553k-start/src/gd32vw553k-start.h        |  12 +++
 7 files changed, 273 insertions(+), 5 deletions(-)

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 1b933fde525..f21730c4027 100644
--- a/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst
+++ b/Documentation/platforms/risc-v/gd32vw55x/boards/gd32vw553k-start/index.rst
@@ -256,6 +256,50 @@ duty (100 Hz, 50 % by default)::
 duration for a single run. Put an LED (with a series resistor) or a scope on
 PA0 to see it.
 
+sdcard
+------
+
+NSH plus an SD card on SPI0 with a FAT filesystem. The card is registered as
+``/dev/mmcsd0`` and ``gd32_bringup()`` mounts it on ``/mnt/sd``.
+
+Wire the card (or a microSD-over-SPI breakout) to the J1 header:
+
+======== ==========
+Signal   Pin
+======== ==========
+SCK      PA2
+MISO     PA1
+MOSI     PA0
+CS       PA4
+======== ==========
+
+.. note::
+   Power the breakout from **5 V**, not 3.3 V. These breakouts carry their
+   own 3.3 V regulator, and the SD card draws current bursts while it powers
+   up; feeding 3.3 V directly leaves the card stuck in the ACMD41 init loop
+   (it answers CMD0/CMD8 but never leaves the idle state). A decoupling
+   capacitor close to the card and short leads help too.
+
+The SPI runs its initialisation at ~625 kHz (PCLK2 / 256), slightly above the
+400 kHz of the SD spec, which the vast majority of cards tolerate.
+
+The block device shows up as ``/dev/mmcsd0`` and the bringup already mounts it
+on ``/mnt/sd``, so no manual ``mount`` is needed::
+
+  nsh> ls /dev/
+  /dev:
+   console
+   mmcsd0
+   null
+   ttyS0
+   zero
+  nsh> mount
+    /mnt/sd type vfat
+  nsh> echo "GD32 on NuttX" > /mnt/sd/hello.txt
+  nsh> cat /mnt/sd/hello.txt
+  GD32 on NuttX
+  nsh> ls -l /mnt/sd
+
 littlefs
 --------
 
diff --git a/boards/risc-v/gd32vw55x/gd32vw553k-start/configs/sdcard/defconfig 
b/boards/risc-v/gd32vw55x/gd32vw553k-start/configs/sdcard/defconfig
new file mode 100644
index 00000000000..c67a13b06b8
--- /dev/null
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/configs/sdcard/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_MMCSD_MMCSUPPORT 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_HELLO=y
+CONFIG_FS_FAT=y
+CONFIG_FS_PROCFS=y
+CONFIG_GD32VW55X_SPI=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_MMCSD=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 da55b089268..9f0be66d09c 100644
--- a/boards/risc-v/gd32vw55x/gd32vw553k-start/include/board.h
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/include/board.h
@@ -71,6 +71,15 @@
 #  define GPIO_SPI_SCK   GPIO_SPI_SCK_1    /* PA2, AF5 */
 #  define GPIO_SPI_MISO  GPIO_SPI_MISO_1   /* PA1, AF5 */
 #  define GPIO_SPI_MOSI  GPIO_SPI_MOSI_1   /* PA0, AF5 */
+
+/* SPI0 chip select for the SD card: a plain GPIO output on PA4 (J1),
+ * driven by gd32_spi0select().  Active low, idles high.
+ */
+
+#  define GPIO_SPI0_CSPIN (GPIO_CFG_MODE_OUTPUT | GPIO_CFG_PUPD_NONE | \
+                           GPIO_CFG_PP | GPIO_CFG_SPEED_MAX | \
+                           GPIO_CFG_OUTPUT_SET | GPIO_CFG_PORT_A | \
+                           GPIO_CFG_PIN_4)
 #endif
 
 /* I2C0 uses PA2 (SCL) / PA3 (SDA) on AF4, the pins broken out on the J1
diff --git a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/Makefile 
b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/Makefile
index 5c24706c83c..7c2b813abe9 100644
--- a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/Makefile
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/Makefile
@@ -38,4 +38,8 @@ ifeq ($(CONFIG_BOARDCTL_RESET),y)
 CSRCS += gd32_reset.c
 endif
 
+ifeq ($(CONFIG_GD32VW55X_SPI),y)
+CSRCS += gd32_spi.c
+endif
+
 include $(TOPDIR)/boards/Board.mk
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 939e36e8c74..6426b0028cf 100644
--- a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_bringup.c
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_bringup.c
@@ -37,6 +37,9 @@
 #ifdef CONFIG_SPI_DRIVER
 #  include <nuttx/spi/spi_transfer.h>
 #endif
+#ifdef CONFIG_MMCSD_SPI
+#  include <nuttx/mmcsd.h>
+#endif
 #ifdef CONFIG_GD32VW55X_ADC
 #  include <nuttx/analog/adc.h>
 #endif
@@ -171,19 +174,47 @@ int gd32_bringup(void)
 #endif
 
 #ifdef CONFIG_GD32VW55X_SPI
-  /* The family has a single SPI instance: bus 0 */
+  /* The family has a single SPI instance: bus 0.  Configure the chip select
+   * GPIOs first, then bring the bus up.
+   */
+
+  gd32_spidev_initialize();
 
   spi = gd32_spibus_initialize(0);
   if (spi == NULL)
     {
       ferr("ERROR: failed to initialize SPI0\n");
     }
-#ifdef CONFIG_SPI_DRIVER
-  else if (spi_register(spi, 0) < 0)
+  else
     {
-      ferr("ERROR: failed to register /dev/spi0\n");
-    }
+#ifdef CONFIG_SPI_DRIVER
+      if (spi_register(spi, 0) < 0)
+        {
+          ferr("ERROR: failed to register /dev/spi0\n");
+        }
 #endif
+
+#ifdef CONFIG_MMCSD_SPI
+      /* Bind SPI0 to the MMC/SD SPI slot (/dev/mmcsd0) and mount it as FAT.
+       * The SD card is wired to SPI0 (SCK PA2, MISO PA1, MOSI PA0) with the
+       * chip select on PA4 -- all on the J1 header.
+       */
+
+      ret = mmcsd_spislotinitialize(0, 0, spi);
+      if (ret < 0)
+        {
+          ferr("ERROR: failed to bind SPI0 to the MMC/SD slot: %d\n", ret);
+        }
+      else
+        {
+          ret = nx_mount("/dev/mmcsd0", "/mnt/sd", "vfat", 0, NULL);
+          if (ret < 0)
+            {
+              ferr("ERROR: failed to mount /mnt/sd: %d\n", ret);
+            }
+        }
+#endif
+    }
 #endif
 
 #ifdef CONFIG_GD32VW55X_ADC
diff --git a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_spi.c 
b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_spi.c
new file mode 100644
index 00000000000..2f6cd3a8448
--- /dev/null
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_spi.c
@@ -0,0 +1,113 @@
+/****************************************************************************
+ * boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_spi.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 <inttypes.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <debug.h>
+
+#include <nuttx/spi/spi.h>
+
+#include <arch/board/board.h>
+
+#include "gd32vw55x_gpio.h"
+#include "gd32vw553k-start.h"
+
+#ifdef CONFIG_GD32VW55X_SPI
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: gd32_spidev_initialize
+ *
+ * Description:
+ *   Configure the SPI chip select GPIO(s).  The bus itself is brought up by
+ *   gd32_spibus_initialize().
+ *
+ ****************************************************************************/
+
+void gd32_spidev_initialize(void)
+{
+  /* The SD card chip select on SPI0, idle (de-asserted, high) */
+
+  gd32_gpio_config(GPIO_SPI0_CSPIN);
+  gd32_gpio_write(GPIO_SPI0_CSPIN, true);
+}
+
+/****************************************************************************
+ * Name: gd32_spi0select and gd32_spi0status
+ *
+ * Description:
+ *   The board-specific select and status methods of the SPI interface (see
+ *   include/nuttx/spi/spi.h).  Chip select is active low.
+ *
+ ****************************************************************************/
+
+void gd32_spi0select(struct spi_dev_s *dev, uint32_t devid, bool selected)
+{
+  spiinfo("devid: %" PRIu32 " CS: %s\n", devid,
+          selected ? "assert" : "de-assert");
+
+  gd32_gpio_write(GPIO_SPI0_CSPIN, !selected);
+}
+
+uint8_t gd32_spi0status(struct spi_dev_s *dev, uint32_t devid)
+{
+  uint8_t status = 0;
+
+  if (devid == SPIDEV_MMCSD(0))
+    {
+      /* There is no card-detect line wired, so assume the card is present */
+
+      status |= SPI_STATUS_PRESENT;
+    }
+
+  return status;
+}
+
+#ifdef CONFIG_SPI_CALLBACK
+/****************************************************************************
+ * Name: gd32_spi0register
+ *
+ * Description:
+ *   Register a media-change callback.  This board has no card-detect line,
+ *   so there is nothing to notify; the slot is reported present by
+ *   gd32_spi0status().
+ *
+ ****************************************************************************/
+
+int gd32_spi0register(struct spi_dev_s *dev, spi_mediachange_t callback,
+                      void *arg)
+{
+  return OK;
+}
+#endif
+
+#endif /* CONFIG_GD32VW55X_SPI */
diff --git a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32vw553k-start.h 
b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32vw553k-start.h
index 9188115254a..5e2af344b18 100644
--- a/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32vw553k-start.h
+++ b/boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32vw553k-start.h
@@ -37,4 +37,16 @@
 
 int gd32_bringup(void);
 
+/****************************************************************************
+ * Name: gd32_spidev_initialize
+ *
+ * Description:
+ *   Configure the SPI chip select GPIO(s) used by the board.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_GD32VW55X_SPI
+void gd32_spidev_initialize(void);
+#endif
+
 #endif /* __BOARDS_RISCV_GD32VW55X_GD32VW553K_START_SRC_GD32VW553K_START_H */

Reply via email to