March 29, 2024

디바이스마트 미디어:

[66호] 원하는 색상으로 제어가 가능한 아두이노 IoT 스마트 무드등 키트 -

2021-06-25

★2021 ICT 융합 프로젝트 공모전 결과 발표! -

2021-05-12

디바이스마트 국내 온라인 유통사 유일 벨로다인 라이다 공급! -

2021-02-16

★총 상금 500만원 /2021 ICT 융합 프로젝트 공모전★ -

2021-01-18

디바이스마트 온라인 매거진 전자책(PDF)이 무료! -

2020-09-29

[61호]음성으로 제어하는 간접등 만들기 -

2020-08-26

디바이스마트 자체제작 코딩키트 ‘코딩 도담도담’ 출시 -

2020-08-10

GGM AC모터 대량등록! -

2020-07-10

[60호]초소형 레이더 MDR, 어떻게 제어하고 활용하나 -

2020-06-30

[60호]NANO 33 IoT보드를 활용한 블루투스 수평계 만들기 -

2020-06-30

라즈베리파이3가 드디어 출시!!! (Now Raspberry Pi 3 is Coming!!) -

2016-02-29

MoonWalker Actuator 판매개시!! -

2015-08-27

디바이스마트 레이저가공, 밀링, 선반, 라우터 등 커스텀서비스 견적요청 방법 설명동영상 입니다. -

2015-06-09

디바이스마트와 인텔®이 함께하는 IoT 경진대회! -

2015-05-19

드디어 adafruit도 디바이스마트에서 쉽고 저렴하게 !! -

2015-03-25

[29호] Intel Edison Review -

2015-03-10

Pololu 공식 Distributor 디바이스마트, Pololu 상품 판매 개시!! -

2015-03-09

[칩센]블루투스 전 제품 10%가격할인!! -

2015-02-02

[Arduino]Uno(R3) 구입시 37종 센서키트 할인이벤트!! -

2015-02-02

[M.A.I]Ahram_ISP_V1.5 60개 한정수량 할인이벤트!! -

2015-02-02

[17호]JK전자와 함께하는 ARM 완전정복(3)-1

jk전자 JK전자와 함/께/하/는 ARM 완전 정복Ⅱ.ARM Applications – 1부글 | JK전자

자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부한다면 큰 도움이 될 것입니다.

ARM Architecture 강의에서는 특정 CPU(S3C2440, STM32Fxx) 에 대한 내용 보다는 ARM Core의 이론적인 구조 자체에 대해서 많은 설명을 하였습니다. 이번 강의에서는 Samsung의 ARM9 CPU S3C2440 개발보드를 이용해서 실제 실습을 통해서 ARM에 대해서 공부해 보도록 하겠습니다.
I. ARM Architecture ~ IV. Cortex-M3 Applications 까지 분명 쉽지 않은 지루하고도 먼 여행이 되겠지만 ARM을 공부하는 임베디드 관련 엔지니어라면 언젠가는 한 번은 넘어야 하는 산이라 생각됩니다. 부디 이 자료가 ARM을 정복하는데 조금이라도 도움이 되시길 바랍니다.

 

강의 전체 로드맵

I. ARM Architecture | 임베디드 시스템 개론에 대한 설명과 ARM7, ARM9 의 구조에 대해서 설명합니다.
II. ARM Applications | 삼성의 S3C2440(ARM9) 개발보드(S3C2440 Mini 개발보드)를 이용해서 어셈블리어와 UART, GPIO 등을 실습합니다.
III. Cortex-M3 Architecture | Cortex-M3의 특징과 구조에 대해서 설명합니다.
IV. Cortex-M3 Applications | STM32F103VCT6 Dragon 개발보드를 이용해서 GPIO, LCD, SPI, UART, MP3, SDIO, I2C 등을 실습합니다.

이 강의 자료에 대한 모든 질의사항은 http://cafe.naver.com/avrstudio의 ARM Architecture Q&A게시판에 글을 남겨 주시거나 jk@deviceshop.net로 메일을 보내주시기 바랍니다. 가급적이면 여러 사람이 질문에 대한 답변을 공유할 수 있도록 네이버 카페 게시판을 이용해주셨으면 합니다. 감사합니다.

Ⅱ. ARM Applications 1부 목차

1. Base of Software Engineering
1.1 Memory Endian Formats
1.2 보수 표현
1.3 논리연산
1.4 진수변환
1.5 Data Types
1.6 Aligned & Un-Aligned Data
2. 어셈블리어 실습
2.1 ARM Simulator 환경 설정
2.2 Data Processing Instructions
2.3 Multiply Instructions
2.4 Load/Store Instructions
2.5 Branch Instructions
2.6 Status Register Access Instructions
2.7 Conditional Execution
3.1 S3C2440 CPU
3.2 S3C2440 Features
3. S3C2440 개발보드 소개
3.3 S3C2440 HW IPs
3.4 Memory Controller
3.5 Timer
3.6 UART
3.7 NAND Booting
4. 개발환경 설정
4.1 IAR Workbench 개발환경 설정
4.2 ARM-JTAG 을 이용한 프로그램 다운로드

1장의 내용은 컴퓨터를 전공한 사람이라면 누구나 다 아는 내용이지만 어셈블리어 실습을 하기위해서는 반드시 알아야 하는 내용입니다. 다 아는 내용이겠지만 기억을 되살리는 차원에서 간단하게만 설명 하도록 하겠습니다.

1. Base of Software Engineering

1.1 Memory Endian Formats

워드 데이터 안에서의 바이트 순서로 크게 빅 엔디언과 리틀 엔디언으로 나눌 수 있습니다. 빅 엔디언은 사람이 숫자를 쓰는 방법과 같이 큰 단위의 바이트가 앞에 오는 방법이고, 리틀 엔디언은 반대로 작은 단위의 바이트가 앞에 오는 방법입니다. 다시 한번 강조하지만 이것은 워드 범위 내에서의 바이트 단위의 순서입니다.
또한 ARM 레지스터에 저장이 될 경우에는 엔디안의 구분이 없고 메모리 접근 측면에서만 구분이 필요합니다.

엔디안 종류 0×1234 0×12345678 아키텍쳐
Big-endian 12 34 12 34 56 78 모토로라 등
Little-endian 34 12 78 56 34 12 x86

* 몇몇 아키텍처는 빅 엔디언과 리틀 엔디언 중 하나를 선택할 수 있도록 설계되어있고, 이를 바이 엔디언(Bi-endian)이라 부릅니다. PowerPC, DEC 알파, MIPS, PA-RISC, IA-64 등은 바이 엔디언을 사용하는 대표적인 아키텍처입니다. 우리가 공부하고 있는 ARM도 엔디언을 선택해서 사용할 수 있도록 설계되어 있습니다.
x86 아키텍처가 리틀 엔디언을 쓰기 때문에, 오늘날 x86 아키텍처를 사용하는 대부분의 데스크톱 컴퓨터는 리틀 엔디언을 쓰며 이를 “인텔 포맷” 이라고 합니다

Example)
32비트 숫자인 0x2A를 Little-endian으로 표시 하면?
0×00 00 00 2A = 2A 00 00 00

1.2 보수 표현
컴퓨터에서 보수를 사용하는 이유는 무엇일까요? 모든 것이 0과 1로 표현되는 컴퓨터에서 음수를 표현하는데 편리하기 때문에 사용합니다. 물론 이를 이용해서 뺄셈도 합니다. 예를 들면 12-3의 수식을 컴퓨터(ALU)에서 계산을 하면 실제로는 12에서 3을 빼는 것이 아니라 12와 3의 2의 보수(3의 음수표현)를 더해서 계산을 하게 됩니다.

1.2.1 “1″ 의 보수
주어진 이진수의 모든 자리 숫자를 반전(0을 1로, 1을 0으로)시키면 1의 보수를 얻을 수 있습니다.

8자리의 이진수 01001011(십진수로 75)의 1의 보수를 구하면 아래와 같습니다.
01001011 의 모든 자리의 수를 반전시킨다.
10110100 –> 1의 보수

1.2.2 “2″ 의 보수
1의 보수를 구한 다음 2진수 “1″ 을 더하면 됩니다.
8자리의 이진수 01001011(십진수로 75)의 2의 보수를 구하면 아래와 같습니다.

01001011 의 모든 자리의 수를 반전시킨다.
10110100 –> 1의 보수

10110100
+) 00000001 –> 1의 보수에서 1을 더합니다.
—————
10110101 –> 2의 보수

보수를 구할 때 한 자리가 더 길어질 경우에는 가장 높은 자리의 숫자는 버립니다.

1.2.3 “2″ 의 보수를 이용한 뺄셈

예제) 100-75를 2의 보수를 이용해서 연산하시요.
100-75는 100+(-75)와 같으므로

01100100 (10진수 100)
+) 10110101 (10진수 75의 2의 보수)
—————
100011001

새로 생긴 가장 높은 자리의 숫자를 빼고 남은 00011001은 십진수로 25와 같으며 이는 계산하려던 식의 결과입니다.

예제) 10-75를 2의 보수를 이용해서 연산하시요.
10-75는 10+(-75)와 같으므로

00001010 (10진수 10)
+) 10110101 (10진수 75의 2의 보수)
—————
10111111 (이 결과는 음수 : MSB가 1 이므로 다시 2의 보수를 취하면 65 즉 -65)

10111111 결과는 MSB가 1(음수)이므로 다시 2의 보수를 취해보면 01000001은 십진수로 65와 같으며 이는 계산하려던 식의 결과 -65가 됩니다.

1.3 논리 연산

1.3.1 NOT
2진수 각 자리의 값을 반대로 바꾸는 연산입니다. 이 연산은 어떤 값의 보수를 구할 때 효과적으로 사용할 수 있습니다.

NOT 0111
= 1000

C나 C++에는 “~” 연산을 통해 이 값을 구할 수 있습니다.

x = ~y;

1.3.2 OR
두 값의 각 자릿수를 비교해, 둘 중 하나라도 1이 있다면 1을, 아니면 0을 계산합니다.

0101
OR 0011
= 0111

C/C++에는 “ | ” 연산자가 이 기능을 제공합니다.

x = y | z;

1.3.3 XOR
두 값의 각 자릿수를 비교해, 값이 같으면 0, 다르면 1을 계산합니다.

0101
XOR 0011
= 0110

C/C++에는 “ ^ ” 연산자가 이 기능을 제공한다.

x = y ^ z;

1.3.4 AND
두 값의 각 자릿수를 비교해, 두 값 모두에 1이 있을 때에만 1을, 나머지 경우에는 0을 계산합니다.

0101
AND 0011
= 0001

C/C++에는 “ & ” 연산자가 이 기능을 제공한다.

x = y & z;

1.4. Shift 연산

1.4.1 왼쪽으로 쉬프트(<<)
“ << ” 키워드는 데이터를 왼쪽으로 비트 수만큼 이동시키기 때문에 2의 “이동할 비트수”를 제곱한 값과 데이터가 곱해진 값이 결과 값으로 도출됩니다. 5(b00000101)를 왼쪽으로 3비트 이동시키면 5 << 3 = 40(b00101000) 즉 5 * 8 한 것과 같은 효과가 나타납니다.

17featureJK023

가중치 128 64 32 16 8 4 2 1
연산전 0 0 0 0 0 1 0 0
연산후 0 0 1 0 1 0 0 0

1.4.2 오른쪽으로 쉬프트(>>)
“>>” 키워드는 데이터를 오른쪽으로 비트 수만큼 이동시키기 때문에 2의 “이동한 비트수”를 제곱한 값으로 데이터를 나눗셈 한 값이 도출됩니다.
40(b00101000)를 오른쪽으로 1비트 이동시키면 40 >> 1 = 20(b00101000) 즉 40/2 한 것과 같은 효과가 있습니다.
17featureJK024

가중치 128 64 32 16 8 4 2 1
연산전 0 0 1 0 2 0 0 0
연산후 0 0 0 1 0 1 0 0

1.4.3 부호가 있는 왼쪽 쉬프트 연산(<<)
79(b01001111) << 1 = -98(b10011110)
부호 비트(“1”)와 그 다음 비트(“0”)가 서로 다른 값인 경우 부호가 바뀌고 Overflow가 발생하게 됩니다. 위의 예제에서는 양수에서 음수로 바뀌면서 Overflow가 발생하였습니다.

17featureJK025

가중치 부호 64 32 16 8 4 2 1
연산전 0 1 0 0 1 1 1 1
연산후 1 0 0 1 1 1 1 0

1.4.4 부호가 있는 오른쪽 쉬프트 연산(>>)
여기서 65의 2의 보수를 이용해서 -65를 표현했습니다. -65(b10111111) >> 1 = -33(b11011111)
예를 들어 위의 그림과 같이 “1011 1111” 값을 오른쪽으로 한번 이동하면 왼쪽에 생긴 빈 공간은 최상위 비트인 1 값으로 채워지는 것입니다. 만약 “-160 >> 4v 를 연산하면 -160 의 이진수 값인“1010 0000”가 오른쪽으로 4비트만큼 이동하고, 왼쪽에 생긴 네개의 빈 공간은 최상위 비트인 1 로 채워지므로 연산 결과는 “1111 1010”가 됩니다.

17featureJK026

 

1.5 Rotate 연산

데이터의 모든 비트들을 각각 서로 이웃한 비트의 자리로 옮기고 한 쪽 끝에서 밀려 나가는 비트가 다시 반대편 끝으로 들어오게 되는 연산입니다.

1.5.1 부호 없는(Rotate no carry) 왼쪽 Rotate
23(b00010111) ROL 1 = 46(b00101110)

17featureJK027
Left circular shift or rotate

1.5.2 부호 없는(Rotate no carry) 오른쪽 Rotate
23(b00010111) ROR 1 = 139(b10001011)

17featureJK028
Right circular shift or rotate

1.5.3 부호 있는(Rotate through carry) 왼쪽 Rotate
ROL과 동일하지만 Carry Flag가 최하위 비트로 이동하고, 최상의 비트의 값이 Carry Flag 로 이동됩니다.
23(b00010111) RCL 1 = 47(b00101111)

17featureJK029
Left rotate through carry

1.5.4 부호 있는(Rotate through carry) 오른쪽 Rotate
23(b00010111) RCR 1 = 267(b100001011)

17featureJK030
Right rotate through carry
아주 기본적인 내용들이지만 기본적인 것부터 정확하게 알고 있어야 합니다. 주로 데이터 암호화나, 고속의 그래픽 처리 작업 등에서 Shift, Rotate 연산을 많이 사용합니다.

1.6 진수변환

2진수를 16진수로 변환할 때 4자리씩 끊어서 계산하면 편리합니다. 자주 쓰이는 수들의 2진수와 16진수들의 예제들입니다.

2^4 = 16B = b0001 0000 = 0×10
2^5 = 32B = b0010 0000 = 0×20
2^6 = 64B = b0100 0000 = 0×40
2^7 = 128B = 0×80
2^8 = 256B = b0001 0000 0000 = 0×100
2^10 = 1KB = b0100 0000 0000 = 0×400
2^20 = 1MB = b0001 0000 0000 0000 0000 0000 = 0×100000
2^30 = 1GB = 0×40000000
2^40 = 1TB = 0X10000000000
4KB = 0×1000, 64KB = 0×10000, 1MB = 0×100000

Ex)
4GB = 4*1GB = 4 * 2^30 = 2^2 * 2^30 = 2^32 = 0×100000000
256KB = 256*1KB = 2^8 * 2^10 = 2^18 = 0×40000
96KB = 64KB + 32KB = 2^6*2^10 + 2^5*2^10 = 0×10000 + 0×3000 = 0×13000
135KB = 128KB + 4KB + 2KB + 1KB = 2^17 + 2^12 + 2^11 + 2^10 = 0×20000 + 0×1000 + 0×800 + 0×400 = 0x21c00

1.7 Data Types

Byte(8 bits)
Halfword(16 bits)
Word (32 bits)
Long Word (64 bits)

- Value ranges

unsigned char val;
0 <= val <= 2^8(255)
signed char val;
-128(0×80) <= val <= 127(0x7F)
int(signed 32bit integer) val;
0×8000 0000 <= val <= 7FFFF FFFF

1.8 Aligned & Un-Aligned Data Access

1.8.1 Aligned Access

(1) Halfword Data Access : 데이터의 주소 값이 짝수이어야 합니다.
(2) Word Data Access : 데이터의 주소 값이 4의 배수이어야 합니다.

Aligned Data Access
char buf[100];int *p;
int gVar;p = (int *)&buf[0];
gVar = *p –> Data Abort 가능성 1p = (int *)&buf[1];
gVar = *p –> Data Abort 가능성 2

- Data Abort 가능성 2 : buf의 데이터형이 char(8 bit) 이기 때문에 0번째 이후 부터는 4의 배수가 아니기 때문에 Data Abort 가능성이 있습니다.
- Data Abort 가능성 1 : 0번째 인덱스인데 어떻게 보면 Data Abort 가능성이 없는 것처럼 보입니다. 보통은 Linker가 알아서 buf 변수의 할당 주소를 4의 배수에 맞추어 주지만 그렇지 않을 가능성도 있기 때문에 링커에 따라서는 Data Abort 가능성이 있는 것입니다. 그렇다면 Data Abort가 발생하지 않도록 char 배열 buf를 선언하려면 어떻게 해야 할까요? 컴파일러 지시자를 사용해서 char 배열 buf를 강제로 4의 배수로 맞추어 주는 것입니다.

Aligned Data Access
#pragma data_alignment = 2 –> 강제로 4의 배수가 되도록 지시
char buf[100];int *p;
int gVar;p = (int *)&buf[0];
gVar = *p –> 정상동작p = (int *)&buf[1];
gVar = *p –> 1번째 배열에서는 여전히 Data Abort 가능성 2

여기서 또 한가지 ARM C언어에서 구조체 선언을 할 때 어떻게 선언하는 것이 효율적인지를 알아 봅시다.

비 효율적인 구조체 데이터 선언
struct {
char a;
int b;
short c;
int d;
} gVar;
메모리 배치17featureJK031

위의 그림을 보면 총 5byte의 메모리 공간을 낭비하였습니다. 그렇다면 선언 순서를 short c, int b 의 순서를 바꾸면 어떻게 될까요?

비 효율적인 구조체 데이터 선언
struct {
char a;
short c;
int b;
int d;
}gVar;
메모리 배치17featureJK032

단지 선언 순서만 바꾸어도 메모리 낭비가 5-byte에서 1-byte로 줄었습니다.

1.8.2 Un-Aligned Data Access

(1) ARM Architecture v6 부터 지원됨
(2) ARM Architecture v4T, v5T(E) 등에서 Un-aligned data를 접근하려고 하면 Data Abort가 발생합니다.


17featureJK033

 

JK전자와 함께하는 ARM 완전정복(3)-2 에서 계속 됩니다.

 

Leave A Comment

*