黄山派 TF卡使用

文章目录

一、简介

思澈芯片配置使用TF卡

需求:SD卡、思澈开发板

相关示例文档:

EMMC/SD卡示例

SPI TF卡文件系统示例

SPI TF

MP3_player

LVGL_V8_examples

LVGL_V8_examples

二、说明

黄山派 :支持采用SPI接口的TF卡,板载Micro SD卡插槽

从左往右引脚号是9~1

接口


三、示例使用

首先通过示例现象来熟悉相关设备使用。

1、读取SD卡ID

相关例程SPI 读取SD卡ID

源码路径:example\rt_device\spi\card

使用说明:直接编译下载即可

现象展示:下载后如果SD卡检测成功,会返回SD卡id


2、TF卡文件系统示例

相关例程SPI TF卡文件系统示例

源码路径:example\rt_device\spi_tf

使用说明:直接编译下载即可

现象展示 :下载成功后检测到SD卡,会自动挂载文件系统,显示挂载成功后可以通过FINSH命令进行使用。


接下来还可以使用定义的FINSH指令来进行测试

3、其他示例

eMMC/SD卡示例:源码路径:example/rt_device/emmc。类似spi_tf例程

MP3_player:源码路径:example/multimedia/audio/mp3_sd_player。可以读取SD卡中音频并播放。

本章着重TF卡的使用,暂时不涉及显示,如果对显示感兴趣,可以尝试下面的例程。

LVGL_V8_examples:源码路径:example\multimedia\lvgl\lvgl_v8_examples。可以读取SD卡图片并播放,该工程是一个多项目工程,需要一定的配置才能显示现象。

LVGL_V8_examples源码路径:example\multimedia\lvgl\lvgl_v9_examples。同V8项目示例。

四、从零配置

经过前面几个示例项目的使用,接下来我们看看如何开始配置一个项目工程。

同时你需要了解相关的前置知识,包括:FINSH/文件系统
FINSH
文件系统

1、项目配置

首先准备一个新的项目工程,这里使用Hello_world例程

打开menuconfig并进行配置

需要配置:
开启SPI1总线

对应 CONFIG_BSP_USING_SPI1


将sd\tf设备挂载在spi总线上

对应CONFIG_RT_USING_SPI_MSD


配置文件路径

对应CONFIG_RT_USING_DFS_ELMFAT


2、代码说明

这些代码就是文件系统的注册与挂载

参考文档:文件系统

头文件&宏定义

c 复制代码
#include "dfs_file.h"
#include "spi_msd.h"

#define FS_ROOT "root"   
#define FS_ROOT_PATH "/" 				//统一根目录路径为 '/'
#define FS_ROOT_OFFSET  0X00000000  	//起始地址
#define FS_ROOT_LEN     500*1024*1024   //500M

#define FS_BLOCK_SIZE 0x200

注册文件系统

c 复制代码
//文件系统注册函数,需要将存储设备注册为块设备才能挂载到文件系统上。

struct rt_device *fal_mtd_msd_device_create(char *name, long offset, long len)
{

    rt_device_t msd = rt_device_find("sd0");
    if (msd == NULL)
    {
        rt_kprintf("Error: the flash device name (sd0) is not found.\n");
        return NULL;
    }
    struct msd_device *msd_dev = (struct msd_device *)msd->user_data;

    struct msd_device *msd_file_dev = (struct msd_device *)rt_malloc(sizeof(struct msd_device));
    if (msd_file_dev)
    {
        msd_file_dev->parent.type        = RT_Device_Class_MTD;
#ifdef RT_USING_DEVICE_OPS
        msd_file_dev->parent.ops        = msd_dev->parent.ops;
#else
        msd_file_dev->parent.init       = msd_dev->parent.init;
        msd_file_dev->parent.open       = msd_dev->parent.open;
        msd_file_dev->parent.close      = msd_dev->parent.close;
        msd_file_dev->parent.read       = msd_dev->parent.read;
        msd_file_dev->parent.write      = msd_dev->parent.write;
        msd_file_dev->parent.control    = msd_dev->parent.control;
#endif
        msd_file_dev->offset            = offset;
        msd_file_dev->spi_device        = msd_dev->spi_device;
        msd_file_dev->geometry.bytes_per_sector = FS_BLOCK_SIZE;
        msd_file_dev->geometry.block_size = FS_BLOCK_SIZE;
        msd_file_dev->geometry.sector_count = len;

        rt_device_register(&msd_file_dev->parent, name,
                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
        rt_kprintf("fal_mtd_msd_device_create dev:sd0 part:%s offset:0x%x, size:0x%x\n", name, msd_file_dev->offset, msd_file_dev->geometry.sector_count);
        return RT_DEVICE(&msd_file_dev->parent);;
    }
    return NULL;
}

初始化并挂载

c 复制代码
int mnt_init(void)
{
    uint16_t time_out = 100;
    while (time_out --)
    {
        rt_thread_mdelay(30);
        if (rt_device_find("sd0"))
            break;
    }
    /* 将'/' 注册为块设备,并挂载 */
    fal_mtd_msd_device_create(FS_ROOT, FS_ROOT_OFFSET >> 9, FS_ROOT_LEN >> 9);

    /* 挂载 FS_ROOT,挂载路径 FS_ROOT_PATH,挂载类型 'elm' */
    if (dfs_mount(FS_ROOT, FS_ROOT_PATH, "elm", 0, 0) == 0) // fs exist
    {
        rt_kprintf("mount fs on flash to root success\n");
    }
    else
    {
        // auto mkfs, remove it if you want to mkfs manual
        rt_kprintf("mount fs on flash to root fail\n");
        if (dfs_mkfs("elm", FS_ROOT) == 0)//Format file system
        {
            rt_kprintf("make elm fs on flash sucess, mount again\n");
            if (dfs_mount(FS_ROOT, "/", "elm", 0, 0) == 0)
                rt_kprintf("mount fs on flash success\n");
            else
            {
                rt_kprintf("mount to fs on flash fail\n");
                return RT_ERROR;
            }
        }
        else
            rt_kprintf("dfs_mkfs elm flash fail\n");
    }
    extern int mkdir(const char *path, mode_t mode);
   
    return RT_EOK;
}
INIT_ENV_EXPORT(mnt_init); //编译时自动调用mnt_init函数,不需要在main函数中再次调用

完整代码

c 复制代码
#include "rtthread.h"
#include "bf0_hal.h"
#include "drv_io.h"
#include "stdio.h"
#include "string.h"


#include "dfs_file.h"
#include "spi_msd.h"

#define FS_ROOT "root"
#define FS_ROOT_PATH "/"
#define FS_ROOT_OFFSET  0X00000000
#define FS_ROOT_LEN     500*1024*1024  //500M

#define FS_BLOCK_SIZE 0x200


struct rt_device *fal_mtd_msd_device_create(char *name, long offset, long len)
{

    rt_device_t msd = rt_device_find("sd0");
    if (msd == NULL)
    {
        rt_kprintf("Error: the flash device name (sd0) is not found.\n");
        return NULL;
    }
    struct msd_device *msd_dev = (struct msd_device *)msd->user_data;

    struct msd_device *msd_file_dev = (struct msd_device *)rt_malloc(sizeof(struct msd_device));
    if (msd_file_dev)
    {
        msd_file_dev->parent.type        = RT_Device_Class_MTD;
#ifdef RT_USING_DEVICE_OPS
        msd_file_dev->parent.ops        = msd_dev->parent.ops;
#else
        msd_file_dev->parent.init       = msd_dev->parent.init;
        msd_file_dev->parent.open       = msd_dev->parent.open;
        msd_file_dev->parent.close      = msd_dev->parent.close;
        msd_file_dev->parent.read       = msd_dev->parent.read;
        msd_file_dev->parent.write      = msd_dev->parent.write;
        msd_file_dev->parent.control    = msd_dev->parent.control;
#endif
        msd_file_dev->offset            = offset;
        msd_file_dev->spi_device        = msd_dev->spi_device;
        msd_file_dev->geometry.bytes_per_sector = FS_BLOCK_SIZE;
        msd_file_dev->geometry.block_size = FS_BLOCK_SIZE;
        msd_file_dev->geometry.sector_count = len;

        rt_device_register(&msd_file_dev->parent, name,
                           RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_REMOVABLE | RT_DEVICE_FLAG_STANDALONE);
        rt_kprintf("fal_mtd_msd_device_create dev:sd0 part:%s offset:0x%x, size:0x%x\n", name, msd_file_dev->offset, msd_file_dev->geometry.sector_count);
        return RT_DEVICE(&msd_file_dev->parent);;
    }
    return NULL;
}

int mnt_init(void)
{
    uint16_t time_out = 100;
    while (time_out --)
    {
        rt_thread_mdelay(30);
        if (rt_device_find("sd0"))
            break;
    }
    fal_mtd_msd_device_create(FS_ROOT, FS_ROOT_OFFSET >> 9, FS_ROOT_LEN >> 9);
    if (dfs_mount(FS_ROOT, FS_ROOT_PATH, "elm", 0, 0) == 0) // fs exist
    {
        rt_kprintf("mount fs on flash to root success\n");
    }
    else
    {
        // auto mkfs, remove it if you want to mkfs manual
        rt_kprintf("mount fs on flash to root fail\n");
        if (dfs_mkfs("elm", FS_ROOT) == 0)//Format file system
        {
            rt_kprintf("make elm fs on flash sucess, mount again\n");
            if (dfs_mount(FS_ROOT, "/", "elm", 0, 0) == 0)
                rt_kprintf("mount fs on flash success\n");
            else
            {
                rt_kprintf("mount to fs on flash fail\n");
                return RT_ERROR;
            }
        }
        else
            rt_kprintf("dfs_mkfs elm flash fail\n");
    }
    extern int mkdir(const char *path, mode_t mode);
    return RT_EOK;
}
INIT_ENV_EXPORT(mnt_init);

/**
 * @brief  Main program
 * @param  None
 * @retval 0 if success, otherwise failure number
 */
int main(void)
{
    /* Output a message on console using printf function */
    rt_kprintf("Hello world!\n");

    /* Infinite loop */
    while (1)
    {
        // Delay for 1000 ms to yield CPU time to other threads
        rt_thread_mdelay(1000);
    }
    return 0;
}

3、项目编译/下载/测试

编译通过,下载查看现象

下载后log自动显示SD卡信息,同时出现mount fs on flash root success 说明文件系统挂载成功

输入创建文件夹指令mkdir可以看到成功创建文件夹

相关推荐
泰迪智能科技0113 小时前
泰迪智能科技案例库 | 农业行业项目案例合集
科技
upper202013 小时前
【炒股学习】集合竞价
学习·区块链
以孝治家行动13 小时前
线上共读传孝道 身体力行润家风——以孝治家家教中心开展线上学习
学习
小智RE0-走在路上15 小时前
Python学习笔记(8) --函数的多返回值,不同传参,匿名函数
笔记·python·学习
charlie11451419116 小时前
现代C++嵌入式教程:C++98基础特性:从C到C++的演进(1)
c语言·开发语言·c++·笔记·学习·教程
喜欢吃豆16 小时前
我把 LLM 技术栈做成了一张“可复用的认知地图”:notes-on-llms 开源仓库介绍
学习·语言模型·架构·开源·大模型·多模态
学烹饪的小胡桃17 小时前
【运维学习】实时性能监控工具 WGCLOUD v3.6.2 更新介绍
linux·运维·服务器·学习·工单系统
nnsix17 小时前
QFramework学习笔记
笔记·学习
我想我不够好。17 小时前
电工实操 电路的接线和理解以及练习 12.21
学习
ys~~17 小时前
git学习
git·vscode·python·深度学习·学习·nlp·github