mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
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 <jorge.gzm@gmail.com>
This commit is contained in:
parent
e33a1f9943
commit
bbc0bdd40c
7 changed files with 273 additions and 5 deletions
|
|
@ -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
|
||||
--------
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
113
boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_spi.c
Normal file
113
boards/risc-v/gd32vw55x/gd32vw553k-start/src/gd32_spi.c
Normal file
|
|
@ -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 */
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue