stm32--FatFs移植(SPIFlash)

添加文件

  1. 获取FatFs库(官网
  2. 将source文件夹全部复制到目标工程中
  3. 添加所有.c文件到工程中,添加相关路径

移植修改

需要修改的文件:

  1. integer.h:修改各种整型的宏定义(注:C99--long long对应64位整型)
  2. ffconf.h:修改各种设置:(全部宏定义意义见官网
    1. FF_USE_STRFUNC设为1:开启字符串功能
    2. FF_USE_FIND设为1:开启查找功能
    3. FF_USE_MKFS设为1:开启格式化功能(在逻辑驱动器上创建一个FAT卷)
    4. FF_CODE_PAGE设为936:简体中文
    5. FF_STR_VOLUME_ID设为1:允许字符串卷ID
    6. FF_VOLUME_STRS设为"NODE":设定字符串卷ID
    7. FF_FS_NORTC设为1:禁用RTC(时间戳)功能,因为stm32不具备获取时间的功能
  3. diskio.c:修改各磁盘IO层操作函数
    1. 修改磁盘设备定义:#define DEV_SPI 1
    2. 修改各函数中case DEV_RAM的操作:stat = STA_NOINIT; 或res = RES_PARERR;
    3. 修改各函数中case DEV_SPI的操作:指向spi_disk.c中的各执行函数
  4. spi_disk.c:自定义文件,是diskio.c中各函数指向的执行函数
    1. 定义静态全局变量_s_SPI_Init_OK,用于指示当前磁盘初始化状态
    2. SPI_disk_status函数:获取驱动器状态。_s_SPI_Init_OK为0时返回STA_NOINIT。
    3. SPI_disk_initialize函数:驱动器初始化。执行SPIFlash初始化函数,执行完毕后将_s_SPI_Init_OK置1。
    4. SPI_disk_read函数:读磁盘驱动器。进行异常处理后,将所有数据读到指定的指针内。
      • 1 DRESULT SPI_disk_read(BYTE *buff, DWORD sector, UINT count) {
        2   if(sector > SEC_MAX || sector + count > SEC_MAX) return RES_PARERR;
        3   if(CS_STATUS() == Bit_RESET) return RES_NOTRDY;
        4   
        5   if(SSTF016B_RD(sector*SEC_SIZE, SEC_SIZE*count, buff) == ERR) {
        6     return RES_ERROR;
        7   }
        8   return RES_OK;
        9 }
        SPI_disk_read
    5. SPI_disk_write函数:写磁盘驱动器。进行异常处理后,将所有数据写入指定的扇区内。
      •  1 DRESULT SPI_disk_write(const BYTE *buff, DWORD sector, UINT count) {
         2   if(sector > SEC_MAX || sector + count > SEC_MAX) return RES_PARERR;
         3   if(CS_STATUS() == Bit_RESET) return RES_NOTRDY;
         4   
         5 
         6   if(SSTF016B_Erase(sector, sector + count - 1) == ERR) {
         7     return RES_ERROR;
         8   }
         9   if(SSTF016B_WR(sector*SEC_SIZE, buff, SEC_SIZE*count) == ERR){
        10     return RES_ERROR;
        11   }
        12   return RES_OK;
        13 }
        SPI_disk_write
    6. SPI_disk_ioctl函数:执行ioctl命令。因为没有开启强制擦除的功能,强制擦除指令不执行任何操作。
      •  1 DRESULT SPI_disk_ioctl(BYTE cmd, void *buff) {
         2   DWORD *pdword = NULL;
         3   WORD  *pword = NULL;
         4   
         5   switch(cmd) {
         6     case CTRL_SYNC://确保写入操作已完成
         7     return RES_OK;
         8     
         9     case GET_SECTOR_COUNT://获取扇区数量
        10       pdword = (DWORD *)buff;
        11       *pdword = SEC_MAX + 1;
        12     return RES_OK;
        13     
        14     case GET_SECTOR_SIZE://获取单个扇区大小
        15       pword = (WORD *)buff;
        16       *pword = SEC_SIZE;
        17     return RES_OK;
        18     
        19     case GET_BLOCK_SIZE://获取擦除块大小
        20       pdword = (DWORD *)buff;
        21       *pdword = SEC_SIZE;
        22     return RES_OK;
        23     
        24     case CTRL_TRIM://强制擦除
        25     return RES_PARERR;
        26   }
        27   return RES_PARERR;
        28 }
        SPI_disk_ioctl
  5. user_fatfs_app.c:自定义文件,定义fatfs的应用函数。
    • 注意事项:
      1. 在单个扇区设为4k时,创建文件系统需要4k的ram(FATFS对象),工作缓冲区需要4k的ram,每一个文件对象需要4k的ram(FIL对象)。当硬件sram不大时,应仅在需要时创建文件对象并使用、使用后马上释放该对象。
      2. 执行写入操作后,如果不关闭文件对象(f_close),则必须执行f_sync函数刷新文件。否则如果意外断电,会发生不可预知的错误。
      3. f_open的第三参数:FA_OPEN_ALWAYS--存在则打开、不存在则创建;FA_OPEN_APPEND--同上,但指针指向文件尾;FA_WRITE--要写入必须带此参数;FA_READ--要读取必须带此参数。
      4. 如何判断f_open函数执行的到底是打开操作还是创建操作?用f_size判断文件大小即可。
    •  1 #include "user_fatfs_app.h"
       2 
       3 extern uint8_t g_User_Data[sizeof(t_g_Statistical_Data)];
       4 extern t_g_Statistical_Data *pg_User_Data;
       5 extern uint8_t g_History_Data[sizeof(t_g_History_Data)];
       6 extern t_g_History_Data *pg_History_Data;
       7 
       8 FATFS g_Fatfs;
       9 BYTE work_buffer[FF_MAX_SS];
      10 
      11 
      12 void fatfs_Init(void) {
      13   f_mkfs("", FM_FAT, 0, work_buffer, FF_MAX_SS);
      14   f_mount(&g_Fatfs, "", 0);
      15   memset(g_User_Data, 0, sizeof(g_User_Data));
      16   memset(g_History_Data, 0, sizeof(g_History_Data));
      17   fatfs_Get_Statistical_Data();
      18 }
      19 
      20 
      21 int8_t fatfs_Get_Statistical_Data(void) {
      22   FIL statistical_data;
      23   UINT len = 0;
      24   int8_t result = 0;
      25   
      26   result = f_open(&statistical_data, "statistical_data.bin", FA_OPEN_ALWAYS | FA_WRITE | FA_READ);//指针指向文件头
      27   if(result == FR_OK) {
      28     if(f_size(&statistical_data) < sizeof(t_g_Statistical_Data)) { //初次创建
      29       f_write(&statistical_data, g_User_Data, sizeof(t_g_Statistical_Data), &len);
      30       f_lseek(&statistical_data, 0);
      31     }
      32     result = f_read(&statistical_data, g_User_Data, sizeof(t_g_Statistical_Data), &len);
      33   } else {
      34     result = -1;
      35   }
      36   f_close(&statistical_data);
      37   free(&statistical_data);
      38   
      39   return result;
      40 }
      41 
      42 
      43 int8_t fatfs_Update_Statistical_Data(void) {
      44   FIL statistical_data;
      45   UINT len = 0;
      46   int8_t result = 0;
      47   
      48   result = f_open(&statistical_data, "statistical_data.bin", FA_OPEN_ALWAYS | FA_WRITE);//指针指向文件头
      49   if(result == FR_OK) {
      50     result = f_write(&statistical_data, g_User_Data, sizeof(t_g_Statistical_Data), &len);
      51   } else {
      52     result = -1;
      53   }
      54   f_close(&statistical_data);
      55   free(&statistical_data);
      56   
      57   return result;
      58 }
      59 
      60 
      61 int8_t fatfs_Add_Historical_Data(void) {
      62   FIL historical_data;
      63   char node_type[2][7] = {"Zigbee", "LoRa"};
      64   char test_result[2][8] = {"Fail", "Success"};
      65   int8_t result = 0;
      66   
      67   result = f_open(&historical_data,  "historical_data.csv",  FA_OPEN_APPEND | FA_WRITE);//指针指向文件尾
      68   if(result == FR_OK) {
      69     result = f_printf(&historical_data, \
      70              "%u,%s,%s,%08x%08x%08x,%04u/%02u/%02u,%02u:%02u:%02u\r\n", \
      71              pg_History_Data->index, node_type[pg_History_Data->type], \
      72              test_result[pg_History_Data->result], pg_History_Data->id[0], \
      73              pg_History_Data->id[1], pg_History_Data->id[2], pg_History_Data->year,\
      74              pg_History_Data->month, pg_History_Data->day, pg_History_Data->hour, \
      75              pg_History_Data->min, pg_History_Data->sec);
      76   } else {
      77     result = -2;
      78   }
      79   f_close(&historical_data);
      80   free(&historical_data);
      81   
      82   return result;
      83 }
      user_fatfs_app.c

本文参照了csdn博客https://blog.csdn.net/little_shrimp/article/details/53214120。

猜你喜欢

转载自www.cnblogs.com/cage666/p/9178326.html
今日推荐