STM32N6 NPU Deployment — Politecnico di Milano  1.0
Documentation for Neural Network Deployment on STM32N6 NPU - Politecnico di Milano 2024-2025
main.c
Go to the documentation of this file.
1 
80 #include "cmw_camera.h"
81 #include "stm32n6570_discovery_bus.h"
82 #include "stm32n6570_discovery_lcd.h"
83 #include "stm32n6570_discovery_xspi.h"
84 #include "stm32n6570_discovery.h"
85 #include "stm32_lcd.h"
86 #include "app_fuseprogramming.h"
87 #include "stm32_lcd_ex.h"
88 #include "app_postprocess.h"
89 #include "ll_aton_runtime.h"
90 #include "app_camerapipeline.h"
91 #include "main.h"
92 #include <stdio.h>
93 #include "app_config.h"
94 #include "crop_img.h"
95 #include "stlogo.h"
96 #include "utils.h"
97 
99 #if POSTPROCESS_TYPE == POSTPROCESS_MPE_YOLO_V8_UF
100  #include "display_mpe.h"
101 #elif POSTPROCESS_TYPE == POSTPROCESS_SPE_MOVENET_UF
102  #include "display_spe.h"
103 #else
104  #error "PostProcessing type not supported"
105 #endif
106 
108 #define MAX_NUMBER_OUTPUT 5
109 
111 #define LCD_FG_WIDTH SCREEN_WIDTH
112 
114 #define LCD_FG_HEIGHT SCREEN_HEIGHT
115 
117 #define LCD_FG_FRAMEBUFFER_SIZE (LCD_FG_WIDTH * LCD_FG_HEIGHT * 2)
118 
124 typedef struct
125 {
126  uint32_t X0;
127  uint32_t Y0;
128  uint32_t XSize;
129  uint32_t YSize;
131 
141 #if ASPECT_RATIO_MODE == ASPECT_RATIO_CROP || ASPECT_RATIO_MODE == ASPECT_RATIO_FIT
142  .X0 = (LCD_FG_WIDTH - LCD_FG_HEIGHT) / 2,
143 #else
144  .X0 = 0,
145 #endif
146  .Y0 = 0,
147  .XSize = 0,
148  .YSize = 0,
149 };
150 
158  .X0 = 0,
159  .Y0 = 0,
160  .XSize = LCD_FG_WIDTH,
161  .YSize = LCD_FG_HEIGHT,
162 };
163 
165 #if POSTPROCESS_TYPE == POSTPROCESS_MPE_YOLO_V8_UF
166  mpe_yolov8_pp_static_param_t pp_params;
167  mpe_pp_out_t pp_output;
168 #elif POSTPROCESS_TYPE == POSTPROCESS_SPE_MOVENET_UF
169  spe_movenet_pp_static_param_t pp_params;
170  spe_pp_out_t pp_output;
171 #endif
172 
179 volatile int32_t cameraFrameReceived;
180 
182 uint8_t *nn_in;
183 
185 BSP_LCD_LayerConfig_t LayerConfig = {0};
186 
192 #define ALIGN_TO_16(value) (((value) + 15) & ~15)
193 
206 #if (NN_WIDTH * NN_BPP) != ALIGN_TO_16(NN_WIDTH * NN_BPP)
207 #define DCMIPP_OUT_NN_LEN (ALIGN_TO_16(NN_WIDTH * NN_BPP) * NN_HEIGHT)
208 #define DCMIPP_OUT_NN_BUFF_LEN (DCMIPP_OUT_NN_LEN + 32 - DCMIPP_OUT_NN_LEN%32)
209 __attribute__ ((aligned (32)))
210 uint8_t dcmipp_out_nn[DCMIPP_OUT_NN_BUFF_LEN];
211 #else
212 uint8_t *dcmipp_out_nn;
213 #endif
214 
221 __attribute__ ((section (".psram_bss")))
222 __attribute__ ((aligned (32)))
223 uint8_t lcd_bg_buffer[800 * 480 * 2];
224 
232 __attribute__ ((section (".psram_bss")))
233 __attribute__ ((aligned (32)))
234 uint8_t lcd_fg_buffer[2][LCD_FG_WIDTH * LCD_FG_HEIGHT * 2];
235 
237 static int lcd_fg_buffer_rd_idx;
238 
239 /* Forward declarations */
240 static void SystemClock_Config(void);
241 static void NPURam_enable(void);
242 static void NPUCache_config(void);
243 static void Display_NetworkOutput(void *p_postprocess, uint32_t inference_ms);
244 static void LCD_init(void);
245 static void Security_Config(void);
246 static void set_clk_sleep_mode(void);
247 static void IAC_Config(void);
248 static void Display_WelcomeScreen(void);
249 static void Hardware_init(void);
250 static void NeuralNetwork_init(uint32_t *nnin_length, float32_t *nn_out[],
251  int *number_output, int32_t nn_out_len[]);
252 
253 
298 int main(void)
299 {
300  Hardware_init();
301 
302  /*** NN Init ****************************************************************/
303  uint32_t pitch_nn = 0;
304  uint32_t nn_in_len = 0;
305  int number_output = 0;
306  float32_t *nn_out[MAX_NUMBER_OUTPUT] = {0};
307  int32_t nn_out_len[MAX_NUMBER_OUTPUT] = {0};
308 
316  LL_ATON_DECLARE_NAMED_NN_INSTANCE_AND_INTERFACE(Default);
317  NeuralNetwork_init(&nn_in_len, nn_out, &number_output, nn_out_len);
318 
319  /*** Post Processing Init ***************************************************/
326  app_postprocess_init(&pp_params);
327 
328  /*** Camera Init ************************************************************/
337 
338  LCD_init();
339 
341  CameraPipeline_DisplayPipe_Start(lcd_bg_buffer, CMW_MODE_CONTINUOUS);
342 
343  /*** App Loop ***************************************************************/
344  while (1)
345  {
348 
349  if (pitch_nn != (NN_WIDTH * NN_BPP))
350  {
356  CameraPipeline_NNPipe_Start(dcmipp_out_nn, CMW_MODE_SNAPSHOT);
357  }
358  else
359  {
361  CameraPipeline_NNPipe_Start(nn_in, CMW_MODE_SNAPSHOT);
362  }
363 
365  while (cameraFrameReceived == 0) {};
367 
368  uint32_t ts[2] = { 0 };
369 
370  if (pitch_nn != (NN_WIDTH * NN_BPP))
371  {
377  SCB_InvalidateDCache_by_Addr(dcmipp_out_nn, sizeof(dcmipp_out_nn));
384  SCB_CleanInvalidateDCache_by_Addr(nn_in, nn_in_len);
385  }
386 
388  ts[0] = HAL_GetTick();
389 
404  LL_ATON_RT_Main(&NN_Instance_Default);
405 
407  ts[1] = HAL_GetTick();
408 
414  int32_t ret = app_postprocess_run((void **) nn_out, number_output,
415  &pp_output, &pp_params);
416  assert(ret == 0);
417 
419  Display_NetworkOutput(&pp_output, ts[1] - ts[0]);
420 
427  for (int i = 0; i < number_output; i++)
428  {
429  float32_t *tmp = nn_out[i];
430  SCB_InvalidateDCache_by_Addr(tmp, nn_out_len[i]);
431  }
432  }
433 }
434 
435 
463 static void Hardware_init(void)
464 {
465  /* Enable Instruction Cache for faster code execution */
466  MEMSYSCTL->MSCR |= MEMSYSCTL_MSCR_ICACTIVE_Msk;
467 
468  /* Reset CPU clock to HSI before reconfiguring PLLs */
469  __HAL_RCC_CPUCLK_CONFIG(RCC_CPUCLKSOURCE_HSI);
470  __HAL_RCC_SYSCLK_CONFIG(RCC_SYSCLKSOURCE_HSI);
471 
472  HAL_Init();
473 
474  SCB_EnableICache();
475 
476 #if defined(USE_DCACHE)
477  /* Enable Data Cache (controlled by USE_DCACHE in app_config.h) */
478  MEMSYSCTL->MSCR |= MEMSYSCTL_MSCR_DCACTIVE_Msk;
479  SCB_EnableDCache();
480 #endif
481 
482  SystemClock_Config(); /* Configure PLLs: CPU@800MHz, NPU@1000MHz */
483  NPURam_enable(); /* Enable all 4 NPU SRAM banks */
484  Fuse_Programming(); /* Program OTP fuses if needed */
485  NPUCache_config(); /* Initialize NPU AXI cache */
486 
487  /* Initialize external OctoFlash (128MB) — stores model weights */
488  BSP_XSPI_RAM_Init(0);
489  BSP_XSPI_RAM_EnableMemoryMappedMode(0);
490 
491  BSP_XSPI_NOR_Init_t NOR_Init;
492  NOR_Init.InterfaceMode = BSP_XSPI_NOR_OPI_MODE;
493  NOR_Init.TransferRate = BSP_XSPI_NOR_DTR_TRANSFER;
494  BSP_XSPI_NOR_Init(0, &NOR_Init);
495  BSP_XSPI_NOR_EnableMemoryMappedMode(0);
496 
497  Security_Config(); /* Grant secure access to NPU, DCMIPP, LTDC, DMA2D */
498  IAC_Config(); /* Configure Illegal Access Controller */
499  set_clk_sleep_mode(); /* Keep NPU + display clocks active during sleep */
500 }
501 
502 
531 static void NeuralNetwork_init(uint32_t *nnin_length, float32_t *nn_out[],
532  int *number_output, int32_t nn_out_len[])
533 {
535  const LL_Buffer_InfoTypeDef *nn_in_info = LL_ATON_Input_Buffers_Info_Default();
536  const LL_Buffer_InfoTypeDef *nn_out_info = LL_ATON_Output_Buffers_Info_Default();
537 
539  nn_in = (uint8_t *) LL_Buffer_addr_start(&nn_in_info[0]);
540 
542  while (nn_out_info[*number_output].name != NULL)
543  {
544  (*number_output)++;
545  }
546  assert(*number_output <= MAX_NUMBER_OUTPUT);
547 
549  for (int i = 0; i < *number_output; i++)
550  {
551  nn_out[i] = (float32_t *) LL_Buffer_addr_start(&nn_out_info[i]);
552  nn_out_len[i] = LL_Buffer_len(&nn_out_info[i]);
553  }
554 
555  *nnin_length = LL_Buffer_len(&nn_in_info[0]);
556 }
557 
558 
581 static void NPURam_enable(void)
582 {
583  __HAL_RCC_NPU_CLK_ENABLE();
584  __HAL_RCC_NPU_FORCE_RESET();
585  __HAL_RCC_NPU_RELEASE_RESET();
586 
588  __HAL_RCC_AXISRAM3_MEM_CLK_ENABLE();
589  __HAL_RCC_AXISRAM4_MEM_CLK_ENABLE();
590  __HAL_RCC_AXISRAM5_MEM_CLK_ENABLE();
591  __HAL_RCC_AXISRAM6_MEM_CLK_ENABLE();
592  __HAL_RCC_RAMCFG_CLK_ENABLE();
593 
594  RAMCFG_HandleTypeDef hramcfg = {0};
595  hramcfg.Instance = RAMCFG_SRAM3_AXI; HAL_RAMCFG_EnableAXISRAM(&hramcfg);
596  hramcfg.Instance = RAMCFG_SRAM4_AXI; HAL_RAMCFG_EnableAXISRAM(&hramcfg);
597  hramcfg.Instance = RAMCFG_SRAM5_AXI; HAL_RAMCFG_EnableAXISRAM(&hramcfg);
598  hramcfg.Instance = RAMCFG_SRAM6_AXI; HAL_RAMCFG_EnableAXISRAM(&hramcfg);
599 }
600 
601 
629 static void set_clk_sleep_mode(void)
630 {
631  __HAL_RCC_XSPI1_CLK_SLEEP_ENABLE();
632  __HAL_RCC_XSPI2_CLK_SLEEP_ENABLE();
633  __HAL_RCC_NPU_CLK_SLEEP_ENABLE();
634  __HAL_RCC_CACHEAXI_CLK_SLEEP_ENABLE();
635  __HAL_RCC_LTDC_CLK_SLEEP_ENABLE();
636  __HAL_RCC_DMA2D_CLK_SLEEP_ENABLE();
637  __HAL_RCC_DCMIPP_CLK_SLEEP_ENABLE();
638  __HAL_RCC_CSI_CLK_SLEEP_ENABLE();
639  __HAL_RCC_FLEXRAM_MEM_CLK_SLEEP_ENABLE();
640  __HAL_RCC_AXISRAM1_MEM_CLK_SLEEP_ENABLE();
641  __HAL_RCC_AXISRAM2_MEM_CLK_SLEEP_ENABLE();
642  __HAL_RCC_AXISRAM3_MEM_CLK_SLEEP_ENABLE();
643  __HAL_RCC_AXISRAM4_MEM_CLK_SLEEP_ENABLE();
644  __HAL_RCC_AXISRAM5_MEM_CLK_SLEEP_ENABLE();
645  __HAL_RCC_AXISRAM6_MEM_CLK_SLEEP_ENABLE();
646 }
647 
648 
660 static void NPUCache_config(void)
661 {
662  npu_cache_init();
663  npu_cache_enable();
664 }
665 
666 
684 static void Security_Config(void)
685 {
686  __HAL_RCC_RIFSC_CLK_ENABLE();
687  RIMC_MasterConfig_t RIMC_master = {0};
688  RIMC_master.MasterCID = RIF_CID_1;
689  RIMC_master.SecPriv = RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV;
690  HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_NPU, &RIMC_master);
691  HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_DMA2D, &RIMC_master);
692  HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_DCMIPP, &RIMC_master);
693  HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_LTDC1, &RIMC_master);
694  HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_LTDC2, &RIMC_master);
695  HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_NPU, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
696  HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_DMA2D, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
697  HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_CSI, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
698  HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_DCMIPP, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
699  HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_LTDC, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
700  HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_LTDCL1, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
701  HAL_RIF_RISC_SetSlaveSecureAttributes(RIF_RISC_PERIPH_INDEX_LTDCL2, RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV);
702 }
703 
704 
715 static void IAC_Config(void)
716 {
717  __HAL_RCC_IAC_CLK_ENABLE();
718  __HAL_RCC_IAC_FORCE_RESET();
719  __HAL_RCC_IAC_RELEASE_RESET();
720 }
721 
722 
730 void IAC_IRQHandler(void)
731 {
732  while (1) {}
733 }
734 
735 
736 /* ============================================================================
737  * DISPLAY HELPER FUNCTIONS
738  * ============================================================================ */
739 
751 static int clamp_point(int *x, int *y)
752 {
753  int xi = *x, yi = *y;
754  if (*x < (int)lcd_bg_area.X0) *x = lcd_bg_area.X0;
755  if (*y < (int)lcd_bg_area.Y0) *y = lcd_bg_area.Y0;
756  if (*x >= lcd_bg_area.X0 + lcd_bg_area.XSize) *x = lcd_bg_area.X0 + lcd_bg_area.XSize - 1;
757  if (*y >= lcd_bg_area.Y0 + lcd_bg_area.YSize) *y = lcd_bg_area.Y0 + lcd_bg_area.YSize - 1;
758  return (xi != *x) || (yi != *y);
759 }
760 
761 
774 static void convert_length(float32_t wi, float32_t hi, int *wo, int *ho)
775 {
776  *wo = lcd_bg_area.XSize * wi;
777  *ho = lcd_bg_area.YSize * hi;
778 }
779 
780 
793 static void convert_point(float32_t xi, float32_t yi, int *xo, int *yo)
794 {
795  *xo = lcd_bg_area.XSize * xi + lcd_bg_area.X0;
796  *yo = lcd_bg_area.YSize * yi + lcd_bg_area.Y0;
797 }
798 
799 
812 static void Display_binding_line(int x0, int y0, int x1, int y1, uint32_t color)
813 {
814  clamp_point(&x0, &y0);
815  clamp_point(&x1, &y1);
816  UTIL_LCD_DrawLine(x0, y0, x1, y1, color);
817 }
818 
819 
843 static void Display_NetworkOutput(void *p_postprocess, uint32_t inference_ms)
844 {
845 #if POSTPROCESS_TYPE == POSTPROCESS_MPE_YOLO_V8_UF
846  mpe_pp_outBuffer_t *rois = ((mpe_pp_out_t *) p_postprocess)->pOutBuff;
847  uint32_t nb_rois = ((mpe_pp_out_t *) p_postprocess)->nb_detect;
848 #elif POSTPROCESS_TYPE == POSTPROCESS_SPE_MOVENET_UF
849  spe_pp_outBuffer_t *roi = ((spe_pp_out_t *) p_postprocess)->pOutBuff;
850 #endif
851  int ret;
852 
854  ret = HAL_LTDC_SetAddress_NoReload(&hlcd_ltdc,
855  (uint32_t) lcd_fg_buffer[lcd_fg_buffer_rd_idx], LTDC_LAYER_2);
856  assert(ret == HAL_OK);
857 
859  UTIL_LCD_FillRect(lcd_fg_area.X0, lcd_fg_area.Y0,
860  lcd_fg_area.XSize, lcd_fg_area.YSize, 0x00000000);
861 
862 #if POSTPROCESS_TYPE == POSTPROCESS_MPE_YOLO_V8_UF
864  for (int i = 0; i < nb_rois; i++)
865  Display_mpe_Detection(&rois[i]);
866  UTIL_LCDEx_PrintfAt(0, LINE(2), CENTER_MODE, "Objects %u", nb_rois);
867 #elif POSTPROCESS_TYPE == POSTPROCESS_SPE_MOVENET_UF
870 #endif
871 
873  UTIL_LCD_SetBackColor(0x40000000); /* Semi-transparent background */
874  UTIL_LCDEx_PrintfAt(0, LINE(20), CENTER_MODE, "Inference: %ums", inference_ms);
875  UTIL_LCD_SetBackColor(0);
876 
878 
880  SCB_CleanDCache_by_Addr(lcd_fg_buffer[lcd_fg_buffer_rd_idx],
882 
884  ret = HAL_LTDC_ReloadLayer(&hlcd_ltdc, LTDC_RELOAD_VERTICAL_BLANKING, LTDC_LAYER_2);
885  assert(ret == HAL_OK);
886 
888  lcd_fg_buffer_rd_idx = 1 - lcd_fg_buffer_rd_idx;
889 }
890 
891 
914 static void LCD_init(void)
915 {
916  BSP_LCD_Init(0, LCD_ORIENTATION_LANDSCAPE);
917 
923  LayerConfig.PixelFormat = LCD_PIXEL_FORMAT_RGB565;
924  LayerConfig.Address = (uint32_t) lcd_bg_buffer;
925  BSP_LCD_ConfigLayer(0, LTDC_LAYER_1, &LayerConfig);
926 
932  LayerConfig.PixelFormat = LCD_PIXEL_FORMAT_ARGB4444;
933  LayerConfig.Address = (uint32_t) lcd_fg_buffer;
934  BSP_LCD_ConfigLayer(0, LTDC_LAYER_2, &LayerConfig);
935 
936  UTIL_LCD_SetFuncDriver(&LCD_Driver);
937  UTIL_LCD_SetLayer(LTDC_LAYER_2);
938  UTIL_LCD_Clear(0x00000000);
939  UTIL_LCD_SetFont(&Font20);
940  UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_WHITE);
941 
943 #if POSTPROCESS_TYPE == POSTPROCESS_MPE_YOLO_V8_UF
946 #elif POSTPROCESS_TYPE == POSTPROCESS_SPE_MOVENET_UF
949 #endif
950 }
951 
952 
963 static void Display_WelcomeScreen(void)
964 {
965  static uint32_t t0 = 0;
966  if (t0 == 0) t0 = HAL_GetTick();
967 
968  if (HAL_GetTick() - t0 < 4000)
969  {
970  UTIL_LCD_FillRGBRect(300, 100, (uint8_t *) stlogo, 200, 107);
971  UTIL_LCD_SetBackColor(0x40000000);
972  UTIL_LCDEx_PrintfAt(0, LINE(16), CENTER_MODE, "Pose estimation");
973  UTIL_LCDEx_PrintfAt(0, LINE(17), CENTER_MODE, WELCOME_MSG_1);
974  UTIL_LCDEx_PrintfAt(0, LINE(18), CENTER_MODE, WELCOME_MSG_2);
975  UTIL_LCD_SetBackColor(0);
976  }
977 }
978 
979 
990 HAL_StatusTypeDef MX_DCMIPP_ClockConfig(DCMIPP_HandleTypeDef *hdcmipp)
991 {
992  RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
993  HAL_StatusTypeDef ret = HAL_OK;
994 
995  RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_DCMIPP;
996  RCC_PeriphCLKInitStruct.DcmippClockSelection = RCC_DCMIPPCLKSOURCE_IC17;
997  RCC_PeriphCLKInitStruct.ICSelection[RCC_IC17].ClockSelection = RCC_ICCLKSOURCE_PLL2;
998  RCC_PeriphCLKInitStruct.ICSelection[RCC_IC17].ClockDivider = 3;
999  ret = HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
1000  if (ret) return ret;
1001 
1002  RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_CSI;
1003  RCC_PeriphCLKInitStruct.ICSelection[RCC_IC18].ClockSelection = RCC_ICCLKSOURCE_PLL1;
1004  RCC_PeriphCLKInitStruct.ICSelection[RCC_IC18].ClockDivider = 40;
1005  ret = HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
1006  return ret;
1007 }
1008 
1009 
1033 static void SystemClock_Config(void)
1034 {
1035  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
1036  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
1037  RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
1038 
1039  BSP_SMPS_Init(SMPS_VOLTAGE_OVERDRIVE); /* Set VDDCORE=0.9V for 800MHz+ operation */
1040 
1041  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_NONE;
1042 
1044  RCC_OscInitStruct.PLL1.PLLState = RCC_PLL_ON;
1045  RCC_OscInitStruct.PLL1.PLLSource = RCC_PLLSOURCE_HSI;
1046  RCC_OscInitStruct.PLL1.PLLM = 2; RCC_OscInitStruct.PLL1.PLLN = 25;
1047  RCC_OscInitStruct.PLL1.PLLFractional = 0;
1048  RCC_OscInitStruct.PLL1.PLLP1 = 1; RCC_OscInitStruct.PLL1.PLLP2 = 1;
1049 
1051  RCC_OscInitStruct.PLL2.PLLState = RCC_PLL_ON;
1052  RCC_OscInitStruct.PLL2.PLLSource = RCC_PLLSOURCE_HSI;
1053  RCC_OscInitStruct.PLL2.PLLM = 8; RCC_OscInitStruct.PLL2.PLLN = 125;
1054  RCC_OscInitStruct.PLL2.PLLFractional = 0;
1055  RCC_OscInitStruct.PLL2.PLLP1 = 1; RCC_OscInitStruct.PLL2.PLLP2 = 1;
1056 
1058  RCC_OscInitStruct.PLL3.PLLState = RCC_PLL_ON;
1059  RCC_OscInitStruct.PLL3.PLLSource = RCC_PLLSOURCE_HSI;
1060  RCC_OscInitStruct.PLL3.PLLM = 8; RCC_OscInitStruct.PLL3.PLLN = 225;
1061  RCC_OscInitStruct.PLL3.PLLFractional = 0;
1062  RCC_OscInitStruct.PLL3.PLLP1 = 1; RCC_OscInitStruct.PLL3.PLLP2 = 2;
1063 
1065  RCC_OscInitStruct.PLL4.PLLState = RCC_PLL_ON;
1066  RCC_OscInitStruct.PLL4.PLLSource = RCC_PLLSOURCE_HSI;
1067  RCC_OscInitStruct.PLL4.PLLM = 8; RCC_OscInitStruct.PLL4.PLLN = 225;
1068  RCC_OscInitStruct.PLL4.PLLFractional = 0;
1069  RCC_OscInitStruct.PLL4.PLLP1 = 6; RCC_OscInitStruct.PLL4.PLLP2 = 6;
1070 
1071  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) while(1);
1072 
1073  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_CPUCLK | RCC_CLOCKTYPE_SYSCLK |
1074  RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 |
1075  RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_PCLK4 |
1076  RCC_CLOCKTYPE_PCLK5);
1077 
1078  RCC_ClkInitStruct.CPUCLKSource = RCC_CPUCLKSOURCE_IC1; /* CPU: PLL1/1 = 800 MHz */
1079  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_IC2_IC6_IC11;
1080  RCC_ClkInitStruct.IC1Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; RCC_ClkInitStruct.IC1Selection.ClockDivider = 1;
1081  RCC_ClkInitStruct.IC2Selection.ClockSelection = RCC_ICCLKSOURCE_PLL1; RCC_ClkInitStruct.IC2Selection.ClockDivider = 2; /* AXI: 400 MHz */
1082  RCC_ClkInitStruct.IC6Selection.ClockSelection = RCC_ICCLKSOURCE_PLL2; RCC_ClkInitStruct.IC6Selection.ClockDivider = 1; /* NPU: 1000 MHz */
1083  RCC_ClkInitStruct.IC11Selection.ClockSelection = RCC_ICCLKSOURCE_PLL3; RCC_ClkInitStruct.IC11Selection.ClockDivider = 1; /* AXISRAM: 900 MHz */
1084  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; /* HCLK: 200 MHz */
1085  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
1086  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1;
1087  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1;
1088  RCC_ClkInitStruct.APB5CLKDivider = RCC_APB5_DIV1;
1089 
1090  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct) != HAL_OK) while(1);
1091 
1092  RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_XSPI1 | RCC_PERIPHCLK_XSPI2;
1093  RCC_PeriphCLKInitStruct.Xspi1ClockSelection = RCC_XSPI1CLKSOURCE_HCLK; /* 200 MHz */
1094  RCC_PeriphCLKInitStruct.Xspi2ClockSelection = RCC_XSPI2CLKSOURCE_HCLK; /* 200 MHz */
1095  if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK) while(1);
1096 }
void CameraPipeline_Init(uint32_t *lcd_bg_width, uint32_t *lcd_bg_height, uint32_t *pitch_nn)
Init the camera and the 2 DCMIPP pipes.
void CameraPipeline_NNPipe_Start(uint8_t *nn_pipe_dst, uint32_t cam_mode)
void CameraPipeline_IspUpdate(void)
void CameraPipeline_DisplayPipe_Start(uint8_t *display_pipe_dst, uint32_t cam_mode)
Central configuration header for the STM32N6570-DK pose estimation firmware application.
void img_crop(uint8_t *src_image, uint8_t *dst_img, const uint32_t src_stride, const uint16_t dst_width, const uint16_t height, const uint16_t dst_bpp)
Definition: crop_img.c:21
void Display_mpe_Detection(mpe_pp_outBuffer_t *detect)
Definition: display_mpe.c:117
void Display_mpe_InitFunctions(int clamp_point_init(int *x, int *y), void convert_length_init(float32_t wi, float32_t hi, int *wo, int *ho), void convert_point_init(float32_t xi, float32_t yi, int *xo, int *yo), void Display_binding_line_init(int x0, int y0, int x1, int y1, uint32_t color))
Definition: display_mpe.c:106
void Display_spe_InitFunctions(int clamp_point_init(int *x, int *y), void convert_length_init(float32_t wi, float32_t hi, int *wo, int *ho), void convert_point_init(float32_t xi, float32_t yi, int *xo, int *yo), void Display_binding_line_init(int x0, int y0, int x1, int y1, uint32_t color))
Definition: display_spe.c:100
void Display_spe_Detection(spe_pp_outBuffer_t *detect)
Definition: display_spe.c:111
#define NN_BPP
Bytes per pixel of the NN input tensor.
Definition: app_config.h:207
#define WELCOME_MSG_1
Welcome screen line 1 — active model filename.
Definition: app_config.h:310
#define NN_HEIGHT
Neural network input image height in pixels.
Definition: app_config.h:182
#define WELCOME_MSG_2
Welcome screen line 2 — memory configuration note.
Definition: app_config.h:316
#define NN_WIDTH
Neural network input image width in pixels.
Definition: app_config.h:195
#define LCD_FG_WIDTH
LCD foreground layer width = full screen width (800 pixels)
Definition: main.c:111
#define MAX_NUMBER_OUTPUT
Conditional postprocessing include based on POSTPROCESS_TYPE in app_config.h.
Definition: main.c:108
static void convert_length(float32_t wi, float32_t hi, int *wo, int *ho)
Convert normalized [0,1] dimensions to LCD pixel dimensions.
Definition: main.c:774
static void Hardware_init(void)
Initialize all hardware peripherals required for the application.
Definition: main.c:463
void IAC_IRQHandler(void)
IAC interrupt handler — traps illegal memory access violations.
Definition: main.c:730
static void Display_binding_line(int x0, int y0, int x1, int y1, uint32_t color)
Draw a skeleton connection line between two keypoints on the LCD.
Definition: main.c:812
static void LCD_init(void)
Initialize the LCD display with dual-layer configuration.
Definition: main.c:914
#define LCD_FG_FRAMEBUFFER_SIZE
Foreground framebuffer size in bytes (RGB565 = 2 bytes/pixel)
Definition: main.c:117
static void convert_point(float32_t xi, float32_t yi, int *xo, int *yo)
Convert normalized [0,1] coordinates to LCD pixel coordinates.
Definition: main.c:793
BSP_LCD_LayerConfig_t LayerConfig
LTDC layer configuration structure.
Definition: main.c:185
static void set_clk_sleep_mode(void)
Configure peripheral clocks to remain active during CPU sleep.
Definition: main.c:629
uint8_t * nn_in
Pointer to the NPU input buffer in AXISRAM (set by NeuralNetwork_init)
Definition: main.c:182
static int clamp_point(int *x, int *y)
Clamp a point to the LCD background area boundaries.
Definition: main.c:751
#define LCD_FG_HEIGHT
LCD foreground layer height = full screen height (480 pixels)
Definition: main.c:114
HAL_StatusTypeDef MX_DCMIPP_ClockConfig(DCMIPP_HandleTypeDef *hdcmipp)
Configure DCMIPP pixel clock (IC17) and CSI clock (IC18).
Definition: main.c:990
Rectangle_TypeDef lcd_bg_area
LCD background area — camera preview region.
Definition: main.c:140
__attribute__((section(".psram_bss")))
LCD background framebuffer — camera preview.
Definition: main.c:221
mpe_yolov8_pp_static_param_t pp_params
Postprocessing parameters — statically allocated, model-specific.
Definition: main.c:166
mpe_pp_out_t pp_output
Definition: main.c:167
static void Display_WelcomeScreen(void)
Display the welcome screen for the first 4 seconds after boot.
Definition: main.c:963
static void IAC_Config(void)
Configure the Illegal Access Controller (IAC).
Definition: main.c:715
uint8_t * dcmipp_out_nn
DCMIPP intermediate buffer for non-16-aligned NN inputs.
Definition: main.c:212
static void NeuralNetwork_init(uint32_t *nnin_length, float32_t *nn_out[], int *number_output, int32_t nn_out_len[])
Initialize the Neural Network input/output buffer pointers.
Definition: main.c:531
static void NPUCache_config(void)
Initialize and enable the NPU AXI cache.
Definition: main.c:660
static void Display_NetworkOutput(void *p_postprocess, uint32_t inference_ms)
Render inference results on the LCD foreground overlay layer.
Definition: main.c:843
static void SystemClock_Config(void)
Configure the system clock tree using four PLLs.
Definition: main.c:1033
Rectangle_TypeDef lcd_fg_area
LCD foreground area — full-screen overlay for inference results.
Definition: main.c:157
static void Security_Config(void)
Configure TrustZone security attributes for hardware peripherals.
Definition: main.c:684
static void NPURam_enable(void)
Enable the NPU clock and all four NPU SRAM banks.
Definition: main.c:581
volatile int32_t cameraFrameReceived
Camera frame ready flag.
Definition: main.c:179
None main(DictConfig cfg)
Rectangle descriptor for LCD layer positioning.
Definition: main.c:125
uint32_t X0
Definition: main.c:126
uint32_t XSize
Definition: main.c:128
uint32_t YSize
Definition: main.c:129
uint32_t Y0
Definition: main.c:127