当前位置:   article > 正文

先楫MCU:HPM6750 移植fatfs读写eMMC_emmc移植

emmc移植

简介

最近用到先楫的单片机HPM6750(HPM6754),由于一些原因需要使用eMMC代替SD卡存储数据,为了方便数据管理与查看,准备使用Fatfs,而官方SDK并未提供eMMC的Fatfs读写例程,因此作者参考先楫官方提供的SD卡的Fatfs例程实现了Fatfs挂载到eMMC设备的数据读写,也就是将Fatfs“移植”到eMMC。

Fatfs说明

现在各种论坛上有很多单片机移植Fatfs的教程与分享,对于不了解Fatfs的读者可以先去了解一下。
Fatfs简单来说就是用于嵌入式的通用 FAT/exFAT文件系统模块,作为嵌入式应用的中间件使用,在对Fatfs模块配置好底层存储设备的IO驱动后,上层应用就可以方便的使用FATfs提供的各种接口对数据以文件的形式进行读写,而无需面对存储设备进行编程。

图片来自官网

Fatfs官网: http://elm-chan.org/fsw/ff/00index_e.html.

我们常说的*FAT是文件配置表(File Allocation Table)*的缩写,FATfs则是根据这样一个标准的文件配置表对数据以文件的形式,使用约定的存储方式(卷、块、扇区)在存储设备内进行读写。由于Windows“兼容”FAT文件系统,因此嵌入式设备存储在SD卡中的文件在PC中可以看到并读写。

图片来源于互联网

一文看懂FAT32、exFAT和NTFS文件系统的区别:https://baijiahao.baidu.com/s?id=1775167484750138683&wfr=spider&for=pc.

驱动eMMC

在移植fatfs前,我们要确保eMMC直接初始化正确、读写正确,即底层驱动的例程应该调试通过。
对于驱动eMMC读取存储设备信息,进行数据直接读取的例程官方已经提供,只需稍加修改即可使用。
在此路径下:sdk_env\hpm_sdk\samples\drivers\sdxc
建议自行修改或者查看以下博主的论文修改:
来自博客园“求隐”:https://www.cnblogs.com/duguqiuying/articles/17823329.html.

在此,作者使用的是江波龙的eMMC,high-speed SDR模式,读写40MB/s左右,与上述博文略有不同。

移植准备

在移植之前,我们需要知道emmc_fatfs工程应该怎么构建的,先楫是使用CMake进行管理工程与控制编译流程的,由于作者在此之前并没有接触过CMake,在移植之前我们需要知道如何添加源文件与头文件路径,以及定义条件编译等。因此我们参考sd_fatfs例程,分析构建工程、移植fatfs的流程。

需要注意的是:与MDK在IDE设置全局定义、管理工程文件与编译器设置等操作不同的是,先楫采用CMake组织管理工程文件,这些设置需要在CMakeList.txt文件中进行配置,官方推荐IDE仅做编译调试使用。

参考:先楫公众号文章:你想要了解的先楫hpm_sdk开发都在这里系列 (一)

首先在sd_fatfs例程下(路径见图片左上角)的CMakeList中定义了CONFIG_SDMMC,CONFIG_FATFS,如下图。
图4-1
middleware文件夹下的CMakeList检测到CONFIG_FATFS则在工程中添加了 middleware\fatfs这个子文件夹,下面存放fatfs的头文件与源代码。检测到CONFIG_SDMMC则在工程中添加了hpm_sdmmc这个子文件夹,下面存放先楫编写的sd/eMMC的底层驱动。如下图。
图4-2
到此例程将两个子文件夹添加入工程,如下图。
图4-3

进入middleware\fatfs下面的CMakeList中,检测到定义了CONFIG_SDMMC,则添加宏定义:SD_FATFS_ENABLE=1。文件开头添加了fatfs的源文件路径,另外添加了porrable子文件夹,此文件夹中包含文件系统的移植程序,也就是移植fatfs需要修改的有关底层硬件驱动的部分。如下图。图4-4

进入Portable文件下的CMakeList中,首先将此文件路径下的头文件与源文件添加进工程,后面判断是否定义CONFIG_XXX,如果定义了就将相应的头文件与源文件添加工程。在此,CONFIG_SDMMC已经定义,因此将sdxc作为头文件路径与源文件路径。
图4-5

移植FAT文件系统过程中,主要需要修改的是portable文件夹下的diskio头文件与源文件,portable\sdxc文件夹下的hpm_sdmmc_disk头文件与源文件。hpm_sdmmc_disk文件中写我们所要移植FAT系统设备(比如SD、flash、eMMC)的底层驱动,而diskio则是用来将我们写的底层驱动封装成FAT其他上层接口认识的底层接口,形象点说就是将函数换个名字,方便上层引用。

读者查看diskio.c文件就会豁然开朗,移植的逻辑很简单,就是根据条件编译,使能不同的函数发生作用,因此我们模仿原程序的结构对eMMC的部分进行补充就好。然后我们可以在middleware\fatfs\src\portable\sdxc下创建emmc的底层接口的驱动文件,根据sd卡的参考例程与eMMC的直接读写例程做修改即可。

开始移植

下面我们开始移植eMMC的FAT文件系统!

==在下面的移植过程中,对一些CMakeList文件的修改,作者往往只是添加了一两句,读者根据上面的分析也可能不易于理解,具体还需读者自己去查看工程文件!!!。

1、在例程路径下,复制emmc文件夹,改名为emmc_fatfs。

复制emmc文件夹

2、emmc_fatfs下的CMakeList文件更改如下

主要是修改变量名、工程名等

# Copyright (c) 2023 HPMicro
# SPDX-License-Identifier: BSD-3-Clause

cmake_minimum_required(VERSION 3.13)

set(CONFIG_eMMC 1)
set(CONFIG_FATFS 1)

find_package(hpm-sdk REQUIRED HINTS $ENV{HPM_SDK_BASE})

project(emmc_fatfs)

sdk_compile_definitions(-DeMMC_FATFS_ENABLE=1)
sdk_compile_definitions(-DFF_CODE_PAGE=437)

sdk_compile_options(-Os)

sdk_inc(src)

sdk_app_src(src/emmc_fatfs.c)
generate_ses_project()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

3、middleware下的CMakeList文件更改如下

# Copyright (c) 2021-2023 HPMicro
# SPDX-License-Identifier: BSD-3-Clause

add_subdirectory_ifdef(CONFIG_LVGL lvgl)
add_subdirectory_ifdef(CONFIG_TINYUSB tinyusb)
add_subdirectory_ifdef(CONFIG_TINYCRYPT tinycrypt)
add_subdirectory_ifdef(CONFIG_FATFS fatfs)
add_subdirectory_ifdef(CONFIG_FREERTOS FreeRTOS)
add_subdirectory_ifdef(CONFIG_MOTORCTRL hpm_mcl)
add_subdirectory_ifdef(CONFIG_SDMMC hpm_sdmmc)
add_subdirectory_ifdef(CONFIG_eMMC hpm_sdmmc)
add_subdirectory_ifdef(CONFIG_LIBJPEG libjpeg-turbo)
add_subdirectory_ifdef(CONFIG_LWIP lwip)
add_subdirectory_ifdef(CONFIG_COREMARK coremark)
add_subdirectory_ifdef(CONFIG_TFLM tflm)
add_subdirectory_ifdef(CONFIG_HPM_MATH hpm_math)
add_subdirectory_ifdef(CONFIG_AUDIO_CODEC audio_codec)
add_subdirectory_ifdef(CONFIG_SEGGER_RTT segger_rtt)
add_subdirectory_ifdef(CONFIG_ERPC erpc)
add_subdirectory_ifdef(CONFIG_CHERRYUSB cherryusb)
add_subdirectory_ifdef(CONFIG_MBEDTLS mbedtls)
add_subdirectory_ifdef(CONFIG_UCOS_III ucos_iii)
add_subdirectory(azure_rtos)
add_subdirectory_ifdef(CONFIG_MICROROS microros)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

4、middleware\fatfs下的cmakelist文件更改如下

# Copyright (c) 2021 HPMicro
# SPDX-License-Identifier: BSD-3-Clause

sdk_inc(src/common)
sdk_src(src/common/ff.c)
sdk_src(src/common/ffunicode.c)

add_subdirectory(src/portable)

if(DEFINED CONFIG_SDMMC)
sdk_compile_definitions(-DSD_FATFS_ENABLE=1)
endif()

if(DEFINED CONFIG_eMMC)
sdk_compile_definitions(-DeMMC_FATFS_ENABLE=1)
endif()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

5、middleware\fatfs\src\portable下的cmakelist文件更改如下

# Copyright (c) 2021 HPMicro
# SPDX-License-Identifier: BSD-3-Clause

sdk_inc(.)
sdk_src(diskio.c)

sdk_inc_ifdef(CONFIG_USB_FATFS usb)
sdk_src_ifdef(CONFIG_USB_FATFS_TINYUSB usb/hpm_fatfs_tinyusb.c)
sdk_src_ifdef(CONFIG_USB_FATFS_CHERRYUSB usb/hpm_fatfs_cherryusb.c)

sdk_inc_ifdef(CONFIG_eMMC sdxc)
sdk_src_ifdef(CONFIG_eMMC sdxc/hpm_emmc_disk.c)

if(NOT DEFINED CONFIG_HPM_SPI_SDCARD)
sdk_inc_ifdef(CONFIG_SDMMC sdxc)
sdk_src_ifdef(CONFIG_SDMMC sdxc/hpm_sdmmc_disk.c)
else()
sdk_inc_ifdef(CONFIG_HPM_SPI_SDCARD spi_sd)
sdk_src_ifdef(CONFIG_HPM_SPI_SDCARD spi_sd/hpm_spi_sd_disk.c)
endif()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

6、将middleware\fatfs\src\portable\sdxc文件夹下的源文件与头文件复制粘贴改名为hpm_emmc_disk.c与.h。

7、修改hpm_emmc_disk.h如下

/*
 * Copyright (c) 2021-2022 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#ifndef HPM_EMMC_DISK_H
#define HPM_EMMC_DISK_H

#include "ff.h"
#include "diskio.h"
#include "hpm_sdmmc_emmc.h"

extern emmc_card_t g_emmc;


#define MAX_ALIGNED_BUF_SIZE (16384U)

#ifdef __cplusplus
extern "C" {
#endif

DSTATUS emmc_disk_initialize(BYTE pdrv);

DSTATUS emmc_disk_deinitialize(BYTE pdrv);

DSTATUS emmc_disk_status(BYTE pdrv);

DSTATUS emmc_disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count);

DSTATUS emmc_disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count);

DRESULT emmc_disk_ioctl(BYTE pdrv, BYTE cmd, void *buff);


#ifdef __cplusplus
}
#endif

#endif /* HPM_eMMC_DISK_H */

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

8、修改hpm_emmc_disk.c如下

/*
 * Copyright (c) 2021-2022 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include "ffconf.h"
#include "hpm_emmc_disk.h"
#include "hpm_l1c_drv.h"
#include "board.h"

#define EMMC_SECTOR_SIZE (512UL)

ATTR_PLACE_AT_NONCACHEABLE_BSS emmc_card_t g_emmc;

ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint32_t g_aligned_buf[MAX_ALIGNED_BUF_SIZE / sizeof(uint32_t)];

DSTATUS emmc_disk_initialize(BYTE pdrv)
{
    static bool has_card_initialized = false;

    if (pdrv != DEV_MMC) {
        return STA_NOINIT;
    }

    if (has_card_initialized) {
        return RES_OK;
    }

    if (emmc_init(&g_emmc) != status_success) {
        emmc_deinit(&g_emmc);
        memset(&g_emmc, 0, sizeof(g_emmc));
        return STA_NODISK;
    }
    has_card_initialized = true;

    return RES_OK;
}

DSTATUS emmc_disk_deinitialize(BYTE pdrv)
{
    emmc_deinit(&g_emmc);

    return RES_OK;
}

DSTATUS emmc_disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
{
    if (pdrv != DEV_MMC) {
        return RES_PARERR;
    }

    if (((uint32_t)buff % 4) != 0) {
        uint32_t sys_aligned_buf_addr = core_local_mem_to_sys_address(BOARD_RUNNING_CORE, (uint32_t)&g_aligned_buf);
        uint32_t remaining_size = EMMC_SECTOR_SIZE * count;
        while(remaining_size > 0) {
            uint32_t write_size = MIN(sizeof(g_aligned_buf), remaining_size);

            memcpy(g_aligned_buf, buff, write_size);
            l1c_dc_flush(sys_aligned_buf_addr, write_size);
            uint32_t sector_count = (uint32_t) write_size / EMMC_SECTOR_SIZE;
            if (emmc_write_blocks(&g_emmc, (const uint8_t *) sys_aligned_buf_addr, (uint32_t) sector, sector_count) != status_success) {
                return RES_ERROR;
            }
            buff += write_size;
            sector += sector_count;
            remaining_size -= write_size;
        }
    } else {
        if (emmc_write_blocks(&g_emmc, (const uint8_t *) buff, (uint32_t) sector, (uint32_t) count) != status_success) {
            return RES_ERROR;
        }
    }

    return RES_OK;
}

DSTATUS emmc_disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
{
    if (pdrv != DEV_MMC) {
        return RES_PARERR;
    }

    if (((uint32_t)buff % 4) != 0) {
        uint32_t sys_aligned_buf_addr = core_local_mem_to_sys_address(BOARD_RUNNING_CORE, (uint32_t)&g_aligned_buf);
        uint32_t remaining_size = EMMC_SECTOR_SIZE * count;
        while(remaining_size > 0) {
            uint32_t read_size = MIN(sizeof(g_aligned_buf), remaining_size);
            uint32_t sector_count = read_size / EMMC_SECTOR_SIZE;
            if (emmc_read_blocks(&g_emmc, (uint8_t *) sys_aligned_buf_addr, sector, sector_count) != status_success) {
                return RES_ERROR;
            }
            l1c_dc_invalidate(sys_aligned_buf_addr, read_size);
            memcpy(buff, g_aligned_buf, read_size);
            buff += read_size;
            sector += sector_count;
            remaining_size -= read_size;
        }
    } else {
      if (emmc_read_blocks(&g_emmc, (uint8_t *) buff, sector, count) != status_success) {
          return RES_ERROR;
      }
    }
    return RES_OK;
}

DRESULT emmc_disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
{
    DRESULT result = RES_PARERR;
    do {
        HPM_BREAK_IF((pdrv != DEV_MMC) || ((cmd != CTRL_SYNC) && (buff == NULL)));
        result = RES_OK;
        switch (cmd) {
        case GET_SECTOR_COUNT:          
            *(uint32_t *) buff = g_emmc.device_attribute.sector_count;	
            break;
        case GET_SECTOR_SIZE:           
            *(uint32_t *) buff = g_emmc.device_attribute.sector_size;
            break;
        case GET_BLOCK_SIZE:            
            *(uint32_t *) buff = g_emmc.device_attribute.erase_group_size;
            break;
        case CTRL_SYNC:
            result = RES_OK;
            break;
        default:
            result = RES_PARERR;
            break;
        }

    } while (false);

    return result;
}

DSTATUS emmc_disk_status(BYTE pdrv)
{
    if (pdrv != DEV_MMC) {
        return STA_NOINIT;
    }

    return RES_OK;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145

9、修改middleware\fatfs\src\portable下的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 existing       */
/* storage control modules to the FatFs module with a defined API.       */
/*-----------------------------------------------------------------------*/

/*
 * Copyright (c) 2021-2023 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include "diskio.h"          /* Declarations of disk functions */

// usb
#if defined(USB_FATFS_ENABLE) && USB_FATFS_ENABLE
#include "./usb/hpm_fatfs_usb.h"
#endif

// sd
#if defined(SD_FATFS_ENABLE) && SD_FATFS_ENABLE

#if defined(SD_SPI_ENABLE) && (SD_SPI_ENABLE)
#include "./spi_sd/hpm_spi_sd_disk.h"
#else
#include "./sdxc/hpm_sdmmc_disk.h"
#endif

#endif

// emmc
#if defined(eMMC_FATFS_ENABLE) && eMMC_FATFS_ENABLE
#include "./sdxc/hpm_emmc_disk.h"
#endif



/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/
DSTATUS disk_status(
        BYTE pdrv   /* Physical drive number to identify the drive */
)
{
    DSTATUS stat = STA_NOINIT;

    switch (pdrv) {
    case DEV_RAM :
        break;

    // case DEV_MMC :
    //     break;

#if defined(USB_FATFS_ENABLE) && USB_FATFS_ENABLE
    case DEV_USB :
        stat = usb_disk_status(pdrv);
        break;
#endif

#if defined(SD_FATFS_ENABLE) && SD_FATFS_ENABLE
    case DEV_SD:
#if defined(SD_SPI_ENABLE) && (SD_SPI_ENABLE)
        stat = spi_sd_disk_status(pdrv);
#else
        stat = sd_disk_status(pdrv);
#endif
        break;
#endif

// emmc
#if defined(eMMC_FATFS_ENABLE) && eMMC_FATFS_ENABLE
    case DEV_MMC:
        stat = emmc_disk_status(pdrv);
        break;
#endif

    default:
        break;
    }

    return stat;
}

/*-----------------------------------------------------------------------*/
/* Initialize a Drive                                                    */
/*-----------------------------------------------------------------------*/
void disk_deinitialize(
        BYTE pdrv   /* Physical drive number to identify the drive */
)
{
    switch (pdrv) {
    case DEV_RAM :
        break;

    // case DEV_MMC :
    //     break;

#if defined(USB_FATFS_ENABLE) && USB_FATFS_ENABLE
    case DEV_USB:
        usb_disk_deinitialize();
        break;
#endif

#if defined(SD_FATFS_ENABLE) && SD_FATFS_ENABLE
    case DEV_SD:
#if defined(SD_SPI_ENABLE) && (SD_SPI_ENABLE)
        spi_sd_disk_deinitialize(pdrv);
#else
        sd_disk_deinitialize(pdrv);
#endif
        break;
#endif

// emmc
#if defined(eMMC_FATFS_ENABLE) && eMMC_FATFS_ENABLE
    case DEV_MMC:
        emmc_disk_deinitialize(pdrv);
        break;
#endif

    default:
        break;
    }
}

DSTATUS disk_initialize(
        BYTE pdrv   /* Physical drive number to identify the drive */
)
{
    DSTATUS stat = STA_NOINIT;

    switch (pdrv) {
    case DEV_RAM :
        break;

    // case DEV_MMC :
    //     break;

#if defined(USB_FATFS_ENABLE) && USB_FATFS_ENABLE
    case DEV_USB :
        stat = usb_disk_initialize(pdrv);
        break;
#endif

#if defined(SD_FATFS_ENABLE) && SD_FATFS_ENABLE
    case DEV_SD:
#if defined(SD_SPI_ENABLE) && (SD_SPI_ENABLE)
        stat = spi_sd_disk_initialize(pdrv);
#else
        stat = sd_disk_initialize(pdrv);
#endif
        break;
#endif

// emmc
#if defined(eMMC_FATFS_ENABLE) && eMMC_FATFS_ENABLE
    case DEV_MMC:
        stat = emmc_disk_initialize(pdrv);
        break;
#endif

    default:
        break;
    }

    return stat;
}

/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/
DRESULT disk_read(
        BYTE pdrv,      /* Physical drive number 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 = RES_ERROR;

    switch (pdrv) {
    case DEV_RAM :
        break;

    // case DEV_MMC :
    //     break;

#if defined(USB_FATFS_ENABLE) && USB_FATFS_ENABLE
    case DEV_USB :
        res = usb_disk_read(pdrv, buff, sector, count);
        break;
#endif

#if defined(SD_FATFS_ENABLE) && SD_FATFS_ENABLE
    case DEV_SD:
#if defined(SD_SPI_ENABLE) && (SD_SPI_ENABLE)
        res = spi_sd_disk_read(pdrv, buff, sector, count);
#else
        res = sd_disk_read(pdrv, buff, sector, count);
#endif
        break;
#endif

// emmc
#if defined(eMMC_FATFS_ENABLE) && eMMC_FATFS_ENABLE
    case DEV_MMC:
        res = emmc_disk_read(pdrv, buff, sector, count);
        break;
#endif

    default:
        res = RES_PARERR;
        break;
    }

    return res;
}

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

#if FF_FS_READONLY == 0

DRESULT disk_write(
        BYTE pdrv,          /* Physical drive number 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 = RES_ERROR;

    switch (pdrv) {
    case DEV_RAM :
        break;

    // case DEV_MMC :
    //     break;

#if defined(USB_FATFS_ENABLE) && USB_FATFS_ENABLE
    case DEV_USB :
        res = usb_disk_write(pdrv, buff, sector, count);
        break;
#endif

#if defined(SD_FATFS_ENABLE) && SD_FATFS_ENABLE
    case DEV_SD:
#if defined(SD_SPI_ENABLE) && (SD_SPI_ENABLE)
        res = spi_sd_disk_write(pdrv, buff, sector, count);
#else
        res = sd_disk_write(pdrv, buff, sector, count);
#endif
        break;
#endif

// emmc
#if defined(eMMC_FATFS_ENABLE) && eMMC_FATFS_ENABLE
    case DEV_MMC:
        res = emmc_disk_write(pdrv, buff, sector, count);
        break;
#endif

    default:
        res = RES_PARERR;
        break;
    }

    return res;
}

#endif

/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/
DRESULT disk_ioctl(
        BYTE pdrv,      /* Physical drive number (0..) */
        BYTE cmd,       /* Control code */
        void *buff      /* Buffer to send/receive control data */
)
{
    DRESULT res = RES_ERROR;

    switch (pdrv) {
    case DEV_RAM :
        break;

    // case DEV_MMC :
    //     break;

#if defined(USB_FATFS_ENABLE) && USB_FATFS_ENABLE
    case DEV_USB :
        res = usb_disk_ioctl(pdrv, cmd ,buff);
        break;
#endif

#if defined(SD_FATFS_ENABLE) && SD_FATFS_ENABLE
    case DEV_SD:
#if defined(SD_SPI_ENABLE) && (SD_SPI_ENABLE)
        res = spi_sd_disk_ioctl(pdrv, cmd, buff);
#else
        res = sd_disk_ioctl(pdrv, cmd, buff);
#endif
        break;
#endif

// emmc
#if defined(eMMC_FATFS_ENABLE) && eMMC_FATFS_ENABLE
    case DEV_MMC:
        res = emmc_disk_ioctl(pdrv, cmd, buff);
        break;
#endif

    default:
        res = RES_ERROR;
        break;
    }

    return res;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326

10、最后生成工程,仿照sd_fatfs修改main.c,测试

/*
 * Copyright (c) 2021-2023 HPMicro
 *
 * SPDX-License-Identifier: BSD-3-Clause
 *
 */

#include "board.h"
#include "hpm_sdmmc_emmc.h"
#include "ff.h"
#include "diskio.h"
#include "hpm_mchtmr_drv.h"
#include "hpm_clock_drv.h"

extern emmc_card_t g_emmc;

FATFS s_emmc_disk;
FIL s_file;
DIR s_dir;
FRESULT fatfs_result;
BYTE work[FF_MAX_SS];

const TCHAR driver_num_buf[3] = {DEV_MMC + '0', ':', '/'};

#define TEST_DIR_NAME "hpmicro_emmc_test_dir0"

void show_menu(void);

const char *show_error_string(FRESULT fresult);

static FRESULT emmc_mount_fs(void);

static FRESULT emmc_mkfs(void);

static FRESULT emmc_write_file(void);

static FRESULT emmc_read_file(void);

static FRESULT emmc_dir_test(void);

static FRESULT emmc_big_file_test(void);


int main(void)
{
    board_init();
    show_menu();
    fatfs_result = emmc_mount_fs();           
    if (fatfs_result == FR_NO_FILESYSTEM) {
        printf("There is no File system available, making file system...\n");
        fatfs_result = emmc_mkfs();           
    }

    while (1) {
        char option = getchar();

        switch (option) {
        case '1':
            fatfs_result = emmc_mkfs();       // Format the SD card with FATFS
            break;
        case '2':
            fatfs_result = emmc_write_file(); // Create hello.txt
            break;
        case '3':
            fatfs_result = emmc_read_file();  // Read 1st line from hello.txt
            break;
        case '4':
            fatfs_result = emmc_dir_test();   // Directory related test
            break;
        case 's':
            fatfs_result = emmc_big_file_test();    // Large file write test
            break;
        default:
            show_menu();
            break;
        }
    }
}

void show_menu(void)
{
    const char menu_str[] = "eMMC FATFS demo\n-----------------------------------\n"
                            "1 - Format the eMMC card with FATFS\n"
                            "2 - Create hello.txt\n"
                            "3 - Read 1st line from hello.txt\n"
                            "4 - Directory related test\n"
                            "s - Large file write test\n"
                            "Others - Show menu\n";

    printf(menu_str);
}




static FRESULT emmc_mount_fs(void)
{
    FRESULT fresult = f_mount(&s_emmc_disk, driver_num_buf, 1);
    if (fresult == FR_OK) {
        printf("eMMC has been mounted successfully\n");
    } else {
        printf("Failed to mount eMMC, cause: %s\n", show_error_string(fresult));
    }

    fresult = f_chdrive(driver_num_buf);
    return fresult;
}

static FRESULT emmc_mkfs(void)
{
    printf("Formatting the eMMC, depending on the eMMC capacity, the formatting process may take a long time\n");
    FRESULT fresult = f_mkfs(driver_num_buf, NULL, work, sizeof(work));
    if (fresult != FR_OK) {
        printf("Making File system failed, cause: %s\n", show_error_string(fresult));
    } else {
        printf("Making file system is successful\n");
    }

    return fresult;
}

static FRESULT emmc_write_file(void)
{
    FRESULT fresult = f_open(&s_file, "readme.txt", FA_WRITE | FA_CREATE_ALWAYS);
    if (fresult != FR_OK) {
        printf("Create new file failed, cause: %d\n", show_error_string(fresult));
    } else {
        printf("Create new file successfully, status=%d\n", fresult);
    }
    char hello_str[] = "Hello, this is eMMC FATFS demo\n";
    UINT byte_written;
    fresult = f_write(&s_file, hello_str, sizeof(hello_str), &byte_written);
    if (fresult != FR_OK) {
        printf("Write file failed, cause: %s\n", show_error_string(fresult));
    } else {
        printf("Write file operation is successfully\n");
    }

    f_close(&s_file);

    return fresult;
}

static FRESULT emmc_read_file(void)
{
    FRESULT fresult = f_open(&s_file, "readme.txt", FA_READ);
    if (fresult != FR_OK) {
        printf("Open file failed, cause: %s\n", show_error_string(fresult));
    } else {
        printf("Open file successfully\n");
    }

    if (fresult != FR_OK) {
        return fresult;
    }

    TCHAR str[100];
    f_gets(str, sizeof(str), &s_file);
    printf("%s\n", str);

    f_close(&s_file);

    return fresult;
}

static FRESULT emmc_big_file_test(void)
{
    FRESULT fresult = f_open(&s_file, "big_file.bin", FA_WRITE | FA_CREATE_ALWAYS);
    if (fresult != FR_OK) {
        printf("Create new file failed, cause: %s\n", show_error_string(fresult));
    } else {
        printf("Create new file successfully\n");
    }

    uint32_t write_size = 1024UL * 1024UL * 100UL;
    static uint8_t buf[32768];
    for (uint32_t i = 0; i < sizeof(buf); i++) {
        buf[i] = i & 0xFF;
    }
    while (write_size > 0) {
        UINT byte_written;
        fresult = f_write(&s_file, buf, sizeof(buf), &byte_written);
        if (fresult != FR_OK) {
            printf("Write file failed, cause: %s\n", show_error_string(fresult));
            return fresult;
        }

        write_size -= byte_written;
    }
    printf("Write file operation is successful\n");

    f_close(&s_file);

    return fresult;
}


static FRESULT emmc_dir_test(void)
{
    FRESULT fresult = f_mkdir(TEST_DIR_NAME);
    if (fresult != FR_OK) {
        printf("Creating new directory failed, cause: %s\n", show_error_string(fresult));
    } else {
        printf("Creating new directory succeeded\n");
    }

    fresult = f_rmdir(TEST_DIR_NAME);
    if (fresult != FR_OK) {
        printf("Removing new directory failed, cause: %s\n", show_error_string(fresult));
    } else {
        printf("Removing new directory succeeded\n");
    }

    return fresult;
}

const char *show_error_string(FRESULT fresult)
{
    const char *result_str;

    switch (fresult) {
    case FR_OK:
        result_str = "succeeded";
        break;
    case FR_DISK_ERR:
        result_str = "A hard error occurred in the low level disk I/O level";
        break;
    case FR_INT_ERR:
        result_str = "Assertion failed";
        break;
    case FR_NOT_READY:
        result_str = "The physical drive cannot work";
        break;
    case FR_NO_FILE:
        result_str = "Could not find the file";
        break;
    case FR_NO_PATH:
        result_str = "Could not find the path";
        break;
    case FR_INVALID_NAME:
        result_str = "Tha path name format is invalid";
        break;
    case FR_DENIED:
        result_str = "Access denied due to prohibited access or directory full";
        break;
    case FR_EXIST:
        result_str = "Access denied due to prohibited access";
        break;
    case FR_INVALID_OBJECT:
        result_str = "The file/directory object is invalid";
        break;
    case FR_WRITE_PROTECTED:
        result_str = "The physical drive is write protected";
        break;
    case FR_INVALID_DRIVE:
        result_str = "The logical driver number is invalid";
        break;
    case FR_NOT_ENABLED:
        result_str = "The volume has no work area";
        break;
    case FR_NO_FILESYSTEM:
        result_str = "There is no valid FAT volume";
        break;
    case FR_MKFS_ABORTED:
        result_str = "THe f_mkfs() aborted due to any problem";
        break;
    case FR_TIMEOUT:
        result_str = "Could not get a grant to access the volume within defined period";
        break;
    case FR_LOCKED:
        result_str = "The operation is rejected according to the file sharing policy";
        break;
    case FR_NOT_ENOUGH_CORE:
        result_str = "LFN working buffer could not be allocated";
        break;
    case FR_TOO_MANY_OPEN_FILES:
        result_str = "Number of open files > FF_FS_LOCK";
        break;
    case FR_INVALID_PARAMETER:
        result_str = "Given parameter is invalid";
        break;
    default:
        result_str = "Unknown error";
        break;
    }
    return result_str;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288

总结

在本文中,

1、我们的目标是移植fatfs实现eMMC文件系统读写。
2、我们需要通过查询了解Fatfs的结构与移植方法。
3、然后针对于先楫处理器的特点,首先通过调试确认eMMC可以直接读写,即底层驱动没问题。
4、然后了解CMake,根据例程学习工程构建与针对先楫处理器的移植。
5、更改IO文件,移植Fatfs到eMMC
理清思路,然后顺序走下去。

最后,一定要细心 细心 细心。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/982549
推荐阅读
相关标签
  

闽ICP备14008679号