Zephyr使用TF卡
本文说明如何在zephyr下使用TF卡.
zephyr使用的device大多是内置几十K到几M Flash, 如果有较大量的数据需要本地存储就需要扩展外部Flash,对于数据存储的情况挂总线flash有io需求,挂SPI Flash容量单价又比较高。然后想起SDCard 有SPI Mode,当然就选它了。 本文的使用的device问nrf53832.
代码说明 链接到标题
原本打算移植或者重写SPI Mode 访问SD Card ,后来在制定API的时候要参考disk_access统一接口,发现zephyr已经有代码可以支援SPI Mode 访问SD CARD,这就省下不少功夫。 源代码参考
subsys/disk/disk_access_spi_sdhc.c
原理不做介绍,只是按照预定的方式通过SPI接口向TF卡发命令和读写数据,感兴趣可以看文末参考内容。
配置 链接到标题
修改DTS 链接到标题
在你板子的dts下添加如下内容
&spi2 {
status = "okay";
sck-pin = <31>;
mosi-pin = <2>;
miso-pin = <3>;
cs-gpios = <&gpio0 30 0>;
sdhc0: sdhc@0 {
compatible = "zephyr,mmc-spi-slot";
reg = <0>;
status = "okay";
label = "SDHC0";
spi-max-frequency = <24000000>;
};
上面的dts内容解释如下:
- tf卡(SDHC)使用spi2作为通信接口
- spi2的pin配置情况是sck-31, mosi-2, miso-3,cs-pin30
- spi通信速率为24M
修改配置文件 链接到标题
配置文件prj.conf添加如下内容
CONFIG_SPI_2=y
CONFIG_SPI_2_NRF_SPI=y
CONFIG_DISK_ACCESS=y
CONFIG_DISK_ACCESS_SDHC=y
CONFIG_DISK_ACCESS_SPI_SDHC=y
CONFIG_DISK_SDHC_VOLUME_NAME="SD"
在zephyr 上面SDHC是专为disk access访问用的,因此必须同时配置启动DISK ACCESS
使用 链接到标题
配置 链接到标题
zephyr上SDHC被放入了disk access,因此我们可以直接搭配文件系统使用,这里配置为FAT
#使用文件系统
CONFIG_FILE_SYSTEM=y
#使用FAT文件系统
CONFIG_FAT_FILESYSTEM_ELM=y
#启动文件系统shell,可选如果只是代码使用文件系统可以不开这项
CONFIG_FILE_SYSTEM_SHELL=y
代码使用文件系统 链接到标题
在app中建立如下代码,可以访问TF卡,详细请看注释说明
初始化disk 链接到标题
static const char *disk_pdrv = "SD";
u64_t memory_size_mb;
u32_t block_count;
u32_t block_size;
//初始化disk
if (disk_access_init(disk_pdrv) != 0) {
LOG_ERR("Storage init ERROR!");
break;
}
//获取disk的sector数量
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);
//获取sector大小
if (disk_access_ioctl(disk_pdrv,
DISK_IOCTL_GET_SECTOR_SIZE, &block_size)) {
LOG_ERR("Unable to get sector size");
break;
}
Mount文件系统 链接到标题
static const char *disk_mount_pt = "/SD:"; //mount点参看CONFIG_DISK_SDHC_VOLUME_NAME
mp.mnt_point = disk_mount_pt;
int res = fs_mount(&mp);
if (res == FR_OK) {
printk("Disk mounted.\n");
lsdir(disk_mount_pt);
} else {
printk("Error mounting disk.\n");
}
文件操作 链接到标题
统一的文件操作接口,可以参考如何使用Zephyr文件系统一文
int res;
struct fs_dir_t dirp;
static struct fs_dirent entry;
//开启mount点文件夹
res = fs_opendir(&dirp, disk_mount_pt);
if (res) {
printk("Error opening dir %s [%d]\n", disk_mount_pt, res);
return res;
}
//列出mount点文件夹下所有的文件
printk("\nListing dir %s ...\n", disk_mount_pt);
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);
}
}
//关闭开启的文件夹
fs_closedir(&dirp);
//创建文件
res = fs_open(&file, "/SD:/log/file.log");
//seek到末尾
res =fs_seek(&file, 0, FS_SEEK_END);
//写文件
res = fs_write(&file, data, len);
printk("%02x ", data[0]);
//sync文件
fs_sync(&file);
//关闭文件
fs_close(&file);
示例log 链接到标题
前文代码示log例如下
[00:00:00.007,934] <inf> spi_nrfx_spi: CS control inhibited (no GPIO device)
[00:00:00.076,965] <inf> sdhc_spi: Found a ~30436 MiB SDHC card.
[00:00:00.078,460] <inf> sdhc_spi: Manufacturer ID=3 OEM='SD' Name='ACLCD' Revision=0x80 Serial=0x1bd93ca8
[00:00:00.078,491] <inf> fstest: Block count 62333952
Sector size 512
Memory Size(MB) 1764
Disk mounted.
Listing dir /SD: ...
[DIR ] LOST.DIR
[DIR ] ANDROI~1
[DIR ] ANDROID
[DIR ] DATAST~1
[DIR ] ICON_P~1
...
[DIR ] LSSPOR~1
[DIR ] LIFESE~1
[DIR ] RECORD~1
open file success.
shell使用文件系统 链接到标题
只要配置CONFIG_FILE_SYSTEM_SHELL后就可以通过shell来通过操作文件系统来读写TF卡,详细请参考如何使用Zephyr文件系统一文
其它事项 链接到标题
- 因为zephyr内没有直接提供创建文件系统的API,所以需要先将TF卡在电脑上格式化为FAT32格式
- 目前测试FAT32下创建文件夹比较慢
参考 链接到标题
http://elm-chan.org/docs/mmc/mmc_e.html https://www.microchip.com/forums/m530149.aspx