SD Card with NRF54L15 and 3.1.0 SDK and 3.0.0 toolchain

Hello,

I have a functional project to access to an SD Card with NRF54L15DK and the version 2.9.2 SDK and 3.1.0 toolchain.

But I have difficulties to access to the SD card with the versions 3.2.0 SDK and 3.2.1 toolchain.

Can you help me please ?

Here is my code :

main.c

/*
 * Copyright (c) 2019 Tavish Naruka <[email protected]>
 * Copyright (c) 2023 Nordic Semiconductor ASA
 * Copyright (c) 2023 Antmicro <www.antmicro.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/* Sample which uses the filesystem API and SDHC driver */

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/storage/disk_access.h>
#include <zephyr/logging/log.h>
#include <zephyr/fs/fs.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>

/* Définition des pins SPI basées sur votre pinctrl */
#define SPI_SCK_PIN  13 // P1.13
#define SPI_MOSI_PIN 12 // P1.12
#define SPI_MISO_PIN 14 // P1.14
#define SPI_CS_PIN   15 // P1.15 (Celui que vous soupçonnez)
#define SPI_PORT     DEVICE_DT_GET(DT_NODELABEL(gpio1))

void test_spi_pins_physical(void) {
    const struct device *gpio_dev = SPI_PORT;
   
    if (!device_is_ready(gpio_dev)) {
        printk("Erreur : GPIO port non prêt pour le test\n");
        return;
    }

    /* Configurer les pins en sortie pour le test */
    gpio_pin_configure(gpio_dev, SPI_SCK_PIN, GPIO_OUTPUT_INACTIVE);
    gpio_pin_configure(gpio_dev, SPI_MOSI_PIN, GPIO_OUTPUT_INACTIVE);
    gpio_pin_configure(gpio_dev, SPI_CS_PIN, GPIO_OUTPUT_INACTIVE);
    /* Le MISO est une entrée, on peut tester son Pull-up */
    gpio_pin_configure(gpio_dev, SPI_MISO_PIN, GPIO_INPUT | GPIO_PULL_UP);

    printk("\n*** TEST PHYSIQUE DES PINS (10 secondes) ***\n");
    printk("Mesurez la Pin 2 (CS), Pin 3 (MOSI) et Pin 5 (CLK) du connecteur...\n");

    for (int i = 0; i < 10; i++) {
        gpio_pin_set(gpio_dev, SPI_SCK_PIN, i % 2);
        gpio_pin_set(gpio_dev, SPI_MOSI_PIN, i % 2);
        gpio_pin_set(gpio_dev, SPI_CS_PIN, i % 2);
       
        int miso_val = gpio_pin_get(gpio_dev, SPI_MISO_PIN);
        printk("Cycle %d - Sorties: %s | MISO lue: %d\n",
                i, (i % 2) ? "3.3V" : "0V", miso_val);
       
        k_msleep(1000);
    }

    /* IMPORTANT : Remettre les pins en état 'déconnecté' pour laisser le SPI travailler */
    gpio_pin_configure(gpio_dev, SPI_SCK_PIN, GPIO_DISCONNECTED);
    gpio_pin_configure(gpio_dev, SPI_MOSI_PIN, GPIO_DISCONNECTED);
    gpio_pin_configure(gpio_dev, SPI_CS_PIN, GPIO_DISCONNECTED);
   
    printk("*** Fin du test physique, demarrage du driver SD ***\n\n");
}

#if defined(CONFIG_FAT_FILESYSTEM_ELM)

#include <ff.h>
PARTITION VolToPart[] = {
    {0, 1},  /* SD1 -> partition 1 */
    {0, 2},  /* SD2 -> partition 2 */
};
/*
 *  Note the fatfs library is able to mount only strings inside _VOLUME_STRS
 *  in ffconf.h
 */
#if defined(CONFIG_DISK_DRIVER_MMC)
#define DISK_DRIVE_NAME "SDHC0"
#else
#define DISK_DRIVE_NAME "SDHC0"
#endif

#define DISK_MOUNT_PT "/"DISK_DRIVE_NAME":"
#define DISK_MOUNT_PTSD1 "/SD1"
#define DISK_MOUNT_PTSD2 "/SD2"

#define MAX_PARTS  2  /* jusqu’à 4 partitions possibles */

#define CD_NODE DT_NODELABEL(sd_cd0)
/* Un FATFS par partition */
static FATFS fat_fs[MAX_PARTS];
static struct fs_mount_t mp[MAX_PARTS];

static const char *disk_names[MAX_PARTS] = {
    "SD1", "SD2"
};

static const char *mount_points[MAX_PARTS] = {
    "/SD1", "/SD2"
};

// static FATFS fat_fs;
// /* mounting info */
// static struct fs_mount_t mp = {
// 	.type = FS_FATFS,
// 	.fs_data = &fat_fs,
// };

#elif defined(CONFIG_FILE_SYSTEM_EXT2)

#include <zephyr/fs/ext2.h>

#define DISK_DRIVE_NAME "SDHC0"
#define DISK_MOUNT_PT "/ext"

static struct fs_mount_t mp = {
	.type = FS_EXT2,
	.flags = FS_MOUNT_FLAG_NO_FORMAT,
	.storage_dev = (void *)DISK_DRIVE_NAME,
	.mnt_point = "/ext",
};

#endif

#if defined(CONFIG_FAT_FILESYSTEM_ELM)
#define FS_RET_OK FR_OK
#else
#define FS_RET_OK 0
#endif

LOG_MODULE_REGISTER(main);

// #define MAX_PATH 128
// #define SOME_FILE_NAME "some.dat"
// #define SOME_DIR_NAME "some"
// #define SOME_REQUIRED_LEN MAX(sizeof(SOME_FILE_NAME), sizeof(SOME_DIR_NAME))

static int lsdir(const char *path);
// #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES
// static bool create_some_entries(const char *base_path)
// {
// 	char path[MAX_PATH];
// 	struct fs_file_t file;
// 	int base = strlen(base_path);

// 	fs_file_t_init(&file);

// 	if (base >= (sizeof(path) - SOME_REQUIRED_LEN)) {
// 		LOG_ERR("Not enough concatenation buffer to create file paths");
// 		return false;
// 	}

// 	LOG_INF("Creating some dir entries in %s", base_path);
// 	strncpy(path, base_path, sizeof(path));

// 	path[base++] = '/';
// 	path[base] = 0;
// 	strcat(&path[base], SOME_FILE_NAME);

// 	if (fs_open(&file, path, FS_O_CREATE) != 0) {
// 		LOG_ERR("Failed to create file %s", path);
// 		return false;
// 	}
// 	fs_close(&file);

// 	path[base] = 0;
// 	strcat(&path[base], SOME_DIR_NAME);

// 	if (fs_mkdir(path) != 0) {
// 		LOG_ERR("Failed to create dir %s", path);
// 		/* If code gets here, it has at least successes to create the
// 		 * file so allow function to return true.
// 		 */
// 	}
// 	return true;
// }
// #endif

static const char *disk_mount_pt = DISK_MOUNT_PT;

static const char *disk_mount_ptSD1 = DISK_MOUNT_PTSD1;

static const char *disk_mount_ptSD2 = DISK_MOUNT_PTSD2;

void mount_all_partitions(void)
{
    for (int i = 0; i < MAX_PARTS; i++) {
		mp[i].type = FS_FATFS;
		mp[i].fs_data = &fat_fs[i];
// 	.fs_data = &fat_fs
		if (i == 0) {
			mp[i].mnt_point = disk_mount_ptSD1;
		}
		if (i == 1) {
			mp[i].mnt_point = disk_mount_ptSD2;
		}
        if (i == 0) {
			mp[i].storage_dev = (void *)"SD1";
		}
		if (i == 1) {
			mp[i].storage_dev = (void *)"SD2";
		}
        int res = fs_mount(&mp[i]);
        if (res == FR_OK) {
            printk("Partition %s montée sur %s\n", disk_names[i], mount_points[i]);
        } else {
            printk("Partition %s non montée (code %d)\n", disk_names[i], res);
        }
    }
}

void UNmount_all_partitions(void)
{
    for (int i = 0; i < MAX_PARTS; i++) {
        mp[i].type = FS_FATFS;
        mp[i].mnt_point = mount_points[i];
        mp[i].fs_data = &fat_fs[i];
        mp[i].storage_dev = (void *)disk_names[i];

        int res = fs_unmount(&mp[i]);
        if (res == FR_OK) {
            printk("Partition %s demontée sur %s\n", disk_names[i], mount_points[i]);
        } else {
            printk("Partition %s non demontée (code %d)\n", disk_names[i], res);
        }
    }
}


static void write_to_sd()
{
    char file_path[64];
    struct fs_file_t file;
    int ret;

    /* Construire le chemin du fichier */
    printk("OK");
strcpy(file_path, "/SD1/test.txt");
printk("OK");
    fs_file_t_init(&file);
    printk("OK");

    /* Ouvrir (ou créer) le fichier en écriture */
    ret = fs_open(&file, file_path, FS_O_CREATE | FS_O_RDWR);
    printk("OK");
    if (ret) {
        LOG_ERR("Erreur d'ouverture du fichier (%d)", ret);
        return;
    }

    /* Données à écrire */
    const char msg[] = "Hello SD card from nRF54L15!\n";

    /* Écriture */
    ret = fs_write(&file, msg, sizeof(msg) - 1);
    if (ret < 0) {
        LOG_ERR("Erreur d'écriture (%d)", ret);
        fs_close(&file);
        return;
    }

    LOG_INF("Écrit %d octets dans %s", ret, file_path);

    /* Fermer le fichier */
    fs_close(&file);

    /* Lire pour vérifier */
    ret = fs_open(&file, file_path, FS_O_READ);
    if (ret) {
        LOG_ERR("Erreur de réouverture du fichier (%d)", ret);
        return;
    }

    char buf[64];
    int n = fs_read(&file, buf, sizeof(buf) - 1);
    if (n >= 0) {
        buf[n] = '\0';
        LOG_INF("Contenu lu : %s", buf);
    } else {
        LOG_ERR("Erreur de lecture (%d)", n);
    }

    fs_close(&file);

	    /* Construire le chemin du fichier */
strcpy(file_path, "/SD2/test.txt");
    fs_file_t_init(&file);

    /* Ouvrir (ou créer) le fichier en écriture */
    ret = fs_open(&file, file_path, FS_O_CREATE | FS_O_RDWR);
    if (ret) {
        LOG_ERR("Erreur d'ouverture du fichier (%d)", ret);
        return;
    }

    /* Données à écrire */
    const char msg2[] = "Hello SD card from nRF54L15!\n";

    /* Écriture */
    ret = fs_write(&file, msg2, sizeof(msg2) - 1);
    if (ret < 0) {
        LOG_ERR("Erreur d'écriture (%d)", ret);
        fs_close(&file);
        return;
    }

    LOG_INF("Écrit %d octets dans %s", ret, file_path);

    /* Fermer le fichier */
    fs_close(&file);

    /* Lire pour vérifier */
    ret = fs_open(&file, file_path, FS_O_READ);
    if (ret) {
        LOG_ERR("Erreur de réouverture du fichier (%d)", ret);
        return;
    }

    n = fs_read(&file, buf, sizeof(buf) - 1);
    if (n >= 0) {
        buf[n] = '\0';
        LOG_INF("Contenu lu : %s", buf);
    } else {
        LOG_ERR("Erreur de lecture (%d)", n);
    }

    fs_close(&file);
}

/* Petit utilitaire pour inspecter le MBR et afficher les partitions trouvées */
static void print_mbr_info(void)
{
    uint8_t mbr[512];
    if (disk_access_read("SD", mbr, 0, 1) != 0) {
        printk("Impossible de lire le MBR (disk_access_read)\n");
        return;
    }
    printk("MBR signature: 0x%02x%02x\n", mbr[510], mbr[511]);
    for (int i = 0; i < 4; i++) {
        uint8_t part_type = mbr[446 + i*16 + 4];
        uint32_t start_lba = mbr[446 + i*16 + 8] |
                             (mbr[446 + i*16 + 9] << 8) |
                             (mbr[446 + i*16 + 10] << 16) |
                             (mbr[446 + i*16 + 11] << 24);
        uint32_t num_sectors = mbr[446 + i*16 + 12] |
                               (mbr[446 + i*16 + 13] << 8) |
                               (mbr[446 + i*16 + 14] << 16) |
                               (mbr[446 + i*16 + 15] << 24);
        if (part_type != 0) {
            printk("Partition %d: type=0x%02x start=%u sectors=%u\n",
                   i+1, part_type, start_lba, num_sectors);
        }
    }
}

// void init_sd_card(void)
// {
//     const char *disk_pdrv = "SD";
//     int ret;

//     ret = disk_access_init(disk_pdrv);
//     if (ret != 0) {
//         printk("Erreur init SD card (%d)\n", ret);
//     } else {
//         printk("SD card initialisée\n");
//     }
// }

int main(void)
{

    //     const struct gpio_dt_spec cd = GPIO_DT_SPEC_GET(CD_NODE, gpios);

    // if (!device_is_ready(cd.port)) {
    //     LOG_ERR("GPIO CD not ready");
    //     return;
    // }

    // gpio_pin_configure_dt(&cd, GPIO_INPUT);

    //     int val = gpio_pin_get_dt(&cd);

    //     if (val < 0) {
    //         LOG_ERR("Read error");
    //     } else {
    //         LOG_INF("Card detect state: %d (%s)",
    //                 val,
    //                 val == 0 ? "CARD INSERTED" : "NO CARD");
    //     }

    
	/* raw disk i/o */
	do {
		static const char *disk_pdrv = "SD";
		uint64_t memory_size_mb;
		uint32_t block_count;
		uint32_t block_size;

		if (disk_access_ioctl(disk_pdrv,
				DISK_IOCTL_CTRL_INIT, NULL) != 0) {
			LOG_ERR("Storage init ERROR!");
			break;
		}

		if (disk_access_ioctl(disk_pdrv,
				DISK_IOCTL_GET_SECTOR_COUNT, &block_count)) {
			LOG_ERR("Unable to get sector count");
			break;
		}
		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");
			break;
		}
		printk("Sector size %u\n", block_size);

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

		if (disk_access_ioctl(disk_pdrv,
				DISK_IOCTL_CTRL_DEINIT, NULL) != 0) {
			LOG_ERR("Storage deinit ERROR!");
			break;
		}
	} while (0);

	

	// mp.mnt_point = disk_mount_pt;

	// int res = fs_mount(&mp);

    //init_sd_card();

    print_mbr_info();

	mount_all_partitions();

// 	if (res == FS_RET_OK) {
// 		printk("Disk mounted.\n");
// 		/* Try to unmount and remount the disk */
// 		res = fs_unmount(&mp);
// 		if (res != FS_RET_OK) {
// 			printk("Error unmounting disk\n");
// 			return res;
// 		}
// 		res = fs_mount(&mp);
// 		if (res != FS_RET_OK) {
// 			printk("Error remounting disk\n");
// 			return res;
// 		}

// 		if (lsdir(disk_mount_pt) == 0) {
// #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES
// 			if (create_some_entries(disk_mount_pt)) {
// 				lsdir(disk_mount_pt);
// 			}
// #endif
// 		}
// 	} else {
// 		printk("Error mounting disk.\n");
// 	}

	write_to_sd();

	// fs_unmount(&mp);

	UNmount_all_partitions();

	while (1) {
		k_sleep(K_MSEC(1000));
	}
	return 0;
}

/* List dir entry by path
 *
 * @param path Absolute path to list
 *
 * @return Negative errno code on error, number of listed entries on
 *         success.
 */
static int lsdir(const char *path)
{
	int res;
	struct fs_dir_t dirp;
	static struct fs_dirent entry;
	int count = 0;

	fs_dir_t_init(&dirp);

	/* Verify fs_opendir() */
	res = fs_opendir(&dirp, path);
	if (res) {
		printk("Error opening dir %s [%d]\n", path, res);
		return res;
	}

	printk("\nListing dir %s ...\n", path);
	for (;;) {
		/* Verify fs_readdir() */
		res = fs_readdir(&dirp, &entry);

		/* entry.name[0] == 0 means end-of-dir */
		if (res || entry.name[0] == 0) {
			break;
		}

		if (entry.type == FS_DIR_ENTRY_DIR) {
			printk("[DIR ] %s\n", entry.name);
		} else {
			printk("[FILE] %s (size = %zu)\n",
				entry.name, entry.size);
		}
		count++;
	}

	/* Verify fs_closedir() */
	fs_closedir(&dirp);
	if (res == 0) {
		res = count;
	}

	return res;
}
prj.conf:
CONFIG_DISK_ACCESS=y
CONFIG_LOG=y
CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y
CONFIG_PRINTK=y
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_NRFX_POWER=y
overlay file :
&spi21 {
    status = "okay";
    compatible = "nordic,nrf-spim";
    pinctrl-0 = <&spi21_default>;
    pinctrl-1 = <&spi21_sleep>;
    pinctrl-names = "default", "sleep";
    cs-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; // P1.06 - SD_nCS
	sdhc0: sdhc@0 {
		compatible = "zephyr,sdhc-spi-slot";
		reg = <0>;
		status = "okay";
		mmc {
			compatible = "zephyr,sdmmc-disk";
			disk-name = "SD";
			status = "okay";
		};
		spi-max-frequency = <25000000>;
	};
};

// / {
//     sd_cd: sd_card_detect {
//         compatible = "gpio-keys";
//         sd_cd0: sd_cd0 {
//             gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
//             label = "SD_CARD_DETECT";
//         };
//     };
// };


&uart20 {
	status = "disabled";
};

&pinctrl {
    spi21_default: spi21_default { 
        group1 { 
            psels = <NRF_PSEL(SPIM_SCK, 1, 13)>, 
                    <NRF_PSEL(SPIM_MOSI, 1, 12)>,
                    <NRF_PSEL(SPIM_MISO, 1, 14)>; 
            }; 
        };

    spi21_sleep: spi21_sleep {
        group1 {
            psels = <NRF_PSEL(SPIM_SCK,  1, 13)>,
                    <NRF_PSEL(SPIM_MOSI, 1, 12)>,
                    <NRF_PSEL(SPIM_MISO, 1, 14)>;
            low-power-enable;
        };
    };
};
Can you explain me the differences between the different versions of SDK and toolchains please ?

Thank you!

Parents
  • Hello Jade,

    I see that you already have a similar case open where you are discussing the same issue with my colleague. In that case, I would recommend closing this ticket and continuing the discussion in the original thread you created.

    Please share the logs in the older ticket, along with details on whether you used a logic analyzer.

    I’m closing this ticket as it is a duplicate of 355696.

    Kind regards,
    Abhijith

Reply
  • Hello Jade,

    I see that you already have a similar case open where you are discussing the same issue with my colleague. In that case, I would recommend closing this ticket and continuing the discussion in the original thread you created.

    Please share the logs in the older ticket, along with details on whether you used a logic analyzer.

    I’m closing this ticket as it is a duplicate of 355696.

    Kind regards,
    Abhijith

Children
No Data
Related