首页 > 评测 > [STM32H7] [STM32H7] STM32H750B-DK TouchGFX 测评视频播放
[STM32H7] [STM32H7] STM32H750B-DK TouchGFX 测评视频播放
- [导读]
- 本帖最后由 ROSHEN_007 于 2023-3-6 13:20 编辑 #申请原创# 一、搭建存储系统 视频播放一般需要SD卡进行视屏文件存储,但是开发板上没有SD卡,查看了板子的硬件资源,发现板子上有两块EMMC,所以想着用EM
本帖最后由 ROSHEN_007 于 2023-3-6 13:20 编辑
#申请原创#
一、搭建存储系统
视频播放一般需要SD卡进行视屏文件存储,但是开发板上没有SD卡,查看了板子的硬件资源,发现板子上有两块EMMC,所以想着用EMMC来作为存储设备,搭建USB+EMMC+FATFS存储读写系统;
1、USB驱动配置
直接使用CUBEMX进行配置,比较方便,需要注意的是,配置时钟的时候,千万别选自动生成USB时钟,自动生成会造成"系统紊乱",因为USB默认时钟是从PLL1上取得,要配置成48MHZ,会改PLL1的输出时钟,很多外设都用PLL1生成时钟,这里直接手动选择RC48即可;
2、EMMC驱动配置
查看STM32H750的手册,发现支持8bit DDR模式,但是实际调试的时候发现速率根本达不到200Mhz,这里简直是深坑,调试出错的时候我以为是EMMC不支持,后来查看EMMC的手册,是可以支持200M ddr模式的,应该还是ST的问题,IO翻转速度达不到200MHZ,时钟改成四分频到50MHZ就可以跑起来了;支持 1线、4线、8线MMC模式,根据需要选择即可,另外打开中断配置;
3、USB MSC驱动代码修改调试
改过SD开驱动的应该都比较熟悉,这里我们直接找到usbd_storage_if.c文件,改写下图中的这些函数,代码下面也贴出,改写的时候主要的是要把自己添加的代码写到“恰当的位置”,不然如果你修改CUBMUX的配置,你辛辛苦苦添加的代码就会消失不见了,我也是刚开始使用cubide,在这上面吃了点小亏;
- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * [url=home.php?mod=space&uid=288409]@file[/url] : usbd_storage_if.c
- * [url=home.php?mod=space&uid=895143]@version[/url] : v1.0_Cube
- * [url=home.php?mod=space&uid=247401]@brief[/url] : Memory management layer.
- ******************************************************************************
- * @attention
- *
- * Copyright (c) 2023 STMicroelectronics.
- * All rights reserved.
- *
- * This software is licensed under terms that can be found in the LICENSE file
- * in the root directory of this software component.
- * If no LICENSE file comes with this software, it is provided AS-IS.
- *
- ******************************************************************************
- */
- /* USER CODE END Header */
- /* Includes ------------------------------------------------------------------*/
- #include "usbd_storage_if.h"
- /* USER CODE BEGIN INCLUDE */
- #include "FreeRTOS.h"
- #include "semphr.h"
- /* USER CODE END INCLUDE */
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- /* Private macro -------------------------------------------------------------*/
- /* USER CODE BEGIN PV */
- /* Private variables ---------------------------------------------------------*/
- /* USER CODE END PV */
- /** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
- * [url=home.php?mod=space&uid=247401]@brief[/url] Usb device.
- * @{
- */
- /** @defgroup USBD_STORAGE
- * [url=home.php?mod=space&uid=247401]@brief[/url] Usb mass storage device module
- * @{
- */
- /** @defgroup USBD_STORAGE_Private_TypesDefinitions
- * [url=home.php?mod=space&uid=247401]@brief[/url] Private types.
- * @{
- */
- /* USER CODE BEGIN PRIVATE_TYPES */
- /* USER CODE END PRIVATE_TYPES */
- /**
- * @}
- */
- /** @defgroup USBD_STORAGE_Private_Defines
- * [url=home.php?mod=space&uid=247401]@brief[/url] Private defines.
- * @{
- */
- #define STORAGE_LUN_NBR 1
- #define STORAGE_BLK_NBR 0x10000
- #define STORAGE_BLK_SIZ 0x200
- /* USER CODE BEGIN PRIVATE_DEFINES */
- //#define EMMC_USE_DMA
- /* USER CODE END PRIVATE_DEFINES */
- /**
- * @}
- */
- /** @defgroup USBD_STORAGE_Private_Macros
- * [url=home.php?mod=space&uid=247401]@brief[/url] Private macros.
- * @{
- */
- /* USER CODE BEGIN PRIVATE_MACRO */
- /* USER CODE END PRIVATE_MACRO */
- /**
- * @}
- */
- /** @defgroup USBD_STORAGE_Private_Variables
- * [url=home.php?mod=space&uid=247401]@brief[/url] Private variables.
- * @{
- */
- /* USER CODE BEGIN INQUIRY_DATA_FS */
- /** USB Mass storage Standard Inquiry Data. */
- const int8_t STORAGE_Inquirydata_FS[] = {/* 36 */
- /* LUN 0 */
- 0x00,
- 0x80,
- 0x02,
- 0x02,
- (STANDARD_INQUIRY_DATA_LEN - 5),
- 0x00,
- 0x00,
- 0x00,
- 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', /* Manufacturer : 8 bytes */
- 'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
- ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
- '0', '.', '0' ,'1' /* Version : 4 Bytes */
- };
- /* USER CODE END INQUIRY_DATA_FS */
- /* USER CODE BEGIN PRIVATE_VARIABLES */
- /* USER CODE END PRIVATE_VARIABLES */
- /**
- * @}
- */
- /** @defgroup USBD_STORAGE_Exported_Variables
- * @brief Public variables.
- * @{
- */
- extern USBD_HandleTypeDef hUsbDeviceFS;
- /* USER CODE BEGIN EXPORTED_VARIABLES */
- volatile uint8_t write_flag = 0, read_flag = 0;
- extern MMC_HandleTypeDef hmmc1;
- extern SemaphoreHandle_t xSemaphoreEmmc;
- /* USER CODE END EXPORTED_VARIABLES */
- /**
- * @}
- */
- /** @defgroup USBD_STORAGE_Private_FunctionPrototypes
- * @brief Private functions declaration.
- * @{
- */
- static int8_t STORAGE_Init_FS(uint8_t lun);
- static int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
- static int8_t STORAGE_IsReady_FS(uint8_t lun);
- static int8_t STORAGE_IsWriteProtected_FS(uint8_t lun);
- static int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
- static int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
- static int8_t STORAGE_GetMaxLun_FS(void);
- /* USER CODE BEGIN PRIVATE_FUNCTIONS_DECLARATION */
- void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
- {
- write_flag = 1;
- }
- void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
- {
- read_flag = 1;
- }
- /* USER CODE END PRIVATE_FUNCTIONS_DECLARATION */
- /**
- * @}
- */
- USBD_StorageTypeDef USBD_Storage_Interface_fops_FS =
- {
- STORAGE_Init_FS,
- STORAGE_GetCapacity_FS,
- STORAGE_IsReady_FS,
- STORAGE_IsWriteProtected_FS,
- STORAGE_Read_FS,
- STORAGE_Write_FS,
- STORAGE_GetMaxLun_FS,
- (int8_t *)STORAGE_Inquirydata_FS
- };
- /* Private functions ---------------------------------------------------------*/
- /**
- * @brief Initializes the storage unit (medium) over USB FS IP
- * @param lun: Logical unit number.
- * @retval USBD_OK if all operations are OK else USBD_FAIL
- */
- int8_t STORAGE_Init_FS(uint8_t lun)
- {
- /* USER CODE BEGIN 2 */
- UNUSED(lun);
- // hmmc1.Instance = SDMMC1;
- // hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
- // hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
- // hmmc1.Init.BusWide = SDMMC_BUS_WIDE_8B;
- // hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
- // hmmc1.Init.ClockDiv = 0;
- // if (HAL_MMC_Init(&hmmc1) != HAL_OK)
- // {
- // return USBD_FAIL;
- // }
- // HAL_MMC_CardStateTypeDef State;
- // HAL_MMC_CardCIDTypeDef EMMC_CardCID;
- // State = HAL_MMC_GetCardState(&hmmc1);
- // if(State == HAL_MMC_CARD_TRANSFER)
- // {
- // HAL_MMC_GetCardCID(&hmmc1,&EMMC_CardCID);
- // }
- // if(HAL_MMC_Erase(&hmmc1,0,hmmc1.MmcCard.BlockNbr) == HAL_OK)
- // {
- // while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
- // }
- return (USBD_OK);
- /* USER CODE END 2 */
- }
- /**
- * @brief Returns the medium capacity.
- * @param lun: Logical unit number.
- * @param block_num: Number of total block number.
- * @param block_size: Block size.
- * @retval USBD_OK if all operations are OK else USBD_FAIL
- */
- int8_t STORAGE_GetCapacity_FS(uint8_t lun, uint32_t *block_num, uint16_t *block_size)
- {
- /* USER CODE BEGIN 3 */
- HAL_MMC_CardStateTypeDef State;
- HAL_MMC_CardCIDTypeDef EMMC_CardCID;
- State = HAL_MMC_GetCardState(&hmmc1);
- if(State == HAL_MMC_CARD_TRANSFER)
- {
- HAL_MMC_GetCardCID(&hmmc1,&EMMC_CardCID);
- *block_num = hmmc1.MmcCard.BlockNbr;
- *block_size = hmmc1.MmcCard.BlockSize;
- return (USBD_OK);
- }
- else
- return USBD_FAIL ;
- /* USER CODE END 3 */
- }
- /**
- * @brief Checks whether the medium is ready.
- * @param lun: Logical unit number.
- * @retval USBD_OK if all operations are OK else USBD_FAIL
- */
- int8_t STORAGE_IsReady_FS(uint8_t lun)
- {
- /* USER CODE BEGIN 4 */
- uint8_t state = 0;
- state = HAL_MMC_GetState(&hmmc1);
- if(HAL_MMC_STATE_READY != state)
- {
- return USBD_FAIL ;
- }
- return (USBD_OK);
- /* USER CODE END 4 */
- }
- /**
- * @brief Checks whether the medium is write protected.
- * @param lun: Logical unit number.
- * @retval USBD_OK if all operations are OK else USBD_FAIL
- */
- int8_t STORAGE_IsWriteProtected_FS(uint8_t lun)
- {
- /* USER CODE BEGIN 5 */
- UNUSED(lun);
- return (USBD_OK);
- /* USER CODE END 5 */
- }
- /**
- * @brief Reads data from the medium.
- * @param lun: Logical unit number.
- * @param buf: data buffer.
- * @param blk_addr: Logical block address.
- * @param blk_len: Blocks number.
- * @retval USBD_OK if all operations are OK else USBD_FAIL
- */
- int8_t STORAGE_Read_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
- {
- /* USER CODE BEGIN 6 */
- int8_t ret = USBD_FAIL;
- BaseType_t semRet = pdFAIL;
- if(xSemaphoreEmmc!=NULL){
- semRet = xSemaphoreTakeFromISR(xSemaphoreEmmc,0);
- }
- if(semRet==pdPASS){
- #ifdef EMMC_USE_DMA
- if(HAL_OK == HAL_MMC_ReadBlocks_DMA(&hmmc1,(uint8_t *)buf, blk_addr , blk_len))
- {
- while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
- ret = USBD_OK;
- }
- #else
- if(HAL_OK == HAL_MMC_ReadBlocks(&hmmc1,(uint8_t *)buf, blk_addr , blk_len,0XFF))
- {
- while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
- ret = USBD_OK;
- }
- #endif
- xSemaphoreGiveFromISR(xSemaphoreEmmc,pdFALSE);
- }
- return ret;
- /* USER CODE END 6 */
- }
- /**
- * @brief Writes data into the medium.
- * @param lun: Logical unit number.
- * @param buf: data buffer.
- * @param blk_addr: Logical block address.
- * @param blk_len: Blocks number.
- * @retval USBD_OK if all operations are OK else USBD_FAIL
- */
- int8_t STORAGE_Write_FS(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len)
- {
- /* USER CODE BEGIN 7 */
- int8_t ret = USBD_FAIL;
- BaseType_t semRet = pdFAIL;
- if(xSemaphoreEmmc!=NULL){
- semRet = xSemaphoreTakeFromISR(xSemaphoreEmmc,0);
- }
- if(semRet==pdPASS){
- #ifdef EMMC_USE_DMA
- if(HAL_OK == HAL_MMC_WriteBlocks_DMA(&hmmc1, (uint8_t *)buf, blk_addr , blk_len))
- {
- while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
- ret = USBD_OK;
- }
- #else
- if(HAL_OK == HAL_MMC_WriteBlocks(&hmmc1, (uint8_t *)buf, blk_addr , blk_len,0XFF))
- {
- while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
- ret = USBD_OK;
- }
- #endif
- xSemaphoreGiveFromISR(xSemaphoreEmmc,pdFALSE);
- }
- return ret;
- /* USER CODE END 7 */
- }
- /**
- * @brief Returns the Max Supported LUNs.
- * @param None
- * @retval Lun(s) number.
- */
- int8_t STORAGE_GetMaxLun_FS(void)
- {
- /* USER CODE BEGIN 8 */
- return (STORAGE_LUN_NBR - 1);
- /* USER CODE END 8 */
- }
- /* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
- /* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
- /**
- * @}
- */
- /**
- * @}
- */
到这里USB MSC的驱动就改完了,插上USB看看,能不能驱动;
在电脑端显示为G盘,首先进行格式化,格式化后看到大小为4GB,与板子上EMMC容量大小一致,然后测试读写是否正常,直接在G盘中新建txt,输入内容保存再打开,显示没问题,说明读写正常;
4、添加文件系统
能把视屏文件存入EMMC了,现在还差文件系统读取视屏文件内容,添加FATFS文件系统,模式选择User-defined,将Code_page改成DBCS;
4、修改文件系统驱动代码这里面需要注意的是任务同步,因为USB驱动里面用EMMC的读写,fatfa也要用EMMC的读写,所以要做任务同步,这里千万不能用互斥体,因为FREERTOS的互斥体
是会自动调节任务优先级的,设计初衷是为了防止低优先级的任务占用锁但是得不到执行,高优先级的任务等锁产生死锁,而且互斥体不能用在中断中;而USB MSC驱动其实是中断执行的,所以要用信号量来完成;代码改写主要就是下面这几个函数
修改的相关代码都贴出来
- /**
- * @brief SDMMC1 Initialization Function
- * @param None
- * @retval None
- */
- static void MX_SDMMC1_MMC_Init(void)
- {
- /* USER CODE BEGIN SDMMC1_Init 0 */
- /* USER CODE END SDMMC1_Init 0 */
- /* USER CODE BEGIN SDMMC1_Init 1 */
- /* USER CODE END SDMMC1_Init 1 */
- hmmc1.Instance = SDMMC1;
- hmmc1.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
- hmmc1.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
- hmmc1.Init.BusWide = SDMMC_BUS_WIDE_1B;
- hmmc1.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
- hmmc1.Init.ClockDiv = 4;
- if (HAL_MMC_Init(&hmmc1) != HAL_OK)
- {
- Error_Handler();
- }
- /* USER CODE BEGIN SDMMC1_Init 2 */
- xSemaphoreEmmc = xSemaphoreCreateBinary();
- if(xSemaphoreEmmc==NULL){
- Error_Handler();
- }else{
- xSemaphoreGive(xSemaphoreEmmc);
- }
- /* USER CODE END SDMMC1_Init 2 */
- }
- /* USER CODE BEGIN Header */
- /**
- ******************************************************************************
- * [url=home.php?mod=space&uid=288409]@file[/url] user_diskio.c
- * @brief This file includes a diskio driver skeleton to be completed by the user.
- ******************************************************************************
- * @attention
- *
- * Copyright (c) 2023 STMicroelectronics.
- * All rights reserved.
- *
- * This software is licensed under terms that can be found in the LICENSE file
- * in the root directory of this software component.
- * If no LICENSE file comes with this software, it is provided AS-IS.
- *
- ******************************************************************************
- */
- /* USER CODE END Header */
- #ifdef USE_OBSOLETE_USER_CODE_SECTION_0
- /*
- * Warning: the user section 0 is no more in use (starting from CubeMx version 4.16.0)
- * To be suppressed in the future.
- * Kept to ensure backward compatibility with previous CubeMx versions when
- * migrating projects.
- * User code previously added there should be copied in the new user sections before
- * the section contents can be deleted.
- */
- /* USER CODE BEGIN 0 */
- /* USER CODE END 0 */
- #endif
- /* USER CODE BEGIN DECL */
- /* Includes ------------------------------------------------------------------*/
- #include <string.h>
- #include "ff_gen_drv.h"
- #include "stm32h7xx_hal.h"
- #include "semphr.h"
- /* Private typedef -----------------------------------------------------------*/
- /* Private define ------------------------------------------------------------*/
- #define EMMC_TIMEOUT 1000
- /* Private variables ---------------------------------------------------------*/
- extern SemaphoreHandle_t xSemaphoreEmmc;
- extern MMC_HandleTypeDef hmmc1;
- extern uint8_t write_flag, read_flag;
- /* Disk status */
- static volatile DSTATUS Stat = STA_NOINIT;
- /* USER CODE END DECL */
- /* Private function prototypes -----------------------------------------------*/
- DSTATUS USER_initialize (BYTE pdrv);
- DSTATUS USER_status (BYTE pdrv);
- DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count);
- #if _USE_WRITE == 1
- DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count);
- #endif /* _USE_WRITE == 1 */
- #if _USE_IOCTL == 1
- DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff);
- #endif /* _USE_IOCTL == 1 */
- Diskio_drvTypeDef USER_Driver =
- {
- USER_initialize,
- USER_status,
- USER_read,
- #if _USE_WRITE
- USER_write,
- #endif /* _USE_WRITE == 1 */
- #if _USE_IOCTL == 1
- USER_ioctl,
- #endif /* _USE_IOCTL == 1 */
- };
- /* Private functions ---------------------------------------------------------*/
- /**
- * @brief Initializes a Drive
- * @param pdrv: Physical drive number (0..)
- * @retval DSTATUS: Operation status
- */
- DSTATUS USER_initialize (
- BYTE pdrv /* Physical drive nmuber to identify the drive */
- )
- {
- /* USER CODE BEGIN INIT */
- Stat = STA_NOINIT;
- if (HAL_MMC_Init(&hmmc1) == HAL_OK){
- Stat &= ~STA_NOINIT;
- }
- return Stat;
- /* USER CODE END INIT */
- }
- /**
- * @brief Gets Disk Status
- * @param pdrv: Physical drive number (0..)
- * @retval DSTATUS: Operation status
- */
- DSTATUS USER_status (
- BYTE pdrv /* Physical drive number to identify the drive */
- )
- {
- /* USER CODE BEGIN STATUS */
- Stat = STA_NOINIT;
- if(HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER )
- {
- Stat &= ~STA_NOINIT;
- }
- return Stat;
- /* USER CODE END STATUS */
- }
- /**
- * @brief Reads Sector(s)
- * @param pdrv: Physical drive number (0..)
- * @param *buff: Data buffer to store read data
- * @param sector: Sector address (LBA)
- * @param count: Number of sectors to read (1..128)
- * @retval DRESULT: Operation result
- */
- DRESULT USER_read (
- BYTE pdrv, /* Physical drive nmuber to identify the drive */
- BYTE *buff, /* Data buffer to store read data */
- DWORD sector, /* Sector address in LBA */
- UINT count /* Number of sectors to read */
- )
- {
- /* USER CODE BEGIN READ */
- DRESULT ret = RES_ERROR;
- BaseType_t semRet = pdFAIL;
- if(xSemaphoreEmmc!=NULL){
- semRet = xSemaphoreTake(xSemaphoreEmmc,portMAX_DELAY);
- }
- if(semRet==pdPASS){
- #ifdef EMMC_USE_DMA
- uint32_t timeout;
- uint32_t alignedAddr;
- alignedAddr = (uint32_t)buff & ~0x1F;
- SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
- if(HAL_MMC_ReadBlocks_DMA(&hmmc1, (uint8_t*)buff,
- (uint32_t) (sector),
- count) == HAL_OK)
- {
- /* Wait that the reading process is completed or a timeout occurs */
- timeout = HAL_GetTick();
- while((read_flag == 0) && ((HAL_GetTick() - timeout) < EMMC_TIMEOUT));
- /* incase of a timeout return error */
- if (read_flag == 0)
- {
- ret = RES_ERROR;
- }
- else
- {
- read_flag = 0;
- timeout = HAL_GetTick();
- while((HAL_GetTick() - timeout) < EMMC_TIMEOUT)
- {
- if (HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
- {
- ret = RES_OK;
- SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
- break;
- }
- }
- }
- }
- #else
- if(HAL_MMC_ReadBlocks(&hmmc1, (uint8_t*)buff,
- (uint32_t) (sector),
- count,EMMC_TIMEOUT) == HAL_OK)
- {
- while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
- ret = RES_OK;
- }
- #endif
- xSemaphoreGive(xSemaphoreEmmc);
- }
- return ret;
- /* USER CODE END READ */
- }
- /**
- * @brief Writes Sector(s)
- * @param pdrv: Physical drive number (0..)
- * @param *buff: Data to be written
- * @param sector: Sector address (LBA)
- * @param count: Number of sectors to write (1..128)
- * @retval DRESULT: Operation result
- */
- #if _USE_WRITE == 1
- DRESULT USER_write (
- BYTE pdrv, /* Physical drive nmuber to identify the drive */
- const BYTE *buff, /* Data to be written */
- DWORD sector, /* Sector address in LBA */
- UINT count /* Number of sectors to write */
- )
- {
- /* USER CODE BEGIN WRITE */
- /* USER CODE HERE */
- DRESULT ret = RES_ERROR;
- BaseType_t semRet = pdFAIL;
- if(xSemaphoreEmmc!=NULL){
- semRet = xSemaphoreTake(xSemaphoreEmmc,portMAX_DELAY);
- }
- if(semRet==pdPASS){
- #ifdef EMMC_USE_DMA
- uint32_t alignedAddr;
- uint32_t timeout;
- alignedAddr = (uint32_t)buff & ~0x1F;
- SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
- if(HAL_MMC_WriteBlocks_DMA(&hmmc1, (uint8_t*)buff,
- (uint32_t) (sector),
- count) == HAL_OK)
- {
- /* Wait that the reading process is completed or a timeout occurs */
- timeout = HAL_GetTick();
- while((write_flag == 0) && ((HAL_GetTick() - timeout) < EMMC_TIMEOUT));
- /* incase of a timeout return error */
- if (write_flag == 0)
- {
- ret = RES_ERROR;
- }
- else
- {
- write_flag = 0;
- timeout = HAL_GetTick();
- while((HAL_GetTick() - timeout) < EMMC_TIMEOUT)
- {
- if (HAL_MMC_GetCardState(&hmmc1) == HAL_MMC_CARD_TRANSFER)
- {
- ret = RES_OK;
- SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*MMC_BLOCKSIZE + ((uint32_t)buff - alignedAddr));
- break;
- }
- }
- }
- }
- #else
- if(HAL_MMC_WriteBlocks(&hmmc1, (uint8_t*)buff,
- (uint32_t) (sector),
- count,EMMC_TIMEOUT) == HAL_OK)
- {
- while(HAL_MMC_GetCardState(&hmmc1)!=HAL_MMC_CARD_TRANSFER);
- ret = RES_OK;
- }
- #endif
- xSemaphoreGive(xSemaphoreEmmc);
- }
- return ret;
- /* USER CODE END WRITE */
- }
- #endif /* _USE_WRITE == 1 */
- /**
- * @brief I/O control operation
- * @param pdrv: Physical drive number (0..)
- * @param cmd: Control code
- * @param *buff: Buffer to send/receive control data
- * @retval DRESULT: Operation result
- */
- #if _USE_IOCTL == 1
- DRESULT USER_ioctl (
- BYTE pdrv, /* Physical drive nmuber (0..) */
- BYTE cmd, /* Control code */
- void *buff /* Buffer to send/receive control data */
- )
- {
- /* USER CODE BEGIN IOCTL */
- DRESULT res = RES_ERROR;
- HAL_MMC_CardInfoTypeDef emmcinfo;
- switch(cmd)
- {
- case CTRL_SYNC:
- res = RES_OK;
- break;
- case GET_SECTOR_SIZE:
- *(WORD*)buff = 512;
- res = RES_OK;
- break;
- case GET_BLOCK_SIZE:
- *(WORD*)buff = 8;
- res = RES_OK;
- break;
- case GET_SECTOR_COUNT:
- HAL_MMC_GetCardInfo(&hmmc1,&emmcinfo);
- *(WORD*)buff = emmcinfo.BlockNbr;
- res = RES_OK;
- break;
- default:
- break;
- }
- return res;
- /* USER CODE END IOCTL */
- }
- #endif /* _USE_IOCTL == 1 */
到此存储加读取部分工作完成;二、视屏播放接口驱动
1、使用LIBJPEG解码库
使用LIBJPEG解码库解码视屏压缩文件;
2、添加DMA2D支持
3、驱动代码修改
整个 代码依据的还是TOUCHGFX框架,这个框架是用C++写的,要熟系C++命名空间的语法,不然看着会很头晕,沥青不算特别复杂,挑重要的相关步骤贴一下从初始化入口
- void touchgfx_init()
- {
- Bitmap::registerBitmapDatabase(BitmapDatabase::getInstance(), BitmapDatabase::getInstanceSize());
- TypedText::registerTexts(&texts);
- Texts::setLanguage(0);
- FontManager::setFontProvider(&fontProvider);
- FrontendHeap& heap = FrontendHeap::getInstance();
- /*
- * we need to obtain the reference above to initialize the frontend heap.
- */
- (void)heap;
- /*
- * Initialize TouchGFX
- */
- hal.initialize();
- }
TouchGFX初始化,初始化解码器
- void TouchGFXHAL::initialize()
- {
- // Calling parent implementation of initialize().
- //
- // To overwrite the generated implementation, omit call to parent function
- // and implemented needed functionality here.
- // Please note, HAL::initialize() must be called to initialize the framework.
- TouchGFXGeneratedHAL::initialize();
- setFrameBufferStartAddresses((void*)frameBuffer0, (void*)frameBuffer1, (void*)animationBuffer);
- instrumentation.init();
- setMCUInstrumentation(&instrumentation);
- enableMCULoadCalculation(true);
- }
- void TouchGFXGeneratedHAL::initialize()
- {
- HAL::initialize();
- registerEventListener(*(Application::getInstance()));
- setFrameBufferStartAddresses((void*)frameBuf, (void*)(frameBuf + sizeof(frameBuf) / (sizeof(uint32_t) * 2)), (void*)0);
- /*
- * Add DMA2D to hardware decoder
- */
- mjpegdecoder1.addDMA(dma);
- /*
- * Add hardware decoder to video controller
- */
- videoController.addDecoder(mjpegdecoder1, 0);
- videoController.setRGBBuffer((uint8_t*)videoRGBBuffer, sizeof(videoRGBBuffer));
- }
控件相关在mainvewbase里面
- MainViewBase::MainViewBase() :
- buttonCallback(this, &MainViewBase::buttonCallbackHandler)
- {
- __background.setPosition(0, 0, 480, 272);
- __background.setColor(touchgfx::Color::getColorFromRGB(0, 0, 0));
- add(__background);
- backgorund.setXY(0, 0);
- backgorund.setBitmap(touchgfx::Bitmap(BITMAP_BACKGROUND_ID));
- add(backgorund);
- video.setPosition(132, 4, 216, 216);
- video.setVideoData(video_SampleVideo2_216x216_bin_start, video_SampleVideo2_216x216_bin_length);
- video.setRepeat(true);
- video.play();
- add(video);
- play.setXY(170, 230);
- play.setBitmaps(touchgfx::Bitmap(BITMAP_BUTTON_PLAY_PINK_ID), touchgfx::Bitmap(BITMAP_BUTTON_PLAY_WHITE_ID));
- play.setAction(buttonCallback);
- add(play);
- pause.setXY(278, 230);
- pause.setBitmaps(touchgfx::Bitmap(BITMAP_BUTTON_PAUSE_PINK_ID), touchgfx::Bitmap(BITMAP_BUTTON_PAUSE_WHITE_ID));
- pause.setAction(buttonCallback);
- add(pause);
- }
到这里video.setVideoData(video_SampleVideo2_216x216_bin_start, video_SampleVideo2_216x216_bin_length);这个函数就是这只播放数据的,这个是内置flash的播放数据,小视屏可放在flash里直接播放,但是大文件的是不可能放在flash里面的,我们要进行改写,这里面用C++的重载特性,函数名不变,改变形参,调用的时候根据形参确定执行哪个函数;
- 本文系21ic原创,未经许可禁止转载!
网友评论
- 联系人:巧克力娃娃
- 邮箱:board@21ic.com
- 我要投稿
-
欢迎入驻,开放投稿
-
人均百万?英伟达中国员工收入曝光! 2024-08-29
-
《黑神话:悟空》玩家硬盘升级攻略:提升游戏体验,畅享3A大作 2024-08-29
-
数睿数据参加《系统与软件工程 低代码开发平台通用技术要求》国家标准编制 2024-08-29
- NRF52810蓝牙数字耳机找人定制
预算:¥30005天前
- 125KW模块式PCS软硬件外包开发
预算:¥1100000015小时前
- 12V汽车启动电源项目BMS设计
预算:¥50000023小时前
- 数据可视化软件 开发
预算:¥5000023小时前
- PLC项目调试修改
预算:¥100001天前
- 起动电机控制器开发
预算:¥1100001天前