当前位置:   article > 正文

STM32CUBEMX FATFS FREERTOS 读写U盘和SPI-Flash注意事项

STM32CUBEMX FATFS FREERTOS 读写U盘和SPI-Flash注意事项

任务目标:

        开发环境为STM32F407VET6 和STM32F105RCT6两个DEMO board,USB Host 在U盘实现FATFS,  SPI Flash上FATFS,当插入U盘后,将SPI Flash 上的文件拷贝至U盘。

        这个要求不为过吧,翻烂了CSDN,都找不到一篇详细的教程,大家都是重复的说来说去,却在关键的点上,都闭口不言。让我想起我读高中时期,有一个数学老师,一旦遇到简单的问题就说的特别详细,一旦有难度,就说交给大家了,让大家自行想办法解决问题。

        经过一段时间的尝试,请大家跟着我的脚步一起完成它。如果你还有问题,你可以在我的CSDN上留言,我会及时的回复,我上CSDN的频率一天为2-4次。

详细步骤:

1.STM32CUBEMX 新建工程:

1.1.仿真口,时钟,FreeRTOS的timeBase

        大家都会,不废话,要的是干货。

1.2.SPI接口,WQ25的驱动程序

        大家都会,不废话,要的是干货。

1.3.USB OTG接口

        USB-OTG-FS  选择host only,FS是full speed 的意思,HS需要额外的时钟电路,我没有尝试过。

        注意选择步骤3,如果这个值默认是128 ,被卡在这儿的概率就很高了,建议用512个words,即2K字节。

1.4.FATFS配置,这个非常关键,ST不建议在SPI Flash上使用Fatfs,原因是没有擦写均衡,如果非常频繁的读写,建议用littleFs替代,LittleFs移植较容易。

        步骤1和2没问题。

        步骤3大家也都没有问题。

        步骤4:千万注意,volumes必须选择2个以上,要实现2个文件系统在两个外设上。MAX Sector Size 和Min Sector Size 分别是4096和512。Flash是4096 ,U盘和Sd卡是512 。

        步骤5:本文最大的干货,必须关闭重入功能,否则,你会卡死在一个信号量的释放上,ST的FAE也不打算解决这个问题。在操作系统的环境下,如果MAX_Secotor Size !=MIN Sector Size,就会卡在一个信号量的释放上。

       SPI Flash的MAX sector size 和MIN sector size必须配置为4096才能正常使用f_mout f_open函数,而U盘却的MAX sector size 和MIN sector size必须配置为512才能正常使用f_mout f_open函数。

        ST的Fae说未来逐渐摆脱FreeRTOS,会切换到Thread-X。

1.5操作系统配置和堆栈设置

堆栈调大一点

 1.6总结

        以上步骤可以确保你一路顺利了,接下来,我会附上我的部分代码。

2.关键程序片段

2.1 f_open函数的说明,它太关键了。

        很多人抄来抄去,从来没有人说明这个函数的具体内容。

  1. FRESULT f_open (
  2. FIL* fp, /* [OUT] Pointer to the file object structure */
  3. const TCHAR* path, /* [IN] File name */
  4. BYTE mode /* [IN] Mode flags */
  5. );

        第一个和第3个参数大家都很清楚,第二个参数很少有人详细的说清楚,都是抄来抄去的重复内容。

STM32CubeMX学习笔记(25)——FatFs文件系统使用(操作SPI Flash)_fa_open_always_Leung_ManWah的博客-CSDN博客

这篇文章,很多人都在看,但是呢,对特别关键的f_open函数并没有说的很清楚,一旦遇到我们有2个逻辑驱动区的时候,就傻眼了,你发现永远也写不到第二个里面。

上图的表里说的很清楚,必须指定逻辑分区。所以正确的f_open 函数应该这样写:

f_open (&fs,"0:/test.txt",FA_READ);

0:/是非常关键的信息,它指的是逻辑分区,当只有一个逻辑分区的时候,是可以省略,但是当有2个以上的时候,就绝对不能省略。

2.2cubemx生成的函数MX_FATFS_Init

  1. void MX_FATFS_Init(void)
  2. {
  3.   /*## FatFS: Link the USBH driver ###########################*/
  4.   retUSBH = FATFS_LinkDriver(&USBH_Driver, USBHPath);
  5.   /*## FatFS: Link the USER driver ###########################*/
  6.   retUSER = FATFS_LinkDriver(&USER_Driver, USERPath);
  7.   /* USER CODE BEGIN Init */
  8.   /* additional user code for init */
  9.   /* USER CODE END Init */
  10. }

这两句话意义上挂载两个逻辑分区,逻辑分区分别是0:/和1:/

先执行的就是逻辑分区0 ,后执行的就是逻辑分区1 。

所以要想写逻辑分区0的文件,必须用f_open(&fs,0:/test.txt,FA_WRITE);

所以要想写逻辑分区1的文件,必须用f_open(&fs,1:/test.txt,FA_WRITE);

2.3.fatfs.c文件

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file fatfs.c
  5. * @brief Code for fatfs applications
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2023 STMicroelectronics.
  10. * All rights reserved.
  11. *
  12. * This software is licensed under terms that can be found in the LICENSE file
  13. * in the root directory of this software component.
  14. * If no LICENSE file comes with this software, it is provided AS-IS.
  15. *
  16. ******************************************************************************
  17. */
  18. /* USER CODE END Header */
  19. #include "fatfs.h"
  20. uint8_t retUSBH; /* Return value for USBH */
  21. char USBHPath[4]; /* USBH logical drive path */
  22. FATFS USBHFatFS; /* File system object for USBH logical drive */
  23. FIL USBHFile; /* File object for USBH */
  24. uint8_t retUSER; /* Return value for USER */
  25. char USERPath[4]; /* USER logical drive path */
  26. FATFS USERFatFS; /* File system object for USER logical drive */
  27. FIL USERFile; /* File object for USER */
  28. /* USER CODE BEGIN Variables */
  29. #include "userDebugCom.h"
  30. extern osMutexId falshMutexHandle;
  31. extern struct systemTime_t sysTime;
  32. static UINT fnum;
  33. static BYTE ReadBuffer[20] = {0}; /* 读缓冲区 */
  34. static BYTE WriteBuffer_Title[] = "This Is File Test\r\n"; /* 写缓冲区*/
  35. static uint8_t flashFlag = 0;
  36. static uint8_t fileSPIWriteFlag = 0;
  37. /* USER CODE END Variables */
  38. void MX_FATFS_Init(void)
  39. {
  40. /*## FatFS: Link the USBH driver ###########################*/
  41. retUSBH = FATFS_LinkDriver(&USBH_Driver, USBHPath);
  42. /*## FatFS: Link the USER driver ###########################*/
  43. retUSER = FATFS_LinkDriver(&USER_Driver, USERPath);
  44. /* USER CODE BEGIN Init */
  45. /* additional user code for init */
  46. /* USER CODE END Init */
  47. }
  48. /**
  49. * @brief Gets Time from RTC
  50. * @param None
  51. * @retval Time in DWORD
  52. */
  53. DWORD get_fattime(void)
  54. {
  55. /* USER CODE BEGIN get_fattime */
  56. #if 1
  57. return ((sysTime.year - 1980) << 25) /* Year = 2010 */
  58. | (sysTime.month << 21) /* Month = 11 */
  59. | (sysTime.day << 16) /* Day = 2 */
  60. | (sysTime.hour << 11) /* Hour = 15 */
  61. | (sysTime.minute << 5) /* Min = 0 */
  62. | (sysTime.second >> 1) /* Sec = 0 */
  63. ;
  64. #endif
  65. return 0;
  66. /* USER CODE END get_fattime */
  67. }
  68. /* USER CODE BEGIN Application */
  69. /**
  70. * @brief 测试fatfs在SPIFlash是否正常工作
  71. *
  72. */
  73. void InitFatFs_SPI_FLASH(void)
  74. {
  75. osMutexWait(falshMutexHandle,osWaitForever);
  76. retUSER = f_mount(&USERFatFS, USERPath, 1);
  77. if (retUSER != FR_OK)
  78. {
  79. Debug_Printf("SPI Flash is not formatted\r\n");
  80. retUSER = f_mkfs(USERPath, 1, 4096); // flash 要格式化1次,不然文件系统记录的不正确
  81. // 千万注意,f_mkfs函数耗时极长,可能到10分钟左右,和SD卡的容量相关?
  82. if (retUSER == FR_OK)
  83. {
  84. Debug_Printf("The FLASH formats the file system successfully\r\n");
  85. retUSER = f_mount(NULL, (TCHAR const *)USERPath, 1);
  86. retUSER = f_mount(&USERFatFS, (TCHAR const *)USERPath, 1);
  87. }
  88. else
  89. {
  90. Debug_Printf("Formatting failure\r\n");
  91. }
  92. }
  93. if (retUSER == FR_OK)
  94. {
  95. Debug_Printf("Fmout OK!\r\n");
  96. uint32_t total;
  97. uint32_t free;
  98. if (exf_getfree((uint8_t *)USERPath, &total, &free) == FR_OK)
  99. {
  100. Debug_Printf("Total=%d KB,Free=%d KB\r\n", total, free);
  101. }
  102. else
  103. {
  104. Debug_Printf("Disk Space Error\r\n");
  105. }
  106. flashFlag = 1;
  107. }
  108. osMutexRelease(falshMutexHandle);
  109. }
  110. void spiFlashSoundPromt(void)
  111. {
  112. if (memcmp(ReadBuffer, WriteBuffer_Title, sizeof(WriteBuffer_Title)) == 0)
  113. {
  114. for (int i = 0; i < 3; i++)
  115. {
  116. HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET);
  117. osDelay(50);
  118. HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
  119. osDelay(50);
  120. }
  121. }
  122. }
  123. /**
  124. * @brief 读写测试文件系统
  125. *
  126. */
  127. void FileReadWriteTest(void)
  128. {
  129. if (flashFlag > 0)
  130. {
  131. osMutexWait(falshMutexHandle,osWaitForever);
  132. Debug_Printf("File Write Test\n");
  133. #if 1
  134. retUSER = f_open(&USERFile, "1:/test.txt", FA_OPEN_ALWAYS | FA_WRITE);
  135. fileSPIWriteFlag = 1;
  136. // f_res = f_lseek(&SDFile, f_size(&SDFile));
  137. if (retUSER == FR_OK)
  138. {
  139. Debug_Printf("Write To file\n");
  140. retUSER = f_write(&USERFile, WriteBuffer_Title, sizeof(WriteBuffer_Title), &fnum);
  141. if (retUSER == FR_OK)
  142. {
  143. Debug_Printf("Write Len=%d\n", fnum);
  144. Debug_Printf("Write Data:\n%s\n", WriteBuffer_Title);
  145. }
  146. else
  147. {
  148. Debug_Printf("Write Fail,Error Code(%d)\n", retUSER);
  149. }
  150. f_close(&USERFile);
  151. fileSPIWriteFlag = 0;
  152. }
  153. else
  154. {
  155. Debug_Printf("打开/创建文件失败。\n");
  156. }
  157. /*------------------- 文件系统测试:读测试 ------------------------------------*/
  158. Debug_Printf("File Read Test\n");
  159. // HAL_IWDG_Refresh(&hiwdg);
  160. retUSER = f_open(&USERFile, "1:/test.txt", FA_OPEN_EXISTING | FA_READ);
  161. fileSPIWriteFlag = 1;
  162. // f_res = f_lseek(&SDFile, 2);
  163. if (retUSER == FR_OK)
  164. {
  165. Debug_Printf("File Opend\r\n");
  166. retUSER = f_read(&USERFile, ReadBuffer, sizeof(ReadBuffer), &fnum);
  167. if (retUSER == FR_OK)
  168. {
  169. Debug_Printf("Read Len=%d\n", fnum);
  170. Debug_Printf("Read Data:\n%s \n", ReadBuffer);
  171. }
  172. else
  173. {
  174. Debug_Printf("Read Fail,Error Code(%d)\n", retUSER);
  175. }
  176. }
  177. else
  178. {
  179. Debug_Printf("File Open Failed\n");
  180. }
  181. f_close(&USERFile);
  182. fileSPIWriteFlag = 0;
  183. #endif
  184. osMutexRelease(falshMutexHandle);
  185. }
  186. }
  187. /**
  188. * @brief 得到磁盘剩余容量
  189. *
  190. * @param drv 磁盘编号("0:"/"1:")
  191. * @param total total capacity (KB)
  192. * @param free free capacity (KB)
  193. * @return uint8_t get status
  194. */
  195. uint8_t exf_getfree(uint8_t *drv, uint32_t *total, uint32_t *free)
  196. {
  197. FATFS *fs1;
  198. uint8_t res;
  199. DWORD fre_clust = 0;
  200. uint32_t fre_sect = 0, tot_sect = 0;
  201. // 得到磁盘信息及空闲簇数量
  202. res = f_getfree((const TCHAR *)drv, &fre_clust, &fs1);
  203. if (res == 0)
  204. {
  205. tot_sect = (fs1->n_fatent - 2) * fs1->csize; // 得到总扇区数
  206. fre_sect = fre_clust * fs1->csize; // 得到空闲扇区????
  207. #if _MAX_SS != 512 // 扇区大小不是512字节,则转换为512字节
  208. tot_sect *= fs1->ssize / 512;
  209. fre_sect *= fs1->ssize / 512;
  210. #endif
  211. *total = tot_sect >> 1; // 单位为KB
  212. *free = fre_sect >> 1; // 单位为KB
  213. }
  214. return res;
  215. }
  216. /* USER CODE END Application */

2.4 user_diskio.c

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file user_diskio.c
  5. * @brief This file includes a diskio driver skeleton to be completed by the user.
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2023 STMicroelectronics.
  10. * All rights reserved.
  11. *
  12. * This software is licensed under terms that can be found in the LICENSE file
  13. * in the root directory of this software component.
  14. * If no LICENSE file comes with this software, it is provided AS-IS.
  15. *
  16. ******************************************************************************
  17. */
  18. /* USER CODE END Header */
  19. #ifdef USE_OBSOLETE_USER_CODE_SECTION_0
  20. /*
  21. * Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
  22. * To be suppressed in the future.
  23. * Kept to ensure backward compatibility with previous CubeMx versions when
  24. * migrating projects.
  25. * User code previously added there should be copied in the new user sections before
  26. * the section contents can be deleted.
  27. */
  28. /* USER CODE BEGIN 0 */
  29. /* USER CODE END 0 */
  30. #endif
  31. /* USER CODE BEGIN DECL */
  32. /* Includes ------------------------------------------------------------------*/
  33. #include <string.h>
  34. #include "ff_gen_drv.h"
  35. #include "w25qxx.h"
  36. /* Private typedef -----------------------------------------------------------*/
  37. /* Private define ------------------------------------------------------------*/
  38. /* Private variables ---------------------------------------------------------*/
  39. /* Disk status */
  40. static volatile DSTATUS Stat = STA_NOINIT;
  41. /* USER CODE END DECL */
  42. /* Private function prototypes -----------------------------------------------*/
  43. DSTATUS USER_initialize (BYTE pdrv);
  44. DSTATUS USER_status (BYTE pdrv);
  45. DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
  46. #if _USE_WRITE == 1
  47. DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
  48. #endif /* _USE_WRITE == 1 */
  49. #if _USE_IOCTL == 1
  50. DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
  51. #endif /* _USE_IOCTL == 1 */
  52. Diskio_drvTypeDef USER_Driver =
  53. {
  54. USER_initialize,
  55. USER_status,
  56. USER_read,
  57. #if _USE_WRITE
  58. USER_write,
  59. #endif /* _USE_WRITE == 1 */
  60. #if _USE_IOCTL == 1
  61. USER_ioctl,
  62. #endif /* _USE_IOCTL == 1 */
  63. };
  64. /* Private functions ---------------------------------------------------------*/
  65. /**
  66. * @brief Initializes a Drive
  67. * @param pdrv: Physical drive number (0..)
  68. * @retval DSTATUS: Operation status
  69. */
  70. DSTATUS USER_initialize (
  71. BYTE pdrv /* Physical drive nmuber to identify the drive */
  72. )
  73. {
  74. /* USER CODE BEGIN INIT */
  75. Stat = STA_NOINIT;
  76. if(W25QXX_Init() == 0)
  77. {
  78. Stat &= ~STA_NOINIT;
  79. }
  80. return Stat;
  81. /* USER CODE END INIT */
  82. }
  83. /**
  84. * @brief Gets Disk Status
  85. * @param pdrv: Physical drive number (0..)
  86. * @retval DSTATUS: Operation status
  87. */
  88. DSTATUS USER_status (
  89. BYTE pdrv /* Physical drive number to identify the drive */
  90. )
  91. {
  92. /* USER CODE BEGIN STATUS */
  93. Stat = STA_NOINIT;
  94. if(W25QXX_Get_State() == W25Q_OK)
  95. {
  96. Stat &= ~STA_NOINIT;
  97. }
  98. return Stat;
  99. /* USER CODE END STATUS */
  100. }
  101. /**
  102. * @brief Reads Sector(s)
  103. * @param pdrv: Physical drive number (0..)
  104. * @param *buff: Data buffer to store read data
  105. * @param sector: Sector address (LBA)
  106. * @param count: Number of sectors to read (1..128)
  107. * @retval DRESULT: Operation result
  108. */
  109. DRESULT USER_read (
  110. BYTE pdrv, /* Physical drive nmuber to identify the drive */
  111. BYTE *buff, /* Data buffer to store read data */
  112. DWORD sector, /* Sector address in LBA */
  113. UINT count /* Number of sectors to read */
  114. )
  115. {
  116. /* USER CODE BEGIN READ */
  117. sector+=1;
  118. W25QXX_Read(buff, sector <<12, count<<12);
  119. return RES_OK;
  120. /* USER CODE END READ */
  121. }
  122. /**
  123. * @brief Writes Sector(s)
  124. * @param pdrv: Physical drive number (0..)
  125. * @param *buff: Data to be written
  126. * @param sector: Sector address (LBA)
  127. * @param count: Number of sectors to write (1..128)
  128. * @retval DRESULT: Operation result
  129. */
  130. #if _USE_WRITE == 1
  131. DRESULT USER_write (
  132. BYTE pdrv, /* Physical drive nmuber to identify the drive */
  133. const BYTE *buff, /* Data to be written */
  134. DWORD sector, /* Sector address in LBA */
  135. UINT count /* Number of sectors to write */
  136. )
  137. {
  138. /* USER CODE BEGIN WRITE */
  139. /* USER CODE HERE */
  140. sector+=1;
  141. W25QXX_Write((void *)(buff),sector<<12,count<<12 );
  142. return RES_OK;
  143. /* USER CODE END WRITE */
  144. }
  145. #endif /* _USE_WRITE == 1 */
  146. /**
  147. * @brief I/O control operation
  148. * @param pdrv: Physical drive number (0..)
  149. * @param cmd: Control code
  150. * @param *buff: Buffer to send/receive control data
  151. * @retval DRESULT: Operation result
  152. */
  153. #if _USE_IOCTL == 1
  154. DRESULT USER_ioctl (
  155. BYTE pdrv, /* Physical drive nmuber (0..) */
  156. BYTE cmd, /* Control code */
  157. void *buff /* Buffer to send/receive control data */
  158. )
  159. {
  160. /* USER CODE BEGIN IOCTL */
  161. DRESULT res = RES_OK;
  162. switch(cmd){
  163. case GET_SECTOR_COUNT:
  164. *(DWORD *)buff = 4095;
  165. break;
  166. case GET_SECTOR_SIZE:
  167. *(DWORD *)buff = 4096;
  168. break;
  169. case GET_BLOCK_SIZE:
  170. *(DWORD *)buff = 1;
  171. break;
  172. }
  173. return res;
  174. /* USER CODE END IOCTL */
  175. }
  176. #endif /* _USE_IOCTL == 1 */

2.4 usb_host.c

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * @file : usb_host.c
  5. * @version : v2.0_Cube
  6. * @brief : This file implements the USB Host
  7. ******************************************************************************
  8. * @attention
  9. *
  10. * Copyright (c) 2023 STMicroelectronics.
  11. * All rights reserved.
  12. *
  13. * This software is licensed under terms that can be found in the LICENSE file
  14. * in the root directory of this software component.
  15. * If no LICENSE file comes with this software, it is provided AS-IS.
  16. *
  17. ******************************************************************************
  18. */
  19. /* USER CODE END Header */
  20. /* Includes ------------------------------------------------------------------*/
  21. #include "usb_host.h"
  22. #include "usbh_core.h"
  23. #include "usbh_msc.h"
  24. /* USER CODE BEGIN Includes */
  25. #include "usart.h"
  26. #include "usb_host.h"
  27. #include "fatfs.h"
  28. #include "userDebugCom.h"
  29. /* USER CODE END Includes */
  30. /* USER CODE BEGIN PV */
  31. /* Private variables ---------------------------------------------------------*/
  32. static uint8_t status = 0;
  33. static char FileWriteBuff[] = "Hello,This is U-Disk\r\n";
  34. static char FileReadBuff[23] = "";
  35. static UINT bw;
  36. static uint8_t fileWriteFlag = 0;
  37. /* USER CODE END PV */
  38. /* USER CODE BEGIN PFP */
  39. /* Private function prototypes -----------------------------------------------*/
  40. /* USER CODE END PFP */
  41. /* USB Host core handle declaration */
  42. USBH_HandleTypeDef hUsbHostFS;
  43. ApplicationTypeDef Appli_state = APPLICATION_IDLE;
  44. /*
  45. * -- Insert your variables declaration here --
  46. */
  47. /* USER CODE BEGIN 0 */
  48. /* USER CODE END 0 */
  49. /*
  50. * user callback declaration
  51. */
  52. static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id);
  53. /*
  54. * -- Insert your external function declaration here --
  55. */
  56. /* USER CODE BEGIN 1 */
  57. /**
  58. * @brief USB 文件测试
  59. *
  60. */
  61. void UdiskBeginTest(void)
  62. {
  63. if (Appli_state == APPLICATION_READY) // U盘已经加轿
  64. {
  65. if (status == 0)
  66. {
  67. status = 1;
  68. fileWriteFlag = 0;
  69. memset(FileReadBuff, 0x00, sizeof(FileReadBuff));
  70. retUSBH = f_mount(NULL, (TCHAR const *)USBHPath, 1);
  71. retUSBH = f_mount(&USBHFatFS, (TCHAR const *)USBHPath, 1);
  72. if (retUSBH == FR_OK)
  73. {
  74. osDelay(100);
  75. f_close(&USBHFile);
  76. if (retUSBH == FR_OK)
  77. {
  78. Debug_Printf("Closed OK\r\n");
  79. }
  80. Debug_Printf("Udisk fmount OK\r\n");
  81. #if 1
  82. uint32_t total;
  83. uint32_t free;
  84. if (exf_getfree((uint8_t *)USBHPath, &total, &free) == FR_OK)
  85. {
  86. Debug_Printf("Total=%d MB,Free=%d MB\r\n", total / 1024, free / 1024);
  87. }
  88. else
  89. {
  90. Debug_Printf("Udisk fmount error\r\n");
  91. }
  92. #endif
  93. //USBHFile.fs=&USBHFatFS;
  94. retUSBH = f_open(&USBHFile, (const char *)"0:/testUdisk.txt", FA_OPEN_ALWAYS | FA_WRITE);
  95. if (retUSBH == FR_OK)
  96. {
  97. Debug_Printf("Opened OK\r\n");
  98. retUSBH = f_write(&USBHFile, FileWriteBuff, sizeof(FileWriteBuff), &bw);
  99. if (retUSBH == FR_OK)
  100. {
  101. Debug_Printf("Writed Udisk Test File OK\r\n");
  102. retUSBH = f_close(&USBHFile);
  103. }
  104. }
  105. retUSBH = f_open(&USBHFile, "0:/testUdisk.txt", FA_OPEN_EXISTING | FA_READ);
  106. // f_res = f_lseek(&SDFile, 2);
  107. if (retUSBH == FR_OK)
  108. {
  109. Debug_Printf("Udisk File Opend\r\n");
  110. retUSBH = f_read(&USBHFile, FileReadBuff, sizeof(FileReadBuff), &bw);
  111. if (retUSBH == FR_OK)
  112. {
  113. Debug_Printf("Udisk Read Len=%d\n", bw);
  114. Debug_Printf("Udisk Read Data:\n%s \n", FileReadBuff);
  115. }
  116. else
  117. {
  118. Debug_Printf("Udisk Read Fail,Error Code(%d)\n", retUSER);
  119. }
  120. }
  121. else
  122. {
  123. Debug_Printf("Udisk File Open Failed\n");
  124. }
  125. f_close(&USBHFile);
  126. }
  127. udiskSoundPromt();
  128. }
  129. }
  130. }
  131. /**
  132. * @brief 测试U盘提示音
  133. *
  134. */
  135. void udiskSoundPromt(void)
  136. {
  137. if (memcmp(FileReadBuff, FileWriteBuff, sizeof(FileWriteBuff)) == 0)
  138. {
  139. for (int i = 0; i < 2; i++)
  140. {
  141. HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_SET);
  142. osDelay(50);
  143. HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, GPIO_PIN_RESET);
  144. osDelay(50);
  145. }
  146. fileWriteFlag = 1;
  147. //sendQueenToCopyFiles();
  148. }
  149. }
  150. /* USER CODE END 1 */
  151. /**
  152. * Init USB host library, add supported class and start the library
  153. * @retval None
  154. */
  155. void MX_USB_HOST_Init(void)
  156. {
  157. /* USER CODE BEGIN USB_HOST_Init_PreTreatment */
  158. /* USER CODE END USB_HOST_Init_PreTreatment */
  159. /* Init host Library, add supported class and start the library. */
  160. if (USBH_Init(&hUsbHostFS, USBH_UserProcess, HOST_FS) != USBH_OK)
  161. {
  162. Error_Handler();
  163. }
  164. if (USBH_RegisterClass(&hUsbHostFS, USBH_MSC_CLASS) != USBH_OK)
  165. {
  166. Error_Handler();
  167. }
  168. if (USBH_Start(&hUsbHostFS) != USBH_OK)
  169. {
  170. Error_Handler();
  171. }
  172. /* USER CODE BEGIN USB_HOST_Init_PostTreatment */
  173. /* USER CODE END USB_HOST_Init_PostTreatment */
  174. }
  175. /*
  176. * user callback definition
  177. */
  178. static void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id)
  179. {
  180. /* USER CODE BEGIN CALL_BACK_1 */
  181. switch(id)
  182. {
  183. case HOST_USER_SELECT_CONFIGURATION:
  184. break;
  185. case HOST_USER_DISCONNECTION:
  186. Appli_state = APPLICATION_DISCONNECT;
  187. status=0;
  188. break;
  189. case HOST_USER_CLASS_ACTIVE:
  190. Appli_state = APPLICATION_READY;
  191. break;
  192. case HOST_USER_CONNECTION:
  193. Appli_state = APPLICATION_START;
  194. break;
  195. default:
  196. break;
  197. }
  198. /* USER CODE END CALL_BACK_1 */
  199. }
  200. /**
  201. * @}
  202. */
  203. /**
  204. * @}
  205. */

2.5 freeRTOS.c

  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4. * File Name : freertos.c
  5. * Description : Code for freertos applications
  6. ******************************************************************************
  7. * @attention
  8. *
  9. * Copyright (c) 2023 STMicroelectronics.
  10. * All rights reserved.
  11. *
  12. * This software is licensed under terms that can be found in the LICENSE file
  13. * in the root directory of this software component.
  14. * If no LICENSE file comes with this software, it is provided AS-IS.
  15. *
  16. ******************************************************************************
  17. */
  18. /* USER CODE END Header */
  19. /* Includes ------------------------------------------------------------------*/
  20. #include "FreeRTOS.h"
  21. #include "task.h"
  22. #include "main.h"
  23. #include "cmsis_os.h"
  24. /* Private includes ----------------------------------------------------------*/
  25. /* USER CODE BEGIN Includes */
  26. #include "usb_host.h"
  27. #include "fatfs.h"
  28. #include "iwdg.h"
  29. /* USER CODE END Includes */
  30. /* Private typedef -----------------------------------------------------------*/
  31. /* USER CODE BEGIN PTD */
  32. /* USER CODE END PTD */
  33. /* Private define ------------------------------------------------------------*/
  34. /* USER CODE BEGIN PD */
  35. /* USER CODE END PD */
  36. /* Private macro -------------------------------------------------------------*/
  37. /* USER CODE BEGIN PM */
  38. /* USER CODE END PM */
  39. /* Private variables ---------------------------------------------------------*/
  40. /* USER CODE BEGIN Variables */
  41. extern struct systemTime_t sysTime;
  42. /* USER CODE END Variables */
  43. osThreadId fileRecordHandle;
  44. osThreadId readRTCHandle;
  45. osThreadId lcdDisplayHandle;
  46. osThreadId keyTaskHandle;
  47. osTimerId softwareTimerHandle;
  48. osMutexId usart1PrintHandle;
  49. osMutexId SetingParameterHandle;
  50. osMutexId falshMutexHandle;
  51. osSemaphoreId TenSecTimeupHandle;
  52. /* Private function prototypes -----------------------------------------------*/
  53. /* USER CODE BEGIN FunctionPrototypes */
  54. /* USER CODE END FunctionPrototypes */
  55. void StartFileRecordTask(void const * argument);
  56. extern void StartReadRTCTask(void const * argument);
  57. extern void StartTasklcdDisplay(void const * argument);
  58. extern void StartkeyTask(void const * argument);
  59. extern void Callback01(void const * argument);
  60. extern void MX_USB_HOST_Init(void);
  61. void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
  62. /**
  63. * @brief FreeRTOS initialization
  64. * @param None
  65. * @retval None
  66. */
  67. void MX_FREERTOS_Init(void) {
  68. /* USER CODE BEGIN Init */
  69. /* USER CODE END Init */
  70. /* Create the mutex(es) */
  71. /* definition and creation of usart1Print */
  72. osMutexDef(usart1Print);
  73. usart1PrintHandle = osMutexCreate(osMutex(usart1Print));
  74. /* definition and creation of SetingParameter */
  75. osMutexDef(SetingParameter);
  76. SetingParameterHandle = osMutexCreate(osMutex(SetingParameter));
  77. /* definition and creation of falshMutex */
  78. osMutexDef(falshMutex);
  79. falshMutexHandle = osMutexCreate(osMutex(falshMutex));
  80. /* USER CODE BEGIN RTOS_MUTEX */
  81. /* add mutexes, ... */
  82. /* USER CODE END RTOS_MUTEX */
  83. /* Create the semaphores(s) */
  84. /* definition and creation of TenSecTimeup */
  85. osSemaphoreDef(TenSecTimeup);
  86. TenSecTimeupHandle = osSemaphoreCreate(osSemaphore(TenSecTimeup), 1);
  87. /* USER CODE BEGIN RTOS_SEMAPHORES */
  88. /* add semaphores, ... */
  89. /* USER CODE END RTOS_SEMAPHORES */
  90. /* Create the timer(s) */
  91. /* definition and creation of softwareTimer */
  92. osTimerDef(softwareTimer, Callback01);
  93. softwareTimerHandle = osTimerCreate(osTimer(softwareTimer), osTimerOnce, NULL);
  94. /* USER CODE BEGIN RTOS_TIMERS */
  95. /* start timers, add new ones, ... */
  96. /* USER CODE END RTOS_TIMERS */
  97. /* USER CODE BEGIN RTOS_QUEUES */
  98. /* add queues, ... */
  99. /* USER CODE END RTOS_QUEUES */
  100. /* Create the thread(s) */
  101. /* definition and creation of fileRecord */
  102. osThreadDef(fileRecord, StartFileRecordTask, osPriorityNormal, 0, 1536);
  103. fileRecordHandle = osThreadCreate(osThread(fileRecord), NULL);
  104. /* definition and creation of readRTC */
  105. osThreadDef(readRTC, StartReadRTCTask, osPriorityIdle, 0, 256);
  106. readRTCHandle = osThreadCreate(osThread(readRTC), NULL);
  107. /* definition and creation of lcdDisplay */
  108. osThreadDef(lcdDisplay, StartTasklcdDisplay, osPriorityLow, 0, 256);
  109. lcdDisplayHandle = osThreadCreate(osThread(lcdDisplay), NULL);
  110. /* definition and creation of keyTask */
  111. osThreadDef(keyTask, StartkeyTask, osPriorityLow, 0, 256);
  112. keyTaskHandle = osThreadCreate(osThread(keyTask), NULL);
  113. /* USER CODE BEGIN RTOS_THREADS */
  114. /* add threads, ... */
  115. /* USER CODE END RTOS_THREADS */
  116. }
  117. /* USER CODE BEGIN Header_StartFileRecordTask */
  118. /**
  119. * @brief Function implementing the fileRecord thread.
  120. * @param argument: Not used
  121. * @retval None
  122. */
  123. /* USER CODE END Header_StartFileRecordTask */
  124. void StartFileRecordTask(void const * argument)
  125. {
  126. /* init code for USB_HOST */
  127. /* USER CODE BEGIN StartFileRecordTask */
  128. osDelay(100);
  129. InitFatFs_SPI_FLASH();
  130. osDelay(100);
  131. FileReadWriteTest();
  132. spiFlashSoundPromt();
  133. osDelay(1000);
  134. MX_USB_HOST_Init();
  135. /* Infinite loop */
  136. for(;;)
  137. {
  138. osDelay(10);
  139. UdiskBeginTest();
  140. HAL_IWDG_Refresh(&hiwdg);
  141. }
  142. /* USER CODE END StartFileRecordTask */
  143. }
  144. /* Private application code --------------------------------------------------*/
  145. /* USER CODE BEGIN Application */
  146. /* USER CODE END Application */

2.6 user_Debug.c

  1. #include "userDebugCom.h"
  2. #include <stdarg.h>
  3. #include "fatfs.h"
  4. extern osMutexId usart1PrintHandle;
  5. #ifdef __cplusplus
  6. extern "C"
  7. {
  8. #endif
  9. #ifdef __GNUC__
  10. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  11. #else
  12. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  13. #endif
  14. PUTCHAR_PROTOTYPE
  15. {
  16. HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
  17. return ch;
  18. }
  19. #ifdef __cplusplus
  20. }
  21. #endif
  22. /**
  23. * @brief 重写printf函数,加上互斥锁
  24. *
  25. * @param format
  26. * @param ...
  27. */
  28. void Debug_Printf(char *format, ...)
  29. {
  30. char buf_str[128];
  31. va_list v_args;
  32. va_start(v_args, format);
  33. (void)vsnprintf((char *)&buf_str[0],
  34. (size_t)sizeof(buf_str),
  35. (char const *)format,
  36. v_args);
  37. va_end(v_args);
  38. /* 互斥信号量 */
  39. osMutexWait(usart1PrintHandle, osWaitForever);
  40. printf("%s", buf_str);
  41. osMutexRelease(usart1PrintHandle);
  42. }
  43. #define CPU_FREQUENCY_MHZ 72 // STM32时钟主频
  44. void delay_us(__IO uint32_t delay)
  45. {
  46. int last, curr, val;
  47. int temp;
  48. while (delay != 0)
  49. {
  50. temp = delay > 900 ? 900 : delay;
  51. last = SysTick->VAL;
  52. curr = last - CPU_FREQUENCY_MHZ * temp;
  53. if (curr >= 0)
  54. {
  55. do
  56. {
  57. val = SysTick->VAL;
  58. } while ((val < last) && (val >= curr));
  59. }
  60. else
  61. {
  62. curr += CPU_FREQUENCY_MHZ * 1000;
  63. do
  64. {
  65. val = SysTick->VAL;
  66. } while ((val <= last) || (val > curr));
  67. }
  68. delay -= temp;
  69. }
  70. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/464026
推荐阅读
相关标签
  

闽ICP备14008679号