[STM32H7] [STM32H7] [STM32H7] STM32H750B-DK TouchGFX 测评——视频播放

[复制链接]
 楼主| ROSHEN_007 发表于 2023-3-6 13:20 | 显示全部楼层 |阅读模式
<
本帖最后由 ROSHEN_007 于 2023-3-6 13:20 编辑

#申请原创#

一、搭建存储系统
视频播放一般需要SD卡进行视屏文件存储,但是开发板上没有SD卡,查看了板子的硬件资源,发现板子上有两块EMMC,所以想着用EMMC来作为存储设备,搭建USB+EMMC+FATFS存储读写系统;
1、USB驱动配置
直接使用CUBEMX进行配置,比较方便,需要注意的是,配置时钟的时候,千万别选自动生成USB时钟,自动生成会造成"系统紊乱",因为USB默认时钟是从PLL1上取得,要配置成48MHZ,会改PLL1的输出时钟,很多外设都用PLL1生成时钟,这里直接手动选择RC48即可;
7104863fc03272ddf8.png
786463fc031025f49.png
2217163fc038e738a2.png
2、EMMC驱动配置
查看STM32H750的手册,发现支持8bit DDR模式,但是实际调试的时候发现速率根本达不到200Mhz,这里简直是深坑,调试出错的时候我以为是EMMC不支持,后来查看EMMC的手册,是可以支持200M ddr模式的,应该还是ST的问题,IO翻转速度达不到200MHZ,时钟改成四分频到50MHZ就可以跑起来了;支持 1线、4线、8线MMC模式,根据需要选择即可,另外打开中断配置;
856763fc04c675a28.png
7327363fc08d281733.png
4303963fc0442768ba.png
1181463fc049499025.png
8818963fc04aa64d9e.png
3、USB  MSC驱动代码修改调试
改过SD开驱动的应该都比较熟悉,这里我们直接找到usbd_storage_if.c文件,改写下图中的这些函数,代码下面也贴出,改写的时候主要的是要把自己添加的代码写到“恰当的位置”,不然如果你修改CUBMUX的配置,你辛辛苦苦添加的代码就会消失不见了,我也是刚开始使用cubide,在这上面吃了点小亏;
8221263fc0674d3541.png
  1. /* USER CODE BEGIN Header */
  2. /**
  3.   ******************************************************************************
  4.   * [url=home.php?mod=space&uid=288409]@file[/url]           : usbd_storage_if.c
  5.   * [url=home.php?mod=space&uid=895143]@version[/url]        : v1.0_Cube
  6.   * [url=home.php?mod=space&uid=247401]@brief[/url]          : Memory management layer.
  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 "usbd_storage_if.h"
  22. /* USER CODE BEGIN INCLUDE */
  23. #include "FreeRTOS.h"
  24. #include "semphr.h"
  25. /* USER CODE END INCLUDE */

  26. /* Private typedef -----------------------------------------------------------*/
  27. /* Private define ------------------------------------------------------------*/
  28. /* Private macro -------------------------------------------------------------*/

  29. /* USER CODE BEGIN PV */
  30. /* Private variables ---------------------------------------------------------*/

  31. /* USER CODE END PV */

  32. /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
  33.   * [url=home.php?mod=space&uid=247401]@brief[/url] Usb device.
  34.   * @{
  35.   */

  36. /** @defgroup USBD_STORAGE
  37.   * [url=home.php?mod=space&uid=247401]@brief[/url] Usb mass storage device module
  38.   * @{
  39.   */

  40. /** @defgroup USBD_STORAGE_Private_TypesDefinitions
  41.   * [url=home.php?mod=space&uid=247401]@brief[/url] Private types.
  42.   * @{
  43.   */

  44. /* USER CODE BEGIN PRIVATE_TYPES */
  45. /* USER CODE END PRIVATE_TYPES */

  46. /**
  47.   * @}
  48.   */

  49. /** @defgroup USBD_STORAGE_Private_Defines
  50.   * [url=home.php?mod=space&uid=247401]@brief[/url] Private defines.
  51.   * @{
  52.   */

  53. #define STORAGE_LUN_NBR                  1
  54. #define STORAGE_BLK_NBR                  0x10000
  55. #define STORAGE_BLK_SIZ                  0x200

  56. /* USER CODE BEGIN PRIVATE_DEFINES */
  57. //#define EMMC_USE_DMA
  58. /* USER CODE END PRIVATE_DEFINES */

  59. /**
  60.   * @}
  61.   */

  62. /** @defgroup USBD_STORAGE_Private_Macros
  63.   * [url=home.php?mod=space&uid=247401]@brief[/url] Private macros.
  64.   * @{
  65.   */

  66. /* USER CODE BEGIN PRIVATE_MACRO */

  67. /* USER CODE END PRIVATE_MACRO */

  68. /**
  69.   * @}
  70.   */

  71. /** @defgroup USBD_STORAGE_Private_Variables
  72.   * [url=home.php?mod=space&uid=247401]@brief[/url] Private variables.
  73.   * @{
  74.   */

  75. /* USER CODE BEGIN INQUIRY_DATA_FS */
  76. /** USB Mass storage Standard Inquiry Data. */
  77. const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */

  78.   /* LUN 0 */
  79.   0x00,
  80.   0x80,
  81.   0x02,
  82.   0x02,
  83.   (STANDARD_INQUIRY_DATA_LEN - 5),
  84.   0x00,
  85.   0x00,
  86.   0x00,
  87.   'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
  88.   'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product      : 16 Bytes */
  89.   ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
  90.   '0', '.', '0' ,'1'                      /* Version      : 4 Bytes */
  91. };
  92. /* USER CODE END INQUIRY_DATA_FS */

  93. /* USER CODE BEGIN PRIVATE_VARIABLES */

  94. /* USER CODE END PRIVATE_VARIABLES */

  95. /**
  96.   * @}
  97.   */

  98. /** @defgroup USBD_STORAGE_Exported_Variables
  99.   * @brief Public variables.
  100.   * @{
  101.   */

  102. extern USBD_HandleTypeDef hUsbDeviceFS;

  103. /* USER CODE BEGIN EXPORTED_VARIABLES */
  104. volatile  uint8_t  write_flag = 0, read_flag = 0;
  105. extern MMC_HandleTypeDef hmmc1;
  106. extern SemaphoreHandle_t xSemaphoreEmmc;
  107. /* USER CODE END EXPORTED_VARIABLES */

  108. /**
  109.   * @}
  110.   */

  111. /** @defgroup USBD_STORAGE_Private_FunctionPrototypes
  112.   * @brief Private functions declaration.
  113.   * @{
  114.   */

  115. static int8_t STORAGE_Init_FS(uint8_t lun);
  116. static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
  117. static int8_t STORAGE_IsReady_FS(uint8_t lun);
  118. static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
  119. static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
  120. static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
  121. static int8_t STORAGE_GetMaxLun_FS(void);

  122. /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
  123. void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
  124. {
  125.         write_flag = 1;
  126. }
  127. void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
  128. {
  129.         read_flag = 1;
  130. }
  131. /* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */

  132. /**
  133.   * @}
  134.   */

  135. USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
  136. {
  137.   STORAGE_Init_FS,
  138.   STORAGE_GetCapacity_FS,
  139.   STORAGE_IsReady_FS,
  140.   STORAGE_IsWriteProtected_FS,
  141.   STORAGE_Read_FS,
  142.   STORAGE_Write_FS,
  143.   STORAGE_GetMaxLun_FS,
  144.   (int8_t *)STORAGE_Inquirydata_FS
  145. };

  146. /* Private functions ---------------------------------------------------------*/
  147. /**
  148.   * @brief  Initializes the storage unit (medium) over USB FS IP
  149.   * @param  lun: Logical unit number.
  150.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  151.   */
  152. int8_t STORAGE_Init_FS(uint8_t lun)
  153. {
  154.   /* USER CODE BEGIN 2 */
  155. UNUSED(lun);
  156. // hmmc1.Instance = SDMMC1;
  157. // hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
  158. // hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  159. // hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;
  160. // hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  161. // hmmc1.Init.ClockDiv = 0;
  162. // if (HAL_MMC_Init(&hmmc1) != HAL_OK)
  163. // {
  164. //   return USBD_FAIL;
  165. // }
  166. // HAL_MMC_CardStateTypeDef State;
  167. // HAL_MMC_CardCIDTypeDef EMMC_CardCID;
  168. // State = HAL_MMC_GetCardState(&hmmc1);
  169. // if(State == HAL_MMC_CARD_TRANSFER)
  170. // {
  171. //        HAL_MMC_GetCardCID(&hmmc1,&EMMC_CardCID);
  172. // }
  173. // if(HAL_MMC_Erase(&hmmc1,0,hmmc1.MmcCard.BlockNbr) == HAL_OK)
  174. // {
  175. //         while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
  176. // }
  177. return (USBD_OK);
  178.   /* USER CODE END 2 */
  179. }

  180. /**
  181.   * @brief  Returns the medium capacity.
  182.   * @param  lun: Logical unit number.
  183.   * @param  block_num: Number of total block number.
  184.   * @param  block_size: Block size.
  185.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  186.   */
  187. int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
  188. {
  189.   /* USER CODE BEGIN 3 */
  190.   HAL_MMC_CardStateTypeDef State;
  191.   HAL_MMC_CardCIDTypeDef EMMC_CardCID;
  192.   State = HAL_MMC_GetCardState(&hmmc1);
  193.   if(State == HAL_MMC_CARD_TRANSFER)
  194.   {
  195.         HAL_MMC_GetCardCID(&hmmc1,&EMMC_CardCID);
  196.         *block_num  = hmmc1.MmcCard.BlockNbr;
  197.         *block_size = hmmc1.MmcCard.BlockSize;
  198.         return (USBD_OK);
  199.   }
  200.   else
  201.         return USBD_FAIL ;
  202.   /* USER CODE END 3 */
  203. }

  204. /**
  205.   * @brief   Checks whether the medium is ready.
  206.   * @param  lun:  Logical unit number.
  207.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  208.   */
  209. int8_t STORAGE_IsReady_FS(uint8_t lun)
  210. {
  211.   /* USER CODE BEGIN 4 */
  212.   uint8_t state = 0;
  213.   state = HAL_MMC_GetState(&hmmc1);
  214.   if(HAL_MMC_STATE_READY != state)
  215.   {
  216.           return USBD_FAIL ;
  217.   }
  218.   return (USBD_OK);
  219.   /* USER CODE END 4 */
  220. }

  221. /**
  222.   * @brief  Checks whether the medium is write protected.
  223.   * @param  lun: Logical unit number.
  224.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  225.   */
  226. int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
  227. {
  228.   /* USER CODE BEGIN 5 */
  229.   UNUSED(lun);

  230.   return (USBD_OK);
  231.   /* USER CODE END 5 */
  232. }

  233. /**
  234.   * @brief  Reads data from the medium.
  235.   * @param  lun: Logical unit number.
  236.   * @param  buf: data buffer.
  237.   * @param  blk_addr: Logical block address.
  238.   * @param  blk_len: Blocks number.
  239.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  240.   */
  241. int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  242. {
  243.   /* USER CODE BEGIN 6 */
  244.   int8_t ret = USBD_FAIL;
  245.   BaseType_t semRet = pdFAIL;
  246.   if(xSemaphoreEmmc!=NULL){
  247.           semRet = xSemaphoreTakeFromISR(xSemaphoreEmmc,0);
  248.   }
  249.   if(semRet==pdPASS){
  250.         #ifdef EMMC_USE_DMA
  251.           if(HAL_OK == HAL_MMC_ReadBlocks_DMA(&hmmc1,(uint8_t *)buf, blk_addr , blk_len))
  252.           {
  253.                  while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
  254.                  ret = USBD_OK;
  255.           }
  256.         #else
  257.           if(HAL_OK == HAL_MMC_ReadBlocks(&hmmc1,(uint8_t *)buf, blk_addr , blk_len,0XFF))
  258.           {
  259.                  while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
  260.                  ret = USBD_OK;
  261.           }
  262.         #endif
  263.           xSemaphoreGiveFromISR(xSemaphoreEmmc,pdFALSE);
  264.   }
  265.   return ret;
  266.   /* USER CODE END 6 */
  267. }

  268. /**
  269.   * @brief  Writes data into the medium.
  270.   * @param  lun: Logical unit number.
  271.   * @param  buf: data buffer.
  272.   * @param  blk_addr: Logical block address.
  273.   * @param  blk_len: Blocks number.
  274.   * @retval USBD_OK if all operations are OK else USBD_FAIL
  275.   */
  276. int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
  277. {
  278.   /* USER CODE BEGIN 7 */
  279.   int8_t ret = USBD_FAIL;
  280.   BaseType_t semRet = pdFAIL;
  281.   if(xSemaphoreEmmc!=NULL){
  282.           semRet = xSemaphoreTakeFromISR(xSemaphoreEmmc,0);
  283.   }
  284.   if(semRet==pdPASS){
  285.         #ifdef EMMC_USE_DMA
  286.           if(HAL_OK == HAL_MMC_WriteBlocks_DMA(&hmmc1, (uint8_t *)buf, blk_addr , blk_len))
  287.           {
  288.                  while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
  289.                  ret = USBD_OK;
  290.           }
  291.         #else
  292.           if(HAL_OK == HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)buf, blk_addr , blk_len,0XFF))
  293.           {
  294.                  while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
  295.                  ret = USBD_OK;
  296.           }
  297.         #endif
  298.           xSemaphoreGiveFromISR(xSemaphoreEmmc,pdFALSE);
  299.   }
  300.   return ret;
  301.   /* USER CODE END 7 */
  302. }

  303. /**
  304.   * @brief  Returns the Max Supported LUNs.
  305.   * @param  None
  306.   * @retval Lun(s) number.
  307.   */
  308. int8_t STORAGE_GetMaxLun_FS(void)
  309. {
  310.   /* USER CODE BEGIN 8 */
  311.   return (STORAGE_LUN_NBR - 1);
  312.   /* USER CODE END 8 */
  313. }

  314. /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */

  315. /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

  316. /**
  317.   * @}
  318.   */

  319. /**
  320.   * @}
  321.   */

到这里USB MSC的驱动就改完了,插上USB看看,能不能驱动;
2504563fc078474f09.png
1716163fc0796b1ee1.png
在电脑端显示为G盘,首先进行格式化,格式化后看到大小为4GB,与板子上EMMC容量大小一致,然后测试读写是否正常,直接在G盘中新建txt,输入内容保存再打开,显示没问题,说明读写正常;
4、添加文件系统
能把视屏文件存入EMMC了,现在还差文件系统读取视屏文件内容,添加FATFS文件系统,模式选择User-defined,将Code_page改成DBCS;
1099663fc090232aa0.png
4、修改文件系统驱动代码这里面需要注意的是任务同步,因为USB驱动里面用EMMC的读写,fatfa也要用EMMC的读写,所以要做任务同步,这里千万不能用互斥体,因为FREERTOS的互斥体
是会自动调节任务优先级的,设计初衷是为了防止低优先级的任务占用锁但是得不到执行,高优先级的任务等锁产生死锁,而且互斥体不能用在中断中;而USB MSC驱动其实是中断执行的,所以要用信号量来完成;代码改写主要就是下面这几个函数
2069963fc0cd03d3c0.png
修改的相关代码都贴出来
  1. /**
  2.   * @brief SDMMC1 Initialization Function
  3.   * @param None
  4.   * @retval None
  5.   */
  6. static void MX_SDMMC1_MMC_Init(void)
  7. {

  8.   /* USER CODE BEGIN SDMMC1_Init 0 */

  9.   /* USER CODE END SDMMC1_Init 0 */

  10.   /* USER CODE BEGIN SDMMC1_Init 1 */

  11.   /* USER CODE END SDMMC1_Init 1 */
  12.   hmmc1.Instance = SDMMC1;
  13.   hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
  14.   hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
  15.   hmmc1.Init.BusWide = SDMMC_BUS_WIDE_1B;
  16.   hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
  17.   hmmc1.Init.ClockDiv = 4;
  18.   if (HAL_MMC_Init(&hmmc1) != HAL_OK)
  19.   {
  20.     Error_Handler();
  21.   }
  22.   /* USER CODE BEGIN SDMMC1_Init 2 */
  23.   xSemaphoreEmmc = xSemaphoreCreateBinary();
  24.   if(xSemaphoreEmmc==NULL){
  25.         Error_Handler();
  26.   }else{
  27.         xSemaphoreGive(xSemaphoreEmmc);
  28.   }

  29.   /* USER CODE END SDMMC1_Init 2 */

  30. }
  1. /* USER CODE BEGIN Header */
  2. /**
  3. ******************************************************************************
  4.   * [url=home.php?mod=space&uid=288409]@file[/url]    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 "stm32h7xx_hal.h"
  36. #include "semphr.h"
  37. /* Private typedef -----------------------------------------------------------*/
  38. /* Private define ------------------------------------------------------------*/
  39. #define EMMC_TIMEOUT 1000
  40. /* Private variables ---------------------------------------------------------*/
  41. extern SemaphoreHandle_t xSemaphoreEmmc;
  42. extern MMC_HandleTypeDef hmmc1;
  43. extern uint8_t  write_flag, read_flag;
  44. /* Disk status */
  45. static volatile DSTATUS Stat = STA_NOINIT;
  46. /* USER CODE END DECL */

  47. /* Private function prototypes -----------------------------------------------*/
  48. DSTATUS USER_initialize (BYTE pdrv);
  49. DSTATUS USER_status (BYTE pdrv);
  50. DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
  51. #if _USE_WRITE == 1
  52.   DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
  53. #endif /* _USE_WRITE == 1 */
  54. #if _USE_IOCTL == 1
  55.   DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
  56. #endif /* _USE_IOCTL == 1 */

  57. Diskio_drvTypeDef  USER_Driver =
  58. {
  59.   USER_initialize,
  60.   USER_status,
  61.   USER_read,
  62. #if  _USE_WRITE
  63.   USER_write,
  64. #endif  /* _USE_WRITE == 1 */
  65. #if  _USE_IOCTL == 1
  66.   USER_ioctl,
  67. #endif /* _USE_IOCTL == 1 */
  68. };

  69. /* Private functions ---------------------------------------------------------*/

  70. /**
  71.   * @brief  Initializes a Drive
  72.   * @param  pdrv: Physical drive number (0..)
  73.   * @retval DSTATUS: Operation status
  74.   */
  75. DSTATUS USER_initialize (
  76.         BYTE pdrv           /* Physical drive nmuber to identify the drive */
  77. )
  78. {
  79.   /* USER CODE BEGIN INIT */
  80.     Stat = STA_NOINIT;
  81.     if (HAL_MMC_Init(&hmmc1) == HAL_OK){
  82.             Stat &= ~STA_NOINIT;
  83.     }
  84.     return Stat;
  85.   /* USER CODE END INIT */
  86. }

  87. /**
  88.   * @brief  Gets Disk Status
  89.   * @param  pdrv: Physical drive number (0..)
  90.   * @retval DSTATUS: Operation status
  91.   */
  92. DSTATUS USER_status (
  93.         BYTE pdrv       /* Physical drive number to identify the drive */
  94. )
  95. {
  96.   /* USER CODE BEGIN STATUS */
  97.     Stat = STA_NOINIT;
  98.     if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER )
  99.     {
  100.       Stat &= ~STA_NOINIT;
  101.     }
  102.     return Stat;
  103.   /* USER CODE END STATUS */
  104. }

  105. /**
  106.   * @brief  Reads Sector(s)
  107.   * @param  pdrv: Physical drive number (0..)
  108.   * @param  *buff: Data buffer to store read data
  109.   * @param  sector: Sector address (LBA)
  110.   * @param  count: Number of sectors to read (1..128)
  111.   * @retval DRESULT: Operation result
  112.   */
  113. DRESULT USER_read (
  114.         BYTE pdrv,      /* Physical drive nmuber to identify the drive */
  115.         BYTE *buff,     /* Data buffer to store read data */
  116.         DWORD sector,   /* Sector address in LBA */
  117.         UINT count      /* Number of sectors to read */
  118. )
  119. {
  120.   /* USER CODE BEGIN READ */
  121.    DRESULT ret = RES_ERROR;
  122.    BaseType_t semRet = pdFAIL;
  123.    if(xSemaphoreEmmc!=NULL){
  124.            semRet = xSemaphoreTake(xSemaphoreEmmc,portMAX_DELAY);
  125.    }
  126.    if(semRet==pdPASS){
  127.    #ifdef EMMC_USE_DMA
  128.            uint32_t timeout;
  129.            uint32_t alignedAddr;
  130.            alignedAddr = (uint32_t)buff & ~0x1F;
  131.            SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
  132.            if(HAL_MMC_ReadBlocks_DMA(&hmmc1, (uint8_t*)buff,
  133.                                                                 (uint32_t) (sector),
  134.                                                                  count) == HAL_OK)
  135.            {

  136.                   /* Wait that the reading process is completed or a timeout occurs */
  137.                   timeout = HAL_GetTick();
  138.                   while((read_flag == 0) && ((HAL_GetTick() - timeout) < EMMC_TIMEOUT));
  139.                   /* incase of a timeout return error */
  140.                   if (read_flag == 0)
  141.                   {
  142.                         ret = RES_ERROR;
  143.                   }
  144.                   else
  145.                   {
  146.                         read_flag = 0;
  147.                         timeout = HAL_GetTick();
  148.                         while((HAL_GetTick() - timeout) < EMMC_TIMEOUT)
  149.                         {
  150.                           if (HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
  151.                           {
  152.                                 ret = RES_OK;
  153.                                 SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
  154.                                 break;
  155.                           }
  156.                         }
  157.                   }
  158.                 }
  159.         #else
  160.                 if(HAL_MMC_ReadBlocks(&hmmc1, (uint8_t*)buff,
  161.                                                                  (uint32_t) (sector),
  162.                                                                   count,EMMC_TIMEOUT) == HAL_OK)
  163.                 {
  164.                         while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
  165.                         ret = RES_OK;
  166.                 }
  167.         #endif
  168.                 xSemaphoreGive(xSemaphoreEmmc);
  169.    }
  170.    return ret;
  171.   /* USER CODE END READ */
  172. }

  173. /**
  174.   * @brief  Writes Sector(s)
  175.   * @param  pdrv: Physical drive number (0..)
  176.   * @param  *buff: Data to be written
  177.   * @param  sector: Sector address (LBA)
  178.   * @param  count: Number of sectors to write (1..128)
  179.   * @retval DRESULT: Operation result
  180.   */
  181. #if _USE_WRITE == 1
  182. DRESULT USER_write (
  183.         BYTE pdrv,          /* Physical drive nmuber to identify the drive */
  184.         const BYTE *buff,   /* Data to be written */
  185.         DWORD sector,       /* Sector address in LBA */
  186.         UINT count          /* Number of sectors to write */
  187. )
  188. {
  189.   /* USER CODE BEGIN WRITE */
  190.   /* USER CODE HERE */
  191.         DRESULT ret = RES_ERROR;
  192.     BaseType_t semRet = pdFAIL;
  193.     if(xSemaphoreEmmc!=NULL){
  194.             semRet = xSemaphoreTake(xSemaphoreEmmc,portMAX_DELAY);
  195.     }
  196.     if(semRet==pdPASS){
  197.         #ifdef EMMC_USE_DMA
  198.            uint32_t alignedAddr;
  199.            uint32_t timeout;

  200.            alignedAddr = (uint32_t)buff & ~0x1F;
  201.                 SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
  202.                 if(HAL_MMC_WriteBlocks_DMA(&hmmc1, (uint8_t*)buff,
  203.                                                                  (uint32_t) (sector),
  204.                                                                  count) == HAL_OK)
  205.                 {
  206.                         /* Wait that the reading process is completed or a timeout occurs */
  207.                   timeout = HAL_GetTick();
  208.                   while((write_flag == 0) && ((HAL_GetTick() - timeout) < EMMC_TIMEOUT));
  209.                   /* incase of a timeout return error */
  210.                   if (write_flag == 0)
  211.                   {
  212.                         ret = RES_ERROR;
  213.                   }
  214.                   else
  215.                   {
  216.                         write_flag = 0;
  217.                         timeout = HAL_GetTick();
  218.                         while((HAL_GetTick() - timeout) < EMMC_TIMEOUT)
  219.                         {
  220.                           if (HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
  221.                           {
  222.                                 ret = RES_OK;
  223.                                 SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
  224.                                 break;
  225.                           }
  226.                         }
  227.                   }
  228.                 }

  229.         #else
  230.                 if(HAL_MMC_WriteBlocks(&hmmc1, (uint8_t*)buff,
  231.                                                                  (uint32_t) (sector),
  232.                                                                   count,EMMC_TIMEOUT) == HAL_OK)
  233.                 {
  234.                         while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
  235.                         ret = RES_OK;
  236.                 }
  237.         #endif
  238.                 xSemaphoreGive(xSemaphoreEmmc);
  239.     }
  240.         return ret;
  241.   /* USER CODE END WRITE */
  242. }
  243. #endif /* _USE_WRITE == 1 */

  244. /**
  245.   * @brief  I/O control operation
  246.   * @param  pdrv: Physical drive number (0..)
  247.   * @param  cmd: Control code
  248.   * @param  *buff: Buffer to send/receive control data
  249.   * @retval DRESULT: Operation result
  250.   */
  251. #if _USE_IOCTL == 1
  252. DRESULT USER_ioctl (
  253.         BYTE pdrv,      /* Physical drive nmuber (0..) */
  254.         BYTE cmd,       /* Control code */
  255.         void *buff      /* Buffer to send/receive control data */
  256. )
  257. {
  258.   /* USER CODE BEGIN IOCTL */
  259.     DRESULT res = RES_ERROR;
  260.     HAL_MMC_CardInfoTypeDef emmcinfo;

  261.     switch(cmd)
  262.         {
  263.                 case CTRL_SYNC:
  264.                         res = RES_OK;
  265.                         break;
  266.                 case GET_SECTOR_SIZE:
  267.                         *(WORD*)buff = 512;
  268.                         res = RES_OK;
  269.                         break;
  270.                 case GET_BLOCK_SIZE:
  271.                         *(WORD*)buff = 8;
  272.                         res = RES_OK;
  273.                         break;
  274.                 case GET_SECTOR_COUNT:
  275.                         HAL_MMC_GetCardInfo(&hmmc1,&emmcinfo);
  276.                         *(WORD*)buff = emmcinfo.BlockNbr;
  277.                         res = RES_OK;
  278.                         break;
  279.                 default:
  280.                         break;
  281.         }
  282.     return res;
  283.   /* USER CODE END IOCTL */
  284. }
  285. #endif /* _USE_IOCTL == 1 */

到此存储加读取部分工作完成;二、视屏播放接口驱动
1、使用LIBJPEG解码库
使用LIBJPEG解码库解码视屏压缩文件;
2023663fc0e3a01711.png
2、添加DMA2D支持
6992563fc0da9d794a.png

3770963fc0df0b3c32.png
3、驱动代码修改
整个 代码依据的还是TOUCHGFX框架,这个框架是用C++写的,要熟系C++命名空间的语法,不然看着会很头晕,沥青不算特别复杂,挑重要的相关步骤贴一下从初始化入口
  1. void touchgfx_init()
  2. {
  3.     Bitmap::registerBitmapDatabase(BitmapDatabase::getInstance(), BitmapDatabase::getInstanceSize());
  4.     TypedText::registerTexts(&texts);
  5.     Texts::setLanguage(0);

  6.     FontManager::setFontProvider(&fontProvider);

  7.     FrontendHeap& heap = FrontendHeap::getInstance();
  8.     /*
  9.      * we need to obtain the reference above to initialize the frontend heap.
  10.      */
  11.     (void)heap;

  12.     /*
  13.      * Initialize TouchGFX
  14.      */
  15.     hal.initialize();
  16. }
TouchGFX初始化,初始化解码器
  1. void TouchGFXHAL::initialize()
  2. {
  3.     // Calling parent implementation of initialize().
  4.     //
  5.     // To overwrite the generated implementation, omit call to parent function
  6.     // and implemented needed functionality here.
  7.     // Please note, HAL::initialize() must be called to initialize the framework.

  8.     TouchGFXGeneratedHAL::initialize();
  9.     setFrameBufferStartAddresses((void*)frameBuffer0, (void*)frameBuffer1, (void*)animationBuffer);
  10.     instrumentation.init();
  11.     setMCUInstrumentation(&instrumentation);
  12.     enableMCULoadCalculation(true);
  13. }
  1. void TouchGFXGeneratedHAL::initialize()
  2. {
  3.     HAL::initialize();
  4.     registerEventListener(*(Application::getInstance()));
  5.     setFrameBufferStartAddresses((void*)frameBuf, (void*)(frameBuf + sizeof(frameBuf) / (sizeof(uint32_t) * 2)), (void*)0);

  6.     /*
  7.      * Add DMA2D to hardware decoder
  8.      */
  9.     mjpegdecoder1.addDMA(dma);

  10.     /*
  11.      * Add hardware decoder to video controller
  12.      */
  13.     videoController.addDecoder(mjpegdecoder1, 0);
  14.     videoController.setRGBBuffer((uint8_t*)videoRGBBuffer, sizeof(videoRGBBuffer));
  15. }

控件相关在mainvewbase里面
  1. MainViewBase::MainViewBase() :
  2.     buttonCallback(this, &MainViewBase::buttonCallbackHandler)
  3. {
  4.     __background.setPosition(0, 0, 480, 272);
  5.     __background.setColor(touchgfx::Color::getColorFromRGB(0, 0, 0));
  6.     add(__background);

  7.     backgorund.setXY(0, 0);
  8.     backgorund.setBitmap(touchgfx::Bitmap(BITMAP_BACKGROUND_ID));
  9.     add(backgorund);

  10.     video.setPosition(132, 4, 216, 216);
  11.     video.setVideoData(video_SampleVideo2_216x216_bin_start, video_SampleVideo2_216x216_bin_length);
  12.     video.setRepeat(true);
  13.     video.play();
  14.     add(video);

  15.     play.setXY(170, 230);
  16.     play.setBitmaps(touchgfx::Bitmap(BITMAP_BUTTON_PLAY_PINK_ID), touchgfx::Bitmap(BITMAP_BUTTON_PLAY_WHITE_ID));
  17.     play.setAction(buttonCallback);
  18.     add(play);

  19.     pause.setXY(278, 230);
  20.     pause.setBitmaps(touchgfx::Bitmap(BITMAP_BUTTON_PAUSE_PINK_ID), touchgfx::Bitmap(BITMAP_BUTTON_PAUSE_WHITE_ID));
  21.     pause.setAction(buttonCallback);
  22.     add(pause);
  23. }
到这里video.setVideoData(video_SampleVideo2_216x216_bin_start, video_SampleVideo2_216x216_bin_length);这个函数就是这只播放数据的,这个是内置flash的播放数据,小视屏可放在flash里直接播放,但是大文件的是不可能放在flash里面的,我们要进行改写,这里面用C++的重载特性,函数名不变,改变形参,调用的时候根据形参确定执行哪个函数;
312463fc1da40607c.png


   
506787841 发表于 2023-5-16 17:17 | 显示全部楼层
你好,usb驱动那部分,我使用不带DMA的才能在电脑上显示出来,困扰好几天了,可以看看你的工程吗,
帮帮孩子吧,不胜感激!QQ:506787841
daichaodai 发表于 2023-5-16 20:07 来自手机 | 显示全部楼层
不错,牛人啊。
Pretext 发表于 2023-5-18 14:43 | 显示全部楼层
有视频播放的视频吗?想看看播放效果。
天天向善 发表于 2023-5-18 14:44 | 显示全部楼层
一看楼主这代码量,就知道楼主撸了很久的代码。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

282

帖子

1

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