【MM32F5270开发板试用】依靠SPI_SD,移植FatFs文件系统

【MM32F5270开发板试用】依靠SPI_SD,移植FatFs文件系统

本次所有代码按照以前习惯全部开源:我的Github地址是:https://github.com/kings669/MM32F5

我的初步计划将完成音乐播放器的开发,所有代码均会在仓库中更新。

一、FatFs
官网:http://elm-chan.org/fsw/ff/00index_e.html
image.png

我们先下载源码包,或者在MindSDK中也有。
在这里插入图片描述

FatFs是用于小型嵌入式系统的通用FAT / exFAT文件系统模块。FatFs模块是按照ANSI
C(C89)编写的,并且与磁盘I/O层完全分开。因此,它独立于平台。它可以并入资源有限的小型微控制器中,例如8051,PIC,AVR,ARM,Z80,RX等。

“FatFs模块是为教育,研究和开发开放的免费软件。您可以在个人项目或商业产品中使用,修改和/或重新分发它,而不受您的责任限制。”

特征

  • DOS / Windows兼容的FAT / exFAT文件系统。
  • 平台无关。易于移植。
  • 程序代码和工作区的占用空间非常小。
    支持以下各种配置选项:
  • ANSI / OEM或Unicode中的长文件名。
  • exFAT文件系统,64位LBA和GPT可存储大量数据。
  • RTOS的线程安全。
  • 多个卷(物理驱动器和分区,最多10个卷)。
  • 可变扇区大小。 多个代码页,包括DBCS。
  • 只读,可选API,I /O缓冲区等…

层级结构
image.png

image.png

文件夹
image.png

documents文件夹中就是官方的文档文件
source文件中就是我们的源文件
还有证书文件
image.png

00history.txt 介绍了 FatFs 的版本更新情况。
00readme.txt 说明了当前目录下 diskio.c diskio.hff.cff.hinteger.h 的功能。
diskio.c 文件是 FatFs 移植最关键的文件,它为文件系统提供了最底层的访问 SPI Flash芯片的方法, FatFs 有且仅有它需要用到与 SPI Flash 芯片相关的函数。
diskio.h 定义了FatFs 用到的宏,以及 diskio.c 文件内与底层硬件接口相关的函数声明。
源码文件功能简介如下:

diskio.c:包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加底层驱动函数。
ff.c:FatFs 核心文件,文件管理的实现方法。该文件独立于底层介质操作文件的函数,利用这些函数实现文件的读写。
二、MindSDK——SD_SPI
我们打开MindSDK的官网:https://mindsdk.mindmotion.com.cn,没有账户的需要注册一下。
image.png

我们构建F5270,系统我的是Win10,编译器是keil,这是我的选择,大家可以根据自己的来选择。
image.png

构建完成后,我们来到以下页面,点击进入

image.png

我们选择进入例程文件中
在这里插入图片描述

image.png
我们选中sdspi_basic,然后点击下载。
image.png

我们编译一下,很好没有问题:

三、移植FatFS
我们把FatFS源代码放在components文件夹中。
image.png

我们需要修改diskio.c文件中的东西。

/*-----------------------------------------------------------------------*/
/* Low level disk I/O module SKELETON for FatFs     (C)ChaN, 2019        */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be        */
/* attached to the FatFs via a glue function rather than modifying it.   */
/* This is an example of glue functions to attach various exsisting      */
/* storage control modules to the FatFs module with a defined API.       */
/*-----------------------------------------------------------------------*/

#include "ff.h"            /* Obtains integer types */
#include "diskio.h"        /* Declarations of disk functions */
#include "sdspi.h"

/* Definitions of physical drive number for each drive */
#define DEV_RAM        0    /* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC        1    /* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB        2    /* Example: Map USB MSD to physical drive 2 */

SDSPI_ApiRetStatus_Type app_sdspi_ret;
SDSPI_CardHandler_Type app_sdspi_card;
extern const SDSPI_Interface_Type board_sdspi_if;

/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
    BYTE pdrv        /* Physical drive nmuber to identify the drive */
)
{
    DSTATUS stat;
    int result;

    switch (pdrv) {
    case DEV_RAM :
        //result = RAM_disk_status();

        // translate the reslut code here

        return stat;

    case DEV_MMC :
        //result = MMC_disk_status();
        stat = RES_OK;
        // translate the reslut code here

        return stat;

    case DEV_USB :
        //result = USB_disk_status();

        // translate the reslut code here

        return stat;
    }
    return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
    BYTE pdrv                /* Physical drive nmuber to identify the drive */
)
{
    DSTATUS stat;
    //int result;

    switch (pdrv) {
    case DEV_RAM :
        //result = RAM_disk_initialize();

        // translate the reslut code here

        return stat;

    case DEV_MMC :
        //result = MMC_disk_initialize();

        if(!SDSPI_Init(&app_sdspi_card, &board_sdspi_if)){
            stat = RES_OK;
        }else{
            stat = STA_NOINIT;
        }
        // translate the reslut code here

        return stat;

    case DEV_USB :
        //result = USB_disk_initialize();

        // translate the reslut code here

        return stat;
    }
    return STA_NOINIT;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
    BYTE pdrv,        /* Physical drive nmuber to identify the drive */
    BYTE *buff,        /* Data buffer to store read data */
    LBA_t sector,    /* Start sector in LBA */
    UINT count        /* Number of sectors to read */
)
{
    DRESULT res;
    //int result;

    switch (pdrv) {
    case DEV_RAM :
        // translate the arguments here

        //result = RAM_disk_read(buff, sector, count);

        // translate the reslut code here

        return res;

    case DEV_MMC :
        // translate the arguments here

        //result = MMC_disk_read(buff, sector, count);
        if(!SDSPI_ReadBlocks(&app_sdspi_card,buff, sector, count))
        {
            res = RES_OK;
        }else{
            res = RES_ERROR;
        }

        // translate the reslut code here

        return res;

    case DEV_USB :
        // translate the arguments here

        //result = USB_disk_read(buff, sector, count);

        // translate the reslut code here

        return res;
    }

    return RES_PARERR;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if FF_FS_READONLY == 0

DRESULT disk_write (
    BYTE pdrv,            /* Physical drive nmuber to identify the drive */
    const BYTE *buff,    /* Data to be written */
    LBA_t sector,        /* Start sector in LBA */
    UINT count            /* Number of sectors to write */
)
{
    DRESULT res;
    //int result;

    switch (pdrv) {
    case DEV_RAM :
        // translate the arguments here

        //result = RAM_disk_write(buff, sector, count);

        // translate the reslut code here

        return res;

    case DEV_MMC :
        // translate the arguments here

        //result = MMC_disk_write(buff, sector, count);
        if(!SDSPI_WriteBlocks(&app_sdspi_card,(uint8_t *)buff, sector, count))
        {
            res = RES_OK;
        }else{
            res = RES_ERROR;
        }

        // translate the reslut code here

        return res;

    case DEV_USB :
        // translate the arguments here

        //result = USB_disk_write(buff, sector, count);

        // translate the reslut code here

        return res;
    }

    return RES_PARERR;
}

#endif


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
    BYTE pdrv,        /* Physical drive nmuber (0..) */
    BYTE cmd,        /* Control code */
    void *buff        /* Buffer to send/receive control data */
)
{
    DRESULT res;
    int result;

    switch (pdrv) {
    case DEV_RAM :

        // Process of the command for the RAM drive

        return res;

    case DEV_MMC :

        // Process of the command for the MMC/SD card
        switch(cmd)
        {
            case GET_SECTOR_COUNT:
         *(DWORD *)buff = app_sdspi_card.blockCount;
         res = RES_OK;
         break;

      case GET_BLOCK_SIZE:
         *(DWORD *)buff = SDSPI_DEFAULT_BLOCK_SIZE;
         res = RES_OK;
         break;
        }

        return res;

    case DEV_USB :

        // Process of the command the USB drive

        return res;
    }

    return RES_PARERR;
}

mian.c:

/*
 * Copyright 2021 MindMotion Microelectronics Co., Ltd.
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "board_init.h"
#include "ffconf.h"
#include "ff.h"


/*
 * Macros.
 */

/*
 * Variables.
 */

FATFS fs;
const TCHAR fs_drv[] = "1:/";
TCHAR fs_path[256] = "\0";


/*
 * Declerations.
 */
 FRESULT app_fatfs_listfiles(const char * dir_path);


/*
 * Functions.
 */
int main(void)
{
    uint8_t ch;

    BOARD_Init();

    printf("sdspi_basic example.\r\n");
    
        /* f_mount().\r\n */
    printf("f_mount(). ");
    if( !f_mount(&fs, fs_drv ,1) )
    {
        printf("succ.\r\n");
    }
    else
    {
        printf("fail.\r\n");
        while (1)
        {}
    }
    
    /* root dir. */
    app_fatfs_listfiles(fs_drv);
    
    /* dir0. */
    fs_path[0] = '\0';
    strcat(fs_path, fs_drv);
    strcat(fs_path, "dir0/");
    app_fatfs_listfiles(fs_path);

    /* dir1. */
    fs_path[0] = '\0';
    strcat(fs_path, fs_drv);
    strcat(fs_path, "dir1/");
    app_fatfs_listfiles(fs_path);
    
    printf("app_fatfs_listfiles() done.\r\n");

    while (1)
    {
        ch = getchar();
        putchar(ch);
    }
}

/* list the file items under the indecated path. */
FRESULT app_fatfs_listfiles(const char * dir_path)
{
    FRESULT res;
    FILINFO fno;
    DIR dir;
    char *fn;

    printf("* %s ->\r\n", dir_path);
    
    res = f_opendir(&dir, dir_path);
    if (res != FR_OK)
    {
        return res;
    }

    for (;;)
    {
        /* read iterator. */
        res = f_readdir(&dir, &fno);
        if ( (res != FR_OK) || (fno.fname[0] == 0) )
        {
            break;
        }

        /* skip the "self" and "father" dir item. */
        if (fno.fname[0] == '.') 
        {
            continue;
        }
        
        /* collect the dir or file name. */
        fn = fno.fname;
        if (fno.fattrib & AM_DIR) /* dir name. */
        {
            printf("\t%s/\r\n", fn);
        } 
        else /* file name */
        {
            printf("\t%s: %u B\r\n", fn, (unsigned)fno.fsize);
        }            
    }

    /* close the opened dir to reest the iterator. */
    res = f_closedir(&dir);

    return res;
}

/* EOF. */

四、验证
image.png

我们插上读卡器:
image.png

在dir0和dir1中也有两个文件夹,是Test3和Test4.这些文件夹都是我自己创建的,MCU已经能够查看到了。没有问题

五、总结
MindSDK使用体验还行,只能提供例子。最好能够有CubeMX这样的配置,添加包就行,就会方便很多。现在移植好了文件系统,下一步就是要进行软解码了,加油💪💪

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的MM32F0144C6读取SPI Flash ID的示例代码: ```c #include "MM32F0144.h" #define SPI_FLASH_CS_LOW() GPIO_ResetBits(GPIOC, GPIO_Pin_4) #define SPI_FLASH_CS_HIGH() GPIO_SetBits(GPIOC, GPIO_Pin_4) #define SPI_FLASH_CMD_READ_ID 0x9F void SPI_Flash_Init(void); uint8_t SPI_Flash_SendByte(uint8_t byte); uint8_t SPI_Flash_ReadByte(void); void SPI_Flash_ReadID(uint8_t *pManufacturerID, uint8_t *pDeviceID); int main(void) { uint8_t manufacturer_id = 0; uint8_t device_id = 0; SPI_Flash_Init(); SPI_Flash_ReadID(&manufacturer_id, &device_id); while(1); } void SPI_Flash_Init(void) { SPI_InitTypeDef SPI_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOC, &GPIO_InitStructure); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI2, &SPI_InitStructure); SPI_Cmd(SPI2, ENABLE); } uint8_t SPI_Flash_SendByte(uint8_t byte) { while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI2, byte); while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPI2); } uint8_t SPI_Flash_ReadByte(void) { return SPI_Flash_SendByte(0xFF); } void SPI_Flash_ReadID(uint8_t *pManufacturerID, uint8_t *pDeviceID) { SPI_FLASH_CS_LOW(); SPI_Flash_SendByte(SPI_FLASH_CMD_READ_ID); *pManufacturerID = SPI_Flash_ReadByte(); *pDeviceID = SPI_Flash_ReadByte(); SPI_FLASH_CS_HIGH(); } ``` 在上面的示例代码中,我们使用了MM32F0144C6的SPI2接口来与SPI Flash通信。我们使用了GPIOC的第4个引脚作为SPI Flash的片选引脚。在初始化SPI接口后,我们可以通过SPI_Flash_SendByte()函数发送字节数据,通过SPI_Flash_ReadByte()函数读取字节数据。在SPI_Flash_ReadID()函数中,我们发送了0x9F命令,读取SPI Flash的制造商ID和设备ID。最后,我们打印出了制造商ID和设备ID。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值