주요 내용으로 건너뛰기

2. CPU Running

개요

이 섹션에서는 MCU 코어, 내부 RAM 및 플래시가 원하는 클록 속도로 실행이 되는지 확인해보겠습니다.

TouchGFX는 어떤 MCU 속도에서든 실행이 가능하지만, 클록 구성이 잘못되면 성능이 필요한 수준보다 낮아질 수 있습니다. 추후 보드 브링업 단계에서 특정 타이밍 파라미터(예: 터치 컨트롤러를 위한 I2C 클록)를 구성해야 합니다. 이는 MCU가 올바른 속도로 실행되는지 확인하지 않고서는 불가능한 작업입니다.

STM32 마이크로컨트롤러에 대한 시스템 클록을 설정합니다. 그러면 이 클록이 분할되어 FCLK 코어 클록과 다양한 주변 장치 클록(예: APB1 주변 장치 클록) 을 생성합니다.

목표

이 섹션의 목표는 프로젝트를 수정하여 올바른 클록 구성을 얻는 것입니다. 또한 내부 RAM과 플래시가 예상 속도로 실행 중인지도 확인해야 합니다.

확인

다음은 이 섹션에서 확인해야 할 사항입니다.

확인사항확인근거
SystemCoreClock 변수의 값이 올바른지 여부마이크로컨트롤러가 원하는 주파수에서 실행되도록 구성되었습니다.
내부 RAM이 읽기 가능한지 여부마이크로컨트롤러가 예상 용량의 내부 RAM을 가지고 있으며, 읽기가 가능하고, 속도가 측정됩니다.
내부 플래시가 읽기 가능한지 여부마이크로컨트롤러가 예상 용량의 내부 플래시를 가지고 있으며, 읽기가 가능하고, 속도가 측정됩니다.
캐시 비활성화 여부캐시가 비활성화된 상태에서 시스템을 실행하면 시스템이 덜 복잡하고 이해하기가 더 쉽습니다.

전제 조건

다음은 이 단계에 대한 전제 조건입니다:

  • 하드웨어 상의 클록 소스에 대한 정보. 보통은 크리스탈을 사용하지만 다른 솔루션도 가능합니다.

실행

지금부터는 필요한 MCU 주파수를 얻기 위해 프로젝트의 클록 구성을 조정하는 단계에 대해 알아보겠습니다. 그런 다음, 내부 플래시의 읽기 속도를 측정하는 방법에 대해 알아보겠습니다.

시스템 클록

STM32CubeMX에서 "Clock Configuration" 탭을 클릭하면 특정 MCU에 대한 클록 트리의 개요가 나타납니다.

클록 구성

이 예제에서는 클록 소스로 HSI를 선택했습니다. 많은 프로젝트들이 외부 크리스탈을 사용하고 있고, 적정 분배기(/M) 와 증배기(/N) 가 포함된 HSE를 사용해야 합니다. 클록 구성에 대한 자세한 설명은 이 가이드에서 다루지 않도록 하겠습니다. 클록 구성을 변경한 후에는 STM32CubeMX에서 프로젝트를 다시 생성해야 합니다(오른쪽 상단 모서리의 'Generate Code' 클릭).

생성된 코드를 통해 코어 클록(HCLK) 을 런타임 시 계산해서 변수에 저장할 수 있습니다. 이 변수는 클록 사이클과 초(예: 시작 타이머) 간의 올바른 전환을 위해 애플리케이션 코드에서 사용됩니다. 변수를 다시 계산하려면 SystemCoreClockUpdate() 함수를 호출해야 합니다. 사용자 코드 섹션에서 main.c에 호출을 삽입합니다.

SystemCoreClockUpdate

함수 마지막에 중단점을 설정한 경우에는 구성에 따라 코어 클록을 확인할 수 있습니다.

SystemCoreClock

테스트에 있어 또 다른 중요 포인트는 바로 System Timer입니다. 이 타이머는 분할된 HCLK에서 실행되어 1ms마다 인터럽트를 제공합니다. 또한 STM32Cube 펌웨어에서 ms 단위의 delay를 구현하는 데 사용됩니다.

예를 들어 메인 루프에 5초의 delay를 삽입해서 이 타이머를 테스트할 수 있습니다. 스톱워치나 유사한 수단을 이용해 확인하십시오.

지연 시간 측정

플래시와 RAM의 크기 및 속도

System Timer를 사용하면 메모리의 읽기 속도를 손쉽게 확인할 수 있습니다. System Timer 인터럽트는 밀리초마다 변수를 증가시킵니다. 코드 조각 전후에 이 변수를 읽어서 코드의 실행 시간을 측정할 수 있습니다(1ms의 해상도로). 이러한 방법을 이용해 애플리케이션의 여러 다른 위치에서도 시간을 측정할 수 있습니다. 오실로스코프 같은 외부 장치가 없다면 아주 정확하지는 않더라도 어느 정도 정확성을 얻을 수 있습니다.

이를 위해서는 먼저 결과를 저장하기 위한 2개의 휘발성 변수가 필요합니다. 여기에 결과를 저장하지 않으면 컴파일러 최적화 과정에서 측정 중인 코드가 제거되는 경우가 발생합니다.

측정 결과를 유지하는 글로벌 휘발성 변수

아래에는 0x08000000 ~ 0x08020000(128Kb) 까지 플래시를 읽고 코드의 실행 시간을 측정하는 예가 나와 있습니다:

읽기 루프 시간 측정

이와 같은 코드를 사용해 서로 다른 메모리의 속도를 확인할 수 있습니다. STM32CubeMX에 설정이 생성되면 읽기 속도를 측정하고 결과를 메모할 수 있습니다. 이후에 측정을 반복해서 수행하고 결과를 확인할 수 있습니다. 메모리의 대역폭(kb/s 단위의 읽기 속도)을 측정하려는 경우에는 측정된 시간과 데이터의 양을 비교할 수 있습니다.

STM32F429 16MHz 에서 코드는 12ms마다 실행되어 128kb/0.012s(10,666 kb/s) 의 내부 플래시(이 메서드 사용) 읽기 속도를 제공합니다.

위와 동일한 루프를 손쉽게 변경해서 모든 내부 플래시의 활성화 및 읽기 가능 여부를 확인할 수 있습니다. 시작 주소와 끝 주소만 바꾸면 됩니다.

또한 코드는 내부 RAM도 확인할 수 있습니다. F429의 RAM은 주소 0x20000000에서 시작합니다. 코어 커플드 메모리(CCM, Core Coupled Memory) 은 0x10000000에서 시작합니다. 해당 메모리 주소의 MCU는 데이터 시트에서 확인하십시오.

서로 다른 메모리를 몇 차례 측정하고 그 결과를 메모해둬야 합니다. RAM에서는 읽기 속도와 쓰기 속도를 모두 테스트하십시오.

링커 스크립트

또 하나 살펴봐야 할 것이 링커 스크립트입니다. 이 구성 파일은 링커에게 시스템의 RAM 및 플래시 주소를 알려줍니다. 링커 스크립트는 프로젝트와 함께 CubeMX에서 생성이 되지만, 검토 해보는 것이 좋습니다. 대부분의 경우에는 추후에 프로젝트의 요구에 맞게 이를 수정해야 합니다.

F7 및 H7의 캐시

ARM Cortex-M7 기반의 STM32F7 및 STM32H7 마이크로컨트롤러에는 데이터와 명령어 캐시가 포함되어 있습니다. 안정적인 플랫폼이 확보될 때까지 최소한 데이터 캐시라도 비활성화하는 것이 좋습니다. 데이터 캐시는 많은 경우에 성능을 대폭 강화하지만, 테스트 과정에서 복잡성을 초래하기도 합니다.

안정적인 플랫폼이 확보되면 데이터 캐시를 활성화할 수 있습니다. 플랫폼은 해당 문제가 데이터 캐시 관리에서 비롯된 것인지 손쉽게 식별할 수 있는데, 이는 캐시 문제가 아니면 플랫폼이 제대로 작동하기 때문입니다.

데이터 캐시의 복잡성은 MCU 코어가 캐시에 대해 읽기와 쓰기를 수행한다는 사실에서 비롯된 것입니다. 반면에 DMA2나 LTDC 같은 주변 장치들은 메모리에서 직접(캐시에서가 아니라) 읽기를 수행합니다. 이러한 이유로 예를 들어 프레임 버퍼에 데이터를 기록해도 디스플레이에 일부 데이터가 표시되지 않는 상황이 발생할 수 있습니다. 왜냐하면 데이터가 캐시에만 기록이 된다는 점에서 LTDC가 RAM에서 새 데이터를 찾지 않았기 때문입니다. 프로젝트의 특정 시점에서 캐시를 정리(flushing) 하는 것도 해결책이지만, 나중에 이 문제를 처리하는 것이 좋습니다.

System Core 섹션의 STM32CubeMX에서 캐시를 비활성화/활성화할 수 있습니다.

TouchGFX의 내부 DCache 상태 머신

TouchGFX Engine은 현재 및 마지막 렌더링 작업을 추적하는데, 상태는 HARDWARE SOFTWARE 두 가지입니다. 그리기 작업의 대다수가 하드웨어에서 수행되므로 초기 상태는 HARDWARE로 설정되어 있습니다. 상태 전환이 발생하면 상태 머신은 해당하는 가상 함수를 호출하여 캐시 무효화를 처리합니다. 상태가 HARDWARE에서 SOFTWARE로 바뀌면 가상 메소드 void touchgfx::HAL::InvalidateCache()를 호출하고, SOFTWARE에서 HARDWARE로 바뀌면 가상 메서드 void touchgfx::HAL::FlushCache()를 호출합니다. 파생된 HAL 클래스에서 사용자가 구현할 수 있도록 이러한 두 함수의 기능이 남아 있습니다.

TouchGFX Engine의 내부 DCache 상태 머신

TouchGFX Generator를 사용하고 있는 경우, 이렇게 파생된 메소드는 DCache 무효화를 위한 함수 호출을 통해 TouchGFXGeneratedHAL 클래스에 구현이 되기 때문에 추가 작업이 필요하지 않습니다.

추가 자료

여기에 링크된 문서들에는 STM32CubeMX 및 STM32 캐시에 대한 자세한 정보가 포함되어 있습니다: