zoukankan      html  css  js  c++  java
  • STM32文件系统的移植

      首先介绍一下window中常见的文件系统格式,包括FAT32、NTFS、exFAT。

      我们嵌入式文件系统一般使用的是FAT格式。一般新的储存芯片(EEPROM、SD卡等)内部是没有文件系统的,他只是一个单纯的能储存数据的扇区而已,而我们需要格式化他们,才能让我们的文件系统认识这块芯片里的内容,并且管理他们。格式化其实就是在芯片中储存一个结构信息,可以理解成一个全局变量,然后文件系统就是靠这个结构去索引,修改我们文件系统中的文件。

      移植主要分3步:修改diskio.c文件(与硬件相关的底层接口);ffconf.c文件(修改相关的宏);格式化文件系统(如果已有文件系统可以不用格式化)

      首先下载FATFS文件系统的源码,可以到我的wp上下载:

      将源码的src目录拷贝到我们的工程中

      1.在工程中添加一个FATFS分组,并将ff.c,diskio.c添加到该分组中

      

      

      添加头文件路径 options terget.. -> C/C++ -> include Paths

      

      

      2.修改diskio.c文件,该文件是关于硬件的底层驱动,包含储存芯片的初始化、读写、状态等接口

      删除官方历程中包含的储存驱动头文件,添加自己的底层驱动

    #include "diskio.h"        /* FatFs lower layer API */
    //#include "usbdisk.h"    /* Example: Header file of existing USB MSD control module */
    //#include "atadrive.h"    /* Example: Header file of existing ATA harddisk control module */
    //#include "sdcard.h"        /* Example: Header file of existing MMC/SDC contorl module */

     #include "sdio_sdcard.h"  //SD卡驱动
     #include "SDram_file.h"

      修改状态文件系统获取硬件底层状态接口,我采取了一种简单粗暴的方式,直接返回OK,什么都不做

    DSTATUS disk_status (
        BYTE pdrv        /* Physical drive nmuber to identify the drive */
    )
    {
        DSTATUS stat = RES_OK;
    
        switch (pdrv) {
        case ATA :
            return stat;
    
        case MMC :
            return stat;
    
        case USB :
            return stat;
        }
        return STA_NOINIT;
    }

      初始化驱动

    DSTATUS disk_initialize (
        BYTE pdrv                /* Physical drive nmuber to identify the drive */
    )
    {
        DSTATUS stat = RES_OK;
    
        switch (pdrv) {
        case ATA :
            SD_Init();    //SD卡初始化
            return stat;
    
        case MMC :
            return stat;
    
        case USB :
            return stat;
        }
        return STA_NOINIT;
    }

      读写驱动,注意这里的读写都是对内存芯片的一个块进行操作的,所以底层读写接口也应该是整个内存块一起操作的,一般SD卡的块大小是512字节,一些储存芯片可能是4096个字节。

    DRESULT disk_read (
        BYTE pdrv,        /* Physical drive nmuber to identify the drive */
        BYTE *buff,        /* Data buffer to store read data */
        DWORD sector,    /* Sector address in LBA */
        UINT count        /* Number of sectors to read */
    )
    {
        DRESULT res = RES_OK;
    
        switch (pdrv) {
        case ATA :
            SD_ReadDisk( buff, sector, count );
            return res;
    
        case MMC :
            return res;
    
        case USB :
            return res;
        }
    
        return RES_PARERR;
    }
    
    
    DRESULT disk_write (
        BYTE pdrv,            /* Physical drive nmuber to identify the drive */
        const BYTE *buff,    /* Data to be written */
        DWORD sector,        /* Sector address in LBA */
        UINT count            /* Number of sectors to write */
    )
    {
        DRESULT res = RES_OK;
    
        switch (pdrv) {
        case ATA :
            SD_WriteDisk(( u8* )buff, sector, count );
            return res;
    
        case MMC :
            return res;
    
        case USB :
            return res;
        }
    
        return RES_PARERR;
    }

      最后还有一些其他的控制接口,比如获取SD卡块大小、容量等操作

    DRESULT disk_ioctl (
        BYTE pdrv,        /* Physical drive nmuber (0..) */
        BYTE cmd,        /* Control code */
        void *buff        /* Buffer to send/receive control data */
    )
    {
        DRESULT res = RES_OK;
        int result;
    
        switch (pdrv) {
        case ATA :
            switch ( cmd )
            {
                case GET_SECTOR_SIZE:
                    *( DWORD* )buff = 512;
                    res = RES_OK;
                    break;
                case GET_BLOCK_SIZE:
                    *( WORD* )buff = SDCardInfo.CardBlockSize;
                    res = RES_OK;
                    break;
                case GET_SECTOR_COUNT:
                    *( DWORD* )buff = SDCardInfo.CardCapacity / 512;
                    res = RES_OK;
                    break;
                default:
                    res = RES_PARERR;
                    break;
            }
            return res;
    
        case MMC :
            return res;
    
        case USB :
            return res;
        }
    
        return RES_PARERR;
    }
    
    //这个是获取时间戳,让文件系统可以记录文件操作的时间,这里我没有实现这个功能,所以直接返回0,必须定义这个,如果没有会报错
    DWORD get_fattime( void )
    {
        return 0;
    }

      

      3.修改ffconf.h文件,改文件实现文件系统的配置和裁剪,这里有几个参数需要配置

    #define _USE_MKFS 1      //是否支持格式化,我们默认0,我们要使能他
    /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */

    #define _CODE_PAGE 936    //文件系统编码格式,我们选择中文编码

    //是否使能长文件名,如果需要长文件名,这里改成2,并且需要在工程中添加cc936.c文件

    #define _USE_LFN 0      
    #define _MAX_LFN 255     //文件名长度

    #define _VOLUMES 1      //设备数量

    //内存块范围,一般SD卡为512字节,有的储存芯片一个块可能为4096个字节
    #define _MIN_SS 512
    #define _MAX_SS 4096

      

      4.最后在主程序中挂载这个卷,就可以使用我们熟悉的f_open、f_close....等功能了

    FRESULT res_flash; 

    /* 如果没有文件系统就格式化创建创建文件系统 */
    if(f_mount(&fs,"0:",1) == FR_NO_FILESYSTEM)
    {
      printf("》FLASH还没有文件系统,即将进行格式化... ");
      /* 格式化 */
      res_flash=f_mkfs("0:",0,0);

      if(res_flash == FR_OK)
      {
        printf("》FLASH已成功格式化文件系统。 ");
        /* 格式化后,先取消挂载 */
        res_flash = f_mount(NULL,"0:",1);
        /* 重新挂载 */
        res_flash = f_mount(&fs,"0:",1);
       }

    }

  • 相关阅读:
    curl命令详解
    Linux 下 set env export declare浅浅 set和shopt命令详解--(shell定制) (转载)
    ps aux指令詳解
    smb设置参考手册 --详细参数
    Ajax
    JSON浅谈
    Date类型
    笔记本电脑不能上网的问题
    editplus 初步设置
    w10 系统升级
  • 原文地址:https://www.cnblogs.com/isyefeng/p/13425855.html
Copyright © 2011-2022 走看看