본문 바로가기

뭐라도 만들어보자!!( 프로젝트 )/임베디드

4. 임베디드 실습 : Main System Clock Source

반응형

  클럭(Clock)을 설정해야 한다. 기기가 제대로 동작하기 위해서는 시간의 기준이 되는 신호가 필요하다. 이 신호가 바로 클럭이다. 클럭의 속도가 빨라지면 내부에서 명령어를 처리하는 속도가 빨라진다. 게임에 관심이 있는 사람이라면 오버클럭(Over clock)이라는 용어를 들어본 적이 있을 것이다. 기존의 안정성을 고려하여 설정된 클럭 수보다 더 높게 클럭을 설정하여 성능을 끌어올리는 것인데, 여기서의 클럭이 우리가 다룰 클럭과 같은 의미이다. 

 클럭을 높이면 왜 동작이 빨라지는 것인가? 앞서서 언급했던 것처럼 클럭은 MCU 동작의 기준이 된다. 예를 들어 0과 1의 값을 반복하는 클럭이 있다면, 특정 레지스터에서 다른 레지스터로 값을 넘길 때는 0에서 1로 클럭 값이 전환되어야 한다는 등 하드웨어적으로 규칙을 이식하는 방식으로 다른 소자들과의 충돌을 막게 된다. 클럭 수를 높인다는 것은 같은 시간 내에 0에서 1로 넘어가는 지점이 많아진다는 것이고, 더 빠르게 값을 전달할 수 있게된다. 그렇다면 클럭 수를 높이는 것이 무조건 좋은 것인가? 답은 "무작정 높이기만 할 수도 없고 좋지도 않다"이다. 신호를 0 또는 1로 판단하기 위해서는 특정 전압 이하로 내려가거나 특정 전압 이상으로 높아져야 한다. 전압이 오르거나 내리는 데는 시간이 소모되는 데, 클럭의 주기가 너무 빠르게 되면 제대로 신호가 전달되지 않을 가능성이 있다. 또한 클럭의 주파수가 증가하게 되면 소모되는 전력의 양이 증가하게 되는데, 이는 베티리 유지시간을 줄이고, 발열이 발생하는 등의 문제를 야기한다.

 본격적으로 클럭 수를 설정해보자. 우선 우리가 사용하는 보드의 사양을 알 필요가 있다.

Main system 클럭 소스에는 3 가지를 꼽을 수있다. HSI(High Speed Internal) oscillator clock , HSE (High Speed External) oscillator clock , PLL(Phased Locked Loop) oscillator clock이 그 것이다. 우리가 실습에서 사용할 것은 PLL(72MHz)이다. 참고로 우리가 사용하는 보드는 다음과 같은 스펙을 가지고 있다.

  • HSI : 8MHz
  • HSE : 8MHz
  • PLL : up to 72MHz
  • LSI : up to 60kHz
  • LSE : 32.768kHz

 넘어가서 메인 클럭 설정을 하는 방법은 다음과 같다.

  1. HSI 클럭 소스 활성화(디폴트 클럭 활성화) 및 시스템 클럭으로 설정
  2. Flash prefetch buffer 활성화
  3. HSE 클럭 소스 활성화
  4. AHB, APB, ADC, PLL entry, HSE divider, PLL Mul 설정
  5. PLL 클럭 소스 활성화
  6. PLL 클럭 소스를 시스템 클럭으로 설정

레지스터의 값을 조작하는 것으로 MCU를 조작한다. 포인터를 이용하여 레지스터에 접근하게 되고, 비트 연산을 활용하여 값을 조작하는 데, 이 글에서는 다루지 않겠다. (모르겠는 사람은 별도로 포인터와 비트 연산에 대해 공부하고 실습하기를 바란다.) 

 우선적으로 레지스터의 주소를 알아야 하는데, 이 부분은 reference manual에서 다루고 있다. reference manual에서 주소를 표기하는 방식은 가장 기본이 되는 BASE_ADDR이 있고 거기에 offset을 더하는 방식으로, 예를 들어 BASE_ADDR이   

0x0000 0000이고 offset이 0x04이면 0x0000 0004가 레지스터있는 주소가 된다. 다음은 실습에 필요한 stm32f1 계열의 메모리 맵과 레지스터 맵이다. (메모리 맵에 형광펜으로 표시된 부분이 사용할 영역이다.)

 

 다음과 같이 레지스터 값을 조작할 준비를 해준다.

 

/*register.h*/

#define PERIPHERAL_BASE			((uint32_t)0x40000000)
#define APB2PERIPH_BASE			(PERIPHERAL_BASE + 0x10000)
#define RCC_BASE				(AHBPERIPH_BASE + 0x1000)

typedef struct
{
	uint32_t CR;
	uint32_t CFGR;
	uint32_t CIR;
	uint32_t APB2RSTR;
	uint32_t APB1RSTR;
	uint32_t AHBENR;
	uint32_t APB2ENR;
	uint32_t APB1ENR;
	uint32_t BDCR;
	uint32_t CSR;
} RCC_type;

#define RCC				((volatile RCC_type   *)   RCC_BASE)

 

 다음은 실제로 클럭 소스를 설정해주는 부분이다.

 

/*clock.c*/
void rcc_init(void)
{
	uint32_t reg32;

	//HSI ON(default)
	RCC->CR |= (uint32_t) 0x00000001;
	DMB();
	while (!(RCC->CR & (1 << 1)))
		;

	reg32 = RCC->CFGR;
	reg32 &= ~((0b1 << 0) | (0b1 << 1));
	RCC->CFGR = reg32 | (0b00 << 0);
	DMB();
	while ((RCC->CFGR & (0b11 << 2)) != 0b0000)
		;

	//FLASH set
	FLASH->ACR = 0x12;
	DMB();

	//HSE ON
	RCC->CR |= (0b1 << 16);
	DMB();
	while (!(RCC->CR & (0b1 << 17)))
		;

	//AHB, APB, APB2, ADC, PLL entry, HSE divider, PLL Mul
    
	//AHB : not divided(/1)
	reg32 = RCC->CFGR;
	reg32 &= ~(0b1111 << 4);
	RCC->CFGR = reg32 | (0b0000 << 4);
	DMB();

	//APB1 : /2
	reg32 = RCC->CFGR;
	reg32 &= ~(0b111 << 8);
	RCC->CFGR = reg32 | (0b100 << 8);
	DMB();

	//APB2 : not divided
	reg32 = RCC->CFGR;
	reg32 &= ~(0b111 << 11);
	RCC->CFGR = reg32 | (0b000 << 11);
	DMB();

	//ADC : /2
	reg32 = RCC->CFGR;
	reg32 &= ~(0b11 << 14);
	RCC->CFGR = reg32 | (0b00 << 14);
	DMB();

	//PLLSRC : HSE oscillator clock selected as PLL input clock
	reg32 = RCC->CFGR;
	reg32 &= ~(0b1 << 16);
	RCC->CFGR = reg32 | (0b1 << 16);
	DMB();

	//PLL entry : HSE clock divided by 2
	reg32 = RCC->CFGR;
	reg32 &= ~(0b1 << 17);
	RCC->CFGR = reg32 | (0b0 << 17);
	DMB();

	//PLL mul : x9
	reg32 = RCC->CFGR;
	reg32 &= ~(0b1111 << 18);
	RCC->CFGR = reg32 | (0b0111 << 18);
	DMB();

	//PLL sysclk source on
	RCC->CR |= (1 << 24);
	DMB();
	while ((RCC->CR & (1 << 25)) == 0);

	//select pll
	reg32 = RCC->CFGR;
	reg32 &= ~((1 << 1) | (1 << 0));
	RCC->CFGR = reg32 | (0b10 << 0);
	DMB();

	while ((RCC->CFGR & (0b11 << 2)) != (0b10 << 2));
	//HSI off
	//RCC->CR &= ~(1 << 0);
}

 

#include "clock.h"

int main()
{
	rcc_init();
	
	while(1)
	{
    
	}

	return 0;
}

 전체적인 코드를 보고 싶으면 깃헙를 참고해주기를 바란다. 클럭 소스를 설정해보았다. 아직은 외부적으로 특별하게 보이는 것이 없다. 다음 글에서는 드디어 led를 켜 볼 생각이다.

https://github.com/youngSeok0413/embedded-system-architecture.git

 

GitHub - youngSeok0413/embedded-system-architecture: repository for studying embedded system architecture

repository for studying embedded system architecture - GitHub - youngSeok0413/embedded-system-architecture: repository for studying embedded system architecture

github.com

 

반응형