[ST_MICRO]/STM32H72018. 12. 1. 04:53

STM32H7 vs STM32F7 MCU성능 테스트 - FPU 성능테스트

 

STM32H7 vs STM32F7 MCU성능 테스트 - FPU 성능테스트

 

STM32H7 GPIO 토글 속도 테스트 결과에서 STM32H7의 버스 구조의 특성상 GPIO접근에 속도 제한이 있다는 것은 확인 했는데 그렇다면 CPU부하를 걸어 속도 체크를 해 보면 루프 성능을 확인 할수 있을것 같다.

 

FPU를 사용할수 있도록 루트처리 함수를 이용해 수행 속도를 측정해 보았다.

 

#include  <math.h>

 
volatile double sq_result;
int i;
 
  while (1)
  {
         GPIO_TEST_PORT->BSRR = GPIO_TEST_PIN;
         d = 0;
         for(i=0;i<10;i++)
         {
                d += sqrt(2.0);
         }
         GPIO_TEST_PORT->BSRR = (uint32_t)GPIO_TEST_PIN << GPIO_NUMBER;
  }

 

 

 

STM32H7 @400Mhz 에서 루트연산을 10번 계산한 결과 190ns로 측정된다.

 

 

 

STM32CubeIDE 에서 STM32H7 FPU옵션 설정

 

 

 

STM32H7 @480Mhz 에서 루트 10번 계산 결과 135ns

 

 

 


 

 

STM32F7에서는 어떨까?

 

테스트 결과 216Mhz에서 450ns 정도 측정되다.

 

 

 

 

 


 

 

 

그렇다면 STM32F4에서는?
5000ns 정도로 H7에 비해 20배 이상 속도 차이가 발생하고 있다.
 
 
 
STM32F4의 경우 FPUv4 이다.

 

 

 

 

결론적으로 STM32H7이 STM32F4보다는 20배 STM32F7보다는 4배 정도 더 빠른것 같다.

Posted by nexp

댓글을 달아 주세요

[ST_MICRO]/STM32H72018. 11. 29. 02:37

STM32H7 vs STM32F7 GPIO 속도 테스트2 - 문제 해결

STM32H7 vs STM32F7 GPIO 속도 테스트2 - 문제 해결


STM32 H7성능 테스트 하면서 오래동안 고심했던 H7 GPIO 속도 문제가 해결됬다.
STM32F7의 GPIO 토글 속도를 측정하면 8ns 정도 나오는데 STM32H7의 GPIO 토글 속도를 측정해 보면 28ns 정도나온다.


결론은 STM32H7, STM32F7의 하드웨어 구조의 차이에서 오는 문제였다.


우선 STM32F7의 경우 GPIO는 AXI -> AHB (216Mhz) 로 바로 출력이 가능하므로 2 머신 사이클에 제어 가능하다.






STM32F7 Series system architecture 를 보면 F7의 하드웨어 구조를 확인 할 수 있다.






STM32H7 의 경우 GPIO는 AXI AHB -> AHB4(200Mhz) 를 통해 제어 가능하기 때문에 지연이 생긴다고 한다.

그래서 DMA나 인터럽트를 통해 제어 하면 2머신 사이클에 제어 가능하다고 한다.






버스 구조가 복잡한 대신 하드웨어로 처리 해 주는 부분이 많아 코드상의 main 루프에서 접근하면 오히려 더 느리게 나왔던 것이다.


STM32H7의 성능 지표를 확인해 보면 속도 차이를 확인해 볼 수 있다.


Posted by nexp

댓글을 달아 주세요

[ST_MICRO]/STM32H72018. 11. 29. 02:36

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);
}






Posted by nexp

댓글을 달아 주세요

[ST_MICRO]/STM32F72018. 5. 8. 03:31

[STM32F7 EVM] STM32F767 성능 테스트 - CubeMX 개발환경 설정

STM32F7 CubeMX 개발환경 설정

CubeMX 실행하고 STM32F767VI 칩을 선택한다.

 

 

 

기본 동작 확인을 위해 GPIO, MCO, UART를 설정한다.

 

 

 

클럭은 내부클럭으로 하고 PLL셋팅을 해서 STM32F7의 최대 클럭인 216Mhz로 설정한다.

 

 

 

MOC1(PA8) 핀으로 CPU의 클럭를 측정 할 수 있다.

 

 

 

 

 

 

 

STM32F7 동작 속도 확인 

CubeMX 가 생성하는 가장 기본 코드에서 클럭 출력하는 코드 추가 해서 클럭을 확인 해보 면

  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);

 

 

STM32 시스템 클럭 216Mhz, PCLK1 은 54Mhz로 정상 출력 되는것을 확인 할 수 있다.

SysClk (System Clock) = 216000000 Hz

HClk (AHB / Main CPU Clock) = 216000000 Hz

PClk1 (Peripherals Clock 1) = 54000000 Hz

PClk2 (Peripherals Clock 2) = 54000000 Hz

 

 

스코프로 RCC_MCO(PA8)핀을 확인해 보면 216Mhz의 2분주 한 108Mhz가 출력되는것을 확인 할 수 있다.

이로서 클럭 설정은 문제 없는것으로 확인 했다.

 


 

STM32F7 성능 테스트

이제 STM32F7의 성능 테스트를 해보자

우선 STM32F7 EVM 보드에 연결되어 있는 PA5 LED를 토글 하는 코드로 테스트 해 보면 36ns( 13Mhz) 정도로 출력이 된다.

 
  while (1)
  {
         GPIO_TEST_PORT->ODR ^= GPIO_TEST_PIN;
  }
 
          GPIOA->ODR ^= GPIO_PIN_5;
800193a:    4a04          ldr    r2, [pc, #16]    ; (800194c <main+0x98>)
800193c:    6953          ldr    r3, [r2, #20]
800193e:    f083 0320     eor.w    r3, r3, #32
8001942:    6153          str    r3, [r2, #20]
 
8001944:    e7fa          b.n    800193c <main+0x88>
8001946:    e7fe          b.n    8001946 <main+0x92>
 
 
 
 
 
 
 
비트 제어로 출력해 보면 4.8ns(21Mhz)로 출력되는 것을 확인 할수 있다.
 while (1)
  {
     GPIOA->BSRR = GPIO_PIN_5;
     GPIOA->BSRR = (uint32_t)GPIO_PIN_5 << GPIO_NUMBER;
  }

 

 

 

 

 

 

좀더 보기 편하게 하기위해 Delay를 주었다. 7.3ns 정도로 측정된다.

 

 

기존 STM32시리즈 중에서는 가장 속도가 빠른것 같다. 다른 MCU속도 측정 결과 참고

 

Posted by nexp

댓글을 달아 주세요

[ST_MICRO]/STM32F0x2017. 6. 1. 03:44

STM32F0 성능 테스트 - STM32CubeMX HAL Code


STM32F0 성능 테스트 - STM32CubeMX HAL Code




STM32F0는 Cortex-M0코어 1$이하의 저렴한 MCU로 가격에 민감한 제품에 사용하기 좋은 제품이다.

GPIO On/Off 주기를 측정해 MCU 성능 체크 해 보고 있는데 [STM32F0-SS EVM] 보드를 이용해서 테스트 해 보았다.


[참고]STM32 MCU 성능 측정 테스트



우선 최대 클럭 48Mh로 설정하고 STM32CubeMX 기본 초기화 코드 생성하고 PB1 을 토글했다. 


static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);

  /*Configure GPIO pin : PB1 */
  GPIO_InitStruct.Pin = GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}




포트 토글 함수 수행 해 보면 476ns(1Mhz) 정도 측정된다. HAL_Code를 사용하면 좀 느린것 같다.

  while (1)
  {
         HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
  }






함수를 사용하지 않고 레지스터를 접근해서 포트 토글 해 보면 186ns(2.6Mhz) 정도 측정이 된다.

  while (1)
  {
         GPIOB->ODR ^= GPIO_PIN_1;
  }






비트 제어 명령으로 제어 해 보면 40ns(6Mhz) 로 측정된다.
  while (1)
  {
         //HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
         GPIOB->BSRR = GPIO_PIN_1;
         GPIOB->BRR = GPIO_PIN_1;
  }







좀더 보기 편하게 하기위해 Delay를 주었다.

  while (1)
  {
         //HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
         GPIOB->BSRR = GPIO_PIN_1;
         GPIOB->BRR = GPIO_PIN_1;
         HAL_Delay(1);
  }



그런데 속도가 40ns에서 60ns 로 느려졌다.

왜 그렇지?
어셈 코드를 확인 해 보니 HAL_Delay() 가 두번 호출 되는듯 한데...
개발환경의 설정 문제인가?

      GPIOB->BSRR = GPIO_PIN_1;
80011f4:    2402          movs    r4, #2
80011f6:    4d04          ldr    r5, [pc, #16]    ; (8001208 <main+0xb0>)
80011f8:    61ac          str    r4, [r5, #24]
      HAL_Delay(1);
80011fa:    2001          movs    r0, #1
      GPIOB->BRR = GPIO_PIN_1;
80011fc:    62ac          str    r4, [r5, #40]    ; 0x28
      HAL_Delay(1);
80011fe:    f7ff f869     bl    80002d4 <HAL_Delay>

8001202:    e7f9          b.n    80011f8 <main+0xa0>





HAL_Delay를 위쪽에 넣으니 어셈코드도 정상적으로 나오고 속도도 40ns로 측정이 된다.

  while (1)
  {
         //HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1);
         HAL_Delay(1);
         GPIOB->BSRR = GPIO_PIN_1;
         GPIOB->BRR = GPIO_PIN_1;
  }


      HAL_Delay(1);
80011f8:    2001          movs    r0, #1
80011fa:    f7ff f86b     bl    80002d4 <HAL_Delay>
      GPIOB->BSRR = GPIO_PIN_1;
80011fe:    61ac          str    r4, [r5, #24]
      GPIOB->BRR = GPIO_PIN_1;
8001200:    62ac          str    r4, [r5, #40]    ; 0x28

8001202:    e7f9          b.n    80011f8 <main+0xa0>






Posted by nexp

댓글을 달아 주세요