微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 第047例: SPI-基于串行Flash的FatFS文件系统

第047例: SPI-基于串行Flash的FatFS文件系统

时间:10-02 整理:3721RD 点击:
【HAL库每天一例】系列例程从今天开始持续更新。
我们将坚持每天至少发布一个基于YS-F1Pro开发板的HAL库例程,
该系列例程将带领大家从零开始使用HAL库,后面会持续添加模块应用例程。
同样的,我们还程序发布基于HAL库的指导文档和视频教程,欢迎持续关注,并提出改进意见。
例程下载:
资料包括程序、相关说明资料以及软件使用截图
链接:http://pan.baidu.com/s/1i574oPv
密码:r3s3
(硬石YS-F1Pro开发板HAL库例程持续更新\1. 软件设计之基本裸机例程(HAL库版本)\YSF1_HAL-047. SPI-基于串行Flash的FatFS文件系统)
/**
  ******************************************************************************
  *                           硬石YS-F1Pro开发板例程功能说明
  *
  *  例程名称: YSF1_HAL-047. SPI-基于串行Flash的FatFS文件系统
  *   
  ******************************************************************************
  * 说明:
  * 本例程配套硬石stm32开发板YS-F1Pro使用。
  *
  * 淘宝:
  * 论坛:http://www.ing10bbs.com
  * 版权归硬石嵌入式开发团队所有,请勿商用。
  ******************************************************************************
  */
【1】例程简介
  串行Flash用于存储数据。YS-F1Pro开发板集成了一个16M字节的W25Q128串行Flash芯片,可以
用于存放数据。该芯片使用SPI1通信接口。
  FatFS是一个专门为嵌入式开发的开源小型文件系统。FatFS可以提供丰富的文件操作函数,方便
文件操作,我们可以在串行Flash空间上移植FatFS文件系统。
【2】跳线帽情况
******* 为保证例程正常运行,必须插入以下跳线帽 **********
丝印编号     IO端口      目标功能引脚        出厂默认设置
  JP1        PA10        TXD(CH340G)          已接入
  JP2        PA9         RXD(CH340G)          已接入
  
【3】操作及现象
使用开发板配套的MINI USB线连接到开发板标示“调试串口”字样的MIMI USB接口(需要安装驱
动),在电脑端打开串口调试助手工具,设置参数为115200 8-N-1。下载完程序之后,在串口调试
助手窗口可接收到信息。
/******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/







spiflash_diskio.c文件内容

  1. /**
  2.   ******************************************************************************
  3.   * 文件名程: spiflash_diskio.c
  4.   * 作    者: 硬石嵌入式开发团队
  5.   * 版    本: V1.0
  6.   * 编写日期: 2015-10-04
  7.   * 功    能: 串行FLASH与FatFS文件系统桥接函数实现
  8.   ******************************************************************************
  9.   * 说明:
  10.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  11.   *
  12.   * 淘宝:
  13.   * 论坛:http://www.ing10bbs.com
  14.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  15.   ******************************************************************************
  16.   */

  17. /* 包含头文件 ----------------------------------------------------------------*/
  18. #include <string.h>
  19. #include "ff_gen_drv.h"
  20. #include "spiflash/bsp_spiflash.h"

  21. /* 私有类型定义 --------------------------------------------------------------*/
  22. /* 私有宏定义 ----------------------------------------------------------------*/
  23. #define SPI_FLASH_REBUILD           1    // 1:使能格式化串行Flash,0:禁用格式化串行Flash
  24. #define SPI_FLASH_SECTOR_SIZE    4096    // 串行Flash扇区大小
  25. #define SPI_FLASH_START_SECTOR   1792    // 串行Flash文件系统FatFS偏移量
  26. #define SPI_FLASH_SECTOR_COUNT   2304    // 串行Flash文件系统FatFS占用扇区个数   



  27. /* 私有变量 ------------------------------------------------------------------*/
  28. static __IO DSTATUS Stat = STA_NOINIT;

  29. /* 扩展变量 ------------------------------------------------------------------*/
  30. /* 私有函数原形 --------------------------------------------------------------*/
  31. DSTATUS SPIFLASH_initialize(BYTE);
  32. DSTATUS SPIFLASH_status(BYTE);
  33. DRESULT SPIFLASH_read(BYTE, BYTE*, DWORD, UINT);

  34. #if _USE_WRITE == 1   // 如果允许写操作
  35.   DRESULT SPIFLASH_write (BYTE, const BYTE*, DWORD, UINT);
  36. #endif /* _USE_WRITE == 1 */

  37. #if _USE_IOCTL == 1   // 如果输入输出操作控制
  38.   DRESULT SPIFLASH_ioctl (BYTE, BYTE, void*);
  39. #endif  /* _USE_IOCTL == 1 */

  40. /* 定义串行FLASH接口函数 */
  41. const Diskio_drvTypeDef  SPIFLASH_Driver =
  42. {
  43.   SPIFLASH_initialize,                   // 串行FLASH初始化
  44.   SPIFLASH_status,                       // 串行FLASH状态获取
  45.   SPIFLASH_read,                         // 串行FLASH读数据
  46. #if  _USE_WRITE == 1
  47.   SPIFLASH_write,                        // 串行FLASH写数据
  48. #endif /* _USE_WRITE == 1 */
  49.   
  50. #if  _USE_IOCTL == 1
  51.   SPIFLASH_ioctl,                         // 获取串行FLASH信息
  52. #endif /* _USE_IOCTL == 1 */
  53. };

  54. /* 函数体 --------------------------------------------------------------------*/
  55. /**
  56.   * 函数功能: 串行FLASH初始化配置
  57.   * 输入参数: 无
  58.   * 返 回 值: 无
  59.   * 说    明: 无
  60.   */
  61. DSTATUS SPIFLASH_initialize(BYTE lun)
  62. {
  63. #if SPI_FLASH_REBUILD == 1
  64.   static uint8_t startflag=1;
  65. #endif
  66.   Stat = STA_NOINIT;
  67.   /* 初始化SPIFLASHIO外设 */
  68.   MX_SPIFlash_Init();
  69.   /* 获取串行FLASH状态 */
  70.   if(SPI_FLASH_ReadID()==SPI_FLASH_ID)
  71.   {
  72. #if SPI_FLASH_REBUILD == 1
  73.       if(startflag)
  74.       {
  75.         SPI_FLASH_SectorErase(SPI_FLASH_START_SECTOR*SPI_FLASH_SECTOR_SIZE);
  76.                           startflag=0;
  77.       }
  78. #endif
  79.     Stat &=~STA_NOINIT;
  80.   }
  81.   return Stat;
  82. }

  83. /**
  84.   * 函数功能: 串行FLASH状态获取
  85.   * 输入参数: lun : 不用
  86.   * 返 回 值: DSTATUS:串行FLASH状态返回值
  87.   * 说    明: 无
  88.   */
  89. DSTATUS SPIFLASH_status(BYTE lun)
  90. {
  91.   Stat = STA_NOINIT;

  92.   if(SPI_FLASH_ReadID()==SPI_FLASH_ID)
  93.   {
  94.     Stat &= ~STA_NOINIT;
  95.   }
  96.   return Stat;
  97. }

  98. /**
  99.   * 函数功能: 从串行FLASH读取数据到缓冲区
  100.   * 输入参数: lun : 不用
  101.   *           buff:存放读取到数据缓冲区指针
  102.   *           sector:扇区地址(LBA)
  103.   *           count:扇区数目
  104.   * 返 回 值: DSTATUS:操作结果
  105.   * 说    明: 无
  106.   */
  107. DRESULT SPIFLASH_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
  108. {
  109.   sector+=SPI_FLASH_START_SECTOR;      
  110.   SPI_FLASH_BufferRead(buff, sector*SPI_FLASH_SECTOR_SIZE, count*SPI_FLASH_SECTOR_SIZE);
  111.   return RES_OK;
  112. }

  113. /**
  114.   * 函数功能: 将缓冲区数据写入到串行FLASH内
  115.   * 输入参数: lun : 不用
  116.   *           buff:存放待写入数据的缓冲区指针
  117.   *           sector:扇区地址(LBA)
  118.   *           count:扇区数目
  119.   * 返 回 值: DSTATUS:操作结果
  120.   * 说    明: 无
  121.   */
  122. #if _USE_WRITE == 1
  123. DRESULT SPIFLASH_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
  124. {
  125.   uint32_t write_addr;
  126.   /* 扇区偏移7MB,外部Flash文件系统空间放在SPI Flash后面9MB空间 */
  127.   sector+=SPI_FLASH_START_SECTOR;
  128.   write_addr = sector*SPI_FLASH_SECTOR_SIZE;   
  129.   SPI_FLASH_SectorErase(write_addr);
  130.   SPI_FLASH_BufferWrite((uint8_t *)buff,write_addr,count*SPI_FLASH_SECTOR_SIZE);
  131.   return RES_OK;
  132. }
  133. #endif /* _USE_WRITE == 1 */

  134. /**
  135.   * 函数功能: 输入输出控制操作(I/O control operation)
  136.   * 输入参数: lun : 不用
  137.   *           cmd:控制命令
  138.   *           buff:存放待写入或者读取数据的缓冲区指针
  139.   * 返 回 值: DSTATUS:操作结果
  140.   * 说    明: 无
  141.   */
  142. #if _USE_IOCTL == 1
  143. DRESULT SPIFLASH_ioctl(BYTE lun, BYTE cmd, void *buff)
  144. {
  145.   DRESULT res = RES_ERROR;
  146.   
  147.   if (Stat & STA_NOINIT) return RES_NOTRDY;
  148.   
  149.   switch (cmd)
  150.   {
  151.   /* Make sure that no pending write process */
  152.   case CTRL_SYNC :
  153.     res = RES_OK;
  154.     break;
  155.   
  156.   /* 获取串行FLASH总扇区数目(DWORD) */
  157.   case GET_SECTOR_COUNT :
  158.     *(DWORD * )buff = SPI_FLASH_SECTOR_COUNT;       
  159.     res = RES_OK;
  160.     break;
  161.   
  162.   /* 获取读写扇区大小(WORD) */
  163.   case GET_SECTOR_SIZE :
  164.     *(WORD * )buff = SPI_FLASH_SECTOR_SIZE;
  165.     res = RES_OK;
  166.     break;
  167.   
  168.   /* 获取擦除块大小(DWORD) */
  169.   case GET_BLOCK_SIZE :
  170.     *(DWORD * )buff = 1;
  171.     res = RES_OK;
  172.     break;
  173.   
  174.   default:
  175.     res = RES_PARERR;
  176.   }
  177.   
  178.   return res;
  179. }
  180. #endif /* _USE_IOCTL == 1 */

  181. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

复制代码


diskio.c文件内容

  1. /*-----------------------------------------------------------------------*/
  2. /* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2014        */
  3. /*                                                                       */
  4. /*   Portions COPYRIGHT 2015 STMicroelectronics                          */
  5. /*   Portions Copyright (C) 2014, ChaN, all right reserved               */
  6. /*-----------------------------------------------------------------------*/
  7. /* If a working storage control module is available, it should be        */
  8. /* attached to the FatFs via a glue function rather than modifying it.   */
  9. /* This is an example of glue functions to attach various exsisting      */
  10. /* storage control modules to the FatFs module with a defined API.       */
  11. /*-----------------------------------------------------------------------*/
  12. /**
  13.   ******************************************************************************
  14.   * 文件名程: diskio.c
  15.   * 作    者: 硬石嵌入式开发团队
  16.   * 版    本: V1.0
  17.   * 编写日期: 2015-10-04
  18.   * 功    能: FatFS文件系统存储设备输入输出接口实现
  19.   ******************************************************************************
  20.   * 说明:
  21.   * 本例程配套硬石stm32开发板YS-F1Pro使用。
  22.   *
  23.   * 淘宝:
  24.   * 论坛:http://www.ing10bbs.com
  25.   * 版权归硬石嵌入式开发团队所有,请勿商用。
  26.   ******************************************************************************
  27.   */

  28. /* 包含头文件 ----------------------------------------------------------------*/
  29. #include "diskio.h"
  30. #include "ff_gen_drv.h"
  31. #include "ff.h"

  32. #if _USE_LFN != 0   // 如果使能长文件名,添加相关解码文件

  33. #if _CODE_PAGE == 936        /* 简体中文:GBK */
  34. #include "option\cc936.c"
  35. #elif _CODE_PAGE == 950        /* 繁体中文:Big5 */
  36. #include "option\cc950.c"
  37. #else                                        /* Single Byte Character-Set */
  38. #include "option\ccsbcs.c"
  39. #endif

  40. #endif

  41. /* 私有类型定义 --------------------------------------------------------------*/
  42. /* 私有宏定义 ----------------------------------------------------------------*/
  43. /* 私有变量 ------------------------------------------------------------------*/
  44. /* 扩展变量 ------------------------------------------------------------------*/
  45. extern Disk_drvTypeDef  disk;

  46. /* 私有函数原形 --------------------------------------------------------------*/
  47. /* 函数体 --------------------------------------------------------------------*/
  48. /**
  49.   * 函数功能: 获取物理设备状态
  50.   * 输入参数: pdrv:物理设备编号
  51.   * 返 回 值: DSTATUS:操作结果
  52.   * 说    明: 无
  53.   */
  54. DSTATUS disk_status (
  55.         BYTE pdrv                /* Physical drive nmuber to identify the drive */
  56. )
  57. {
  58.   DSTATUS stat;
  59.   
  60.   stat = disk.drv[pdrv]->disk_status(disk.lun[pdrv]);
  61.   return stat;
  62. }

  63. /**
  64.   * 函数功能: 初始化物理设备
  65.   * 输入参数: pdrv:物理设备编号
  66.   * 返 回 值: DSTATUS:操作结果
  67.   * 说    明: 无
  68.   */
  69. DSTATUS disk_initialize (
  70.         BYTE pdrv                                /* Physical drive nmuber to identify the drive */
  71. )
  72. {
  73.   DSTATUS stat = RES_OK;
  74.   
  75.   if(disk.is_initialized[pdrv] == 0)
  76.   {
  77.     disk.is_initialized[pdrv] = 1;
  78.     stat = disk.drv[pdrv]->disk_initialize(disk.lun[pdrv]);
  79.   }
  80.   return stat;
  81. }

  82. /**
  83.   * 函数功能: 从物理设备读取数据到缓冲区
  84.   * 输入参数: pdrv:物理设备编号
  85.   *           buff:存放待写入数据的缓冲区指针
  86.   *           sector:扇区地址(LBA)
  87.   *           count:扇区数目(1..128)
  88.   * 返 回 值: DSTATUS:操作结果
  89.   * 说    明: 无
  90.   */
  91. DRESULT disk_read (
  92.         BYTE pdrv,                /* Physical drive nmuber to identify the drive */
  93.         BYTE *buff,                /* Data buffer to store read data */
  94.         DWORD sector, /* Sector address in LBA */
  95.         UINT count                /* Number of sectors to read */
  96. )
  97. {
  98.   DRESULT res;

  99.   res = disk.drv[pdrv]->disk_read(disk.lun[pdrv], buff, sector, count);
  100.   return res;
  101. }

  102. /**
  103.   * 函数功能: 将缓冲区数据写入到物理设备内
  104.   * 输入参数: pdrv:物理设备编号
  105.   *           buff:存放待写入数据的缓冲区指针
  106.   *           sector:扇区地址(LBA)
  107.   *           count:扇区数目
  108.   * 返 回 值: DSTATUS:操作结果
  109.   * 说    明: SD卡写操作没有使用DMA传输
  110.   */
  111. #if _USE_WRITE == 1
  112. DRESULT disk_write (
  113.         BYTE pdrv,                /* Physical drive nmuber to identify the drive */
  114.         const BYTE *buff,        /* Data to be written */
  115.         DWORD sector,                /* Sector address in LBA */
  116.         UINT count                /* Number of sectors to write */
  117. )
  118. {
  119.   DRESULT res;
  120.   
  121.   res = disk.drv[pdrv]->disk_write(disk.lun[pdrv], buff, sector, count);
  122.   return res;
  123. }
  124. #endif /* _USE_WRITE == 1 */

  125. /**
  126.   * 函数功能: 输入输出控制操作(I/O control operation)
  127.   * 输入参数: pdrv:物理设备编号
  128.   *           cmd:控制命令
  129.   *           buff:存放待写入或者读取数据的缓冲区指针
  130.   * 返 回 值: DSTATUS:操作结果
  131.   * 说    明: 无
  132.   */
  133. #if _USE_IOCTL == 1
  134. DRESULT disk_ioctl (
  135.         BYTE pdrv,                /* Physical drive nmuber (0..) */
  136.         BYTE cmd,                /* Control code */
  137.         void *buff                /* Buffer to send/receive control data */
  138. )
  139. {
  140.   DRESULT res;

  141.   res = disk.drv[pdrv]->disk_ioctl(disk.lun[pdrv], cmd, buff);
  142.   return res;
  143. }
  144. #endif /* _USE_IOCTL == 1 */

  145. /**
  146.   * 函数功能: 获取实时时钟
  147.   * 输入参数: 无
  148.   * 返 回 值: 实时时钟(DWORD)
  149.   * 说    明: 无
  150.   */
  151. __weak DWORD get_fattime (void)
  152. {
  153.           /* 返回当前时间戳 */
  154.         return          ((DWORD)(2015 - 1980) << 25)        /* Year 2015 */
  155.                         | ((DWORD)10 << 21)                                /* Month 10 */
  156.                         | ((DWORD)4  << 16)                                /* Mday 4 */
  157.                         | ((DWORD)10 << 11)                                /* Hour 10 */
  158.                         | ((DWORD)15 << 5)                                /* Min 15 */
  159.                         | ((DWORD)46 >> 1);                                /* Sec 46 */
  160. }

  161. /******************* (C) COPYRIGHT 2015-2020 硬石嵌入式开发团队 *****END OF FILE****/

复制代码




Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top