본문 바로가기

ARM 프로세서가 많이 쓰이는 이유는?

히언|2011.12.26 16:56

-작게 +크게
신고
500 ARM 프로세서가 많이 쓰이는 이유는?뭘 알아야 이해를 하지

임베디드 시스템에서는 다양한 종류의 프로세서가 사용되고 있어요. 예전에는 임베디드 시스템이라는 용어가 낯설기만 했지만 휴대폰이 보편화 되면서 이제는 우리의 일상이 됐답니다. 임베디드 시장은 매우 크고 넓은데 그 중에서 일부 이긴 하지만 휴대폰 및 휴대기기 시장이 있답니다.휴대기기 시장에는 많은 제품들이 있으며, 이러한 제품의 절대 강자는 뭐니뭐니해도 베터리 사용량이며, 얼마나 오랫동안 사용할 수가 있느냐 랍니다. 여기서 키 포인터가 "어떤 프로세서가 더 저전력인가" 라는 거죠. CPU를 만드는 많은 업체들이 가장 치열하게 경쟁하고 있는 항목 중에 하나가 저전력이랍니다. 저전력이라고 하면 역시 ARM 프로세서를 뺄 수가 없죠. 그 외에도 몇 가지의 이유가 있는데, 어떤 특징이 있는지 알아 보아요.첫 번째, RISC 아키텍쳐랍니다. ARM 프로세서는 RISC 아키텍쳐이며, 명령어와 내부 레지스터가 32bit로 구성되어 있답니다. RISC(Reduced Instruction Set Computer)는 CISC(Complex Instruction Set Computer)에 비해 명령어 구조가 간단하고 명령어 수가 적어 보다 빠르고 효율적으로 처리가 가능하답니다. Host PC(노트북,데스크탑)에서 사용하는 대부분의 프로세서는 CISC랍니다. 이 프로세서는 열이 많이 발생하기 때문에 반드시 열을 내려주는 냉각팬(Cooling fan)이 필요하지만 RISC는 냉각팬이 필요하지 않답니다. 냉각팬이 없어도 된다는 것은 그만큼 부피가 작은 휴대기기를 만들 수가 있다는 것이죠. 그래서 대부분의 임베디드 시스템에는 RISC 아키텍쳐를 선호한답니다. 명령어와 내부 레지스터가 32bit로 구성되어 있다는 말은 어떤 의미를 담고 있을까요?ARM 프로세서 내에 있는 ARM core를 우선 살펴봐야 해요. 아래 그림은 ARM9TDMI core랍니다.   



REGBANK① 안에는 레지스터들이 있답니다. ARM core에는 37개의 레지스터들이 있는데, 개발자는 하드웨어 디버거를 이용하면 직접 레지스터의 값들을 볼 수가 있답니다.   

CPSR 레지스터는 32bit로 구성되어 있는데, 37개의 레지스터들 모두가 32bit의 length를 가지고 있기 때문에 32Bit 구성이라고 부른답니다. 그런데 여기까지만 이해하시면 안되구요 전체 흐름까지 파악을 해야 하죠. 아래를 보시면 메모리로부터 CPU 안으로 ① 패치(Fetch)를 한답니다. 여기서 CPU 안이라고 하는 것은 ARM core를 의미하는 것이고, ARM core는 메모리로부터 데이타를 읽어 드린 후 ARM 어셈블리 명령어②로 해석하게 되죠.  
ARM 어셈블리 명령어는 32bit에 맞게 해석② 되는 과정을 디코딩(Decoding)이라고 합니다. 하지만 반드시 32bit 명령어로 형태로 변환되는 것이 아니라 컴파일을 할 때 어떤 옵션을 사용했느냐에 따라 32bit 명령어 또는 16bit 명령어 형태로 변환 된답니다.두 번째, 32bit 명령어(ARM)와 16bit 명령어(THUMB) 구성이랍니다.C 언어로 만든 소스를 컴파일을 하기 위해서 makefile을 많이 사용합니다. makefile에서 CFLAGS 설정 값을 보면 '-m'으로 시작되는 옵션이 있답니다.

▶코드 makefile
#### Option Definition
#### AFLAGS = -marm9tdmi -EL -M --gdwarf2 CFLAGS = CFLAGS = -g -gdwarf-2 -O0 -c -marm -mcpu=arm9tdmi -mlittle-endian -mno-apcs-frame -mno-apcs-stack-checkLFLAGS = -eEVT -nostartfiles -Xlinker --script=linker.ld -lc #-L.


여기에서 '-marm' 을 '-mthumb' 라는 옵션으로 하면 16bit로 어셈블리 명령어로 만들어지게 한답니다.그럼 두 가지 명령어가 시스템에 어떤 영향을 끼칠까요? MCU에서 SDRAM으로 인터페이스하기 위해서는 ①, ② 과 같이 16bit 로 구성되어 있답니다. MCU는 16bit 또는 32bit로 인터페이스를 할 수가 있지만 현재 임베디드 시스템에서 사용하는 SDRAM은 대부분 16bit로 구성되어 있어 있기 때문이죠. 이 말은 ARM core가 메모리로 한 번 접근할 때 최대한으로 가져 올 수 있는 데이타는 16bit라는 얘기죠. 32bit가 데이타가 필요하면 2번 접근을 해야 32bit 값을 볼 수가 있답니다. 아무리 ARM core가 32bit를 가진 레지스터가 있어도 메모리로 접근할 때 만큼은 한 번에 읽어 올 수 있는 값이 16bit로 제한되기 때문에, 32bit 명령어보다 16bit 명령어가 더 빨리 읽어 와서 실행을 할 수가 있답니다. 그래서 개발자는 컴파일 옵션을 어떻게 하느냐에 따라 시스템 전체에 끼치는 영향력이 달라진답니다. 만약 SDRAM을 16bit가 아닌 32bit라면 또 달라질 수가 있겠죠? 그리고 16bit를 병렬로 연결하면 32bit가 되니 어떻게 시스템을 꾸미느냐에 따라 많은 차이점이 있다고 보시면 됩니다.   


아래는 같은 C 언어로 만들었지만 컴파일을 할 때, 어떤 옵션을 사용했느냐에 따라 어셈블리 코드가 달라지는 것을 확인해 볼 수 있답니다.

▶코드 main.c
main(){
   int j;
   char * p;
   vtripplearray[0][0][0] = 1;
   vtripplearray[1][0][0] = 2;
   vtripplearray[0][1][0] = 3;
   vtripplearray[0][0][1] = 4;}

ARM 명령어 ③
   SR:00002078|E92D4030 main: stmdb   r13!,{r4-r5,r14}
   SR:0000207C|E24DD008         sub     r13,r13,#0x8
   SR:00002080|E3A00001         mov     r0,#0x1
   SR:00002084|E59F1200         ldr     r1,0x228C
   SR:00002088|E5C10000         strb     r0,[r1]
   SR:0000208C|E3A01002         mov     r1,#0x2
   SR:00002090|E59F01F4         ldr     r0,0x228C
   SR:00002094|E5C0100C         strb     r1,[r0,#0x0C]
   SR:00002098|E3A00003         mov     r0,#0x3
   SR:0000209C|E59F11E8         ldr     r1,0x228C
   SR:000020A0|E5C10004         strb     r0,[r1,#0x4]
   SR:000020A4|E3A01004         mov     r1,#0x4
   SR:000020A8|E59F01DC         ldr     r0,0x228C
   SR:000020AC|E5C01001         strb     r1,[r0,#0x1]
  총 메모리 사용량:   14(instruction) * 4(byte) = 56 byte


THUMB 명령어 ④
ST:00001A78|B590 main: push {r4,r7,r14}  
ST:00001A7A|B082         sub sp,#0x8  
ST:00001A7C|2001         mov r0,#0x1  
ST:00001A7E|4954         ldr r1,0x1BD0  
ST:00001A80|7008         strb r0,[r1]  
ST:00001A82|2002         mov r0,#0x2  
ST:00001A84|7308         strb r0,[r1,#0x0C]  
ST:00001A86|2003         mov r0,#0x3  
ST:00001A88|7108         strb r0,[r1,#0x4]  
ST:00001A8A|2004         mov r0,#0x4  
ST:00001A8C|7048         strb r0,[r1,#0x1]

총 메모리 사용량:11(instruction) * 2(byte) = 22 byte

이 뿐만 아니라 똑 같은 일을 처리하지만 ARM 명령어보다 THUMB 명령어는 메모리 공간도 효율적으로 사용하게 된답니다.세 번째, Big Endian과 Little Endian이랍니다.Endian 말의 유래는 달걀을 깰 때 뾰족한 끝(little-end)을 먼저 깰 것인가 뭉툭한 끝(big-end)을 먼저 깰 것인가에 대한 이야기에서 나왔다고 해요. 개발자가 만든 소스를 컴파일하고 나면 바이너리가 생성되는데, 어떤 배열의 순서로 만들 것인가를 결정한답니다. Endian 은 Big Endian과 Little Endian 두 가지가 있는데, 각각의 차이점을 알아 보아요.우선 Endian 결정은 Makefile에서 CFLAGS 설정 값을 보면 '-mlittle-endian'으로 시작되는 옵션이 있답니다.

▶코드 makefile
#### Option Definition ####AFLAGS = -marm9tdmi -EL -M --gdwarf2 CFLAGS = CFLAGS = -g -gdwarf-2 -O0 -c -marm -mcpu=arm9tdmi -mlittle-endian -mno-apcs-frame -mno-apcs-stack-checkLFLAGS = -eEVT -nostartfiles -Xlinker --script=linker.ld -lc #-L.

그리고 링크 스크립트에서도 설정을 한답니다.


▶코드 linker.ld
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")OUTPUT_ARCH(arm)ENTRY(_start)....

이제 make를 해서 컴파일을 하면 최종 바이너리가 Endian 에 따라 생성된답니다.   




컴파일 되는 과정에서 Endian 정렬이 되기 전에 원본 데이타가 0x12345678 이라고 가정해 볼게요.메모리 주소 배열은 0x0번지에서 0x3번지까지 있으며, 주소 배열 단위는 바이트(Byte)랍니다.

원본 데이타  = 0x12345678


Big 의 경우

LittleEndian의 경우

0x0[0]= 0x12

0x1[1]= 0x34

0x2[2]= 0x56

0x3[3]= 0x78

0x0[0]= 0x78

0x1[1]= 0x56

0x2[2]= 0x34

0x3[3]= 0x12



실제 코드를 가지고 확인 해 보죠.   


네 번째, FIQ 인터럽트랍니다.

일반적으로 대부분의 프로세서는 IRQ(Interrupt reQu-est)를 사용한답니다. 그런데 ARM core는 특별하게도 FIQ(Fast Interrupt reQuest) 모드가 존재한답니다. 같은 기능을 하는 인터럽트이지만 FIQ 가 IRQ보다 빠르게 동작한답니다. FIQ 모드는 8개 레지스터가 있으며 IRQ 모드는 3개 레지스터가 있어요. 단순 비교를 해 봐도 FIQ 모드 레지스터 개수가 많기 때문에 빠를 수 밖에 없지요. 레지스터는 일꾼이랍니다. 일꾼이 많을 수록 일을 빨리 끝낼 수가 있잖아요. ㅎㅎ 마지막으로 ARM 프로세서의 족보를 살펴보죠.

마지막으로 ARM 프로세서의족보를 살펴보죠.

아키텍처

프로세서 

V4

ARM7TDMI, ARM920T 

V5TE

ARM926E,ARM946E-S

V5EJ

ARM926EJ-S

V6

ARM1136JF-S,ARM1176JZF-S

V7

Cortex-A, Cortex-R, Cortex-M

 

프로세서 이름에서 영문마다 의미가 있는데그 특징을 나열해 보면 다음과 같아요.

T

Thumb16비트 디코더

D

JTAG

M

곱셈 지원

I

EmbeddedICE macrocell, Breakpoint

E

DSP

J

Java

F

VFP

S

Synthesizible 지원

 
makefile - "302"   링커스크립트 - "303"   JTAG - "207"   VFP – “504”


덧글 +3 트랙백 0

아래 URL을 전체 선택하면 복사할 수 있습니다.

닫기

SOTO Story 카테고리의 다른 글

이전 다음
TOP