Chapter 6. General Purpose Peripheral
이번 chapter는 NVIC, clock, tick interrupt & timer, GPIO, watchdog 5가지의 사용방법에 대해 배운다. 간단한 개념과 상세한 코드 상 구현에 대한 내용이 이어지므로 이해가 힘들고 정리가 어려워 개념 위주로 정리하고 넘어간다.
6.1. NVIC (Nested Vector Interrupt Controller)
- ARM Cortex-M 제품군이 유명한 이유는 인터럽트 컨트롤러에 대한 사용자 제어를 허용했기 때문이다.
- NVIC는 사용자 정의 interrupt를 포함한 각 interrupts 사이의 우선순위를 결정해 인터럽트가 연쇄되는 상황에서 interrupt의 지연을 현저히 줄여주는 역할을 수행한다.
- 이미 정의된 우선순위는 런타임에도 변경이 가능하고 각 인터럽트는 서로를 선점하기 때문에 프로그래머의 선택의 자유가 최대한 보장된다는 점에서 매력적이다.
6.2. Clock
프로그램 개발 때 우리는 시간을 계측할 상황을 빈번하게 만날 수 있다. 시간 계측에는 시스템의 clock을 측정하고 사용자가 원하는 시간을 계산할 수 있어야 한다.
- Clock의 환경설정은 RCC(Reset and Clock Control) 레지스터를 통해 가능하다. RCC의 환경설정은 PLL(Phase-Locked Loop) 로직에 따라 천차만별로 다르므로 반드시 datasheet를 참고한다.
- RCC 레지스터를 제어해 clock을 올바르게 설정했다면 ‘Peripheral Clock Source Register’의 대응하는 bit를 설정해서 주변장치를 위한 clock을 활성화할 수 있다.
- 안정된 CPU clock을 설정했다면, SysTick 타이머에 대한 환경설정을 진행한다. RVR(Reload Value Register) 레지스터를 사용하면 CPU clock을 n으로 나눠서 우리가 원하는 타이머 주기를 SysTick에 설정할 수 있다. SysTick의 CSR(Control State Register) 레지스터의 하위 3bit를 설정해서 SysTick을 활성화한다.
이때 timer 변수는 항상 volatile
로 선언한다! 컴파일러는 최적화 동작 때 예측 가능한 동작에 대해 멋대로 값을 변경하기 때문이다! 따라서 최적화를 사용하지 않도록 volatile
선언을 해줘야 한다.
6.3. GPIO
MCU의 GPIO는 몇 가지 그룹(A, B, C, D …)으로 나뉘고 각 그룹과 관련한 레지스터들이 존재한다. GPIO를 사용하고 디지털 출력 또는 입력을 하기 위해서는 이 레지스터 값을 변경하면 된다. (직접 해본 내용들이라 생략한다.)
간단하게 과정을 요약하면 다음과 같다.
- GPIO 그룹을 위한 clock source을 활성화한다.
- GPIO 핀에 대해 입출력 모드를 결정한다.
- GPIO 핀에 대해 풀업/풀다운 여부를 결정한다.
- GPIO 핀에 대해 set/reset bit를 설정해서 값을 출력하거나 입력받는다.