赞
踩
最近用到先楫的单片机HPM6750(HPM6754),由于一些原因需要使用eMMC代替SD卡存储数据,为了方便数据管理与查看,准备使用Fatfs,而官方SDK并未提供eMMC的Fatfs读写例程,因此作者参考先楫官方提供的SD卡的Fatfs例程实现了Fatfs挂载到eMMC设备的数据读写,也就是将Fatfs“移植”到eMMC。
现在各种论坛上有很多单片机移植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.
在移植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仅做编译调试使用。
首先在sd_fatfs例程下(路径见图片左上角)的CMakeList中定义了CONFIG_SDMMC,CONFIG_FATFS,如下图。
middleware文件夹下的CMakeList检测到CONFIG_FATFS则在工程中添加了 middleware\fatfs这个子文件夹,下面存放fatfs的头文件与源代码。检测到CONFIG_SDMMC则在工程中添加了hpm_sdmmc这个子文件夹,下面存放先楫编写的sd/eMMC的底层驱动。如下图。
到此例程将两个子文件夹添加入工程,如下图。
进入middleware\fatfs下面的CMakeList中,检测到定义了CONFIG_SDMMC,则添加宏定义:SD_FATFS_ENABLE=1。文件开头添加了fatfs的源文件路径,另外添加了porrable子文件夹,此文件夹中包含文件系统的移植程序,也就是移植fatfs需要修改的有关底层硬件驱动的部分。如下图。
进入Portable文件下的CMakeList中,首先将此文件路径下的头文件与源文件添加进工程,后面判断是否定义CONFIG_XXX,如果定义了就将相应的头文件与源文件添加工程。在此,CONFIG_SDMMC已经定义,因此将sdxc作为头文件路径与源文件路径。
移植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文件的修改,作者往往只是添加了一两句,读者根据上面的分析也可能不易于理解,具体还需读者自己去查看工程文件!!!。
主要是修改变量名、工程名等
# 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()
# 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)
# 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()
# 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()
/* * 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 */
/* * 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; }
/*-----------------------------------------------------------------------*/ /* 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; }
/* * 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、我们的目标是移植fatfs实现eMMC文件系统读写。
2、我们需要通过查询了解Fatfs的结构与移植方法。
3、然后针对于先楫处理器的特点,首先通过调试确认eMMC可以直接读写,即底层驱动没问题。
4、然后了解CMake,根据例程学习工程构建与针对先楫处理器的移植。
5、更改IO文件,移植Fatfs到eMMC
理清思路,然后顺序走下去。
最后,一定要细心 细心 细心。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。