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=yoverlay 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!