
라즈베리 파이의 부팅 과정 (간단 version)
- 파워 온! → GPU가 먼저 켜진다. (CPU는 죽어있는 상태)
- 1단계 부트로더 (ROM) : GPU가 이걸 ROM에서 실행. 이 단계에서 SD Card에서 2단계 부트로더를 찾음
- 2단계 부트로더 (bootcode.bin) : SDRAM의 활성화. 이 단계에서 RAM에 3단계 부트로더를 로드
- 3단계 부트로더 (start.elf) : GPU Firmware로 동작하며, 커널 이미지를 읽어옴
- 커널 부팅 준비 (start.elf) : 시스템 설정을 읽고, 커널 이미지 로드 + CPU에게 제어권 넘기기
- 커널 부팅 시작 : 리눅스 커널이 CPU에서 실행되기 시작
ㅤㅤ
라즈베리 파이는 GPU가 주도권을 가지고 부팅을 시작한다.
단계별로 나눠둔 이유? 각 단계마다 필요로 하는 메모리 공간이 다르기 때문.
놀랍게도 CPU는 마지막 단계에 와서야 활성화된다.
위 과정이 어떻게 일어나는지에 대해서 한 번 살펴보자.
왜 GPU 먼저 켜지나?
이거는 그냥 라즈베리파이의 태생과 관련된 이유였음.
ㅤㅤ
브로드컴에서 만든 BCM 칩인 Broadcom BCM2711 을 기반으로 우리의 SoC와 보드가 만들어졌음. 이 회사는 원래 셋톱박스를 만들던 회사라서, 칩 자체가 TV 영상처리나 영상 디코딩 같은 미디어 처리를 위해 설계된 칩임. → 이걸 싸게 구매해서 라즈베리파이에다가 올린 것임!
ㅤㅤ
그렇다보니, 칩을 설계할 때 CPU 보다 GPU 를 중심으로 설계가 되었고 최적화가 진행되었음. GPU를 중심에 두고 CPU를 주변장치처럼 사용하는게 원래 이 칩의 설계 의도. (나는 CPU가 무조건 주인인 줄 알았는데, 아닌 경우도 있나보다. 역시 식견이 중요해.)
ㅤㅤ
이 칩을 구성할 때 고려했던 시나리오에 의하면, 아예 CPU를 사용할 일이 없었을 수도 있음. 왜냐? “전원이 들어와서 GPU 활성화 → 들어오는 영상에 대한 데이터를 바로 가공해서 비디오로 출력하기.” 위 동작만 한다면 사실 CPU가 개입하지 않아도 된다. 필요한 경우에 CPU를 켜고 동작을 수행하는게 더 최적화가 가능하니깐. CPU는 풀파워로 항상 켜져있지 않고 그냥 대기만 하다가 필요한 순간에 CPU를 깨우고 일 시키고 다시 잠재우는 방식을 해도 괜찮음. (진짜 리눅스의 커널 모듈처럼)
ㅤㅤ
GPU 도 Fetch → Decode → Execute의 구조로 동작한다. CPU랑 사실상 다를바가 없다.
그렇기 때문에 가장 먼저 GPU가 불려서 HW를 초기화하고 깨우는 작업을 처리하게 된다.
ㅤㅤ
그러면 혹시 라즈베리파이에서는 커널을 돌리고 프로세스들을 관리할 때 GPU가 여전히 주인일까?
ㅤㅤ
놉! 이때는 CPU가 주인이 되어서 OS를 실행하고 애플리케이션을 실행하고 시스템을 관리한다. GPU는 그냥 CPU의 연산 가속기 역할만 한다. 그럼에도 전체 칩 자체의 주인은 GPU이기 때문에, CPU의 클럭이나 부팅 설정, 전원 관리 등의 중요한 역할은 GPU의 명령으로 동작한다.
ㅤㅤ
HW 레벨의 관리는 GPU / SW 레벨의 관리자는 CPU
ㅤㅤ
부트로더의 단계가 나눠진 이유?
각각의 단계마다 설정이 필요한 자원 (메모리)를 사용하게 된다.
위처럼 단계를 나눠둔 이유는 SDRAM을 활성화하기 전 (활성화를 위한 준비) / SDRAM의 활성화 / SDRAM의 활성화 이후 라고 생각하면 된다.
ㅤㅤ
- 1단계 : ROM (L2 Cache의 크기 제한) → SDRAM이 없는 상태라서 아주 작은 부트로더만 실행할 수 있음
- 2단계 : SDRAM의 활성화가 목적 → 이걸 활성화하면 RAM에 큰 프로그램들을 올려서 실행할 수 있음
- 3단계 : RAM이 활성화 되었음 → 이제 복잡한 GPU Firmware 프로그램이나 커널 로딩 등을 수행할 수 있음
ㅤㅤ
부팅 시퀀스
1단계 부트로더 ROM
SoC 내부 ROM에 이미 구워져있어서 변경할 수 없다.
이건 VideoCore GPU 가 돌려야하는 코드이기 때문에, GPU의 명령어로 작성되어있다.
SDRAM의 활성화를 통해 RAM에 프로그램을 올리고 실행해야 하는데, 이 타이밍에는 SDRAM이 아직 죽어있는 상태 → RAM의 초기화를 하기 위해서 잠시 L2 cache를 이용한다.
- 128KB 정도의 크기L2 cache를 사용한다.
bootcode.bin를 L2 cache로 올리는게 목적- L2 캐시는 HW적으로 보드에 붙어있고, 전원만 인가하면 바로 사용이 가능한 작은 HW 메모리
- ㅤㅤ
주요한 역할은 SD Card를 활성화하고, boodcode.bin 이라는 파일을 찾는 것이다.
1. Power ON → GPU의 Reset Vector부터 실행 시작
2. ROM에 하드코딩된 코드 실행
3. SD Card 인터페이스 초기화
4. SD Card의 FAT32 파일시스템 마운트
5. bootcode.bin 파일 찾기
6. bootcode.bin을 L2 cache로 읽어들임
7. L2 cache의 bootcode.bin으로 점프
ㅤㅤ
2단계 부트로더 bootcode.bin
L2 cache에 올라와있는 bootcode.bin 에서 실행이 시작된다. 이것도 VideoCore GPU가 돌려야하는 코드. GPU 명령어로 작성되어있다.
ㅤㅤ
2단계에서부터 드디어 SDRAM을 활성화하기 시작한다. 주요한 역할은 SDRAM을 초기화하고 RAM에 3단계를 위한 start.elf을 올리는 것.
1. L2 cache에서 실행 시작
2. SDRAM 컨트롤러 초기화
- 클럭 설정
- 타이밍 파라미터 설정
- SDRAM 칩 초기화 시퀀스
3. SDRAM 테스트 (정상 동작 확인)
4. SD Card에서 loader.bin (start.elf) 읽기
5. loader.bin을 RAM에 로드
6. RAM의 loader.bin으로 점프
ㅤㅤ
3단계 부트로더 start.elf
RAM에 올라와있는 start.elf 를 실행한다. 아직까지도 CPU는 살려주지 않았다. GPU가 이 코드를 실행하며, 그렇기에 이 녀석도 GPU 명령어로 작성되어있다.
ㅤㅤ
주요한 역할은 RAM에 Linux 커널의 로드와 CPU를 활성화하는 것.
1. RAM에서 실행 시작 (이제 메모리 제약 없음)
2. config.txt 읽기
- GPU 메모리 할당
- ARM CPU 클럭 설정
- 오버클럭 설정 등
3. cmdline.txt 읽기 (커널 부팅 파라미터)
4. kernel.img 읽기
5. kernel.img을 RAM의 특정 주소(보통 0x8000)에 로드
6. Device Tree (*.dtb) 로드
7. ARM CPU 설정:
- CPU 클럭 활성화
- Reset Vector 설정 (0x8000)
- ARM CPU에게 reset 신호 해제
8. ARM CPU 실행 시작!
ㅤㅤ
3단계 부트로더가 끝나는 시점부터 (reset 신호 해제) CPU가 이 시스템의 주인이 되어서 동작하기 시작한다. kernel.img의 첫 주소를 읽으면서 Linux 커널의 부팅이 시작된다.
ㅤㅤ
Linux 커널의 부팅은 FreeRTOS의 커널에서 봤던 것처럼 필요한 모듈들의 초기화 + 커널 운영을 위한 시스템 설정 초기화 + 스케줄링 등의 작업을 처리하게 되지 않을까. (필요하면 나중에 찾아보기!)
ㅤㅤ
'Embedded System > Embedded Linux' 카테고리의 다른 글
| [Embedded Linux] 리눅스의 프로세스 타파 (0) | 2025.11.27 |
|---|---|
| [Embedded Linux] Linux 커널 아키텍처 (1) | 2025.11.25 |
| [Embedded Linux] 시스템콜 함수가 호출되면 아래에선 무슨일이 일어나나 (0) | 2025.11.24 |
| [Embedded Linux] UNIX, POSIX 그리고 LINUX (1) | 2025.11.23 |