首頁(yè) > 評(píng)測(cè) > [STM32H7] [STM32H7] STM32H750B-DK TouchGFX 測(cè)評(píng)視頻播放
[STM32H7] [STM32H7] STM32H750B-DK TouchGFX 測(cè)評(píng)視頻播放
- [導(dǎo)讀]
- 本帖最后由 ROSHEN_007 于 2023-3-6 13:20 編輯 #申請(qǐng)?jiān)瓌?chuàng)# 一、搭建存儲(chǔ)系統(tǒng) 視頻播放一般需要SD卡進(jìn)行視屏文件存儲(chǔ),但是開(kāi)發(fā)板上沒(méi)有SD卡,查看了板子的硬件資源,發(fā)現(xiàn)板子上有兩塊EMMC,所以想著用EM
本帖最后由 ROSHEN_007 于 2023-3-6 13:20 編輯
#申請(qǐng)?jiān)瓌?chuàng)#
一、搭建存儲(chǔ)系統(tǒng)
視頻播放一般需要SD卡進(jìn)行視屏文件存儲(chǔ),但是開(kāi)發(fā)板上沒(méi)有SD卡,查看了板子的硬件資源,發(fā)現(xiàn)板子上有兩塊EMMC,所以想著用EMMC來(lái)作為存儲(chǔ)設(shè)備,搭建USB+EMMC+FATFS存儲(chǔ)讀寫系統(tǒng);
1、USB驅(qū)動(dòng)配置
直接使用CUBEMX進(jìn)行配置,比較方便,需要注意的是,配置時(shí)鐘的時(shí)候,千萬(wàn)別選自動(dòng)生成USB時(shí)鐘,自動(dòng)生成會(huì)造成"系統(tǒng)紊亂",因?yàn)閁SB默認(rèn)時(shí)鐘是從PLL1上取得,要配置成48MHZ,會(huì)改PLL1的輸出時(shí)鐘,很多外設(shè)都用PLL1生成時(shí)鐘,這里直接手動(dòng)選擇RC48即可;
2、EMMC驅(qū)動(dòng)配置
查看STM32H750的手冊(cè),發(fā)現(xiàn)支持8bit DDR模式,但是實(shí)際調(diào)試的時(shí)候發(fā)現(xiàn)速率根本達(dá)不到200Mhz,這里簡(jiǎn)直是深坑,調(diào)試出錯(cuò)的時(shí)候我以為是EMMC不支持,后來(lái)查看EMMC的手冊(cè),是可以支持200M ddr模式的,應(yīng)該還是ST的問(wèn)題,IO翻轉(zhuǎn)速度達(dá)不到200MHZ,時(shí)鐘改成四分頻到50MHZ就可以跑起來(lái)了;支持 1線、4線、8線MMC模式,根據(jù)需要選擇即可,另外打開(kāi)中斷配置;
3、USB MSC驅(qū)動(dòng)代碼修改調(diào)試
改過(guò)SD開(kāi)驅(qū)動(dòng)的應(yīng)該都比較熟悉,這里我們直接找到usbd_storage_if.c文件,改寫下圖中的這些函數(shù),代碼下面也貼出,改寫的時(shí)候主要的是要把自己添加的代碼寫到“恰當(dāng)?shù)奈恢?rdquo;,不然如果你修改CUBMUX的配置,你辛辛苦苦添加的代碼就會(huì)消失不見(jiàn)了,我也是剛開(kāi)始使用cubide,在這上面吃了點(diǎn)小虧;
- /* 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的驅(qū)動(dòng)就改完了,插上USB看看,能不能驅(qū)動(dòng);
在電腦端顯示為G盤,首先進(jìn)行格式化,格式化后看到大小為4GB,與板子上EMMC容量大小一致,然后測(cè)試讀寫是否正常,直接在G盤中新建txt,輸入內(nèi)容保存再打開(kāi),顯示沒(méi)問(wèn)題,說(shuō)明讀寫正常;
4、添加文件系統(tǒng)
能把視屏文件存入EMMC了,現(xiàn)在還差文件系統(tǒng)讀取視屏文件內(nèi)容,添加FATFS文件系統(tǒng),模式選擇User-defined,將Code_page改成DBCS;
4、修改文件系統(tǒng)驅(qū)動(dòng)代碼這里面需要注意的是任務(wù)同步,因?yàn)閁SB驅(qū)動(dòng)里面用EMMC的讀寫,fatfa也要用EMMC的讀寫,所以要做任務(wù)同步,這里千萬(wàn)不能用互斥體,因?yàn)镕REERTOS的互斥體
是會(huì)自動(dòng)調(diào)節(jié)任務(wù)優(yōu)先級(jí)的,設(shè)計(jì)初衷是為了防止低優(yōu)先級(jí)的任務(wù)占用鎖但是得不到執(zhí)行,高優(yōu)先級(jí)的任務(wù)等鎖產(chǎn)生死鎖,而且互斥體不能用在中斷中;而USB MSC驅(qū)動(dòng)其實(shí)是中斷執(zhí)行的,所以要用信號(hào)量來(lái)完成;代碼改寫主要就是下面這幾個(gè)函數(shù)
修改的相關(guān)代碼都貼出來(lái)
- /**
- * @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 */
到此存儲(chǔ)加讀取部分工作完成;二、視屏播放接口驅(qū)動(dòng)
1、使用LIBJPEG解碼庫(kù)
使用LIBJPEG解碼庫(kù)解碼視屏壓縮文件;
2、添加DMA2D支持
3、驅(qū)動(dòng)代碼修改
整個(gè) 代碼依據(jù)的還是TOUCHGFX框架,這個(gè)框架是用C++寫的,要熟系C++命名空間的語(yǔ)法,不然看著會(huì)很頭暈,瀝青不算特別復(fù)雜,挑重要的相關(guān)步驟貼一下從初始化入口
- 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));
- }
控件相關(guān)在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);這個(gè)函數(shù)就是這只播放數(shù)據(jù)的,這個(gè)是內(nèi)置flash的播放數(shù)據(jù),小視屏可放在flash里直接播放,但是大文件的是不可能放在flash里面的,我們要進(jìn)行改寫,這里面用C++的重載特性,函數(shù)名不變,改變形參,調(diào)用的時(shí)候根據(jù)形參確定執(zhí)行哪個(gè)函數(shù);
- 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!
網(wǎng)友評(píng)論
- 聯(lián)系人:巧克力娃娃
- 郵箱:board@21ic.com
- 我要投稿
-
歡迎入駐,開(kāi)放投稿
- NRF52810藍(lán)牙數(shù)字耳機(jī)找人定制
預(yù)算:¥30005天前
- 125KW模塊式PCS軟硬件外包開(kāi)發(fā)
預(yù)算:¥1100000015小時(shí)前
- 12V汽車啟動(dòng)電源項(xiàng)目BMS設(shè)計(jì)
預(yù)算:¥50000023小時(shí)前
- 數(shù)據(jù)可視化軟件 開(kāi)發(fā)
預(yù)算:¥5000023小時(shí)前
- PLC項(xiàng)目調(diào)試修改
預(yù)算:¥100001天前
- 起動(dòng)電機(jī)控制器開(kāi)發(fā)
預(yù)算:¥1100001天前