[STM32] RCC

pikamon·2020년 12월 28일
1

STM32

목록 보기
2/12

본 글은 STM32F769I MCU를 기준으로 작성되었습니다.
세부적인 내용은 제품군마다 조금씩 다를 수 있습니다.


1. RCC란?

RCC란 Reset and Clock Control의 줄임말로, STM32에 있는 각 모듈의 동작 주파수를 제어하는 모듈을 말한다. STM32에서는 RCC를 이용하여 CPU 코어나 각 주변장치 컨트롤러에 들어가는 클럭의 주파수를 제어할 수 있다.

2. Oscillator 종류

STM32에서 사용되는 오실레이터는 총 4개이며, 아래와 같다.

  • HSE: High Speed External Oscillator (25MHz)
  • HSI: High Speed Internal Oscillator (16MHz)
  • LSE: Low Speed External Oscillator (32.768KHz)
  • LSI: Low Speed Internal Oscillator (32KHz)

주파 속도에 따라 High/Low Speed가 나뉘어지며, 외장/내장 여부에 따라 External과 Internal로 나뉘어진다.

이를 표로 나타내면 아래와 같다.

-ExternalInternal
High SpeedHSEHSI
Low SpeedLSELSI

위 네 가지 오실레이터 중 하나 또는 여러 개를 선택하여 클럭을 생성할 수 있다.

아래 Clock Configuration 그림을 보면 선택한 오실레이터로부터 각종 클럭이 만들어지는 것을 볼 수 있다.

아래 글을 보면, 기본적으로 아무 설정도 하지 않으면 16MHz의 HSI를 디폴트로 사용한다고 되어 있다. 실제로는 PLL에 들어간 HSI의 주파수가 뻥튀기되어 사용된다.

3. Clock Tree

STM32769I의 클럭 트리는 아래와 같다.

OSC32, OSC, I2S, PHY Ethernet, USB 2.0으로부터 들어온 클럭이 멀티플렉서, 프리스케일러 등을 거치면서 MCU 내 모듈들에서 사용하기 위한 주파수들로 변환되어 각 모듈에 입력으로 들어가는 모습을 위 그림을 통해 알 수 있다.

4. Configuration

Configuration에서 RCC 설정을 변경해보자.

ioc 파일에서 Pinout & Configuration - System Core - RCC를 선택한 다음, HSE와 LSE를 Crystal/Ceramic Resonator로 활성화시킨다.
클럭 출력 확인을 위해 MCO1번도 체크해준다.

그리고 Clock Configuration에서 PLL Source Mux의 오실레이터를 HSE로 선택한 후, 'Resolve Clock Issues' 버튼을 누른다.

그러면 아래와 같이 PLL Clock의 소스가 HSE로 설정되며, 자동으로 prescale 값이 조정되는 것을 볼 수 있다.

SYSCLK이 100MHz로 설정된 것을 볼 수 있다. 실제론 PLL 모듈을 이용하여 SYSCLK을 216MHz까지 설정할 수 있다고 하니, 더 높은 클럭이 필요하다면 prescale 숫자를 정교히 잘 맞춰서 216MHz로 설정하면 될 것 같다.

그리고 저장하면 설정에 맞는 코드가 자동으로 생성된다.

5. Source Code

생성된 코드는 아래와 같다.

#include "main.h"

void SystemClock_Config(void);
static void MX_GPIO_Init(void);

int main(void)
{
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();

	while (1)
	{
		;
	}
}

void SystemClock_Config(void)
{
	RCC_OscInitTypeDef RCC_OscInitStruct = { 0, };
	RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0, };

	HAL_PWR_EnableBkUpAccess();

	__HAL_RCC_PWR_CLK_ENABLE();
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE3);

	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSE; /* 1 */
	RCC_OscInitStruct.HSEState = RCC_HSE_ON; /* 2 */
	RCC_OscInitStruct.HSIState = RCC_HSI_ON;
	RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; /* 3 */
	RCC_OscInitStruct.PLL.PLLM = 12; /* 4 */
	RCC_OscInitStruct.PLL.PLLN = 192;
	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
	RCC_OscInitStruct.PLL.PLLQ = 4;

	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
	{
		Error_Handler();
	}

	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
	{
		Error_Handler();
	}

	HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1); /* 5 */
}

static void MX_GPIO_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = { 0, };

	__HAL_RCC_GPIOA_CLK_ENABLE();

	GPIO_InitStruct.Pin = GPIO_PIN_8;
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
	GPIO_InitStruct.Alternate = GPIO_AF0_MCO;
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void Error_Handler(void)
{
	__disable_irq();

	while (1)
	{
		; // Infinite loop
	}
}

설명을 위해 각 코드 우측에 주석으로 번호를 표시하였다.

  1. 오실레이터 초기화 시 HSE도 같이 초기화하는 것을 볼 수 있다.
  2. HSE State를 On으로 설정하는 것을 볼 수 있다.
  3. PLL Mux에서 HSE를 선택하는 것을 볼 수 있다.
  4. 'Resolve Clock Issues' 선택 시 PLLM의 값이 12로 바뀐 것을 해당 코드에서 확인할 수 있다.
  5. PA8 핀으로 출력할 클럭 소스를 정하는 부분이다. HSE를 출력하려면 RCC_MCO1SOURCE_HSE을, HSI를 출력하려면 RCC_MCO1SOURCE_HSI를 입력하면 된다.

6. Test

위 코드를 실행하면 시스템 클럭이 100MHz HSE로 설정되는 것을 볼 수 있다.
PA8 핀에서는 출력되는 클럭의 파형을 볼 수 있는데, 아래 회로도 그림을 보면 PA8 핀이 STM32F769I-DISC1 보드 위에서 TP2와 연결되어 있는 것을 볼 수 있다.

보드에서 TP2를 찾아서 오실로스코프로 찍어보면 100MHz에 해당하는 구형파 신호가 나오는 것을 볼 수 있다.

profile
개발자입니당 *^^* 깃허브 https://github.com/pikamonvvs

0개의 댓글