硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3880|回复: 19
收起左侧

[USB] STM32H7使用RL-FlashFS外挂U盘,SD卡和NAND三合一制作成功,并且RL-USB同时虚拟NAND和SD卡两个U盘也搞好了

  [复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
发表于 2021-2-17 09:12:15 | 显示全部楼层 |阅读模式
这个功能已经在V5,V6和V7的RTX5全家桶综合模板全部实现成功,下次升级将整合进去。

1、RL-USB同时虚拟NAND和SD卡两个U盘


2、下面是FlashFS同时外挂U盘,NAND和SD卡三合一测试代码:

  1. /*
  2. *********************************************************************************************************
  3. *
  4. *        模块名称 : FlashFS文件系统演示模块。
  5. *        文件名称 : demo_flashfs.c
  6. *        版    本 : V1.0
  7. *        说    明 : 该例程移植FlashFS文件系统,主要学习FlashFS的综合操作。
  8. *
  9. *        修改记录 :
  10. *                版本号    日期         作者            说明
  11. *       V1.0    2021-02-16   Eric2013    1. RL-FlashFS短文件名版本V6.x
  12. *
  13. *        Copyright (C), 2021-2030, 安富莱电子 www.armfly.com
  14. *
  15. *********************************************************************************************************
  16. */
  17. #include "includes.h"



  18. /* 用于测试读写速度 */
  19. #define TEST_FILE_LEN                        (2*1024*1024)        /* 用于测试的文件长度 */
  20. #define BUF_SIZE                                (4*1024)                /* 每次读写SD卡的最大数据长度 */

  21. /* 仅允许本文件内调用的函数声明 */
  22. static void ViewSDCapacity(char *_path);
  23. static void ViewRootDir(char *_path);
  24. static void CreateNewFile(char *_path);
  25. static void ReadFileData(char *_path);
  26. static void SeekFileData(char *_path);
  27. static void DeleteDirFile(char *_path);
  28. static void WriteFileTest(char *_path);
  29. static void WriteCSVFile(char *_path);
  30. static void ReadCSVFileData(char *_path);
  31. static void DispMenu(void);
  32. static void DotFormat(uint64_t _ullVal, char *_sp);

  33. /* FlashFS API的返回值 */
  34. static const char * ReVal_Table[]=
  35. {
  36.         "fsOK:成功",                                                      
  37.         "fsError:未指定的错误",
  38.         "fsUnsupported:操作不支持",
  39.         "fsAccessDenied:资源访问被拒绝",
  40.       
  41.         "fsInvalidParameter:参数无效",
  42.         "fsInvalidDrive:驱动无效或驱动不存在",
  43.         "fsInvalidPath:路径无效",
  44.         "fsUninitializedDrive:驱动未初始化 ",

  45.         "fsDriverError:读写操作",
  46.         "fsMediaError:媒介错误",
  47.         "fsNoMedia:媒介不存在,或者未初始化",
  48.         "fsNoFileSystem:文件系统未格式化",

  49.         "fsNoFreeSpace:没有可用空间",
  50.         "fsFileNotFound:文件未找到",
  51.         "fsDirNotEmpty:文件夹非空",
  52.         "fsTooManyOpenFiles:打开文件太多",
  53. };

  54. static char * DevicePath[]=
  55. {
  56.         "M0:", /* SD卡 */                                               
  57.         "U0:", /* U盘  */
  58.         "N0:", /* NAND */
  59. };

  60. uint8_t g_TestBuf[BUF_SIZE];

  61. /*
  62. *********************************************************************************************************
  63. *        函 数 名: DemoFlashFS
  64. *        功能说明: FlashFS件系统演示主程序
  65. *        形    参: 无
  66. *        返 回 值: 无
  67. *********************************************************************************************************
  68. */
  69. void DemoFlashFS(void)
  70. {
  71.         uint8_t cmd;
  72.         uint8_t result;
  73.     char *_path = DevicePath[0];
  74.     usbStatus ustatus;

  75.         /* 打印命令列表,用户可以通过串口操作指令 */
  76.         DispMenu();
  77.       
  78.         while(1)
  79.         {
  80.                 if (comGetChar(COM1, &cmd))        /* 从串口读入一个字符(非阻塞方式) */
  81.                 {
  82.                         printf("\r\n");
  83.                         switch (cmd)
  84.                         {
  85.                                 case '1':
  86.                                         printf("【1 - ViewSDCapacity】\r\n");
  87.                                         ViewSDCapacity(_path);                /* 挂载,卸载及其容量显示 */
  88.                                         break;
  89.                               
  90.                                 case '2':
  91.                                         printf("【2 - ViewRootDir】\r\n");
  92.                                         ViewRootDir(_path);                    /* 显示SD卡根目录下的文件名 */
  93.                                         break;
  94.                               
  95.                                 case '3':
  96.                                         printf("【3 - CreateNewFile】\r\n");
  97.                                         CreateNewFile(_path);            /* 创建三个text文本并使用不同函数写入内容 */
  98.                                         break;
  99.                               
  100.                                 case '4':
  101.                                         printf("【4 - ReadFileData】\r\n");
  102.                                         ReadFileData(_path);                /* 使用三个不同函数读取文本  */
  103.                                         break;

  104.                                 case '5':
  105.                                         printf("【5 - SeekFileData】\r\n");
  106.                                         SeekFileData(_path);                /* 创建一个text文本,在指定位置对其进行读写操作  */
  107.                                         break;
  108.                               
  109.                                 case '6':
  110.                                         printf("【6 - DeleteDirFile】\r\n");
  111.                                         DeleteDirFile(_path);            /* 删除文件夹和文件  */
  112.                                         break;
  113.                               
  114.                                 case '7':
  115.                                         printf("【7 - WriteFileTest】\r\n");
  116.                                         WriteFileTest(_path);            /* 测试文件读写速度  */
  117.                                         break;
  118.                               
  119.                                 case '8':
  120.                                         printf("【8 - WriteCSVFile】\r\n");
  121.                                         WriteCSVFile(_path);                /* 写数据到CSV文件中  */
  122.                                         break;
  123.                               
  124.                                 case '9':
  125.                                         printf("【9 - ReadCSVFileData】\r\n");
  126.                                         ReadCSVFileData(_path);            /* 从CSV文件中读数据  */
  127.                                         break;
  128.                               
  129.                                 case 'M':
  130.                 case 'm':
  131.                                         printf("【m - OpenSDCard】\r\n");
  132.                     if(strncmp("U0:", _path, 3) == 0)
  133.                     {
  134.                         USBH_MSC_Uninitialize(0);
  135.                         USBH_Uninitialize(0U);
  136.                     }
  137.                                         _path = DevicePath[0];
  138.                                         break;

  139.                                 case 'U':
  140.                 case 'u':
  141.                                         printf("【u - OpenUsbDevice】\r\n");
  142.                     printf("初始化枚举U盘中....");
  143.                     USBH_Initialize(0U);                 
  144.                     USBH_MSC_Initialize(0U);
  145.                     while (USBH_MSC_GetStatus (0) != usbOK)
  146.                     {
  147.                         osDelay(500);
  148.                         printf(".");
  149.                     }
  150.                     printf("\r\n");            
  151.                                         _path = DevicePath[1];
  152.                                         break;      

  153.                                 case 'N':
  154.                 case 'n':
  155.                                         printf("【n - OpenNand】\r\n");
  156.                     if(strncmp("U0:", _path, 3) == 0)
  157.                     {
  158.                         USBH_MSC_Uninitialize(0);
  159.                         USBH_Uninitialize(0U);
  160.                     }
  161.                                         _path = DevicePath[2];
  162.                                         break;                    
  163.                
  164.                 case 'A':
  165.                                 case 'a':
  166.                                         printf("【a - OpenUSB Device】\r\n");
  167.                                         printf("注意,SD卡挂载期间,不可操作其它命令,要卸载后才可以操作!!\r\n");
  168.                                         USBD_Initialize(0U);                 
  169.                                         USBD_Connect   (0U);      
  170.                                         break;      

  171.                 case 'B':
  172.                                 case 'b':
  173.                                         printf("【b - CloseUSB Device】\r\n");
  174.                                         USBD_Disconnect(0);
  175.                                         USBD_Uninitialize(0);
  176.                                         break;

  177.                                 default:
  178.                                         DispMenu();
  179.                                         break;
  180.                         }
  181.                 }
  182.                
  183.                 osDelay(10);
  184.         }
  185. }

  186. /*
  187. *********************************************************************************************************
  188. *        函 数 名: DispMenu
  189. *        功能说明: 显示操作提示菜单
  190. *        形    参: 无
  191. *        返 回 值: 无
  192. *********************************************************************************************************
  193. */
  194. static void DispMenu(void)
  195. {
  196.         printf("\r\n------------------------------------------------\r\n");
  197.         printf("请选择串口操作命令,电脑键盘打印数字即可:\r\n");
  198.         printf("首次使用,如果操作NAND,务必调用串口命令0,进行NAND Flash的低级格式化和文件系统格式化\r\n");      
  199.         printf("1 - 显示卡容量和剩余容量\r\n");
  200.         printf("2 - 显示卡根目录下的文件\r\n");
  201.         printf("3 - 创建三个text文本并使用不同函数写入内容\r\n");
  202.         printf("4 - 使用三个不同函数读取文本\r\n");
  203.         printf("5 - 创建一个text文本并指定一个位置对其进行读写操作\r\n");
  204.         printf("6 - 删除文件夹和文件\r\n");
  205.         printf("7 - 测试文件读写速度\r\n");
  206.         printf("8 - 写数据到CSV文件中\r\n");
  207.         printf("9 - 从CSV文件中读数据\r\n");
  208.         printf("m - 操作SD卡命令\r\n");
  209.         printf("u - 操作U盘命令\r\n");
  210.         printf("n - 操作NAND命令\r\n");
  211.         printf("b - 关闭SD模拟U盘\r\n");   
  212.         printf("a - 打开SD模拟U盘\r\n");
  213.         printf("b - 关闭SD模拟U盘\r\n");
  214. }

  215. /*
  216. *********************************************************************************************************
  217. *        函 数 名: DotFormatjavascript:;
  218. *        功能说明: 将数据规范化显示,方便用户查看
  219. *             比如
  220. *             2345678   ---->  2.345.678
  221. *             334426783 ---->  334.426.783
  222. *             以三个数为单位进行显示
  223. *        形    参: _ullVal   需要规范显示的数值
  224. *             _sp       规范显示后数据存储的buf。
  225. *        返 回 值: 无
  226. *********************************************************************************************************
  227. */
  228. static void DotFormat(uint64_t _ullVal, char *_sp)
  229. {
  230.         /* 数值大于等于10^9 */
  231.         if (_ullVal >= (uint64_t)1e9)
  232.         {
  233.                 _sp += sprintf (_sp, "%d.", (uint32_t)(_ullVal / (uint64_t)1e9));
  234.                 _ullVal %= (uint64_t)1e9;
  235.                 _sp += sprintf (_sp, "%03d.", (uint32_t)(_ullVal / (uint64_t)1e6));
  236.                 _ullVal %= (uint64_t)1e6;
  237.                 sprintf (_sp, "%03d.%03d", (uint32_t)(_ullVal / 1000), (uint32_t)(_ullVal % 1000));
  238.                 return;
  239.         }
  240.       
  241.         /* 数值大于等于10^6 */
  242.         if (_ullVal >= (uint64_t)1e6)
  243.         {
  244.                 _sp += sprintf (_sp,"%d.", (uint32_t)(_ullVal / (uint64_t)1e6));
  245.                 _ullVal %= (uint64_t)1e6;
  246.                 sprintf (_sp,"%03d.%03d", (uint32_t)(_ullVal / 1000), (uint32_t)(_ullVal % 1000));
  247.                 return;
  248.         }
  249.       
  250.         /* 数值大于等于10^3 */
  251.         if (_ullVal >= 1000)
  252.         {
  253.                 sprintf (_sp, "%d.%03d", (uint32_t)(_ullVal / 1000), (uint32_t)(_ullVal % 1000));
  254.                 return;
  255.         }
  256.       
  257.         /* 其它数值 */
  258.         sprintf (_sp,"%d",(uint32_t)(_ullVal));
  259. }

  260. /*
  261. *********************************************************************************************************
  262. *        函 数 名: ViewSDCapacity
  263. *        功能说明: 设备的挂载,卸载及其容量显示
  264. *        形    参: _path,U盘,SD卡和NAND
  265. *        返 回 值: 无
  266. *********************************************************************************************************
  267. */
  268. static void ViewSDCapacity(char *_path)
  269. {
  270.         uint8_t result;
  271.         fsMediaInfo info;
  272.         uint64_t ullSdCapacity;
  273.         int32_t id;  
  274.         uint8_t buf[15];
  275.         uint32_t ser_num;
  276.         fsStatus restatus;
  277.         char *opt;
  278.    
  279.     result = finit(_path);
  280.         if(result != NULL)
  281.         {
  282.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  283.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  284.                 return;      
  285.         }
  286.         else
  287.         {
  288.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  289.         }
  290.    
  291.         /* 加载设备 */
  292.         result = fmount(_path);
  293.         if(result != NULL)
  294.         {
  295.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  296.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  297.         
  298.         /* 格式化 */
  299.         if(strncmp(_path, _path, 3) == 0)
  300.         {
  301.             opt = "/LL /L nand /FAT16";
  302.             printf("文件系统格式中......\r\n");
  303.             result = fformat (_path, opt);
  304.             printf("文件系统格式化 (%s)\r\n", ReVal_Table[result]);
  305.             if(result != NULL)
  306.             {
  307.                 return;
  308.             }
  309.         }
  310.         else
  311.         {
  312.             return;
  313.         }
  314.         }
  315.         else
  316.         {
  317.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  318.         }
  319.    
  320.    
  321.         printf("------------------------------------------------------------------\r\n");
  322.       
  323.         /* 获取volume label */
  324.         if (fvol (_path, (char *)buf, &ser_num) == 0)
  325.         {
  326.                 if (buf[0])
  327.                 {
  328.                         printf ("volume label是 %s\r\n", buf);
  329.                 }
  330.                 else
  331.                 {
  332.                         printf ("没有volume label\r\n");
  333.                 }
  334.                
  335.                 printf ("volume serial number是 %d\r\n", ser_num);
  336.         }
  337.         else
  338.         {
  339.                 printf ("Volume访问错误\r\n");
  340.         }

  341.         /* 获取剩余容量 */
  342.         ullSdCapacity = ffree(_path);
  343.         DotFormat(ullSdCapacity, (char *)buf);
  344.         printf("剩余容量 = %10s字节\r\n", buf);

  345.         /* 卸载设备 */
  346.         result = funmount(_path);
  347.         if(result != NULL)
  348.         {
  349.                 printf("卸载文件系统失败\r\n");
  350.         }
  351.         else
  352.         {
  353.                 printf("卸载文件系统成功\r\n");
  354.         }
  355.    
  356.     result = funinit(_path);
  357.         if(result != NULL)
  358.         {
  359.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  360.         }
  361.         else
  362.         {
  363.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  364.         }

  365.         printf("------------------------------------------------------------------\r\n");
  366. }

  367. /*
  368. *********************************************************************************************************
  369. *        函 数 名: ViewRootDir
  370. *        功能说明: 显示根目录下的文件名
  371. *        形    参: _path,U盘,SD卡和NAND
  372. *        返 回 值: 无
  373. *********************************************************************************************************
  374. */
  375. static void ViewRootDir(char *_path)
  376. {
  377.         uint8_t result;
  378.         fsFileInfo info;
  379.         uint8_t buf[15];
  380.     char pathbuf[20];
  381.       
  382.     info.fileID = 0;   /* 每次使用ffind函数前,info.fileID必须初始化为0 */

  383.     result = finit(_path);
  384.         if(result != NULL)
  385.         {
  386.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  387.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  388.                 return;      
  389.         }
  390.         else
  391.         {
  392.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  393.         }
  394.    
  395.         /* 加载 */
  396.         result = fmount(_path);
  397.       
  398.         if(result != NULL)
  399.         {
  400.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  401.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  402.                 goto access_fail;
  403.         }
  404.         else
  405.         {
  406.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  407.         }
  408.       
  409.         printf("------------------------------------------------------------------\r\n");
  410.         printf("文件名                 |  文件大小     | 文件ID  | 属性      |日期\r\n");
  411.       
  412.         /*
  413.            将根目录下的所有文件列出来。
  414.            1. "*" 或者 "*.*" 搜索指定路径下的所有文件
  415.            2. "abc*"         搜索指定路径下以abc开头的所有文件
  416.            3. "*.jpg"        搜索指定路径下以.jpg结尾的所有文件
  417.            4. "abc*.jpg"     搜索指定路径下以abc开头和.jpg结尾的所有文件
  418.       
  419.            以下是实现搜索根目录下所有文件
  420.         */
  421.     sprintf(pathbuf, "%s*.*", _path);
  422.         while(ffind (pathbuf, &info) == 0)  
  423.         {
  424.                 /* 调整文件显示大小格式 */
  425.                 DotFormat(info.size, (char *)buf);
  426.                
  427.                 /* 打印根目录下的所有文件 */
  428.                 printf ("%-20s %12s bytes, ID: %04d  ",
  429.                                 info.name,
  430.                                 buf,
  431.                                 info.fileID);
  432.                
  433.                 /* 判断是文件还是子目录 */
  434.                 if (info.attrib & FS_FAT_ATTR_DIRECTORY)
  435.                 {
  436.                         printf("(0x%02x)目录", info.attrib);
  437.                 }
  438.                 else
  439.                 {
  440.                         printf("(0x%02x)文件", info.attrib);
  441.                 }
  442.                
  443.                 /* 显示文件日期 */
  444.                 printf ("  %04d.%02d.%02d  %02d:%02d\r\n",
  445.                  info.time.year, info.time.mon, info.time.day,
  446.                info.time.hr, info.time.min);
  447.     }
  448.       
  449.         if (info.fileID == 0)  
  450.         {
  451.                 printf ("卡中没有存放文件\r\n");
  452.         }

  453. access_fail:
  454.         /* 卸载 */
  455.         result = funmount(_path);
  456.         if(result != NULL)
  457.         {
  458.                 printf("卸载文件系统失败\r\n");
  459.         }
  460.         else
  461.         {
  462.                 printf("卸载文件系统成功\r\n");
  463.         }
  464.    
  465.     result = funinit(_path);
  466.         if(result != NULL)
  467.         {
  468.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  469.         }
  470.         else
  471.         {
  472.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  473.         }
  474.       
  475.         printf("------------------------------------------------------------------\r\n");
  476. }

  477. /*
  478. *********************************************************************************************************
  479. *        函 数 名: CreateNewFile
  480. *        功能说明: 创建三个text文本,分别使用fwrite,fprintf和fputs写数据。
  481. *        形    参: _path,U盘,SD卡和NAND
  482. *        返 回 值: 无
  483. *********************************************************************************************************
  484. */
  485. static void CreateNewFile(char *_path)
  486. {
  487.         const uint8_t WriteText[] = {"武汉安富莱电子有限公司\r\n2015-09-06\r\nwww.armfly.com\r\nWWW.ARMFLY.COM"};
  488.         const uint8_t WriteText1[] = {"武汉安富莱电子有限公司\r"};
  489.         FILE *fout;
  490.         uint32_t bw;
  491.         uint32_t i = 2;
  492.         uint8_t result;
  493.     char namepath[30];

  494.    
  495.     result = finit(_path);
  496.         if(result != NULL)
  497.         {
  498.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  499.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  500.                 return;      
  501.         }
  502.         else
  503.         {
  504.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  505.         }
  506.    
  507.         /* 加载 */
  508.         result = fmount(_path);
  509.       
  510.         if(result != NULL)
  511.         {
  512.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  513.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  514.                 goto access_fail;
  515.         }
  516.         else
  517.         {
  518.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  519.         }
  520.    
  521.         printf("------------------------------------------------------------------\r\n");
  522.       
  523.         /**********************************************************************************************************/
  524.         /* 打开文件夹test中的文件test1.txt,如果没有子文件夹和txt文件会自动创建*/
  525.     sprintf(namepath, "%s\\test\\test1.txt", _path);
  526.         fout = fopen (namepath, "w");
  527.         if (fout != NULL)
  528.         {
  529.                 printf("打开文件\\test\\test1.txt成功,如果没有子文件夹和txt文件会自动创建\r\n");
  530.                 /* 写数据 */
  531.                 bw = fwrite (WriteText, sizeof(uint8_t), sizeof(WriteText)/sizeof(uint8_t), fout);
  532.                 if(bw == sizeof(WriteText)/sizeof(uint8_t))
  533.                 {
  534.                         printf("写入内容成功\r\n");
  535.                 }
  536.                 else
  537.                 {
  538.                         printf("写入内容失败\r\n");
  539.                 }
  540.                
  541.                 /* 关闭文件 */
  542.                 fclose(fout);
  543.         }
  544.         else
  545.         {
  546.                 printf("打开文件\\test\\test.txt失败\r\n");
  547.         }
  548.       
  549.         /**********************************************************************************************************/
  550.         /* 打开文件夹test中的文件test2.txt,如果没有子文件夹和txt文件会自动创建*/
  551.     sprintf(namepath, "%s\\test\\test2.txt", _path);
  552.         fout = fopen (namepath, "w");
  553.         if (fout != NULL)
  554.         {
  555.                 printf("打开文件\\test\\test2.txt成功,如果没有子文件夹和txt文件会自动创建\r\n");
  556.                
  557.                 /* 写数据 */
  558.                 bw = fprintf (fout, "%d %d %f\r\n", i, i*5, i*5.55f);
  559.                
  560.                 /* 使用函数ferror检测是否发生过错误 */
  561.                 if (ferror(fout) != NULL)  
  562.                 {
  563.                         printf("写入内容失败\r\n");
  564.                 }
  565.                 else
  566.                 {
  567.                         printf("写入内容成功\r\n");      
  568.                 }
  569.                
  570.                 /* 关闭文件 */
  571.                 fclose(fout);
  572.         }
  573.         else
  574.         {
  575.                 printf("打开文件\\test\\test.txt失败\r\n");
  576.         }
  577.       
  578.         /**********************************************************************************************************/
  579.         /* 打开文件夹test中的文件test3.txt,如果没有子文件夹和txt文件会自动创建*/
  580.         sprintf(namepath, "%s\\test\\test3.txt", _path);   
  581.         fout = fopen (namepath, "w");
  582.         if (fout != NULL)
  583.         {
  584.                 printf("打开文件\\test\\test3.txt成功,如果没有子文件夹和txt文件会自动创建\r\n");
  585.                
  586.                 /* 写数据 */
  587.                 fputs((const char *)WriteText1, fout);
  588.                
  589.                 /* 使用函数ferror检测是否发生过错误 */
  590.                 if (ferror(fout) != NULL)  
  591.                 {
  592.                         printf("写入内容失败\r\n");
  593.                 }
  594.                 else
  595.                 {
  596.                         printf("写入内容成功\r\n");      
  597.                 }
  598.                
  599.                 /* 关闭文件 */
  600.                 fclose(fout);
  601.         }
  602.         else
  603.         {
  604.                 printf("打开文件\\test\\test.txt失败\r\n");
  605.         }

  606. access_fail:      
  607.         /* 卸载 */
  608.         result = funmount(_path);
  609.         if(result != NULL)
  610.         {
  611.                 printf("卸载文件系统失败\r\n");
  612.         }
  613.         else
  614.         {
  615.                 printf("卸载文件系统成功\r\n");
  616.         }
  617.    
  618.     result = funinit(_path);
  619.         if(result != NULL)
  620.         {
  621.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  622.         }
  623.         else
  624.         {
  625.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  626.         }

  627.         printf("------------------------------------------------------------------\r\n");
  628. }

  629. /*
  630. *********************************************************************************************************
  631. *        函 数 名: ReadFileData
  632. *        功能说明: 分别使用fread,fscan和fgets读取三个不同的txt文件。
  633. *        形    参: _path,U盘,SD卡和NAND
  634. *        返 回 值: 无
  635. *********************************************************************************************************
  636. */
  637. static void ReadFileData(char *_path)
  638. {
  639.         const uint8_t WriteText[] = {"武汉安富莱电子有限公司\r\n2015-09-06\r\nwww.armfly.com\r\nWWW.ARMFLY.COM"};
  640.         uint8_t Readbuf[50];
  641.         FILE *fin;
  642.         uint32_t bw;
  643.         uint32_t index1, index2;
  644.         float  count = 0.0f;
  645.         uint8_t result;
  646.         char namepath[30];

  647.     result = finit(_path);
  648.         if(result != NULL)
  649.         {
  650.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  651.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  652.                 return;      
  653.         }
  654.         else
  655.         {
  656.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  657.         }
  658.    
  659.         /* 加载 */
  660.         result = fmount(_path);
  661.       
  662.         if(result != NULL)
  663.         {
  664.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  665.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  666.                 goto access_fail;
  667.         }
  668.         else
  669.         {
  670.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  671.         }
  672.    
  673.         printf("------------------------------------------------------------------\r\n");
  674.       
  675.         /**********************************************************************************************************/
  676.         /* 打开文件夹test中的文件test1.txt */
  677.         sprintf(namepath, "%s\\test\\test1.txt", _path);
  678.         fin = fopen (namepath, "r");
  679.         if (fin != NULL)
  680.         {
  681.                 printf("<1>打开文件\\test\\test1.txt成功\r\n");
  682.                
  683.                 /* 防止警告 */
  684.                 (void) WriteText;
  685.                
  686.                 /* 读数据 */
  687.                 bw = fread(Readbuf, sizeof(uint8_t), sizeof(WriteText)/sizeof(uint8_t), fin);
  688.                 if(bw == sizeof(WriteText)/sizeof(uint8_t))
  689.                 {
  690.                         Readbuf[bw] = NULL;
  691.                         printf("test1.txt 文件内容 : \r\n%s\r\n", Readbuf);
  692.                 }
  693.                 else
  694.                 {
  695.                         printf("读内容失败\r\n");
  696.                 }
  697.                
  698.                 /* 关闭文件 */
  699.                 fclose(fin);
  700.         }
  701.         else
  702.         {
  703.                 printf("打开文件\\test\\test.txt失败, 可能文件不存在\r\n");
  704.         }
  705.       
  706.         /**********************************************************************************************************/
  707.         /* 打开文件夹test中的文件test2.txt */
  708.         sprintf(namepath, "%s\\test\\test2.txt", _path);
  709.         fin = fopen (namepath, "r");
  710.         if (fin != NULL)
  711.         {
  712.                 printf("\r\n<2>打开文件\\test\\test2.txt成功\r\n");
  713.                
  714.                 bw = fscanf(fin, "%d %d %f", &index1, &index2, &count);

  715.                 /* 3参数都读出来了 */
  716.                 if (bw == 3)  
  717.                 {
  718.                         printf("读出的数值\r\nindex1 = %d index2 = %d count = %f\r\n", index1, index2, count);
  719.                 }
  720.                 else
  721.                 {
  722.                         printf("读内容失败\r\n");      
  723.                 }
  724.                
  725.                 /* 关闭文件 */
  726.                 fclose(fin);
  727.         }
  728.         else
  729.         {
  730.                 printf("打开文件\\test\\test.txt失败(%s)\r\n", ReVal_Table[result]);
  731.         }
  732.       
  733.         /**********************************************************************************************************/
  734.         /* 打开文件夹test中的文件test3.txt,如果没有子文件夹和txt文件会自动创建*/
  735.         sprintf(namepath, "%s\\test\\test3.txt", _path);
  736.         fin = fopen (namepath, "r");
  737.         if (fin != NULL)
  738.         {
  739.                 printf("\r\n<3>打开文件\\test\\test3.txt成功\r\n");
  740.                
  741.                 /* 读数据 */
  742.                 if(fgets((char *)Readbuf, sizeof(Readbuf), fin) != NULL)
  743.                 {
  744.                         printf("test3.txt 文件内容 : \r\n%s\r\n", Readbuf);
  745.                 }
  746.                 else
  747.                 {
  748.                         printf("读内容失败\r\n");
  749.                 }
  750.                
  751.                 /* 关闭文件 */
  752.                 fclose(fin);
  753.         }
  754.         else
  755.         {
  756.                 printf("打开文件\\test\\test.txt失败\r\n");
  757.         }
  758.       
  759. access_fail:
  760.         /* 卸载 */
  761.         result = funmount(_path);
  762.         if(result != NULL)
  763.         {
  764.                 printf("卸载文件系统失败\r\n");
  765.         }
  766.         else
  767.         {
  768.                 printf("卸载文件系统成功\r\n");
  769.         }
  770.    
  771.     result = funinit(_path);
  772.         if(result != NULL)
  773.         {
  774.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  775.         }
  776.         else
  777.         {
  778.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  779.         }

  780.         printf("------------------------------------------------------------------\r\n");
  781. }

  782. /*
  783. *********************************************************************************************************
  784. *        函 数 名: SeekFileData
  785. *        功能说明: 创建一个text文本,在指定位置对其进行读写操作。
  786. *        形    参: _path,U盘,SD卡和NAND
  787. *        返 回 值: 无
  788. *********************************************************************************************************
  789. */
  790. static void SeekFileData(char *_path)
  791. {
  792.         const uint8_t WriteText[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"};
  793.         FILE *fin, *fout;
  794.         uint32_t bw;
  795.         uint32_t uiPos;
  796.         uint8_t ucChar;
  797.         uint8_t result;
  798.         char namepath[30];
  799.    

  800.     result = finit(_path);
  801.         if(result != NULL)
  802.         {
  803.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  804.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  805.                 return;      
  806.         }
  807.         else
  808.         {
  809.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  810.         }
  811.    
  812.         /* 加载 */
  813.         result = fmount(_path);
  814.       
  815.         if(result != NULL)
  816.         {
  817.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  818.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  819.                 goto access_fail;
  820.         }
  821.         else
  822.         {
  823.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  824.         }
  825.         printf("------------------------------------------------------------------\r\n");
  826.       
  827.         /**********************************************************************************************************/
  828.         /* 打开文件夹test中的文件test1.txt,如果没有子文件夹和txt文件会自动创建*/
  829.         sprintf(namepath, "%s\\test.txt", _path);
  830.         fout = fopen (namepath, "w");
  831.         if (fout != NULL)
  832.         {
  833.                 printf("打开文件\\test.txt成功,如果没有txt文件会自动创建\r\n");
  834.                 /* 写数据 */
  835.                 bw = fwrite (WriteText, sizeof(uint8_t), sizeof(WriteText)/sizeof(uint8_t), fout);
  836.                 if(bw == sizeof(WriteText)/sizeof(uint8_t))
  837.                 {
  838.                         printf("写入内容成功\r\n");
  839.                 }
  840.                 else
  841.                 {
  842.                         printf("写入内容失败\r\n");
  843.                 }
  844.                        
  845.                 /* 关闭文件 */
  846.                 fclose(fout);
  847.         }
  848.         else
  849.         {
  850.                 printf("打开文件\\test.txt失败\r\n");
  851.         }
  852.       
  853.         /***********************************************/
  854.         sprintf(namepath, "%s\\test.txt", _path);
  855.         fin = fopen (namepath,"r");
  856.         if (fin != NULL)  
  857.         {
  858.                 printf("\r\n打开文件\\test.txt成功\r\n");
  859.                
  860.                 /* 读取文件test.txt的位置0的字符 */
  861.                 fseek (fin, 0L, SEEK_SET);
  862.                 uiPos = ftell(fin);        
  863.                 ucChar = fgetc (fin);               
  864.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);
  865.                
  866.                 /* 读取文件test.txt的位置1的字符 */
  867.                 fseek (fin, 1L, SEEK_SET);
  868.                 uiPos = ftell(fin);        
  869.                 ucChar = fgetc (fin);               
  870.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);

  871.                 /* 读取文件test.txt的位置25的字符 */
  872.                 fseek (fin, 25L, SEEK_SET);
  873.                 uiPos = ftell(fin);        
  874.                 ucChar = fgetc (fin);               
  875.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);
  876.                
  877.                 /* 通过上面函数的操作,当前读写位置是26
  878.                    下面函数是在当前位置的基础上后退2个位置,也就是24,调用函数fgetc后,位置就是25
  879.                  */
  880.                 fseek (fin, -2L, SEEK_CUR);
  881.                 uiPos = ftell(fin);        
  882.                 ucChar = fgetc (fin);               
  883.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);
  884.                
  885.                 /* 读取文件test.txt的倒数第2个字符, 最后一个是'\0' */
  886.                 fseek (fin, -2L, SEEK_END);
  887.                 uiPos = ftell(fin);
  888.                 ucChar = fgetc (fin);
  889.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);
  890.                
  891.                 /* 将读取位置重新定位到文件开头 */
  892.                 rewind(fin);  
  893.                 uiPos = ftell(fin);
  894.                 ucChar = fgetc (fin);
  895.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);      
  896.                
  897.                 /*
  898.                    这里是演示一下ungetc的作用,此函数就是将当前的读取位置偏移回一个字符,
  899.                    而fgetc调用后位置增加一个字符。
  900.                  */
  901.                 fseek (fin, 0L, SEEK_SET);
  902.                 ucChar = fgetc (fin);
  903.                 uiPos = ftell(fin);
  904.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);
  905.                 ungetc(ucChar, fin);
  906.                 uiPos = ftell(fin);
  907.                 printf("文件test.txt当前读取位置:%02d,字符:%c\r\n", uiPos, ucChar);
  908.                
  909.                 /* 关闭*/
  910.                 fclose (fin);
  911.         }
  912.         else
  913.         {
  914.                 printf("打开文件\\test.txt失败\r\n");
  915.         }
  916.       
  917. access_fail:      
  918.         /* 卸载 */
  919.         result = funmount(_path);
  920.         if(result != NULL)
  921.         {
  922.                 printf("卸载文件系统失败\r\n");
  923.         }
  924.         else
  925.         {
  926.                 printf("卸载文件系统成功\r\n");
  927.         }
  928.    
  929.     result = funinit(_path);
  930.         if(result != NULL)
  931.         {
  932.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  933.         }
  934.         else
  935.         {
  936.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  937.         }

  938.         printf("------------------------------------------------------------------\r\n");
  939.       
  940. }

  941. /*
  942. *********************************************************************************************************
  943. *        函 数 名: DeleteDirFile
  944. *        功能说明: 删除文件夹和文件
  945. *        形    参: _path,U盘,SD卡和NAND
  946. *        返 回 值: 无
  947. *********************************************************************************************************
  948. */
  949. static void DeleteDirFile(char *_path)
  950. {
  951.         uint8_t result;
  952.         uint8_t i;
  953.         fsStatus restatus;
  954.         char FileName[50];
  955.       
  956.     result = finit(_path);
  957.         if(result != NULL)
  958.         {
  959.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  960.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  961.                 return;      
  962.         }
  963.         else
  964.         {
  965.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  966.         }
  967.    
  968.         /* 加载 */
  969.         result = fmount(_path);
  970.       
  971.         if(result != NULL)
  972.         {
  973.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  974.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  975.                 goto access_fail;
  976.         }
  977.         else
  978.         {
  979.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  980.         }
  981.         printf("------------------------------------------------------------------\r\n");
  982.       
  983.         /* 删除文件 speed1.txt */
  984.         for (i = 0; i < 20; i++)
  985.         {
  986.         sprintf(FileName, "%s\\Speed%02d.txt", _path, i);/* 每写1次,序号递增 */      
  987.                 restatus = fdelete (FileName, NULL);
  988.                 if (restatus != NULL)
  989.                 {
  990.                         printf("%s文件不存在(返回值:%d)\r\n", FileName, result);
  991.                 }
  992.                 else
  993.                 {
  994.                         printf("删除%s文件成功\r\n", FileName);
  995.                 }
  996.         }
  997.       
  998.         for(i = 1; i < 4; i++)
  999.         {
  1000.         sprintf(FileName, "%s\\test\\test%01d.txt", _path, i);   /* 每写1次,序号递增 */
  1001.                 restatus = fdelete (FileName, NULL);
  1002.                 if (restatus != NULL)
  1003.                 {
  1004.                         printf("%s文件不存在(返回值:%d)\r\n", FileName, result);
  1005.                 }
  1006.                 else
  1007.                 {
  1008.                         printf("删除%s文件成功\r\n", FileName);
  1009.                 }      
  1010.         }
  1011.       
  1012.         /* 删除文件夹test */
  1013.     sprintf(FileName, "%s\\test", _path);
  1014.         restatus = fdelete (FileName, NULL);   
  1015.         if (restatus != NULL)
  1016.         {
  1017.                 printf("test文件夹非空或不存在(返回值:%d)\r\n", result);
  1018.         }
  1019.         else
  1020.         {
  1021.                 printf("删除test文件夹成功\r\n");
  1022.         }
  1023.       
  1024.         /* 删除csv文件 */

  1025.     sprintf(FileName, "%s\\record.csv", _path);
  1026.         restatus = fdelete (FileName, NULL);  
  1027.         if (restatus != NULL)
  1028.         {
  1029.                 printf("record.csv文件不存在(返回值:%d)\r\n", result);
  1030.         }
  1031.         else
  1032.         {
  1033.                 printf("删除record.csv件成功\r\n");
  1034.         }
  1035.       
  1036. access_fail:
  1037.         /* 卸载 */
  1038.         result = funmount(_path);
  1039.         if(result != NULL)
  1040.         {
  1041.                 printf("卸载文件系统失败\r\n");
  1042.         }
  1043.         else
  1044.         {
  1045.                 printf("卸载文件系统成功\r\n");
  1046.         }
  1047.    
  1048.     result = funinit(_path);
  1049.         if(result != NULL)
  1050.         {
  1051.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1052.         }
  1053.         else
  1054.         {
  1055.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1056.         }
  1057.                
  1058.         printf("------------------------------------------------------------------\r\n");
  1059. }

  1060. /*
  1061. *********************************************************************************************************
  1062. *        函 数 名: WriteFileTest
  1063. *        功能说明: 测试文件读写速度
  1064. *        形    参: _path,U盘,SD卡和NAND
  1065. *        返 回 值: 无
  1066. *********************************************************************************************************
  1067. */
  1068. static void WriteFileTest(char *_path)
  1069. {
  1070.         FILE *fout;
  1071.         uint32_t bw;
  1072.         uint32_t i,k;
  1073.         uint32_t runtime1,runtime2,timelen;
  1074.         uint8_t err = 0, result;
  1075.         char TestFileName[13];
  1076.         static uint8_t s_ucTestSn = 0;

  1077.         for (i = 0; i < sizeof(g_TestBuf); i++)
  1078.         {
  1079.                 g_TestBuf[i] = (i / 512) + '0';
  1080.         }

  1081.     result = finit(_path);
  1082.         if(result != NULL)
  1083.         {
  1084.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  1085.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1086.                 return;      
  1087.         }
  1088.         else
  1089.         {
  1090.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1091.         }
  1092.    
  1093.         /* 加载 */
  1094.         result = fmount(_path);
  1095.       
  1096.         if(result != NULL)
  1097.         {
  1098.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  1099.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1100.                 goto access_fail;
  1101.         }
  1102.         else
  1103.         {
  1104.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1105.         }
  1106.       
  1107.         printf("------------------------------------------------------------------\r\n");

  1108.         /* 打开文件 -----------------------------------------*/
  1109.         sprintf(TestFileName, "%s\\Speed%02d.txt", _path, s_ucTestSn++);                /* 每写1次,序号递增 */
  1110.         fout = fopen (TestFileName, "w");
  1111.         if (fout ==  NULL)
  1112.         {
  1113.                 printf("文件: %s创建失败\r\n", TestFileName);
  1114.                 goto access_fail;
  1115.         }
  1116.       
  1117.         /* 写一串数据 测试写速度-----------------------------------------*/
  1118.         printf("开始写文件%s %dKB ...\r\n", TestFileName, TEST_FILE_LEN / 1024);
  1119.         runtime1 = osKernelGetTickCount();        /* 读取系统运行时间 */
  1120.         for (i = 0; i < TEST_FILE_LEN / BUF_SIZE; i++)
  1121.         {
  1122.                 bw = fwrite (g_TestBuf, sizeof(uint8_t), BUF_SIZE, fout);   
  1123.                 if (bw == BUF_SIZE)
  1124.                 {
  1125.                         if (((i + 1) % 8) == 0)
  1126.                         {
  1127.                                 printf(".");
  1128.                         }
  1129.                 }
  1130.                 else
  1131.                 {
  1132.                         err = 1;
  1133.                         printf("%s文件写失败\r\n", TestFileName);
  1134.                         break;
  1135.                 }
  1136.         }
  1137.         runtime2 = osKernelGetTickCount();        /* 读取系统运行时间 */

  1138.         if (err == 0)
  1139.         {
  1140.                 timelen = (runtime2 - runtime1);
  1141.                 printf("\r\n  写耗时 : %dms   平均写速度 : %dB/S (%dKB/S)\r\n",
  1142.                         timelen,
  1143.                         (TEST_FILE_LEN * 1000) / timelen,
  1144.                         ((TEST_FILE_LEN / 1024) * 1000) / timelen);
  1145.         }
  1146.       
  1147.         /* 使用函数ferror再次检测是否发生过错误 -----------------------*/
  1148.         if (ferror (fout))  
  1149.         {
  1150.                 printf ("写数据过程中出现过错误\r\n\n");
  1151.     }
  1152.         else
  1153.         {
  1154.                 printf ("写数据过程中未出现过错误\r\n\n");               
  1155.         }

  1156.         fclose (fout);        /* 关闭文件*/


  1157.         /* 开始读文件,测试读速度 ---------------------------------------*/
  1158.         fout = fopen (TestFileName, "r");
  1159.         if (fout ==  NULL)
  1160.         {
  1161.                 printf("文件: %s读取失败\r\n", TestFileName);
  1162.                 goto access_fail;
  1163.         }

  1164.         printf("开始读文件 %dKB ...\r\n", TEST_FILE_LEN / 1024);
  1165.         runtime1 = osKernelGetTickCount();        /* 读取系统运行时间 */
  1166.         for (i = 0; i < TEST_FILE_LEN / BUF_SIZE; i++)
  1167.         {
  1168.                 bw = fread(g_TestBuf, sizeof(uint8_t), BUF_SIZE, fout);   
  1169.                 if (bw == BUF_SIZE)
  1170.                 {
  1171.                         if (((i + 1) % 8) == 0)
  1172.                         {
  1173.                                 printf(".");
  1174.                         }

  1175.                         /* 比较写入的数据是否正确,此语句会导致读卡速度结果降低 */
  1176.                         for (k = 0; k < sizeof(g_TestBuf); k++)
  1177.                         {
  1178.                                 if (g_TestBuf[k] != (k / 512) + '0')
  1179.                                 {
  1180.                                           err = 1;
  1181.                                         printf("Speed1.txt 文件读成功,但是数据出错\r\n");
  1182.                                         break;
  1183.                                 }
  1184.                         }
  1185.                         if (err == 1)
  1186.                         {
  1187.                                 break;
  1188.                         }
  1189.                 }
  1190.                 else
  1191.                 {
  1192.                         err = 1;
  1193.                         printf("Speed1.txt 文件读失败\r\n");
  1194.                         break;
  1195.                 }
  1196.         }
  1197.         runtime2 = osKernelGetTickCount();        /* 读取系统运行时间 */

  1198.         if (err == 0)
  1199.         {
  1200.                 timelen = (runtime2 - runtime1);
  1201.                 printf("\r\n  读耗时 : %dms   平均读速度 : %dB/S (%dKB/S)\r\n", timelen,
  1202.                         (TEST_FILE_LEN * 1000) / timelen, ((TEST_FILE_LEN / 1024) * 1000) / timelen);
  1203.         }
  1204.       
  1205.         /* 使用函数ferror再次检测是否发生过错误 -----------------------*/
  1206.         if (ferror (fout))  
  1207.         {
  1208.                 printf ("读数据过程中出现过错误\r\n");
  1209.     }
  1210.         else
  1211.         {
  1212.                 printf ("读数据过程中未出现过错误\r\n");               
  1213.         }

  1214.         fclose (fout);        /* 关闭文件*/
  1215.       
  1216. access_fail:
  1217.         /* 卸载 */
  1218.         result = funmount(_path);
  1219.         if(result != NULL)
  1220.         {
  1221.                 printf("卸载文件系统失败\r\n");
  1222.         }
  1223.         else
  1224.         {
  1225.                 printf("卸载文件系统成功\r\n");
  1226.         }
  1227.    
  1228.     result = funinit(_path);
  1229.         if(result != NULL)
  1230.         {
  1231.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1232.         }
  1233.         else
  1234.         {
  1235.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1236.         }
  1237.       
  1238.         printf("------------------------------------------------------------------\r\n");
  1239. }

  1240. /*
  1241. *********************************************************************************************************
  1242. *        函 数 名: WriteCSVFile
  1243. *        功能说明: 写数据到CSV文件中
  1244. *        形    参: _path,U盘,SD卡和NAND
  1245. *        返 回 值: 无
  1246. *********************************************************************************************************
  1247. */
  1248. static void WriteCSVFile(char *_path)
  1249. {
  1250.         const uint8_t WriteText[] = {"记录时间,标号,记录数值一,记录数值二\r\n"};
  1251.         FILE *fout;
  1252.         uint8_t result;
  1253.         static uint16_t i = 1;
  1254.         static uint8_t ucFirstRunFlag = 0;
  1255.         char namepath[30];

  1256.     result = finit(_path);
  1257.         if(result != NULL)
  1258.         {
  1259.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  1260.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1261.                 return;      
  1262.         }
  1263.         else
  1264.         {
  1265.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1266.         }
  1267.    
  1268.         /* 加载 */
  1269.         result = fmount(_path);
  1270.       
  1271.         if(result != NULL)
  1272.         {
  1273.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  1274.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1275.                 goto access_fail;
  1276.         }
  1277.         else
  1278.         {
  1279.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1280.         }
  1281.         printf("------------------------------------------------------------------\r\n");
  1282.       
  1283.         /**********************************************************************************************************/
  1284.         /*
  1285.           1. 打开文件record.csv,如果没有此文件会自动创建。
  1286.           2. 第二个参数表示向此文件写数据都从尾部开始添加。
  1287.         */
  1288.         sprintf(namepath, "%s\\record.csv", _path);
  1289.         fout = fopen (namepath, "a");
  1290.         if (fout != NULL)
  1291.         {
  1292.                 printf("打开文件M0:\\record.csvt成功,如果没有此文件会自动创建\r\n");
  1293.                
  1294.                 /* 写数据,如果是第一次写数据,先写CSV文件的表项的题目,以后写数据不再需要写此表项 */
  1295.                 if(ucFirstRunFlag == 0)
  1296.                 {
  1297.                         fprintf(fout, (char *)WriteText);
  1298.                         ucFirstRunFlag = 1;
  1299.                 }
  1300.                
  1301.                 /* 依次写5行数据 */
  1302.                 fprintf (fout, "%d, %d, %f\r\n", i, i*5, i*5.55f);
  1303.                
  1304.                 i++;
  1305.                 fprintf (fout, "%d, %d, %f\r\n", i, i*5, i*5.55f);
  1306.                
  1307.                 i++;
  1308.                 fprintf (fout, "%d, %d, %f\r\n", i, i*5, i*5.55f);
  1309.                
  1310.                 i++;
  1311.                 fprintf (fout, "%d, %d, %f\r\n", i, i*5, i*5.55f);
  1312.                
  1313.                 i++;
  1314.                 fprintf (fout, "%d, %d, %f\r\n", i, i*5, i*5.55f);
  1315.                 i++;
  1316.                
  1317.                 /* 使用函数ferror检测是否发生过错误 */
  1318.                 if (ferror(fout) != NULL)  
  1319.                 {
  1320.                         printf("写入内容失败\r\n");
  1321.                 }
  1322.                 else
  1323.                 {
  1324.                         printf("写入内容成功\r\n");      
  1325.                 }
  1326.                
  1327.                 /* 关闭文件 */
  1328.                 fclose(fout);
  1329.         }
  1330.         else
  1331.         {
  1332.                 printf("打开文件M0:\\record.csv失败\r\n");
  1333.         }

  1334. access_fail:      
  1335.         /* 卸载 */
  1336.         result = funmount(_path);
  1337.         if(result != NULL)
  1338.         {
  1339.                 printf("卸载文件系统失败\r\n");
  1340.         }
  1341.         else
  1342.         {
  1343.                 printf("卸载文件系统成功\r\n");
  1344.         }
  1345.    
  1346.     result = funinit(_path);
  1347.         if(result != NULL)
  1348.         {
  1349.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1350.         }
  1351.         else
  1352.         {
  1353.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1354.         }

  1355.         printf("------------------------------------------------------------------\r\n");
  1356. }

  1357. /*
  1358. *********************************************************************************************************
  1359. *        函 数 名: ReadCSVFileData
  1360. *        功能说明: 读取CSV文件中的数据。
  1361. *        形    参: _path,U盘,SD卡和NAND
  1362. *        返 回 值: 无
  1363. *********************************************************************************************************
  1364. */
  1365. static void ReadCSVFileData(char *_path)
  1366. {
  1367.         uint8_t Readbuf[50];
  1368.         FILE *fin;
  1369.         uint8_t result;
  1370.         char namepath[30];

  1371.     result = finit(_path);
  1372.         if(result != NULL)
  1373.         {
  1374.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  1375.                 printf("初始化文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1376.                 return;      
  1377.         }
  1378.         else
  1379.         {
  1380.                 printf("初始化文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1381.         }
  1382.    
  1383.         /* 加载 */
  1384.         result = fmount(_path);
  1385.       
  1386.         if(result != NULL)
  1387.         {
  1388.                 /* 如果挂载失败,务必不要再调用FlashFS的其它API函数,防止进入硬件异常 */
  1389.                 printf("挂载文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1390.                 goto access_fail;
  1391.         }
  1392.         else
  1393.         {
  1394.                 printf("挂载文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1395.         }
  1396.         printf("------------------------------------------------------------------\r\n");
  1397.       
  1398.         /**********************************************************************************************************/
  1399.         /* 打开record.csv文件 */
  1400.         sprintf(namepath, "%s\\record.csv", _path);
  1401.         fin = fopen (namepath, "r");
  1402.         if (fin != NULL)
  1403.         {
  1404.                 printf("打开文件M0:\\record.csv成功\r\n");
  1405.                
  1406.                 /* 将所有数据都读出来,使用fgets函数的好处就是可以一行一行的读取,因为此函数遇到'\n'换行符就会停止读取 */
  1407.                 while (fgets((char *)Readbuf, sizeof(Readbuf), fin) != NULL)  
  1408.                 {
  1409.                         printf("%s", Readbuf);      
  1410.                 }
  1411.                
  1412.                 /* 使用函数ferror检测是否发生过错误 */
  1413.                 if (ferror(fin) != NULL)  
  1414.                 {
  1415.                         printf("读出内容失败\r\n");
  1416.                 }
  1417.                 else
  1418.                 {
  1419.                         printf("record.csv里面的内容全部正确读出\r\n");      
  1420.                 }
  1421.                
  1422.                 /* 关闭文件 */
  1423.                 fclose(fin);
  1424.         }
  1425.         else
  1426.         {
  1427.                 printf("打开文件M0:\\record.csv失败\r\n");
  1428.         }
  1429.       
  1430. access_fail:
  1431.         /* 卸载 */
  1432.         result = funmount(_path);
  1433.         if(result != NULL)
  1434.         {
  1435.                 printf("卸载文件系统失败\r\n");
  1436.         }
  1437.         else
  1438.         {
  1439.                 printf("卸载文件系统成功\r\n");
  1440.         }
  1441.    
  1442.     result = funinit(_path);
  1443.         if(result != NULL)
  1444.         {
  1445.                 printf("复位文件系统失败 (%s)\r\n", ReVal_Table[result]);
  1446.         }
  1447.         else
  1448.         {
  1449.                 printf("复位文件系统成功 (%s)\r\n", ReVal_Table[result]);
  1450.         }

  1451.         printf("------------------------------------------------------------------\r\n");
  1452. }

  1453. /***************************** 安富莱电子 www.armfly.com (END OF FILE) *********************************/
复制代码



回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2021-2-18 15:47:30 | 显示全部楼层
有测试过读写速度吗?
回复

使用道具 举报

0

主题

6

回帖

6

积分

新手上路

积分
6
发表于 2021-2-18 15:48:10 | 显示全部楼层
本帖最后由 xjmlfm 于 2021-2-18 15:55 编辑

有测试过读写速度吗?
编辑:抱歉,没看到有审核,造成了重复发贴。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-2-18 16:37:35 | 显示全部楼层
xjmlfm 发表于 2021-2-18 15:48
有测试过读写速度吗?
编辑:抱歉,没看到有审核,造成了重复发贴。

都测了。

1、USB2.0全速理论值是1.5MB/S,这里实际外挂测试是800KB左右,这种属于正常测试速度。
2、下面NAND的测试。http://www.armbbs.cn/forum.php?mod=viewthread&tid=94277
写速度2-3MB/S,读速度4-6MB/S,可以修改FMC参数,加大NAND缓冲和设置MDK优化提升速度


3、下面是SD Class10测试,10-15MB/S

http://www.armbbs.cn/forum.php?mod=viewthread&tid=104012



回复

使用道具 举报

23

主题

1406

回帖

1475

积分

至尊会员

积分
1475
发表于 2021-2-19 15:44:20 | 显示全部楼层
又可以白嫖了
代码不规范,亲人两行泪!
回复

使用道具 举报

0

主题

17

回帖

17

积分

新手上路

积分
17
发表于 2021-2-21 20:59:35 | 显示全部楼层
老大这个搞定了吧,能否先放出来给我们玩玩
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-2-21 22:52:41 | 显示全部楼层
bradley 发表于 2021-2-21 20:59
老大这个搞定了吧,能否先放出来给我们玩玩

可以,代码还没有整合到RTX5模板中,等下周整合了再发布。
回复

使用道具 举报

1

主题

22

回帖

25

积分

新手上路

积分
25
发表于 2021-3-9 10:53:01 | 显示全部楼层
eric2013 发表于 2021-2-18 16:37
都测了。

1、USB2.0全速理论值是1.5MB/S,这里实际外挂测试是800KB左右,这种属于正常测试速度。

您好,手邊用V7進行開發,
由於將應用於嚴苛的工業環境,選用NAND (非SDHC卡) 實測2.n MM/S,太過臨界
,若想要提升至4MB/S 有何建議嗎?
更換高效NAND?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-3-9 11:35:08 | 显示全部楼层
James2jian 发表于 2021-3-9 10:53
您好,手邊用V7進行開發,
由於將應用於嚴苛的工業環境,選用NAND (非SDHC卡) 實測2.n MM/S,太過臨界
...

底层有个for循环的写入,你可以考虑改成DMA
回复

使用道具 举报

1

主题

22

回帖

25

积分

新手上路

积分
25
发表于 2021-3-9 15:07:12 | 显示全部楼层
eric2013 发表于 2021-3-9 11:35
底层有个for循环的写入,你可以考虑改成DMA

Eric 您好,兩點請教:
1.範例程式中的如下部分 調整成 HAL_MDMA_DeInit(&hmdma);   是嗎?
        for (i = 0; i < sizeof(g_TestBuf); i++)
        {
                g_TestBuf = (i / 512) + '0';
        }

2.手邊進行把NAND FLASH (AC5) 改成AC6  有發生3 Warning:
請教需要排除嗎? 還是可忽略?
../../Libraries/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c(785): warning: '__packed__' attribute ignored when parsing type [-Wignored-attributes]
      USBx_DFIFO(ch_ep_num) = *((__packed uint32_t *)src);
                                 ^~~~~~~~
../../Libraries/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_def.h(133): note: expanded from macro '__packed'
    #define __packed __attribute__((__packed__))
                                    ^~~~~~~~~~
../../Libraries/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c(812): warning: '__packed__' attribute ignored when parsing type [-Wignored-attributes]
    *(__packed uint32_t *)dest = USBx_DFIFO(0);
      ^~~~~~~~
../../Libraries/STM32H7xx_HAL_Driver/Inc/stm32h7xx_hal_def.h(133): note: expanded from macro '__packed'
    #define __packed __attribute__((__packed__))
以上請教,謝謝。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-3-9 15:24:08 | 显示全部楼层
James2jian 发表于 2021-3-9 15:07
Eric 您好,兩點請教:
1.範例程式中的如下部分 調整成 HAL_MDMA_DeInit(&hmdma);   是嗎?
        for (i = 0; ...

不是这个,是RL-FlashFS的底层函数。

需要AC6,此贴

http://www.armbbs.cn/forum.php?mod=viewthread&tid=104012
回复

使用道具 举报

5

主题

166

回帖

181

积分

初级会员

积分
181
发表于 2021-3-9 16:56:04 | 显示全部楼层
硬汉哥,可以通过网络ftp的形式访问这个存储吗
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-3-9 17:18:57 | 显示全部楼层
yuanzhongda 发表于 2021-3-9 16:56
硬汉哥,可以通过网络ftp的形式访问这个存储吗

已经发布了FTP支持

基于STM32H7的RTX5+RL-USB+RL-FlashFS+RL-TCPnet+emWin6.x综合模板发布,含MDK AC5和AC6,升级至V1.1(2021-03-01)
http://www.armbbs.cn/forum.php?m ... 4012&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1

主题

22

回帖

25

积分

新手上路

积分
25
发表于 2021-3-10 16:15:59 | 显示全部楼层
eric2013 发表于 2021-3-9 11:35
底层有个for循环的写入,你可以考虑改成DMA

硬漢哥, 感謝提供方向,但如何設定,該NAND FLASH 的DMA 功能,不太明白的,請教有該設定參考碼嗎?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-3-10 17:54:57 | 显示全部楼层
James2jian 发表于 2021-3-10 16:15
硬漢哥, 感謝提供方向,但如何設定,該NAND FLASH 的DMA 功能,不太明白的,請教有該設定參考碼嗎?

使用内存到内存方式,看此教程的第62章

【安富莱】STM32H7用户手册发布,重在BSP驱动包设计方法,HAL库的框架学习,授人以渔,更新至89章(2021-01-18)
http://www.armbbs.cn/forum.php?m ... 6980&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1

主题

22

回帖

25

积分

新手上路

积分
25
发表于 2021-3-10 18:28:37 | 显示全部楼层
eric2013 发表于 2021-3-10 17:54
使用内存到内存方式,看此教程的第62章

【安富莱】STM32H7用户手册发布,重在BSP驱动包设计方法,HAL ...

好的,著手測調研究,謝謝。
回复

使用道具 举报

1

主题

22

回帖

25

积分

新手上路

积分
25
发表于 2021-3-11 12:10:48 | 显示全部楼层
硬漢哥,請教是否有該RTX5 全家桶的 Clock Configuration 的(倍/除)頻樹狀圖可分享嗎?
或是 CubeMx 的nnn.ioc 檔案可參考?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-3-11 15:58:38 | 显示全部楼层
James2jian 发表于 2021-3-11 12:10
硬漢哥,請教是否有該RTX5 全家桶的 Clock Configuration 的(倍/除)頻樹狀圖可分享嗎?
或是 CubeMx 的nnn. ...

我们没有做这个。
回复

使用道具 举报

2

主题

38

回帖

44

积分

新手上路

积分
44
发表于 2021-4-14 17:54:10 | 显示全部楼层
硬汉哥 我最近在测试sd卡模拟u盘的实验,现在情况是:当我调用1挂载和2打开文件这两个函数之后,我的模拟u盘就可以正常在pc上显示出来;但是当我没调用这俩函数的时候,就会提示我进行初始化,但是初始化会失败;参照的你的flash/sd/nand模拟u盘的那个工程。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107020
QQ
 楼主| 发表于 2021-4-15 08:37:21 | 显示全部楼层
wangertan 发表于 2021-4-14 17:54
硬汉哥 我最近在测试sd卡模拟u盘的实验,现在情况是:当我调用1挂载和2打开文件这两个函数之后,我的模拟u ...

建议直接在我发的RTX5综合模板上修改。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-14 10:17 , Processed in 0.400717 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表