[单片机芯片] 【CH32X035评估板测评】SPI flash+fatfa V0.15文件系统

[复制链接]
 楼主| xiaoqi976633690 发表于 2023-9-28 09:51 | 显示全部楼层 |阅读模式
本帖最后由 xiaoqi976633690 于 2023-9-28 09:56 编辑

1、开发环境
开发板:CH32X035C-R0-1V2
IDE:MounRiver Studio
仿真器:WCHLINKE
flash :W25Q16fatfs:FatFs R0.15
http://elm-chan.org/fsw/ff/doc/mkfs.html
2、硬件配置
/*
*SPI interface operation flash peripheral routine:
*Master:SPI1_SCK(PA5)、SPI1_MISO(PA6)、SPI1_MOSI(PA7).
*This example demonstrates SPI operation Winbond W25Qxx SPIFLASH.
*
*pins:
*    CS   -- PA2
*    DO   -- PA6(SPI1_MISO)
*    WP   -- 3.3V
*    DI   -- PA7(SPI1_MOSI)
*    CLK  -- PA5(SPI1_SCK)
*    HOLD -- 3.3V
*
*/

3、代码实现

0.png
SPI底层 flash驱动官方已经写好了只要调用就好了。
a.fatfs移植

integer.h:文件中包含了一些数值类型定义。
diskio.c:包含底层存储介质的操作函数,这些函数需要用户自己实现,主要添加底层驱动函数。
ff.c:FatFs核心文件,文件管理的实现方法。该文件独立于底层介质操作文件的函数,利用这些函数实现文件的读写。(相当于C语言中的stdio.h)
cc936.c:本文在option目录下,是简体中文支持所需要添加的文件,包含了简体志文的GBK和Unicode相互转换功能函数。
ffconf.h:这个头文件包含了对FatFs功能配置的宏定义,通过修改这些宏定义就可以裁剪FatFs的功能。如需要支持简体中文,需要把ffconf.h中的_CODE_PAGE的宏改成936并把上面的cc936.c文件加入到工程之中。

diskio.c需要用户自己实现
user_diskio.c文件里主要是disk_initializedisk_statusdisk_readdisk_write 4个函数,后面两个函数容易出错,我是参考了正点原子的。
  1. DSTATUS disk_status(
  2.         BYTE pdrv /* Physical drive nmuber to identify the drive */
  3. )
  4. {

  5.     if(pdrv==SPI_FLASH)
  6.     {

  7.         return RES_OK; //直接返回OK即可

  8.     }
  9.     else
  10.         {
  11.             printf("!!!disk_status ERR\r\n");
  12.             return RES_PARERR;
  13.         }

  14. }
  1. DSTATUS disk_initialize(
  2.         BYTE pdrv /* Physical drive nmuber to identify the drive */
  3. )
  4. {
  5.     if(pdrv == SPI_FLASH)
  6.         {
  7.             SPI_Flash_Init();//初始化 spi flash
  8.            // printf("!!!SPI_Flash_Init OK\r\n");
  9.             return RES_OK;
  10.         }
  11.         else
  12.         {
  13.             printf("!!!disk_initialize ERR\r\n");
  14.             return RES_PARERR;
  15.         }

  16. }
  1. DRESULT disk_read(
  2.         BYTE pdrv,          /* Physical drive nmuber to identify the drive */
  3.         BYTE *buff,          /* Data buffer to store read data */
  4.         LBA_t sector, /* Start sector in LBA */
  5.         UINT count          /* Number of sectors to read */
  6. )
  7. {
  8.     DRESULT res;
  9.         //uart_printf("disk_read---sector:%d,count:%d\r\n",sector,count);
  10.         if(pdrv == SPI_FLASH)
  11.         {
  12.             for(;count>0;count--)
  13.             {
  14.                 SPI_Flash_Read(buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
  15.                 sector++;
  16.                 buff+=FLASH_SECTOR_SIZE;
  17.             }
  18.            // SPI_Flash_Read(buff,sector,count);//spi flash的读接口,注意函数参数类型一致性
  19.             res = 0;
  20.             return res;
  21.         }
  22.         else
  23.         {
  24.             printf("!!!disk_read ERR\r\n");
  25.             return RES_PARERR;
  26.         }

  27. }


  1. DRESULT disk_write(
  2.         BYTE pdrv,                  /* Physical drive nmuber to identify the drive */
  3.         const BYTE *buff, /* Data to be written */
  4.         LBA_t sector,          /* Start sector in LBA */
  5.         UINT count                  /* Number of sectors to write */
  6. )
  7. {
  8.     DRESULT res;

  9.         if(pdrv == SPI_FLASH)
  10.         {
  11.             for(;count>0;count--)
  12.             {
  13.                 SPI_Flash_Write((u8*)buff,sector*FLASH_SECTOR_SIZE,FLASH_SECTOR_SIZE);
  14.                 sector++;
  15.                 buff+=FLASH_SECTOR_SIZE;
  16.             }
  17.             res=0;

  18.             return res;
  19.         }
  20.         else
  21.         {
  22.             printf("!!!disk_write ERR\r\n");
  23.             return RES_PARERR;
  24.         }

  25. }


  1. DRESULT disk_ioctl(
  2.         BYTE pdrv, /* Physical drive nmuber (0..) */
  3.         BYTE cmd,  /* Control code */
  4.         void *buff /* Buffer to send/receive control data */
  5. )
  6. {
  7.     if (pdrv == SPI_FLASH)
  8.         {
  9.             switch (cmd)
  10.             {
  11.              case CTRL_SYNC:
  12.                  return RES_OK;

  13.              /* 扇区数量 1024*1024*1024 =4 (MB) */

  14.              case GET_SECTOR_COUNT:

  15.                  *(DWORD * )buff = 512;//W25Q32 有1024个大小为4k bytes 的扇区
  16.                  return RES_OK;

  17.              /* 扇区大小 */

  18.              case GET_SECTOR_SIZE :

  19.                  *(WORD * )buff = 2048;//spi flash的扇区大小是 4K Bytes
  20.                  return RES_OK;

  21.              /*块大小 */

  22.              case GET_BLOCK_SIZE :
  23.                  *(DWORD * )buff = 1;
  24.                  return RES_OK;

  25.              default:
  26.                  return RES_PARERR;
  27.              }
  28.         }
  29.         else
  30.         {
  31.             printf("!!!disk_ioctl ERR\r\n");
  32.             return RES_PARERR;
  33.         }

  34. }
  1. DWORD get_fattime (void)
  2. {
  3.   return 0;
  4. }
实现底层就可以开始了

4.png
  1. void fs_test(void)
  2. {
  3.            /* Filesystem object */
  4.     FIL fil;            /* File object */
  5.     FRESULT res;  /* API result code */
  6.     UINT bw;            /* Bytes written */
  7.     BYTE work[FF_MAX_SS]; /* Work area (larger is better for processing time) */
  8.     BYTE mm[50];//读缓存
  9.     UINT i;

  10.     printf("file system start:\r\n");
  11.     fs = malloc(sizeof (FATFS));
  12.     res = f_mount(fs, "0:",1);
  13.     printf("res=%d\n\r",res);
  14.     /* 格式化文件系统 */
  15.     if(res!=0)
  16.         {
  17.             res = f_mkfs("0:",0,work,sizeof work );
  18.             /* 卸载文件系统 */
  19.             f_mount(NULL,"0:",1);
  20.             /* 挂载文件系统 */
  21.             res = f_mount(fs, "0:",1);

  22.         }
  23.     if(res==0) printf("mkfs is success!%d\n\r",res);
  24.     else printf("mkfs is fail!%d\n\r",res);
  25.    
  26.     if(res==0) printf("f_mount is success!%d\n\r",res);
  27.     else printf("f_mount is fail!%d\n\r",res);

  28.     /* Create a file as new */
  29.     res = f_open(&fil, "0:/1.txt", FA_CREATE_NEW | FA_WRITE | FA_READ);
  30.     if (res)
  31.     {
  32.         printf("open file fail.id=%d\r\n",res);

  33.     }
  34.     else
  35.     {
  36.         printf("open file success.\r\n");
  37.     }
  38.     /* Write a message */
  39.     res = f_write(&fil, "Hello,World!", 12, &bw);
  40.     //printf("res write:%d\r\n",res);
  41.     if (bw == 12)
  42.     {
  43.         printf("writing ok!\r\n");
  44.     }
  45.     else
  46.     {
  47.         printf("writing fail!\r\n");
  48.     }
  49.     res = f_size(&fil);
  50.     printf("file size:%d Bytes.\r\n",res);
  51.     memset(mm,0x0,50);
  52.     f_lseek(&fil,0);
  53.     res = f_read(&fil,mm,12,&i);
  54.     if (res == FR_OK)
  55.     {
  56.         printf("read file ok!\r\n");
  57.         printf("read file lengh:%d Bytes.\r\n",i);
  58.     }
  59.     else
  60.     {
  61.         printf("read fail\r\n");
  62.     }
  63.     printf("read file:\r\n");

  64.     printf("%s\n\r",mm);

  65.     /* Close the file */
  66.     f_close(&fil);
  67.     /*卸载文件系统*/
  68.     f_mount(0, "0:", 0);
  69.     free(fs);
  70.     printf("file system down.\r\n");
  71. }
  1. int main(void)
  2. {
  3.     u8  datap[SIZE];
  4.     u16 Flash_Model;
  5.     FRESULT res;
  6.     FATFS * fs;

  7.     SystemCoreClockUpdate();
  8.     Delay_Init();
  9.     USART_Printf_Init(115200);
  10.     printf("SystemClk:%d\r\n", SystemCoreClock);
  11.     printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );

  12.    // SPI_Flash_Init();
  13.     disk_initialize(0);
  14.     Flash_Model = SPI_Flash_ReadID();

  15.     switch(Flash_Model)
  16.     {
  17.         case W25Q80:
  18.             printf("W25Q80 OK!\r\n");

  19.             break;

  20.         case W25Q16:
  21.             printf("W25Q16 OK!\r\n");

  22.             break;

  23.         case W25Q32:
  24.             printf("W25Q32 OK!\r\n");

  25.             break;

  26.         case W25Q64:
  27.             printf("W25Q64 OK!\r\n");

  28.             break;

  29.         case W25Q128:
  30.             printf("W25Q128 OK!\r\n");

  31.             break;

  32.         default:
  33.             printf("Fail!\r\n");

  34.             break;
  35.     }

↑↑↑↑↑↑↑main函数老是复制不上来↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓接上面↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  1. Delay_Ms(1000);
  2.     fs_test();

  3.     while(1)
  4.     {
  5.             Delay_Ms(1000);
  6.         fs = malloc(sizeof (FATFS));
  7.         res = f_mount(fs, "0:",1);
  8.         printf("mount=%d\n\r",res);
  9.         get_fatfs_free();
  10.         Delay_Ms(500);

  11.             res=f_mount(0, "0:", 0);
  12.         free(fs);
  13.             printf("un mount=%d\n\r",res);


  14. //        printf("Start Read W25Qxx....\r\n");
  15. //        SPI_Flash_Read(datap, 0x0, SIZE);
  16. //        printf("%s\r\n", datap);

  17.     }
  18. }



4、实验效果

1.png
3.jpg

每次上电都要格式化,百度必应了半天也没有解决。
后来发现是例程的扇区擦除函数没有删掉。
排查了老半天!!!!


    //printf("Start Erase W25Qxx....\r\n");
    //SPI_Flash_Erase_Sector(0);
   // printf("W25Qxx Erase Finished!\r\n");
附件:
SPI_FLASH.zip (3.27 MB, 下载次数: 34) https://bbs.21ic.com/forum.php?mod=attachment&aid=MjE2NjMyNHw1MWJmYzNkNXwxNzU2MDYxODkxfDB8


dvacos 发表于 2023-10-8 12:36 | 显示全部楼层
学习!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

204

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部

35

主题

204

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部