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

一、搭建存储系统
视频播放一般需要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++的重载特性,函数名不变,改变形参,调用的时候根据形参确定执行哪个函数;

 ---------------------
作者:ROSHEN_007
链接:https://bbs.21ic.com/icview-3286860-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值