[STM32H7] 【STM32H745I-DISCO试用】8、jpeg硬件解码+DMA2D

[复制链接]
 楼主| sujingliang 发表于 2025-1-30 18:54 | 显示全部楼层 |阅读模式
<
本帖最后由 sujingliang 于 2025-1-31 09:52 编辑



1、MPU配置
50.png
51.png

对应代码:
外存只配了16MB,应该可以配32MB
  1. void MPU_Config(void)
  2. {
  3.   MPU_Region_InitTypeDef MPU_InitStruct = {0};

  4.   /* Disables the MPU */
  5.   HAL_MPU_Disable();

  6.   /** Initializes and configures the Region and the memory to be protected
  7.   */
  8.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  9.   MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  10.   MPU_InitStruct.BaseAddress = 0x0;
  11.   MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
  12.   MPU_InitStruct.SubRegionDisable = 0x87;
  13.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  14.   MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
  15.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  16.   MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
  17.   MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  18.   MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

  19.   HAL_MPU_ConfigRegion(&MPU_InitStruct);

  20.   /** Initializes and configures the Region and the memory to be protected
  21.   */
  22.   MPU_InitStruct.Number = MPU_REGION_NUMBER1;
  23.   MPU_InitStruct.BaseAddress = 0xD0000000;
  24.   MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
  25.   MPU_InitStruct.SubRegionDisable = 0x0;
  26.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  27.   MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  28.   MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  29.   MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  30.   HAL_MPU_ConfigRegion(&MPU_InitStruct);
  31.   /* Enables the MPU */
  32.   HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

  33. }


2、FMC配置
52.png

对应代码:

  1. void MX_FMC_Init(void)
  2. {

  3.   /* USER CODE BEGIN FMC_Init 0 */

  4.   /* USER CODE END FMC_Init 0 */

  5.   FMC_SDRAM_TimingTypeDef SdramTiming = {0};

  6.   /* USER CODE BEGIN FMC_Init 1 */

  7.   /* USER CODE END FMC_Init 1 */

  8.   /** Perform the SDRAM2 memory initialization sequence
  9.   */
  10.   hsdram2.Instance = FMC_SDRAM_DEVICE;
  11.   /* hsdram2.Init */
  12.   hsdram2.Init.SDBank = FMC_SDRAM_BANK2;
  13.   hsdram2.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
  14.   hsdram2.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
  15.   hsdram2.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
  16.   hsdram2.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  17.   hsdram2.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
  18.   hsdram2.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  19.   hsdram2.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
  20.   hsdram2.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
  21.   hsdram2.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
  22.   /* SdramTiming */
  23.   SdramTiming.LoadToActiveDelay = 2;
  24.   SdramTiming.ExitSelfRefreshDelay = 6;
  25.   SdramTiming.SelfRefreshTime = 4;
  26.   SdramTiming.RowCycleDelay = 6;
  27.   SdramTiming.WriteRecoveryTime = 2;
  28.   SdramTiming.RPDelay = 2;
  29.   SdramTiming.RCDDelay = 2;

  30.   if (HAL_SDRAM_Init(&hsdram2, &SdramTiming) != HAL_OK)
  31.   {
  32.     Error_Handler( );
  33.   }

  34.   /* USER CODE BEGIN FMC_Init 2 */

  35.   /* USER CODE END FMC_Init 2 */
  36. }
3、JPEG配置
53.png
对应代码:
  1. static void MX_JPEG_Init(void)
  2. {

  3.   /* USER CODE BEGIN JPEG_Init 0 */

  4.   /* USER CODE END JPEG_Init 0 */

  5.   /* USER CODE BEGIN JPEG_Init 1 */

  6.   /* USER CODE END JPEG_Init 1 */
  7.   hjpeg.Instance = JPEG;
  8.   if (HAL_JPEG_Init(&hjpeg) != HAL_OK)
  9.   {
  10.     Error_Handler();
  11.   }
  12.   /* USER CODE BEGIN JPEG_Init 2 */

  13.   /* USER CODE END JPEG_Init 2 */

  14. }



4、DMA2D配置
54.png

关于LTDC配置略,与前文相同。

5、JPEG硬件解码

功能依次读取MMC中的1.jpg-18.jpg,通过JPEG_Decode_DMA解码,DMA2D_CopyBuffer显示在LCD。

jpeg文件缓存:
uint8_t jpeg_buffer[1024*1024] __attribute__((section(".bss.ARM.__at_0xD0200000")));

0xD0000000:LTDC显存地址
0xD0100000:解码后数据首地址
0xD0200000:解码前数据首地址
  1. static void JPEG_hard_decode(uint8_t index)
  2. {
  3.                 FRESULT res;
  4.                 uint32_t xPos = 0, yPos = 0;
  5.                 char image_file[50];
  6.                 memset(image_file,0,50);
  7.                 sprintf(image_file,"image%d.jpg",index);
  8.                
  9.                 if(f_mount(&MMCFatFs, (TCHAR const*)MMCPath, 0) != FR_OK)
  10.                 {
  11.                         printf("f_mount error\r\n");
  12.                         return;
  13.                 }
  14.                
  15.                 if(f_open(&MyFile, image_file, FA_READ) != FR_OK)
  16.     {
  17.                         printf("f_open jpeg error\r\n");
  18.       return;
  19.     }else{
  20.                         printf("f_open jpeg ok\r\n");
  21.                 }
  22.                
  23.                 if(FR_OK==f_read(&MyFile,jpeg_buffer,sizeof(jpeg_buffer),&jpeg_read_size))
  24.                 {
  25.                         printf("f_read ok\r\n");
  26.                         printf("jpeg_read_size:%d\r\n",jpeg_read_size);
  27.                         JPEG_Decode_DMA(&hjpeg, 0xD0200000, jpeg_read_size , 0xD0100000);//(uint32_t)jpeg_buffer,(uint32_t)_onepic
  28.                           while(Jpeg_HWDecodingEnd == 0)
  29.                         {
  30.                         }
  31.                         HAL_JPEG_GetInfo(&hjpeg, &JPEG_Info);  
  32.                         xPos = (LCD_RES_X - JPEG_Info.ImageWidth)/2;
  33.                         yPos = (LCD_RES_Y - JPEG_Info.ImageHeight)/2;   
  34.                        
  35.                         printf("xPos:%d,yPos:%d,ImageWidth:%d,ImageHeight:%d,ChromaSubsampling:%d\r\n", xPos , yPos, JPEG_Info.ImageWidth, JPEG_Info.ImageHeight, JPEG_Info.ChromaSubsampling);
  36.                         DMA2D_CopyBuffer((uint32_t *)0xD0100000, (uint32_t*)LCD_FRAME_BUFFER, xPos , yPos, JPEG_Info.ImageWidth, JPEG_Info.ImageHeight, JPEG_Info.ChromaSubsampling);
  37.                        
  38.                 }
  39.                 else
  40.                         printf("f_read error\r\n");
  41.                
  42.                 f_close(&MyFile);
  43. }


JPEG_Decode_DMA函数来自例程中decode_dma.c文件。

  1. uint32_t JPEG_Decode_DMA(JPEG_HandleTypeDef *hjpeg, uint32_t FrameSourceAddress ,uint32_t FrameSize, uint32_t DestAddress)
  2. {
  3.   JPEGSourceAddress =  FrameSourceAddress ;
  4.   FrameBufferAddress = DestAddress;
  5.   Input_frameIndex=0;
  6.   Input_frameSize = FrameSize;
  7.   
  8.   Jpeg_HWDecodingEnd = 0;
  9.   
  10.   /* Start JPEG decoding with DMA method */
  11.   HAL_JPEG_Decode_DMA(hjpeg ,(uint8_t *)JPEGSourceAddress ,CHUNK_SIZE_IN ,(uint8_t *)FrameBufferAddress ,CHUNK_SIZE_OUT);
  12.   
  13.   
  14.   return 0;
  15.   
  16. }
DMA2D_CopyBuffer内容如下,也是源于例程
  1. static void DMA2D_CopyBuffer(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize, uint32_t ChromaSampling)
  2. {   
  3.   
  4.   uint32_t cssMode = DMA2D_CSS_420, inputLineOffset = 0;  
  5.   uint32_t destination = 0;
  6.         uint16_t timeout=0;
  7.   
  8.   if(ChromaSampling == JPEG_420_SUBSAMPLING)
  9.   {
  10.     cssMode = DMA2D_CSS_420;
  11.    
  12.     inputLineOffset = xsize % 16;
  13.     if(inputLineOffset != 0)
  14.     {
  15.       inputLineOffset = 16 - inputLineOffset;
  16.     }   
  17.   }
  18.   else if(ChromaSampling == JPEG_444_SUBSAMPLING)
  19.   {
  20.     cssMode = DMA2D_NO_CSS;
  21.    
  22.     inputLineOffset = xsize % 8;
  23.     if(inputLineOffset != 0)
  24.     {
  25.       inputLineOffset = 8 - inputLineOffset;
  26.     }   
  27.   }
  28.   else if(ChromaSampling == JPEG_422_SUBSAMPLING)
  29.   {
  30.     cssMode = DMA2D_CSS_422;
  31.    
  32.     inputLineOffset = xsize % 16;
  33.     if(inputLineOffset != 0)
  34.     {
  35.       inputLineOffset = 16 - inputLineOffset;
  36.     }      
  37.   }  
  38.   
  39.   /*##-1- Configure the DMA2D Mode, Color Mode and output offset #############*/
  40.   hlcd_dma2d.Init.Mode         = DMA2D_M2M_PFC;
  41.   hlcd_dma2d.Init.ColorMode    = DMA2D_OUTPUT_ARGB8888;
  42.   hlcd_dma2d.Init.OutputOffset = LCD_RES_X - xsize;
  43.   hlcd_dma2d.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;  /* No Output Alpha Inversion*/  
  44.   hlcd_dma2d.Init.RedBlueSwap   = DMA2D_RB_REGULAR;     /* No Output Red & Blue swap  DMA2D_RB_SWAP*/  
  45.   
  46.   /*##-2- DMA2D Callbacks Configuration ######################################*/
  47.   hlcd_dma2d.XferCpltCallback  = NULL;
  48.   
  49.   /*##-3- Foreground Configuration ###########################################*/
  50.   hlcd_dma2d.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
  51.   hlcd_dma2d.LayerCfg[1].InputAlpha = 0xFF;
  52.   hlcd_dma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_YCBCR;
  53.   hlcd_dma2d.LayerCfg[1].ChromaSubSampling = DMA2D_NO_CSS;//cssMode;
  54.   hlcd_dma2d.LayerCfg[1].InputOffset = inputLineOffset;
  55.   hlcd_dma2d.LayerCfg[1].RedBlueSwap = DMA2D_RB_REGULAR; /* No ForeGround Red/Blue swap */
  56.   hlcd_dma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA; /* No ForeGround Alpha inversion */  
  57.   
  58.   hlcd_dma2d.Instance          = DMA2D;
  59.   
  60.   /*##-4- DMA2D Initialization     ###########################################*/
  61.   HAL_DMA2D_Init(&hlcd_dma2d);
  62.   HAL_DMA2D_ConfigLayer(&hlcd_dma2d, 1);
  63.   
  64.   /*##-5-  copy the new decoded frame to the LCD Frame buffer ################*/
  65.   //BSP_LCD_GetXSize(0, &LCD_X_Size);
  66.   destination = (uint32_t)pDst + ((y * LCD_RES_X) + x) * 4;

  67.         SCB_CleanDCache_by_Addr((uint32_t*)pSrc, xsize*ysize*3);
  68.   HAL_DMA2D_Start(&hlcd_dma2d, (uint32_t)pSrc, destination, xsize, ysize);
  69.   HAL_DMA2D_PollForTransfer(&hlcd_dma2d, 25);  /* wait for the previous DMA2D transfer to ends */
  70.         while((__HAL_DMA2D_GET_FLAG(&hlcd_dma2d,DMA2D_FLAG_TC)==0)&&(timeout<0X5000))//等待DMA2D完成
  71.         {
  72.                 timeout++;
  73.         }
  74. }
jpeg硬件解码后的数据格式为YCBCR,经过DMA2D转换为ARGB8888

您需要登录后才可以回帖 登录 | 注册

本版积分规则

84

主题

146

帖子

3

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

84

主题

146

帖子

3

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