Design Notes

STM32 Zephyr SD Card Support

I couldn't find much info on adding SD card support to an existing zephyr application. Sharing my setup here.

Device tree and configuration changes

Added this to the board-name.dts file

&sdmmc1 {
	compatible = "st,stm32-sdmmc";
	pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9
				&sdmmc1_d2_pc10 &sdmmc1_d3_pc11
				&sdmmc1_ck_pc12 &sdmmc1_cmd_pd2>;
	pinctrl-names = "default";
	pwr-gpios = <&gpiod 15 GPIO_ACTIVE_HIGH>; // required
	status = "okay";
};

Added this to the board-name_defconfig file

#enable disk
CONFIG_DISK_ACCESS=y
CONFIG_DISK_DRIVER_SDMMC=y
CONFIG_SDMMC_STM32=y
CONFIG_FAT_FILESYSTEM_ELM=y

Integrating sample code into your application to read directory contents

#ifdef CONFIG_FAT_FILESYSTEM_ELM
#include <ff.h>
#include <string.h>
/* FatFs work area */
FATFS fatfs_fs;
/* mounting info */
static struct fs_mount_t fat_fs_mnt = {
	.type = FS_FATFS,
	.fs_data = &fatfs_fs,
	.mnt_point = "/SD:"
};
#endif

static int lsdir(const char *path)
{
	int res;
	struct fs_dir_t dirp;
	static struct fs_dirent entry;
	
	fs_dir_t_init(&dirp);
	
	/* Verify fs_opendir() */
	res = fs_opendir(&dirp, path);
	if (res) {
		LOG_WRN("Error opening dir %s [%d]", path, res);
		return res;
	}
	
	LOG_INF("Listing dir %s ...", 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) {
			if(strchr(entry.name, '~') != NULL){
				LOG_INF("[DIR ] %s", entry.name);
			}

		} else {
			if(entry.name[0] != '_'){
				LOG_INF("[FILE] %s (size = %zu)",
					entry.name, entry.size);
			}

		}
	}
	
	/* Verify fs_closedir() */
	fs_closedir(&dirp);
	
	return res;
}

static int fatfs_mount()
{
	/* 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_init(disk_pdrv) != 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;
			}
		LOG_INF("Sector size %u", block_size);
		
		memory_size_mb = (uint64_t)block_count * block_size;
		LOG_INF("Memory Size(MB) %u", (uint32_t)(memory_size_mb >> 20));
	} while (0);

	int res = fs_mount(&fat_fs_mnt);
	
	if (res == FR_OK) {
		LOG_INF("SD Card mounted.");
		lsdir(fat_fs_mnt.mnt_point);
	} else {
		LOG_WRN("Error mounting disk.\n");
	}	
	return 0;
}

Results:

After zephyr boots, the application is able to connect to sd card, mount fat file system and read its contexts.

uart:~$ 

*** Booting Zephyr OS build zephyr-v3.2.0-4019-g16d723ee1be9 ***
[00:00:02.065,000] <inf> file_system: Begin File System
[00:00:02.253,000] <inf> file_system: Block count 62333952
[00:00:02.261,000] <inf> file_system: Sector size 512
[00:00:02.269,000] <inf> file_system: Memory Size(MB) 30436
[00:00:02.279,000] <inf> file_system: SD Card mounted.
[00:00:02.286,000] <inf> file_system: Listing dir /SD: ...
[00:00:02.295,000] <inf> file_system: [DIR ] SPOTLI~1
[00:00:02.303,000] <inf> file_system: [FILE] NOTE.PDF (size = 315197)
[00:00:02.312,000] <inf> file_system: [FILE] AA2.TXT (size = 2704195)
[00:00:02.321,000] <inf> file_system: [FILE] A.TXT (size = 6)

Zephyr page on stm32 sd card link

#sd card #stm32 #zephyr