[STM32N6] 【STM32N6570-DK测评】jpeg硬解码并显示到LCD

[复制链接]
 楼主| xhackerustc 发表于 2025-5-5 23:22 | 显示全部楼层 |阅读模式
<
STM32N6系列硬件上集成jpeg decoder和encoder,所以可以用此jpeg deocder来硬解码,免去libjpeg或者tjpgdec等软件jpeg解码库的移植,而且速度上基于硬件的jpeg解码肯定快,且占用资源少。

可能是STM32N6很新的缘故,STM32Cube_FW_N6自带的例子中只有jpeg解码(Projects/STM32N6570-DK/Examples/JPEG/JPEG_DecodingFromOSPI_DMA/),但无显示到LCD的动作,咱写点代码给他添上。

理论篇:
STM32N6的jpeg decoder解码输出是标准YCbCr格式,但要显示到LCD还需要转成RGB格式。因STM32Cube_FW_N6中STM32N6570-DK bsp中LCD默认采取RGB565格式,所以我们需要做一个YCbCr->RGB565的转换,这个转换可以由软件做,也可以由硬件做。幸运的是STM32N6的集成的DMA2D有这个转换功能,配置好DMA2D参数即可高效率转换。

实做篇:
充分利用N6的大sram
因N6有4.2MB的sram,而且物理地址连续,大可以充分利用起来,不过这里需要注意下有些SRAM默认是disable的,可能为省电的缘故,比如AXISRAM3\4\5\6默认是disable的。笔者使能它们的代码如下:
  1.   RCC->MEMENSR = RCC_MEMENSR_AXISRAM3ENS |

  2.                  RCC_MEMENSR_AXISRAM4ENS |

  3.                  RCC_MEMENSR_AXISRAM5ENS |

  4.                  RCC_MEMENSR_AXISRAM6ENS |

  5.                  RCC_MEMENSR_CACHEAXIRAMENS;

  6.   RAMCFG_SRAM3_AXI->CR &= ~RAMCFG_CR_SRAMSD;

  7.   RAMCFG_SRAM4_AXI->CR &= ~RAMCFG_CR_SRAMSD;

  8.   RAMCFG_SRAM5_AXI->CR &= ~RAMCFG_CR_SRAMSD;

  9.   RAMCFG_SRAM6_AXI->CR &= ~RAMCFG_CR_SRAMSD;


LCD buffer地址
改动stm32n6570_discovery_conf.h中默认的LCD buffer的地址为AXISRAM3的基地址
  1. #define LCD_LAYER_0_ADDRESS                 0x34200000U



MPU设置
上述地址空间按ARMV8M默认是cacheable地址,用于LCD buffer时cache无用,所以配置下MPU

  1.   MPU_Region_InitTypeDef default_config = {0};
  2.   MPU_Attributes_InitTypeDef attr_config = {0};
  3.   uint32_t primask_bit = __get_PRIMASK();

  4.   /* disable the MPU */
  5.   HAL_MPU_Disable();
  6.   /* create an attribute configuration for the MPU */
  7.   attr_config.Attributes = INNER_OUTER(MPU_NOT_CACHEABLE);
  8.   attr_config.Number = MPU_ATTRIBUTES_NUMBER0;
  9.   HAL_MPU_ConfigMemoryAttributes(&attr_config);
  10.   /* Create a non cacheable region */
  11.   /*Normal memory type, code execution allowed */
  12.   default_config.Enable = MPU_REGION_ENABLE;
  13.   default_config.Number = MPU_REGION_NUMBER0;
  14.   default_config.BaseAddress = 0x34200000;
  15.   default_config.LimitAddress = 0x34270000;
  16.   default_config.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  17.   default_config.AccessPermission = MPU_REGION_ALL_RW;
  18.   default_config.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  19.   default_config.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
  20.   HAL_MPU_ConfigRegion(&default_config);

  21.   /* enable the MPU */
  22.   HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
  23.   /* Exit critical section to lock the system and avoid any issue around MPU mechanisme */
  24.   __set_PRIMASK(primask_bit);


JPED decoder -> LTDC pipeline关键代码
JPEG decoder -> DMA 搬运到sram -> DMA2D YCbCr RGB565转换-> LTDC pipeline关键代码:

  1.   /* Initialize the LCD   */
  2.   BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);

  3.   UTIL_LCD_SetFuncDriver(&LCD_Driver);
  4.   UTIL_LCD_SetLayer(0);

  5.   /* Get the LCD Width */
  6.   BSP_LCD_GetXSize(0,&LCD_X_Size);
  7.   BSP_LCD_GetYSize(0,&LCD_Y_Size);

  8.   /* Display example brief   */
  9.   LCD_BriefDisplay();

  10.   HAL_Delay(1000);

  11.   MX_HPDMA1_Init();
  12.   MX_JPEG_Init();
  13.   tickstart = HAL_GetTick();

  14.   /*JPEG Decoding with DMA (Not Blocking ) Method */
  15.   JPEG_Decode_DMA(&hjpeg, (uint32_t)image_320_240_jpg, IMAGE_320_240_JPG_SIZE, (uint32_t)
  16. rawBuffer);

  17.   /* Wait till end of JPEG decoding or exceed TimeOut*/
  18.   while((Jpeg_HWDecodingEnd == 0) && ((HAL_GetTick() - tickstart) < 5000))
  19.   {
  20.   }

  21.   if (Jpeg_HWDecodingEnd != 0)
  22.   {
  23.     BSP_LED_On(LED_GREEN);
  24.   }
  25.   else
  26.   {
  27.     BSP_LED_On(LED_RED);
  28.   }
  29.   /*##-5- Get JPEG Info  ###############################################*/
  30.   HAL_JPEG_GetInfo(&hjpeg, &JPEG_Info);

  31.   /*##-9- Copy RGB decoded Data to the display FrameBuffer  ############*/
  32.   xPos = (LCD_X_Size - JPEG_Info.ImageWidth)/2;
  33.   yPos = (LCD_Y_Size - JPEG_Info.ImageHeight)/2;

  34.   DMA2D_CopyBuffer((uint32_t *)rawBuffer, (uint32_t *)LCD_LAYER_0_ADDRESS, xPos , yPos, JPEG_Info.ImageWidth, JPEG_Info.ImageHeight, JPEG_Info.ChromaSubsampling);

  35.   /* Infinite loop */
  36.   while (1)
  37.   {
  38.   }


运行结果:
1078405710.jpg

stormwind123 发表于 2025-6-5 17:26 | 显示全部楼层
需注意内存和CPU资源的限制。
probedog 发表于 2025-6-5 17:27 | 显示全部楼层
用DMA进行数据传输,减少CPU的干预;优化解码算法,提高解码速度等。
AdaMaYun 发表于 2025-6-8 21:16 | 显示全部楼层
STM32N6系列硬件上集成jpeg decoder和encoder,所以可以用此jpeg deocder来硬解码,免去libjpeg或者tjpgdec等软件jpeg解码库的移植,而且速度上基于硬件的jpeg解码肯定快,且占用资源少。
gejigeji521 发表于 2025-6-11 12:15 | 显示全部楼层
那就可以看压缩图片了
Ketose 发表于 2025-7-8 15:58 | 显示全部楼层
收一块STM32N6开发板。
szt1993 发表于 2025-7-8 19:37 | 显示全部楼层
应该有必要的解码库文件吧[em
您需要登录后才可以回帖 登录 | 注册

本版积分规则

42

主题

165

帖子

2

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