ARMv8-A 아키텍처는 애플리케이션 프로파일을 대상으로 하는 최신 세대의 ARM 아키텍처입니다. ARMv8이라는 이름은 이제 32비트 실행과 64비트 실행을 모두 포함하는 전체 아키텍처를 설명하는 데 사용됩니다. 기존 ARMv7 소프트웨어와의 하위 호환성을 유지하면서 64비트 와이드 레지스터로 실행할 수 있는 기능을 도입했습니다.
ARMv8-A 아키텍처는 여러 가지 변경 사항을 도입하여 훨씬 더 높은 성능의 프로세서 구현을 설계할 수 있게 합니다.
Large physical address
프로세서가 4GB 이상으로 접근이 가능하도록 합니다.
64-bit virtual addressing
4GB 제한을 초과하는 가상메모리를 사용할 수 있습니다. memory mapped file I/O 또는 sparse addressing (희소 주소 지정)을 사용하는 최신 데스크톱 및 서버 소프트웨어에 중요합니다.
Automatic event signaling
전력 효율이 높고 고성능의 spinlock을 구현할 수 있습니다.
Larger register files
31개의 64비트 범용 레지스터는 성능을 향상시키고 스택 사용량을 줄입니다.
Efficient 64-bit immediate generation
리터럴풀 사용을 줄일 수 있습니다.
Large PC-relative addressing range
공유 라이브러리 및 위치 독립 실행 파일 내에서 효율적인 데이터 주소 지정을 위한 +/-4GB 주소 범위.
Additional 16KB and 64KB translation granules
번역 조회 버퍼(TLB) 누락률과 페이지 탐색 깊이가 줄어듭니다.
New exception model
이를 통해 운영체제 및 하이퍼바이저 소프트웨어의 복잡성이 줄어듭니다.
Eifficient cache management
사용자 공간 캐시 작업은 동적 코드 생성 효율성을 향상시킵니다. 데이터 캐시 제로 명령어를 사용한 빠른 데이터 캐시 클리어 기능도 제공합니다.
Hadware-accelerated cryptography
3배에서 10배 향상된 소프트웨어 암호화 성능을 제공합니다. 이는 HTTPS와 같이 하드웨어 가속기로 효율적으로 오프로드하기에는 너무 작은 단위의 암호화 및 복호화에 유용합니다.
Load-Acquire, Store-Release instructions
C++11, C11, Java 메모리 모델에 맞춰 설계되었습니다. 명시적인 메모리 배리어 명령어를 제거하여 스레드 안전 코드의 성능을 향상시킵니다.
임베디드 시스템 개발 및 분석 중 라즈베리 파이4를 통해 디버깅 및 테스트를 하는 것이 제일 간단하고 유용할 것으로 예상되어 찾아본 결과 라즈베리파이4 자체의 JTAG Pin을 활용하여 ARM64 환경의 Bare-Metal Code 테스트를 진행 할 수 있으며 쉽게 테스트 및 디버깅이 가능하여 테스트 및 응용에 매우 강력하고 유용한 플랫폼으로 활용이 가능할 것으로 생각한다.
대략적인 연결 방법은 라즈베리파이4 Bare-Metal Code 로드 및 디버깅과 커널 디버깅에 사용할 수 있도록 OpenOCD를 사용하여 JTAG Interface를 활용 및 연결해야 한다.
그러기 위해서 라즈베리파이의 JTAG Pin을 소유하고 있는 JTAG Debugger (Olimex ARM-USB-OCD-H) 연결하여 TAP 인식 및 ARM Core Debugging 이 가능하다.
라즈베리파이4의 JTAG Pin 위치는 하기와 같다.
위에 나와있는 그림처럼 RPI의 JTAG Pin을 참고하여 사용하고자 하는 JTAG(여기서는 Olimex ARM-USB-OCD-H)의 Pin Map을 확인하여 1대1 연결하여 JTAG 통신 환경을 구축한다.
라즈베리파이에서 JTAG Pin을 사용하기 위해서는 Default Pin Func(Mux)가 JTAG 용도로 정의 되어 있지 않기 때문에
하기와 같이 booting 시 config.txt에 기입하여 Pin Mux를 진행하여야 한다.
OpenOCD에서 rpi4 디버깅 연결을 위하여 하기와 같이 rpi4 관련된 config 파일을 생성해야 하는데 하기와 같이 작성하여
rpi4.cfg를 /share/openocd/script/targets 내에 저장해준다.
# SPDX-License-Identifier: GPL-2.0-or-later
# The Broadcom BCM2711 used in Raspberry Pi 4
# No documentation was found on Broadcom website
# Partial information is available in raspberry pi website:
# https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2711/
if { [info exists CHIPNAME] } {
set _CHIPNAME $CHIPNAME
} else {
set _CHIPNAME bcm2711
}
if { [info exists CHIPCORES] } {
set _cores $CHIPCORES
} else {
set _cores 4
}
if { [info exists USE_SMP] } {
set _USE_SMP $USE_SMP
} else {
set _USE_SMP 0
}
if { [info exists DAP_TAPID] } {
set _DAP_TAPID $DAP_TAPID
} else {
set _DAP_TAPID 0x4ba00477
}
jtag newtap $_CHIPNAME cpu -expected-id $_DAP_TAPID -irlen 4
adapter speed 3000
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
# MEM-AP for direct access
target create $_CHIPNAME.ap mem_ap -dap $_CHIPNAME.dap -ap-num 0
# these addresses are obtained from the ROM table via 'dap info 0' command
set _DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000}
set _CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000}
set _smp_command "target smp"
for { set _core 0 } { $_core < $_cores } { incr _core } {
set _CTINAME $_CHIPNAME.cti$_core
set _TARGETNAME $_CHIPNAME.cpu$_core
cti create $_CTINAME -dap $_CHIPNAME.dap -ap-num 0 -baseaddr [lindex $_CTIBASE $_core]
target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase [lindex $_DBGBASE $_core] -cti $_CTINAME
set _smp_command "$_smp_command $_TARGETNAME"
}
if {$_USE_SMP} {
eval $_smp_command
}
# default target is cpu0
targets $_CHIPNAME.cpu0
OpenOCD 실행을 하기와 같이 JTAG Interface와 RPI4에 관련된 cfg 파일을 -f 매개인자를 통하여 실행한다.
일반적인 Rockchip AP의 부팅 흐름 및 Rockchip Wiki의 내용을 정리 및 설명한 글입니다.
글 하단에 참조된 Rockchip wiki에서 추가적인 내용 및 영문 내용을 확인 할 수 있으니 참고 바랍니다.
Rockchip 부팅 흐름에서 부트로더 단계에서 두개의 스테이지를 가지고 있는데, 첫번째 스테이지는 Rockchip의 miniloader 또는 u-boot의 tpl/spl 단계에서 ddr initialize 및 초기 설정 후 두번째 스테이지에서 kernel 로 점프하기 위한 준비를 위하여 u-boot을 실행한다.
U-Boot TPL/SPL or rockchip U-Boot, fully source code
Rockchp idbLoader which is combinded by Rockchip ddr init bin and miniloader bin from Rockchip rkbin project;
일반적인 U-Boot 부팅 스테이지 사용 시 하기의 표를 참고
Rochip Wiki U-Boot Boot Stage table
Boot Rom에 Rom Code(idbLoader)를 Write하여 ddr init 및 초기 AP initialize가 필요한 부분을 수행하고 u-boot 코드로 점프하게 된다.
일반적인 이미지 업데이트 모드는 u-boot 에서 GPIO Pin 형태로 Boot-pin 또는 switch 인식하여 전환하게 되는데,
만약 BootRom 내에 이미 Code가 Write 되어 Rom 내역을 수행하고 U-Boot로 jump하는 흐름에서 문제 발생되었을 때는 정상적으로 부팅을 하지 못하게 된다.
이 상황에서 Mask Rom 모드로 진입이 가능하도록 eMMC 또는 부팅 매체로 jump되지 못하도록 설정하여 Rom 이미지를 다시 Write 또는 설정한다.
Rockhip AP의 Boot Flow는 아래의 그림과 같다.
Rochip Wiki U-Boot Boot Flow
위의 그림에서 각각 나와 있는 부팅 흐름은 크게 두가지이다.
Boot Flow 1 : 일반 적인 Rockchip Boot Flow로 Rockchip miniloader 바이너리를 사용
Boot Flow 2 : 일반적인 대부분의 AP 부팅 시퀀스로 U-Boot TPL/SPL에서 DDR init 을 진행하고 다음 스테이지 진행
보통의 경우 위의 두 가지 중 Boot Flow 1을 주로 쓰며, 바이너리 형태로 배포되는 miniloader 를 rkbin github에서 받아
ARM 프로세서에는 7개의 동작 모드가 있습니다. 동작 모드는 프로세서가 어떠한 권한을 가지고 어떠한 일을 처리하고 있는지 나타내는 Processor의 동작 상태를 말합니다. 각각의 7개의 모드는 따로 SP(Stack Point)를 갖고 있습니다. (User와 System은 같은 Stack을 사용, 6개의 Stack이 존재합니다.)
각각의 모드는 아래의 표와 같습니다.
Mode
Description
CPSR M[4:0]
User
User Task나 Application을 수항 할때의 동작모드로 모든 동작모드 중 유일하게 비특권 모드이다. User Mode는 메모리, I/O장치와 같은 시스템 자원을 사용하는데 제한을 두어 사용자의 실수를 방지한다. 다른 모드(SVC)로 이동하기 위한 방법으로는 소프트웨어 인터럽트를 발생시킨다.
10000b
FIQ(Fast IRQ)
2개의 인터럽트 소스 중 아주 빠르게 인터럽트를 처리할 수 있도록 구성된 모드이다. 빠른 처를 위해서 Exception Vector에서도 최하단에 존재하고 별도의 레지스터를 소유한다.
10001b
IRQ(Interrupt Request)
일반적으로 사용되는 인터럽트로 외부 장치에서 요청되는 하드웨어적인 IRQ의 발생에 의해 ARM Core는 IRQ모드로 전환하고 인터럽트를 처리한다.
10010b
SVC(Superviser)
대부분의 시스템 자원을 자유롭게 관리할 수 있는 동작모드로 주로 커널이나 디바이스 드라이버를 처리할 때(System Call) 동작되는 모드이다.
Reset 신호 입력 시 및 SWI가 발생하면 SVC Mode로 전환된다.
10011b
Abort
메모리에서 명령을 읽거나 데이터를 읽거나 쓸때 오류가 발생할 때 Abort Mode로 전환하여 오류를 처리한다. 커널등의 패닉시 Abort Mode로 전환되어 스택 내용이 전달됨을 알 수 있다.
10111b
Undefined
명령어를 읽어 실행하고자 하나 읽어온 명령이 디코더에 정의되어 있지 않은 명령인 경우 발생되는 오류를 처리하는 모드이다.
11011b
System
User Mode와 동일한 Register를 사용하고 동일한 용도로 사용된다. User Mode와의 차이점은 특권을 갖고 있다는 것이다. (ex : OS Kernel)
11111b
위 표에 표시된 우측의 5bit 데이터는 CPSR이라는 Status Register 내에 저장된 데이터입니다. CPSR은 현재 Mode의 Status를 저장하고 있는데, 그중 우측 0~4bit인 총 5bit는 각 모드의 정보를 담고 있습니다. 32bit 중 나머지 bit는 N, Z, C, V로 컨디션 코드 및 기타 정보로 사용됩니다.
인터럽트나 에러 또는 프로그래머에 의하여 모드가 변경될 수 있습니다. Exception에 의하여 모드가 변경되기에, 각 모드의 특징에 대해 알아야만 합니다.
Abort, FIQ, IRQ 이외의 System, User, SVC Mode가 상호 모드 전환 간의 명확한 정의가 필요합니다.
System과 User는 같은 Stack을 사용하여 거의 Mode간의 차이가 없으나, User Mode에서는 Device등의 자원을 사용하는데 제한이 주어집니다. SVC Mode는 처음 Reset되었을 때 접근하는 Mode로 시스템 자원을 자유롭게 관리가 가능하며 별도의 Stack을 이용합니다.
User Mode는 OS상에 올라가는 Application의 수행 시,
OS는 기본적으로 System Mode이며,
OS나 Application이 시스템 자원(I/O등의 장치)을 사용할때에는 SVC Mode로 전환 후 사용됩니다.
이때, SVC Mode로 전환되어 시스템 자원을 사용할 권한을 얻는 것을 OS에서는 System Call이라 말합니다. OS에서 Application에 필요한 메모리 공간과 OS의 실행에 따른 메모리 공간을 분리시켜 관리합니다. Application에서 접근 권한이 없는 시스템 자원에 접근하게 허용하기 위해 운영체제는 프로세서가 제공하는 Mode 전환을 System Call Function으로 정의하여 개발자에게 제공합니다.
ARM Core의 default Mode는 SVC Mode 입니다. SVC에서 출발하여 boot up시에 ARM Core에 대한 모든 권한을 행사할 수 있어야 하기 때문입니다. U-Boot 등의 부트로더 등의서 ARM Core 부팅 및 리셋 시 SVC 모드로 Start.S 등의 어셈블리어 코드가 실행됨을 알 수 있습니다.
영국의 ARM(Advanced RISC Machines)회사는 RISC 프로세서를 설계하고 라이센싱하는 회사입니다. 그 중에서 ARM社의 주요 사항은 ARM 아키쳐를 개발 및 CPU를 디자인 합니다. ARM Processor는 로드 및 저장 아키텍처를 구현하므로 일반적인 RISC 프로세서입니다. 로드 및 저장 명령어만 메모리에 액세스할 수 있고 데이터 처리 명령어는 레지스터 내용에 대해서만 작동합니다. ARM에서 구현된 Thumb®, Thumb-2, NEON™, VFP 또는 Wireless MMX 명령어 등의 여러 명령어들에 의해 정리되고, 실행 됩니다.
ARM社는 직접 processor 반도체를 제조해 판매하지 않습니다. 대신 설계한 processor를 Intellectual property(IP) 형태로 제공하며, 이에 대한 license를 판매합니다. ARM processor IP는 일종의 설계도로, 여러 반도체 회사들이 여기에 필요한 주변장치들을 추가해 System On Chip(Soc) 형태로 반도체를 제조해 판매합니다.
ARM processor의 가장 큰 장점은 성능에 비해 전력 소비량이 작다는 것입니다. 때문에 스마트폰이나 PDA 같은 비교적 큰 computing power가 필요하지만 전력 소비량이 작아야 하는 휴대용 기기 또는 임베디드 분야에서 많이 사용합니다.
용어정리
ARM 관련 자료에는 ARM architecture, ARM core, ARM processor라는 용어들이 자주 나오는데, 각각의 의미는 다음과 같습니다. 먼저, ARM architecture는 명령어, 레지스터 구조, 메모리 구조 등의 processor 기본 구조와 동작원리에 대한 정의를 의미합니다. 그리고 이 ARM architecture에 따라 구현한 processor의 핵십 부분을 ARM core라고 합니다.
이 ARM core에 Cache, Memory Management Unit(이하 MMU), Memory Protection Unit(이하 MPU), Tightly Coupled Memory (이하 TCM), Bus Interface Unit (이하 BIU) 등의 핵심 주변장치들을 추가해놓은 것을 ARM processor라고 합니다. 아래 표는 ARM architecture와 그 architecture를 따르는 주요 ARM core 및 그 특징을 보여줍니다.
ARM architecture 별 특징과 구현 ARM core 예
Arichitecture
특징
Core
ARMv1
첫 ARM processor
26 bit addressing
ARM1
ARMv2
32 bit multiplier
32 bit coprocessor 지원
ARM2
ARMv2a
On-Chip cache
SWAP 명령 추가
ARM3
ARMv3
32 bit addressing
CPSR과 SPSR regisger 분리
Mode 추가 (undefined mode, abort mode)
MMU 지원 (가상 메모리)
ARM6 ARM7DI
ARMv3M
Signed/unsigned long multiply 명령 추가
ARM7M
ARMv4
Signed/unsigned halfwords/bytes load-store 명령 추가
Mode 추가 (system mode)
26 bit addressing 지원하지 않음
StrongARM
ARMv4T
Thumb 명령 추가
ARM7TDMI ARM9TDMI
ARMv5TE
ARMv4T의 확장판
향상된 ARM과 Thumb state 간 전환 명령 추가
Digital Signal Processing(이하 DSP) 성능 향상을 위한 명령 추가 (Enhanced DSP 명령)
ARM9E ARM10E
ARMv5TEJ
Java bytecode 성능 향상을 위한 명령 추가 (Jazelle 기술)
ARM7EJ ARM926EJ
ARMv6
Multiprocessor 명령 개선
Unaligned and mixed endian 데이터 처리 지원
Multimedia 명령 추가
ARM11
ARM core는 특징에 따라 몇 개의 family로 구분합니다. 아래 표는 ARM core family와 그 familiy에 속하는 ARM core의 대략적인 특징을 보여줍니다.
ARM core family 별 특징
ARM7
ARM9
ARM10
ARM11
파이프라인 단계
3
5
6
8
동작 주파수 (MHz)
(Worst case)
125
220 ~ 250
266 ~ 325
400
전력 소비량 (mW/MHz)
0.06
0.4
(+cache)
0.5
(+cache)
0.4
(+cache)
성능 (MIPS/MHz)
0.9
1.1
1.3
1.2
구조
Von Neumann
Harvard
Harvard
Harvard
mW/MHz: 0.13 micron 공정일 경우
MIPS: Dhrystone 2.1
ARM architecture, ARM core, 또는 ARM processor 이름에 포함된 알파벳과 숫자의 의미는 다음과 같습니다.
ARM [a] [b] [T] [D] [M] [I] [E] [J] [F] [-S]
a : 속한 ARM core family
b : memory management unit, memory protection unit, cache, TCM 구성
T : Thumb 명령 지원
D : 디버그 기능 지원
M : 64 bit 결과를 내는 곱셈기 지원
I : In-Circuit Emulator(이하 ICE) 기능 지원
E : DSP 성능 향상을 위한 명령(Enhanced DSP 명령) 지원
J : Java bytecode 성능 향상을 위한 명령(Jazelle 기술) 지원
F : Vector Floating-Point(이하 VFP) 구조 지원
-S: Electronic Design Automation(이하 EDA) 도구로 synthesis 할 수 있음
예를 들어, ARM926EJ-S의 “9”는 ARM 9 family에 속함을, “26”은 MMU와 cache 그리고 TCM 지원을, “E”는 DSP 성능 향상을 위한 명령(Enhanced DSP 명령) 지원을, J는 Java bytecode 성능 향상을 위한 명령(Jazelle 기술) 지원을, -S는 EDA 도구로 synthesis 할 수 있음을 의미합니다. 그리고 ARM 9 family 부터는 대부분 “T”, “D”, “M”, “I” 가 나타내는 기능들을 기본적으로 포함하기 때문에 이 알파벳들은 생략합니다.
Programmer's Model
Programmer's model이란 프로그래머가 프로그램을 작성하기 위해 필요한 정보를 의미합니다. 명령어, 메모리 구조, 동작 모드, 레지스터, 예외처리 방법, 인터럽트 처리 방법 등이 이에 해당합니다. 이 programmer’s model은 ARM architecture에 따라 조금씩 달라집니다.
명령어 집합, 명령어 집합 상태, 동작 모드
ARM Thumb instruction set
ARM은 ARM instruction set과 Thumb instruction set이라는 두 종류의 명령어 집합(instruction set)을 지원한다. ARM instruction set에 속하는 명령어들은 모두 32비트 명령어입니다. Thumb instruction set에 속하는 명령어들은 모두 16비트 명령어입니다. 따라서 동일한 C언어 소스코드로 작성된 프로그램을 ARM 명령어 집합으로 컴파일 했을 때와 Thumb 명령어 집합으로 컴파일 했을 때에 생성되는 바이너리 이미지의 크기는 이상적인 상황에서 ARM 명령어 집합으로 컴파일하는 것이 Thumb 명령어 집합으로 컴파일 하는 것 보다 정확히 두 배 커야 합니다.
물론 여러가지 최적화 기법을 컴파일러가 적용하기 때문에 실제로 ARM 명령어 집합의 바이너리 이미지가 Thumb 명령어 집합의 바이너리 이미지보다 두 배 큰 경우는 거의 생기지 않습니다.
Instruction Set State
ARM은 명령어 집합이 두 개이므로 해당 명령어 집합을 실행하는 프로세서의 상태도 이에 연동되어 두 개이다. ARM 명령어 집합에 해당하는 32비트 명령어를 실행하는 프로세서의 상태를 ARM 상태(ARM state)라고 하고 마찬가지로, Thumb 명령어 집합에 해당하는 16비트 명령어를 실행하는 상태를 Thumb 상태(Thumb state)라고 합니다.
당연히 ARM 상태와 Thumb 상태는 프로세서가 동작하는 중간에 서로 변경 가능하다. ARM 명령어 중에 BX나 BLX를 사용해서 ARM 상태에서 Thumb 상태로 변경할 수 있습니다. 서로 상태를 바꾸어가며 변경이 가능할 뿐 두 명령어 집합을 섞어서 사용할 순 없습니다. ARM 상태에서 ARM 명령어 집합의 명령을 수행하다가 Thumb 명령어가 나오면 반드시 프로세서의 명령어 수행 상태를 변경해야 합니다.
Cortex-A5에서는 추가로 두 가지 프로세서 상태가 더 존재 하는데, ThumbEE 상태와 Jazelle 상태입니다. ThumbEE 상태는 Thumb 명령어와는 다른 명령어로 프로그램이 실행되는 중간에 실행코드를 만들어 내며, 일종의 바이트 코드의 형태라고 보면 됩니다. Jazelle 상태는 1바이트 단위로 정렬되고 길이가 가변적인 Java 바이트 코드를 해석하기 위한 프로세서 동작 상태입니다.