ARM의 온칩 버스 규격(AMBA)에서 고속 버스와 저속 버스를 나눈 것.
왜 나누는가
-
CPU, DMA, 메모리 — → 매우 빠르게 동작해야 한다
-
UART, GPIO, 타이머 — → 그렇게 빠를 필요가 없다
-
전부 고속 버스에 붙이면?
-
느린 주변장치가 버스 전체의 속도를 끌어내린다
-
게이트 수와 전력 소모가 불필요하게 커진다
속도가 다른 것들을 분리하고 브리지로 연결하는 것이 해법이다.
구조
┌──────────────────────────────────┐
CPU ────┤ │
DMA ────┤ AHB (고속) │
│ 플래시 SRAM 이더넷 USB │
└───────────┬──────────────────────┘
│ AHB-APB Bridge
┌───────────┴──────────────────────┐
│ APB (저속) │
│ UART SPI I2C TIM GPIO ADC │
└──────────────────────────────────┘
비교
| AHB | APB | |
|---|---|---|
| 속도 | 시스템 클럭 그대로 | 분주(1/2, 1/4 …) |
| 파이프라인 | 있음 | 없음 |
| 버스트 전송 | 지원 | 미지원 |
| 멀티 마스터 | 지원 (CPU, DMA 동시) | 단일 마스터 |
| 복잡도·전력 | 높음 | 낮음 |
| 접근당 사이클 | 1~2 | 2 이상 |
APB는 단순함이 목적이다. 주변장치 IP를 만들 때 인터페이스가 간단하면 개발·검증 비용이 줄어든다.
AXI — 더 고성능
AHB : 단일 채널. 주소와 데이터가 순차적 AXI : 읽기/쓰기 채널이 분리되고 out-of-order 지원
- Cortex-A, Cortex-M7 등 고성능 코어에서 사용
실무에서 왜 알아야 하나 — 세 가지
① 클럭 설정과 최대 주파수
SYSCLK 168MHz
├─ AHB (HCLK) = 168MHz (분주 1)
├─ APB1 (PCLK1) = 42MHz (분주 4) ← 최대 42MHz 제한
└─ APB2 (PCLK2) = 84MHz (분주 2) ← 최대 84MHz 제한
APB에는 최대 주파수 제한이 있다. 분주비를 잘못 잡으면 동작하지 않거나 불안정해진다. 데이터시트의 제한을 반드시 확인한다.
② 타이머 클럭의 함정 — 매우 자주 틀리는 부분
- APB 분주비가 1이면 — → 타이머 클럭 = APB 클럭 APB 분주비가 1이 아니면 → 타이머 클럭 = APB 클럭 × 2 ★
APB1 = 42MHz (분주 4) → TIM2의 클럭은 84MHz
이것을 모르고 42MHz로 계산하면 PWM 주파수가 정확히 절반이 된다. "타이머 주기가 계산의 2배로 나온다"는 증상의 원인이다.
③ 주변장치 클럭을 켜야 한다
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // GPIOA 는 AHB1
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // TIM2 는 APB1
RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // USART1 은 APB2
클럭을 안 켜면 레지스터에 써도 값이 안 들어간다. 읽으면 0이 나오고 아무 반응이 없다.
"레지스터에 값을 썼는데 읽으면 0" 이면 십중팔구 클럭 미인가다. 임베디드 입문자가 가장 많이 겪는 문제이며, 경험자도 새 주변장치를 쓸 때 종종 잊는다.
어느 버스에 붙어 있는지는 레퍼런스 매뉴얼의 블록 다이어그램에서 확인한다. 같은 종류라도 칩마다 다르다 — STM32F4에서 USART1은 APB2, USART2는 APB1이다.
클럭 게이팅과 저전력
안 쓰는 주변장치의 클럭을 끄면 → 동적 전력 소모가 줄어든다 저전력 모드에서는 버스 자체를 정지시킨다 배터리 기기에서는 필요한 주변장치만 켜는 것이 기본 설계다.
버스 매트릭스
여러 마스터(CPU, DMA1, DMA2, 이더넷)가 여러 슬레이브(플래시, SRAM1, SRAM2)에 동시에 접근할 수 있게 교차 연결한 구조
서로 다른 경로면 동시에 진행된다. 그래서 DMA 버퍼를 CPU가 쓰는 SRAM과 다른 블록에 두면 경합이 줄어 성능이 올라간다.