Unable to connect to SD card via SPI

Hi,
I would like to write a log to an SD card but I am completely unable to even connect to it using SPI in Zephyr/nRF Connect SDK.
There seems to be some mismatch between the prj.conf and the overlay files which I do not know how to resolve: interestingly, my code compiles when the overlay file (see below) says compatible="sdhc" but then it fails to initialize the SD card, throwing error code -22 (src/main.c, line 15 below). However, when I am putting compatible="zephyr,sdhc-spi-slot", I am getting a persistent error message. I tried many other combinations and ways to write my overlay file, but I am always either able to compile but not resolve (it seems) the SD card, or I cannot compile.
What am I missing? What is the correct way to initialize and write to an SD card? Any input is highly appreciated.
Thanks
Armand

# prj.conf:

CONFIG_DISK_ACCESS=y
CONFIG_SDMMC_STACK=y
CONFIG_SPI=y
CONFIG_SPI_NRFX=y
CONFIG_SDHC=y

// nrf52dk_nrf52832.overlay:

&spi0 {	status = "disabled";};
&i2c1 {	status = "disabled";};

&spi1 {
    status = "okay";

    sdhc0: sdhc@0 {
        compatible = "zephyr,sdhc-spi-slot";
        // compatible = "sdhc";
        reg = <0>;
        status = "okay";
        spi-max-frequency = <24000000>;
        cs-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
        label = "SD";
        disk-name = "SD";
    };
};

// src/main.c:

#include <zephyr/device.h>
#include <zephyr/drivers/disk.h>
#include <zephyr/storage/disk_access.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);

#define DISK_NAME "SD"

int main(void) {
    int ret = disk_access_init(DISK_NAME);
    if (ret) {
        printk("Failed to initialize SD card\n");
        return -1;
    }
    printk("Successfully initialized SD card\n");
    return 0;
}

# Compiler output and error:

 *  Executing task: nRF Connect: Build [pristine]: sd-problem/build (active) 

Building sd-problem
west build --build-dir /Users/devzone/Documents/GitHub/sd-problem/build /Users/devzone/Documents/GitHub/sd-problem --pristine --board nrf52dk/nrf52832 -- -DNCS_TOOLCHAIN_VERSION=NONE -DBOARD_ROOT=/Users/devzone/Documents/GitHub/sd-problem

-- west build: generating a build system
Loading Zephyr default modules (Zephyr base).
-- Application: /Users/devzone/Documents/GitHub/sd-problem
-- CMake version: 3.21.0
-- Found Python3: /opt/nordic/ncs/toolchains/f8037e9b83/opt/[email protected]/bin/python3.9 (found suitable version "3.9.6", minimum required is "3.8") found components: Interpreter 
-- Cache files will be written to: /Users/devzone/Library/Caches/zephyr
-- Zephyr version: 3.6.99 (/opt/nordic/ncs/v2.7.0/zephyr)
-- Found west (found suitable version "1.2.0", minimum required is "0.14.0")
-- Board: nrf52dk, qualifiers: nrf52832
-- Found host-tools: zephyr 0.16.5 (/opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk)
-- Found toolchain: zephyr 0.16.5 (/opt/nordic/ncs/toolchains/f8037e9b83/opt/zephyr-sdk)
-- Found Dtc: /opt/nordic/ncs/toolchains/f8037e9b83/bin/dtc (found suitable version "1.6.1", minimum required is "1.4.6") 
-- Found BOARD.dts: /opt/nordic/ncs/v2.7.0/zephyr/boards/nordic/nrf52dk/nrf52dk_nrf52832.dts
-- Found devicetree overlay: /Users/devzone/Documents/GitHub/sd-problem/boards/nrf52dk_nrf52832.overlay
'label' is marked as deprecated in 'properties:' in /opt/nordic/ncs/v2.7.0/zephyr/dts/bindings/sdhc/zephyr,sdhc-spi-slot.yaml for node /soc/spi@40004000/sdhc@0.
devicetree error: 'cs-gpios' appears in /soc/spi@40004000/sdhc@0 in /Users/devzone/Documents/GitHub/sd-problem/build/zephyr/zephyr.dts.pre, but is not declared in 'properties:' in /opt/nordic/ncs/v2.7.0/zephyr/dts/bindings/sdhc/zephyr,sdhc-spi-slot.yaml
-- In: /Users/devzone/Documents/GitHub/sd-problem/build/zephyr, command: /opt/nordic/ncs/toolchains/f8037e9b83/opt/[email protected]/bin/python3.9;/opt/nordic/ncs/v2.7.0/zephyr/scripts/dts/gen_defines.py;--dts;/Users/devzone/Documents/GitHub/sd-problem/build/zephyr/zephyr.dts.pre;--dtc-flags;'-Wno-unique_unit_address_if_enabled';--bindings-dirs;/opt/nordic/ncs/v2.7.0/nrf/dts/bindings;/opt/nordic/ncs/v2.7.0/zephyr/dts/bindings;--header-out;/Users/devzone/Documents/GitHub/sd-problem/build/zephyr/include/generated/devicetree_generated.h.new;--dts-out;/Users/devzone/Documents/GitHub/sd-problem/build/zephyr/zephyr.dts.new;--edt-pickle-out;/Users/devzone/Documents/GitHub/sd-problem/build/zephyr/edt.pickle;--vendor-prefixes;/opt/nordic/ncs/v2.7.0/nrf/dts/bindings/vendor-prefixes.txt;--vendor-prefixes;/opt/nordic/ncs/v2.7.0/zephyr/dts/bindings/vendor-prefixes.txt
CMake Error at /opt/nordic/ncs/v2.7.0/zephyr/cmake/modules/dts.cmake:296 (message):
  gen_defines.py failed with return code: 1
Call Stack (most recent call first):
  /opt/nordic/ncs/v2.7.0/zephyr/cmake/modules/zephyr_default.cmake:132 (include)
  /opt/nordic/ncs/v2.7.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:66 (include)
  /opt/nordic/ncs/v2.7.0/zephyr/share/zephyr-package/cmake/ZephyrConfig.cmake:92 (include_boilerplate)
  CMakeLists.txt:2 (find_package)


-- Configuring incomplete, errors occurred!
FATAL ERROR: command exited with status 1: /opt/nordic/ncs/toolchains/f8037e9b83/bin/cmake -DWEST_PYTHON=/opt/nordic/ncs/toolchains/f8037e9b83/opt/[email protected]/bin/python3.9 -B/Users/devzone/Documents/GitHub/sd-problem/build -GNinja -DBOARD=nrf52dk/nrf52832 -DNCS_TOOLCHAIN_VERSION=NONE '-DBOARD_ROOT=/Users/devzone/Documents/GitHub/ncs-inter/lesson5/inter_less5_exer1_solution;/Users/devzone/Documents/GitHub/ncs-inter/lesson5/inter_less5_exer1;/Users/devzone/Documents/GitHub/ncs-fund/v2.x.x/lesson2/fund_less2_exer2_solution;/Users/devzone/Documents/GitHub/sd-problem' -S/Users/devzone/Documents/GitHub/sd-problem

 *  The terminal process terminated with exit code: 1. 
 *  Terminal will be reused by tasks, press any key to close it. 

Tools:
- nRF Connect SDK and toolchains v2.7.0
- nRF52DK_nRF52832 (PCA10040)
- SD Card: SanDisk Ultra 32GB micro-SD, FAT32 formatted, empty.
- Mac OSX 14.6.1
- Visual Studio Code Version: 1.94.2

Parents
  • I believe its in the DTS from some of the SD card examples, but you need to know what to look for:

    sdhc0: sdhc@0 {
    		compatible = "zephyr,sdhc-spi-slot";
    		reg = <0x0 >;
    // ... more stuff here, skipped
            mmc {
    			compatible = "zephyr,sdmmc-disk";
    			status = "okay";
    			
    		};
        };
    

    The "Disk" part is on an internal node - maybe in order to support other SDIO cards. But these typically don't support SPI mode.

  • Hi Turbo J,
    Thanks for your reply. Yes, I believe that something like what you are suggesting will be the solution. I have tried variants of the following overlay and I was able to get it to compile, but not to connect to the disk.

    Here is the an overlay file I used similar to what you are suggesting. Note that I am using the depricated property "label", here. What is the current way to connect to such a device?

    // boards/nrf52dk_nrf52832.overlay:
    
    &spi0 { status = "disabled";};
    &i2c1 { status = "disabled";};
    
    &spi1 {
        status = "okay";
        cs-gpios = < &gpio0 28 GPIO_ACTIVE_HIGH >;
        label = "SD";
        sdhc-spi-slot@0 {
            compatible = "zephyr,sdhc-spi-slot";
            status = "okay";
            reg = <0x0 >;
            spi-max-frequency = <8000000>;
            
            mmc {
                compatible = "zephyr,sdmmc-disk";
                status = "okay";
            };  
        };
    };
    

    It seems that the problem is precisely between the Devicetree and main.c working with the correct GPIO ports to do the SPi. In fact, I tried disk_access_init("SD") using this overlay file but was never able to initialize the SD card, always getting error code -22, and I never even saw any communications when checking with my oscilloscope.

  • CS is an active low signal, try GPIO_ACTIVE_LOW in the overlay.

    A logic analyser is recommended.

  • Good catch. Just implemented the GPIO_ACTIVE_LOW change in the overlay file and I checked with my logic analyzer (for-loop with 100 repeated attempts at initializing). Same as before: no activity on SPI pins, and disk_access_init() returns -22.

Reply Children
  • Looking at the SPI signals showed that the chip-select pin is never pulled low, which I interpret as disk_access_init(DISK_NAME) not being able to find the (correct) SD card Devicetree entry. Therefore, my hunch is that the problem is either in how I am defining the label in the overlay and/or in the prj.conf file. In fact, src/main.c shows that device_get_binding(...) is able to locate the Devicetree entry. In contrast, I found diving into the source code that disk_access_init(...), which tries to locate the Devicetree entry using disk_access_get_di(...) cannot. Thoughts?

    PS: For reference, I am pasting below:

    • the corrected overlay file: I played with putting the label property at different places in the overlay structure but it did not seem to make a difference. Also, I tried different psi-max-frequency values ranging from 240k to 24M without success. Please note that the Zephyr documentation on Disk Access defines the cs-gpios as &porta, not as &gpio0, and it does not use label, but disk-name, which leads to a compilation error on my system.
    • src/main.c file without the debugging for-loop (which repeats the connection attempt 100 times) for simplicity.
    • prj.conf now including the LOG and GPIO configs just in case; I played with that adding and removing lines but could not get it to work properly. Is there a config that I should add and don't know about?
    • nRF Serial Terminal output showing that the device binding works vial the label property but not when trying to initialize disk access.

    // boards/nrf52dk_nrf52832.overlay:
    
    &spi1 {
        status = "okay";
        cs-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>;
        sdhc0: sdhc@0 {
                compatible = "zephyr,sdhc-spi-slot";
                reg = <0x0>;
                status = "okay";
                label="SD";
                mmc {
                    compatible = "zephyr,sdmmc-disk";
                    status = "okay";
                };
                spi-max-frequency = <24000000>;
        };
    };

    // src/main.c: 
    
    #include <zephyr/device.h>
    #include <zephyr/drivers/disk.h>
    #include <zephyr/storage/disk_access.h>
    #include <zephyr/logging/log.h>
    
    LOG_MODULE_REGISTER(sd_problem, LOG_LEVEL_INF);
    
    #define DISK_NAME "SD"
    
    int main(void) {
        const struct device *SD_dev = device_get_binding(DISK_NAME);
        LOG_INF("SD_dev pointer address: %i; name: %s.", (int)SD_dev, SD_dev->name);
        int ret = disk_access_init(DISK_NAME);
        if (ret) {
            LOG_ERR("Failed to initialize SD card: %i", ret);
    
        } else {
            LOG_INF("Successfully initialized SD card");
        return 0;
    } 

    # prj.conf:
    
    CONFIG_GPIO=y
    CONFIG_LOG=y
    CONFIG_SPI=y
    CONFIG_DISK_ACCESS=y
    CONFIG_DISK_DRIVERS=y
    CONFIG_SDMMC_STACK=y
    CONFIG_SPI_NRFX=y
    CONFIG_SDHC=y
    

    # serial terminal output:
    
    *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [00:00:00.460,388] <inf> sd_problem: SD_dev pointer address: 36708; name: SD.
    [00:00:00.460,418] <err> sd_problem: Failed to initialize SD card: -22

Related