打印
[STM32H7]

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

[复制链接]
1985|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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++的重载特性,函数名不变,改变形参,调用的时候根据形参确定执行哪个函数;



   

使用特权

评论回复
沙发
506787841| | 2023-5-16 17:17 | 只看该作者
你好,usb驱动那部分,我使用不带DMA的才能在电脑上显示出来,困扰好几天了,可以看看你的工程吗,
帮帮孩子吧,不胜感激!QQ:506787841

使用特权

评论回复
板凳
daichaodai| | 2023-5-16 20:07 | 只看该作者
不错,牛人啊。

使用特权

评论回复
地板
Pretext| | 2023-5-18 14:43 | 只看该作者
有视频播放的视频吗?想看看播放效果。

使用特权

评论回复
5
天天向善| | 2023-5-18 14:44 | 只看该作者
一看楼主这代码量,就知道楼主撸了很久的代码。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

282

帖子

1

粉丝