본문 바로가기

[ST_MICRO]/STM32H7

STM32H7 EVM 보드 개발 환경 설정 및 STM32 H7성능 테스트


STM32H7 EVM 보드 개발 환경 설정 및 STM32 H7성능 테스트



STM32CubeMX 를 이용하여 STM32H7 EVM 보드의 동작 테스트를 진행해 보았다.

우선 STM32H743 을 선택하고 기본 핀맵 세팅을 해 준다.



STM32H7의 클럭은 내부 64Mhz RC로 하고 400Mhz로 구동 할수 있도록 했다.










가장 기본이 되는 포트 제어 레지스터를 토글해 보니 80ns가 측정된다.

좀 이상하네..


  while (1)
  {
         GPIO_TEST_PORT->ODR ^= GPIO_TEST_PIN;
  }

      GPIO_TEST_PORT->ODR ^= GPIO_TEST_PIN;
 8003d76: 4a04      ldr r2, [pc, #16] ; (8003d88 <main+0x10c>)
 8003d78: 6953      ldr r3, [r2, #20]
 8003d7a: f083 0320 eor.w r3, r3, #32
 8003d7e: 6153      str r3, [r2, #20]
 8003d80: e7fa      b.n 8003d78 <main+0xfc>
 8003d82: bf00      nop




클럭을 외부클럭으로 하고 480Mhz로 구동 되도록 설정해 보았다. 그래도 58ns로 느리다.








그러면 비트제어 레지스터로 제어 해 보자


  while (1)
  {
         //GPIO_TEST_PORT->ODR ^= GPIO_TEST_PIN;
         GPIO_TEST_PORT->BSRR = GPIO_TEST_PIN;
         GPIO_TEST_PORT->BSRR = (uint32_t)GPIO_TEST_PIN << GPIO_NUMBER;
  }

       GPIO_TEST_PORT->BSRR = GPIO_TEST_PIN;
 8003df6: 4b05      ldr r3, [pc, #20] ; (8003e0c <main+0x190>)
      GPIO_TEST_PORT->BSRR = (uint32_t)GPIO_TEST_PIN << GPIO_NUMBER;
 8003df8: f44f 1100 mov.w r1, #2097152 ; 0x200000
      GPIO_TEST_PORT->BSRR = GPIO_TEST_PIN;
 8003dfc: 619c      str r4, [r3, #24]
      GPIO_TEST_PORT->BSRR = (uint32_t)GPIO_TEST_PIN << GPIO_NUMBER;
 8003dfe: 6199      str r1, [r3, #24]
 8003e00: e7fc      b.n 8003dfc <main+0x180>
 8003e02: bf00      nop


480Mhz 구동시에 25ns로 STM32F4 보다 느린 속도가 측정된다




메인 루프에서  GPIO를 On/Off 했을때 시간을 측정 해보면..

  while (1)
  {
      //GPIO_TEST_PORT->ODR ^= GPIO_TEST_PIN;
         HAL_Delay(1);
      GPIO_TEST_PORT->BSRR = GPIO_TEST_PIN;
      GPIO_TEST_PORT->BSRR = (uint32_t)GPIO_TEST_PIN << GPIO_NUMBER;
  }


역시 25ns 로 측정된다.



STM32F7 EVM 보드의 GPIO 성능테스트 결과에서 8ns와 비교하면 3~4배 정도 느리다. 왜 이럴까?
분명 클럭이 480Mhz로 2배 이상 빠른데...



D캐시  I캐시를 사용으로 설정해도 결과는 동일한다.

  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();
  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();



데이터시트를 좀더 찾아 보자
GPIO 최대 클럭주파수를 보면 220Mhz까지 사용 가능한데...




시스템 클럭을 확인해 보면 480Mhz로 출력된다. 클럭 설정에는 문제가 없는데...

  SysClk = HAL_RCC_GetSysClockFreq();

  HClk = HAL_RCC_GetHCLKFreq();

  PClk1 = HAL_RCC_GetPCLK1Freq();

  PClk2 = HAL_RCC_GetPCLK2Freq();



  printf("SysClk (System Clock) = %lu Hz\r\n", SysClk);

  printf("HClk (AHB / Main CPU Clock) = %lu Hz\r\n", HClk);

  printf("PClk1 (Peripherals Clock 1) = %lu Hz\r\n", PClk1);

  printf("PClk2 (Peripherals Clock 2) = %lu Hz\r\n", PClk2);



Clk1=480000000

SysClk (System Clock) = 480000000 Hz

HClk (AHB / Main CPU Clock) = 240000000 Hz

PClk1 (Peripherals Clock 1) = 120000000 Hz

PClk2 (Peripherals Clock 2) = 120000000 Hz




MCO 핀으로 출력 클럭을 확인해 보면 480Mhz을 4분주한 120Mhz가 출력이 된다.
그런데 왜 GPIO 토글 속도가 느릴까? 

뭔가 설정에 문제가 있을것 같은데..
28ns면 STM32F1 GPIO 속도 테스트 결과 와 비슷하다. 너무 느리다.


무엇이 문제 일까?



[최종 결론] STM32H7 vs STM32F7 GPIO 속도 테스트2 - 문제 해결 참고





//HSI 64Mhz - >480Mhz
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 60;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART1;
  PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLL1QCLK, RCC_MCODIV_8);
}








//HSE 25Mhz -> 400Mhz
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  /** Supply configuration update enable
  */
  HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
  /** Configure the main internal regulator output voltage
  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 5;
  RCC_OscInitStruct.PLL.PLLN = 160; //192 -> 480Mhz
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB busses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_HRTIM1|RCC_PERIPHCLK_USART1;
  PeriphClkInitStruct.Usart16ClockSelection = RCC_USART16CLKSOURCE_D2PCLK2;
  PeriphClkInitStruct.Hrtim1ClockSelection = RCC_HRTIM1CLK_TIMCLK;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLL1QCLK, RCC_MCODIV_4);
}






반응형