Trouble setting up SDHC memory card with FATFS

Hi, I'm trying to set up an SDHC card with SPI plus filesystem (fatfs) on a custom board based on the nRF5340 SoC.

Unfortunately, I'm running into issues using the fs api to mount the fs, although I suspect problems in the lower layer(s).

Concretely, running the code snippet below, I get the following output:

[00:00:00.009,124] <inf> settings_storage: Block count 0
[00:00:00.009,155] <inf> settings_storage: Sector size 512

[00:00:00.009,155] <inf> settings_storage: Memory Size(MB) 0

[00:00:00.009,216] <err> fs: fs mount error (-5)
[00:00:00.009,216] <err> settings_storage: Mounting failed (-5)

Adding to prj.conf the following

CONFIG_DEBUG=y
CONFIG_SD_LOG_LEVEL_DBG=y
CONFIG_SDHC_LOG_LEVEL_DBG=y

shows a bit more detailed dbg log as follows:
[00:00:00.000,793] <dbg> sd: sd_init_io: Resetting power to card
[00:00:00.004,516] <dbg> sdhc_spi: sdhc_spi_send_cmd: cmd0 arg 0x0
[00:00:00.005,310] <dbg> sdhc_spi: sdhc_spi_send_cmd: cmd8 arg 0x1aa
[00:00:00.006,042] <dbg> sd: sd_send_interface_condition: Found SDHC with CMD8 support
[00:00:00.006,072] <dbg> sdhc_spi: sdhc_spi_send_cmd: cmd59 arg 0x1
[00:00:00.006,835] <dbg> sdhc_spi: sdhc_spi_send_cmd: cmd58 arg 0x0
[00:00:00.007,720] <dbg> sdhc_spi: sdhc_spi_send_cmd: cmd58 arg 0x40000000
[00:00:00.008,483] <dbg> sdhc_spi: sdhc_spi_send_cmd: cmd10 arg 0x0
[00:00:00.008,850] <dbg> sd: sdmmc_spi_read_cxd: CMD10 failed: -22
[00:00:00.008,880] <dbg> sd: card_read_cid: Card MID: 0x0, OID: 
[00:00:00.008,911] <dbg> sdhc_spi: sdhc_spi_send_cmd: cmd9 arg 0x0
[00:00:00.009,2d: -22

The code snippet to produce the above output is as follows:

#include <zephyr/device.h>
#include <zephyr/fs/fs.h>
#include <zephyr/storage/disk_access.h>
#include <ff.h>
#include <zephyr/storage/flash_map.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(storage);

#define DISK_DRIVE_NAME "SD"
#define DISK_MOUNT_POINT "/SD:"

/* FILESYSTEM */
static FATFS fat_fs;
static struct fs_mount_t mp = {
    .type = FS_FATFS,
    .fs_data = &fat_fs,
    .storage_dev = (void *)DISK_DRIVE_NAME,
};
static const char *disk_mount_pt = DISK_MOUNT_POINT;
struct fs_file_t filep;

int init_sd_card(void)
{
    int ret;
    static const char *disk_pdrv = DISK_DRIVE_NAME;
    uint64_t memory_size_mb;
    uint32_t block_count;
    uint32_t block_size;

    ret = disk_access_init(disk_pdrv);
    if (ret != 0)
    {
        LOG_ERR("Storage init ERROR (%d)", ret);
        return ret;
    }

    if (disk_access_ioctl(disk_pdrv,
                          DISK_IOCTL_GET_SECTOR_COUNT, &block_count))
    {
        LOG_ERR("Unable to get sector count");
        return -1;
    }
    LOG_INF("Block count %u", block_count);

    if (disk_access_ioctl(disk_pdrv,
                          DISK_IOCTL_GET_SECTOR_SIZE, &block_size))
    {
        LOG_ERR("Unable to get sector size");
        return -1;
    }
    LOG_INF("Sector size %u\n", block_size);

    memory_size_mb = (uint64_t)block_count * block_size;
    LOG_INF("Memory Size(MB) %u\n", (uint32_t)(memory_size_mb >> 20));

    mp.mnt_point = disk_mount_pt;
    ret = fs_mount(&mp);
    if (ret != FR_OK)
    {
        LOG_ERR("Mounting failed (%d)", ret);
        return ret;
    }

    return ret;
}

Kconfig is as follows:

#Enable the LittleFS file system.
CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y

#Enable file system commands
CONFIG_MCUMGR_GRP_FS=y

CONFIG_DISK_ACCESS=y
CONFIG_DISK_DRIVERS=y
CONFIG_DISK_DRIVER_SDMMC=y
CONFIG_SDMMC_SUBSYS=y
CONFIG_SDMMC_STACK=y
CONFIG_SPI_SDHC=y

and devicetree overlay:

&pinctrl {
	spi2_default: spi2_default {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 8)>,
			        <NRF_PSEL(SPIM_MISO, 0, 11)>,
			        <NRF_PSEL(SPIM_MOSI, 0, 9)>;
		};
	};

	spi2_sleep: spi2_sleep {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 8)>,
			        <NRF_PSEL(SPIM_MISO, 0, 11)>,
			        <NRF_PSEL(SPIM_MOSI, 0, 9)>;
			low-power-enable;

		};//
	};
};

/delete-node/ &qspi;
/delete-node/ &uart0;

&spi2 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    cs-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
    pinctrl-0 = <&spi2_default>;
    pinctrl-1 = <&spi2_sleep>;
    pinctrl-names = "default", "sleep";
    sdhc0: sdhc@0 {
        compatible = "zephyr,sdhc-spi-slot";
        reg = <0>;
        spi-max-frequency = <100000>;
        status = "okay";
        mmc {
            compatible = "zephyr,sdmmc-disk";
            status = "okay";
        };
    };
};

I have tried to different SDHC cards, one 32 GB SanDisk and one 16 GB different brand, both
formatted with FAT32 - same result.
Likewise I played around with spi-max-frequency, but no luck.
VDD for SD card ist 3.2 something V, which should be well withing spec.

I read similar issues on the forum, what seemed plausible was a pin clash where some of the pins
used by SPI are also used by the UART, but I checked the `zephyr.dts` in build and this does not seem to be the case.
(Where else could this be checked?)

Any ideas what else to investigate? I'd be grateful for any hints. Also, in case there are any
other samples coversing SDHC + SPI + FATFS, I'd be grateful for pointers.

Parents
  • Hi

    From the error -22 you see in your debug log, that points to an invalid argument being used when you try sending command (opcode) 10 with an 0x0 argument. Are you sure your SDHC card supports this OP code? Do you have its product specification?

    In your pin configs I also see that the pins you're using for SPI2 are the ones dedicated for the high-speed SPI (SPIM4), so there might be some conflicts there. Or if you want to use the high-speed SPI, you can use these (and SPIM4), but then the MISO pin will need to be P0.10 instead of P0.11.

    Best regards,

    Simon

Reply
  • Hi

    From the error -22 you see in your debug log, that points to an invalid argument being used when you try sending command (opcode) 10 with an 0x0 argument. Are you sure your SDHC card supports this OP code? Do you have its product specification?

    In your pin configs I also see that the pins you're using for SPI2 are the ones dedicated for the high-speed SPI (SPIM4), so there might be some conflicts there. Or if you want to use the high-speed SPI, you can use these (and SPIM4), but then the MISO pin will need to be P0.10 instead of P0.11.

    Best regards,

    Simon

Children
Related