<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NTREXGO - 디바이스마트, 엔티렉스 컨텐츠 통합 사이트 &#187; 특집</title>
	<atom:link href="http://www.ntrexgo.com/archives/tag/%ed%8a%b9%ec%a7%91/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ntrexgo.com</link>
	<description>엔티렉스, 디바이스마트 컨텐츠 통합 사이트</description>
	<lastBuildDate>Thu, 03 Mar 2022 06:47:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>[58호]Battleship 2인용 게임기</title>
		<link>http://www.ntrexgo.com/archives/37988</link>
		<comments>http://www.ntrexgo.com/archives/37988#comments</comments>
		<pubDate>Thu, 20 Feb 2020 00:00:28 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[Feature]]></category>
		<category><![CDATA[ict]]></category>
		<category><![CDATA[공모전]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[참가상]]></category>
		<category><![CDATA[프로젝트]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=37988</guid>
		<description><![CDATA[디바이스마트매거진 58호 &#124; battleship 보드게임 원리에 착안하여 시중에서 판매되는 게임기와 비슷한 외형의 디지털 게임기를 제작한다.]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-15.png" rel="lightbox[37988]"><img class="alignnone size-large wp-image-38064" alt="58 ict 배틀쉽 (15)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-15-620x176.png" width="620" height="176" /></a></p>
<p><strong>2019 ICT 융합 프로젝트 공모전 참가상</strong></p>
<p><strong><span style="font-size: x-large">Battleship 2인용 게임기</span></strong></p>
<p style="text-align: right">글 | 국민대학교 오재홍, 이강민</p>
<p style="text-align: right">
<p><span style="color: #0000ff"><strong>1. 심사평</strong></span><br />
<strong>칩센</strong> 보드게임을 디지털화하였다는 것에서 재미있는 발상이라 생각합니다. 하드웨어 구성에 있어서 게임기 조작부는 기성 조이스틱 등을 사용하여 조금 더 심플한 방법을 추구하고, Display 부분에 dot/character 보다 더 유려한 형태의 구성으로 했다면 재미있어 보이지 않았을까 합니다. 모듈 문제로 적용하지 못한 블루투스 기능 또한 아쉬움으로 남습니다.<br />
<strong>뉴티씨</strong> 한때 유행하던 8비트 임베디드 게임기를 상상하게 만든 작품이었습니다. 실제로 블루투스를 넣어서 서로 통신하여 게임할 수 있도록 된 점도 잘된 점이라고 생각합니다. 다만, 스마트폰을 LCD 표현용으로 사용하고 스마트폰과 연결하여 게임기로 쓸 수 있도록 하였다면, 보조장치로 더 좋지 않을까 생각합니다.<br />
<strong>위드로봇</strong> 보드 게임을 임베디드 시스템으로 구현한 부분이 재미있는 작품입니다.<br />
<strong>펌테크</strong> 과거 오락실 게임을 연상시키는 흥미로운 작품이라고 생각합니다. 단순해 보이지만 프로그래밍 과정을 통해 게임 구성에 관한 Algorithm 구현, GLCD를 통한 상태 표시 등은 기술적 구현이 쉽지는 않았을 것으로 예상됩니다. 비록 2대의 게임기기 상호 간 무선통신을 통한 구현을 최종 완성시키지 못했지만 유선상의 구현만으로도 충분히 가치가 있는 작품이라고 생각합니다.</p>
<p><span style="color: #0000ff"><strong>2. 작품 개요</strong></span><br />
· 2대의 ATmega128을 이용한 유선 통신 기능 구현<br />
· 기존의 종이나 장난감으로 하는 보드게임을 디지털화하여 시중에서 판매되는 게임기와 비슷한 외형의 디지털 게임기 제작</p>
<p><span style="color: #0000ff"><strong>3. 작품 설명</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-1.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38043" alt="58 ict 배틀쉽 (1)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-1.png" width="610" height="344" /></a></p>
<p>이 작품은 battleship 보드게임 원리에 착안해 만들었다. 기존의 battleship 보드게임은 10&#215;10의 보드에서 이루어지고, 우선 각자 자신의 보드에 각각 크기가 5,4,3,3,2인 다섯 개의 배(종류는 4종류, 각각 Aircraft(크기 5), Battleship(크기 4), Cruiser(크기 3), Destroyer(크기 2))를 가로 혹은 세로로 겹치지 않게 배열한다. 그리고 서로 돌아가며 상대의 배의 위치를 추측한다. 한 번씩 돌아가며 상대의 배가 있을 걸로 예상되는 위치(게임 보드 위의 한 점)를 지목한 뒤, 그 결과를 듣고 다시 그 결과를 바탕으로 추측하여 먼저 상대의 배가 있는 위치를 모두 맞춘 쪽이 승리하는 게임이다. 이 작품은 기존 battleship 보드게임과 달리 상대방의 5칸 크기의 배를 파괴하거나 5칸 크기의 배가 아닌 배를 3척 파괴하는 것이 승리조건이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-2.png" rel="lightbox[37988]"><img class="size-full wp-image-38045 aligncenter" alt="58 ict 배틀쉽 (2)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-2.png" width="412" height="491" /></a><br />
차이점은 이 작품에서는 크기가 5,4,3,2인 배가 있고 한 칸 크기의 함정이 있다는 것이다. 이 함정은 배와 겹치지 않게 배열하고 상대방이 함정을 공격했을 때 배를 공격했다고 착각하게 만드는 역할을 하여 배의 모양을 쉽게 예측하지 못하게 만들었다는 것이다. 마지막으로 스캔 기능이 추가되었다. 자신이 공격에 성공한 배가 어떤 배인지 알기 위한 기회가 3번이 주어진다. 자신의 공격 턴에 지정한 좌표에 스캔 버튼을 누르면 배의 종류를 알려준다.<br />
이러한 게임 규칙의 변화, 아이템 사용 효과 추가, 아날로그 게임의 디지털화를 통해서 기존 battleship 보드게임에서 보다 더 재미의 요소를 추가하였다.</p>
<p><span style="color: #33cccc"><strong>3.1. 주요 동작 및 특징</strong></span><br />
<span style="color: #339966"><strong>가. 스위치 동작</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-1.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38042" alt="58 ict 배틀쉽 (1)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-1.jpg" width="610" height="163" /></a><br />
(1) 리셋 스위치<br />
(2) 상하좌우 스위치<br />
(3) 포격/확인 스위치<br />
(4) 회전/스캔 스위치</p>
<p><span style="color: #339966"><strong>나. 게임 진행 순서</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-3.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38047" alt="58 ict 배틀쉽 (3)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-3.png" width="610" height="276" /></a></p>
<p>① 게임기 상단에 부착된 스위치를 이용해 각자의 배 배치를 완료한다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-4.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38049" alt="58 ict 배틀쉽 (4)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-4.png" width="610" height="278" /></a></p>
<p>② 배 배치가 완료된 후 한 사람씩 공격을 하게 되는데 상대방의 배 위치를 맞췄을 때는 X표시가 되며 한 번 더 차례를 진행하고 공격에 실패했을 때는 *표시가 되며 상대방의 턴으로 넘어간다. 특정 알파벳 배의 모양을 완전히 파괴하게 되면 화면 하단에 있는 알파벳 현황판 숫자가 달라진다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-2.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38044" alt="58 ict 배틀쉽 (2)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-2.jpg" width="610" height="239" /></a></p>
<p>③ 게임기 스위치 좌측 상단에 LED는 자신의 턴일 때는 초록색, 상대방의 턴일 때는 빨간색에 불이 들어온다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-3.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38046" alt="58 ict 배틀쉽 (3)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-3.jpg" width="610" height="131" /></a></p>
<p>④ 공격 시 파란색 버튼을 이용하여 스캔 기능을 사용함으로써 상대방 특정 위치의 배 종류를 알 수 있다. 스캔 기능은 각 플레이어에게 3번의 사용 기회가 주어진다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-5.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38051" alt="58 ict 배틀쉽 (5)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-5.png" width="610" height="131" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-6.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38053" alt="58 ict 배틀쉽 (6)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-6.png" width="610" height="131" /></a></p>
<p>&nbsp;</p>
<p>⑤ 게임 진행 중 승리조건이 달성되면 승리 문구가 표시되고 흰색 버튼을 눌러 새로운 게임을 시작할 수 있다.</p>
<p><span style="color: #33cccc"><strong>3.2. 전체 시스템 구성</strong></span><br />
<span style="color: #339966"><strong>가. 스위치 구성</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-7.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38055" alt="58 ict 배틀쉽 (7)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-7.png" width="610" height="431" /></a> <a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-8.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38057" alt="58 ict 배틀쉽 (8)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-8.png" width="620" height="261" /></a></p>
<p>한 대의 게임기 안에 있는 7개 스위치는 모두 풀업 저항 회로로 구성되어 있고 스위치를 누를 때 연결된 포트의 HIGH 신호를 LOW 신호로 바꾸어 입력 신호를 변경한다. 스위치는 모두 폴링(Polling)방식으로 동작되며 RESET 단자에 연결된 스위치를 제외한 나머지는 모두 PORTD에 연결하였다.</p>
<p><span style="color: #339966"><strong>나. 사운드</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-9.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38058" alt="58 ict 배틀쉽 (9)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-9.png" width="620" height="240" /></a></p>
<p>게임의 효과음은 전기 신호를 소리로 변환시켜 주는 부저(Buzzer)를 통해서 제작하였다.<br />
부저에는 내부에 전자석과 진동을 일으키는 판으로 이루어져 있으며, 전자석이 진동판을 아주 빠르게 흔들어 소리를 발생 시키는 원리를 가지고 있어 타이머/카운터를 이용하여 주파수를 정해주어 소리를 발생시켰다.<br />
하나의 효과음은 여러 가지 주파수의 배열로 만들었고 타이머/카운터 레지스터를 조절하는 함수의 인자로 사용하였다.</p>
<p><span style="color: #339966"><strong>다. 통신 방법</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-10.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38059" alt="58 ict 배틀쉽 (10)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-10.png" width="620" height="353" /></a></p>
<p>게임기의 통신은 USART(Universal Synchronous and Asynchronous Receive and Transmitter) 통신 방식을 사용한다. USART 통신을 하기 위해서 2대의 ATmega128 Tx/Rx 포트를 서로 교차하여 선을 연결하고 양쪽 ATmega128 모두 송수신 속도, 전송 문자의 데이터 비트수 등 데이터를 송수신 하는데 필요한 레지스터들을 동일하게 설정한다.<br />
정보를 보낼 때 UDR0에 데이터를 넣어 인터럽트를 발생시키고 그 데이터를 받을 때는 미리 선언한 flag 값만 변경시켜 인터럽트를 통해 실시간으로 정보를 주고받는다.</p>
<p><span style="color: #339966"><strong>라. 배터리</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-4.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38048" alt="58 ict 배틀쉽 (4)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-4.jpg" width="300" height="357" /></a></p>
<p>게임기의 GLCD 백라이트와 부저에 전원을 공급하기 위해서 약 5V의 전압이 필요하다. 따라서 게임기의 하단부에 AA배터리 소켓을 4개 부착하였고 1.5V AA건전지 4개를 직렬 연결하여 총 6V의 전압을 공급할 수 있도록 설계하였다.</p>
<p><span style="color: #339966"><strong>마. 게임 알고리즘</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-11.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38060" alt="58 ict 배틀쉽 (11)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-11.png" width="620" height="467" /></a></p>
<p><span style="color: #33cccc"><strong>3.3. 개발 환경(개발 언어, Tool, 사용 시스템 등)</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-12.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38061" alt="58 ict 배틀쉽 (12)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-12.png" width="620" height="148" /></a></p>
<p><span style="color: #0000ff"><strong>4. 단계별 제작 과정</strong></span><br />
<span style="color: #33cccc"><strong>4.1. 코드 제작</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-13.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38062" alt="58 ict 배틀쉽 (13)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-13.png" width="620" height="512" /></a></p>
<p>① Visual Studio와 Code Vision AVR 모두 C언어를 기반으로 한 플랫폼이기 때문에 먼저 Visual Studio로 게임 알고리즘을 제작한 후 Code Vision AVR에 부합하는 코드로 변환하여 GLCD에 영상을 띄웠다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-5.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38050" alt="58 ict 배틀쉽 (5)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-5.jpg" width="620" height="424" /></a></p>
<p>② ATmega128간의 USART 유선통신의 데이터 송수신을 간단한 스위치 동작으로 확인하였다.</p>
<p><span style="color: #33cccc"><strong>4.2. 하드웨어 제작</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-6.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38052" alt="58 ict 배틀쉽 (6)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-6.jpg" width="620" height="149" /></a></p>
<p>① 스위치와 리드선을 글루건으로 고정시키고 스티로폼에 스위치만 보이게 하여 실제 게임기 스위치 같은 외형을 제작하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-14.png" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38063" alt="58 ict 배틀쉽 (14)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-14.png" width="620" height="276" /></a></p>
<p>② 아크릴판으로 틀을 제작하고 게임기의 윗면에 GLCD와 스위치를 아랫면에는 ATmega128, 부저, 브레드보드를 위치시켰다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-7.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38054" alt="58 ict 배틀쉽 (7)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-7.jpg" width="620" height="201" /></a></p>
<p>③ 2대의 게임기를 붙여 게임기 하단에 배터리를 넣으면 게임이 작동하도록 제작하였다.</p>
<p><span style="color: #0000ff"><strong>5. 기타</strong></span><br />
<span style="color: #33cccc"><strong>5.1. 소스코드</strong></span><br />
<span style="color: #339966"><strong>가. 배 배치 알고리즘</strong></span></p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>void print_ship(int x, int y, int ship_length, char ship_name)<br />
{<br />
if(turn==0)<br />
for (i = 0; i &lt; ship_length; i++)<br />
board_char[y][x+i] = ship_name;</p>
<p>else<br />
{<br />
for (i = 0; i &lt; ship_length; i++)<br />
board_char[y+i][x] = ship_name;<br />
}<br />
}</p>
<p>print_ship 함수는 x,y 좌표, 배의 길이, 배 이름을 인수로 받아 전역변수 turn이 0이면<br />
배의 이름을 board_char 배열에 가로로 넣고 turn이 1이면 board_char 배열에 세로로 넣는다.</p>
<p>void MapDraw(void)<br />
{<br />
for(i = 0; i &lt; 10; i++)<br />
{<br />
for(j = 0; j &lt;10; j++)<br />
{<br />
GLCD_TextGoTo(i,j);<br />
GLCD_WriteChar(board_char[j][i]);<br />
}<br />
}<br />
}</p>
<p>MapDraw 함수는 board_char 배열에 저장된 데이터를 GLCD에 찍어주는 역할을 한다.</p>
<p>switch(PIND)<br />
{<br />
case 0xfd: // 아래로 움직이는 키를 눌렀을 때 (PORTD1)<br />
if (turn == 0 &amp;&amp; player_y != 9)<br />
{<br />
player_x+=0; player_y+=1;<br />
_delay_ms(3000);<br />
}<br />
if (turn == 1)<br />
{<br />
if(board_char[player_y + ship_length][9] == ‘.’){<br />
player_x+=0; player_y+=1;<br />
_delay_ms(3000);<br />
}<br />
}<br />
</div>
<p>배를 이동하기 코드의 일부를 발췌한 부분이다.<br />
turn이 0이면 배가 가로로 되어있는 상태이고 1이면 세로로 되어있는 상태이기 때문에 turn이 0이고 y좌표가 (x,9) 가 아닌 경우에 한 칸 내려갈 수 있고,<br />
turn이 1이고 y좌표와 배의 길이를 더한 좌표에 있는 문자가. 맵의 기본 모양이라면 한 칸 내려갈 수 있기 때문에 y좌표에 1을 더해주었다. GLCD의 좌표는 첫 번째 줄의 y좌표는 0이고 아래로 내려갈수록 +1씩 된다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>void enter_ship(int x, int y, int ship_length, char ship_name)<br />
{<br />
if (turn == 0)<br />
for (i = 0; i&lt;ship_length; i++)<br />
{<br />
grid[y][x + i] = ship_name;<br />
}<br />
else<br />
for (i = 0; i&lt;ship_length; i++)<br />
{<br />
grid[y + i][x] = ship_name;<br />
}<br />
placement_cnt++;<br />
enter_cnt++;<br />
}<br />
</div>
<p>enter_ship 함수는 turn의 값을 통해 배의 방향을 판단하고 반복문을 이용해 grid 배열에 배치할 배의 이름을 넣어주는 함수이다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>void erase_ship(int x, int y, int ship_length)<br />
{<br />
if (turn == 0)<br />
for (i = 0; i &lt; ship_length; i++)<br />
board_char[y][x + i] = grid[y][x + i];</p>
<p>else<br />
for (i = 0; i &lt; ship_length; i++)<br />
board_char[y + i][x] = grid[y + i][x];<br />
}<br />
</div>
<p>erase_ship 함수는 x,y 좌표, 배의 길이를 인수로 받아 board_char 배열에 grid 배열을 넣어준다. 이 함수는 좌표값을 이동시켰을 때 이전에 print_ship 함수로 board_char 배열에 넣어주어 Mapdraw 함수로 GLCD에 배열을 표현했을 때 잔상이 남는 것을 지워주는 역할을 한다. board_char 배열에 넣어주는 grid 함수는 배를 배치했을 때 배열 안에 값이 저장된다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>while(1)<br />
{<br />
print_ship<br />
-&gt; MapDraw<br />
-&gt; swich case 문을 이용하여 버튼 눌렀을 때 좌표 이동 및 배 배치<br />
-&gt; erase_ship<br />
}</p>
</div>
<p><span style="color: #339966"><strong>나. 부저 사운드 함수</strong></span></p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>float start3[]= {329.6, 329.6, 329.6, 293.7, 329.6, 0, 329.6, 329.6 ,329.6, 293.7, 392.0, 349.2, 329.6,-1}; // start 사운드<br />
float end_win[] = {261.6, 329.6, 392.0, 523.3, -1}; // 승리 사운드<br />
float end_lose[] = {277.2, 261.6, 246.9, 223.1,-1}; // 패배 사운드<br />
float fire[]= {261.6, -1}; // 포격 성공 사운드<br />
float wrecked[] = {130.8, 123.5, -1}; // 침몰사운드<br />
float miss[] = {392.0 ,-1}; // miss 사운드<br />
float scan2[] = {440.0, -1}; // scan 사운드<br />
void Buzzer(float arr[])<br />
{<br />
int i = 0;<br />
DDRB |=(1&lt;&lt;DDB4); //5번 핀으로 소리 출력<br />
TCCR0 = 0x1D;<br />
TCCR1A = 0&#215;00;<br />
TCCR1B = 0&#215;04;<br />
TCNT0 = 0;<br />
TCNT1 = 65536 &#8211; 55000;</p>
<p>while(arr[i] != -1)<br />
{<br />
OCR0 = (int)(8000000/(arr[i]*256));<br />
while((TIFR &amp; 0&#215;04) == 0);<br />
TIFR |= 0&#215;04;<br />
TCNT1 = 61250;<br />
//=====================<br />
OCR0 = 0;<br />
while((TIFR &amp; 0&#215;04) == 0);<br />
TIFR |= 0&#215;04;<br />
TCNT1 = 55000;<br />
i++;<br />
}<br />
TCCR0 = 0;<br />
}<br />
</div>
<p>타이머/카운터 레지스터를 설정하고 while문의 인자에는 arr[i] 배열의 인자(주파수)를 하나씩 실행 시키는데 -1이 나오면 효과음이 끝나도록 설정 하였고 하나의 효과음이 모두 나온 후에 다음 동작(화면이 바뀌거나 스위치를 작동하는 행위)이 실행된다.<br />
빠른 게임 진행을 위해서 게임 시작, 게임 종료를 나타내는 효과음 이외의 배열(arr[i])의 길이를 짧게 설정하였다.</p>
<p><span style="color: #339966"><strong>다. 통신 방법</strong></span></p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>void Init_interrupt_usart(void) // 인터럽트 레지스터 설정<br />
{<br />
UCSR0A = 0&#215;00;<br />
UCSR0C = 0&#215;06;<br />
UCSR0B = 0xd8; // 1101 1000</p>
<p>UBRR0H = 0&#215;00;<br />
UBRR0L = 0&#215;07; // 115200bps<br />
SREG|=0&#215;80;<br />
}<br />
ISR(USART0_TX_vect) // led 제어, 끝나는거 제어<br />
{<br />
tx_done=0;<br />
}</p>
<p>ISR(USART0_RX_vect)<br />
{<br />
data = UDR0;</p>
<p>if(data==1) ////////////////////////<br />
led_turn=1;<br />
if(data==0) ////////////////////////<br />
led_turn=0;</p>
<p>if(data==Game_set)<br />
{<br />
end_flag=1;<br />
loss_cnt++;<br />
}<br />
if(data == re_game)<br />
re_game_flag2=1;</p>
<p>if(data == C_zero)<br />
C_zero_flag=1;</p>
<p>if(data == B_zero)<br />
B_zero_flag=1;</p>
<p>if(data == S_zero)<br />
S_zero_flag=1;</p>
<p>if(data == M_zero)<br />
M_zero_flag=1;</p>
<p>if(data == D_zero)<br />
D_zero_flag=1;<br />
}<br />
</div>
<p>인터럽트 ISR(USART0_TX_vect)은 메인문에서 UDR0 값을 넣어줬을 때 tx_done=0 으로 만들면서 ISR을 빠져나가게 되면서 while(tx_done);을 다음 코드로 진행할 수 있게 구성하였다.<br />
인터럽트 ISR(USART0_TX_vect)에서 정보는 최소화 하였고 보내는데 필요한 정보들은 flag 변수를 이용하여 주로 처리하였다.<br />
인터럽트 ISR(USART0_RX_vect)은 UDR0 값을 받아 변수 data에 저장 후 필요한 flag를 1로 set 하는 용도로 쓰였다.</p>
<p><span style="color: #33cccc"><strong>5.2. 아쉬운 점</strong></span><br />
<strong>블루투스 페어링(pairing) 오류</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-8.jpg" rel="lightbox[37988]"><img class="alignnone size-full wp-image-38056" alt="58 ict 배틀쉽 (8)" src="http://www.ntrexgo.com/wp-content/uploads/2020/02/58-ict-배틀쉽-8.jpg" width="620" height="459" /></a></p>
<p>기존 작품 설계 방향은 무선통신을 이용한 2인용 게임기를 만드는 것 이 목표였기 때문에 아두이노를 이용하여 블루투스를 페어링 하려 했지만 블루투스 모듈 문제로 페어링이 되지 않아 유선통신을 하게 되었다. 그림은 블루투스 모듈인 hc-05와 hc-06을 페어링 하고 있는 모습이다.<br />
<strong></strong></p>
<p><strong>휴대하기에는 큰 부피</strong><br />
기존에 보유하고 있던 큰 크기의 브레드보드를 기준으로 회로를 설계하고 게임기 외형을 제작하였기 때문에 휴대하기에는 큰 부피로 작품이 제작되었다.<br />
<strong></strong></p>
<p><strong>시간제한 기능 미사용</strong><br />
타이머 인터럽트를 사용해서 사용자가 공격하는데 30초의 시간제한을 두려 하였지만 여러 개의 인터럽트를 동시에 사용하여 충돌이 생겨 타이머가 제대로 작동하지 않았다.<br />
아래 내용은 타이머 인터럽트만을 사용하여 GLCD에 30초 타이머 기능을 구현한 코드와 코드의 설명이다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>ISR(TIMER0_COMP_vect) // 타이머 ISR (30초 카운트)<br />
{<br />
total_count++;<br />
if ( total_count == 1000 ) // total_cound는 1ms<br />
{<br />
if(++sec_first&gt;9){ s=0; // 1초 단위<br />
if(++sec_second&gt;2){ s1=0; //10초 단위<br />
}<br />
}<br />
//sec_first와 sec_second는 전역변수<br />
GLCD_TextGoTo(2,1); GLCD_WriteChar(sec_first+’0’); // GLCD에 1초 단위 표기<br />
GLCD_TextGoTo(1,1); GLCD_WriteChar(sec_second+’0’); // GLCD에 10초단위 표기<br />
_delay_ms(1);</p>
<p>total_count = 0;<br />
}<br />
}</p>
<p>void Init_Timer(void) // 타이머/카운터0 레지스터 설정을 통한 타이머 Init<br />
{<br />
TCCR0 |= (1&lt;&lt;CS02); // 프리스케일러로 64를 선택<br />
TCCR0 |= (1&lt;&lt;WGM01); // CTC 모드<br />
TCNT0 = 0; // 카운터 초기화<br />
OCR0 = 249; // TOP 정의<br />
TIMSK |= (1&lt;&lt;OCIE0); // 타이머/카운터0 Compare Match 인터럽트 활성화<br />
sei(); // 전역 인터럽트 활성화<br />
total_count = 0; // total_count 초기화<br />
}</p>
<p>void Quit_Timer(void) // Timer 레지스터 설정을 통한 Timer Quit<br />
{<br />
TIMSK = 0&#215;00; // 타이머/카운터의 interrupt를 비활성화<br />
sec_first = 0; // sec_first를 초기화<br />
sec_second = 0; // sec_second를 초기화<br />
total_count = 0; // total_count를 초기화<br />
}<br />
</div>
<p>타이머 기능: Init_Timer에서 타이머/카운터0의 레지스터 설정을 통해 1ms마다 total_count가 1씩 증가하는 타이머를 만들었다. 각 레지스터의 설정은 다음과 같다. Init_Timer함수의 주석을 통해서 설명되어 있다.<br />
Init_Timer를 통해서 타이머/카운터0이 활성화 되면 TCNT가 OCR과 같아지는 순간 타이머0 ISR(TIMER0_COMP_vect)로 진입하여total_count가 1ms마다 증가하며, total_count가 1000이 되는 순간 sec_first를 1씩 증가시킨다. sec_fisrt가 10이 되는순간 sec_first는 0으로 초기화되고, sec_second가 1씩 증가한다. sec_second가 3이되는 순간 sec_second는 0으로 초기화 된다.<br />
코드를 통해, 위 내용을 확인할 수 있으며, sec_first와 sec_second는 각각 1초 단위 10초 단위를 의미한다.<br />
종합 의견 : 완성된 작품에서 무선통신과 타이머 기능을 추가하고 작은 크기의 브레드보드를 사용하여 외형을 제작한다면 보다 편리하고 직관적인 게임기의 기능을 갖추게 될 것이다.</p>
<p><span style="color: #33cccc"><strong>5.3. 참고문헌</strong></span><br />
· 뉴티씨 (newtc) : http://www.newtc.co.kr/dpshop/bbs/board.php?bo_table=m41&amp;wr_id=745&amp;page=5<br />
· 인터럽트 레지스터 설정 : https://webnautes.tistory.com/984<br />
· USART 통신 : https://blog.naver.com/xisaturn/220750649418<br />
· 그림 1,2 battleship 보드게임 예시 : https://en.wikipedia.org/wiki/Battleship_(game)<br />
· 그림 3. ATmega128 data sheet : http://www.siphec.com/item/AVR-ATmega128-ATmega1281-ATmega2561.html<br />
· 그림 6. 주파수와 피에조 부저의 음계 : https://kocoafab.cc/tutorial/view/626<br />
· 그림 7. ATmega USART Tx/Rx 연결 회로도 : https://blog.naver.com/iintuition_/220587315291</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/37988/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[45호]색종이로 작곡하는 춤추고 노래하는 자동차로봇</title>
		<link>http://www.ntrexgo.com/archives/34454</link>
		<comments>http://www.ntrexgo.com/archives/34454#comments</comments>
		<pubDate>Sat, 25 Nov 2017 00:00:51 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[blog-posts]]></category>
		<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[45호]]></category>
		<category><![CDATA[Feature]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[융합]]></category>
		<category><![CDATA[입선작]]></category>
		<category><![CDATA[프로젝트 공모전]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=34454</guid>
		<description><![CDATA[디바이스마트매거진 45호 &#124; 색상 인식으로 춤추고 노래하는 자동차 로봇을 개발하였다.]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-27-40-142.png" rel="lightbox[34454]"><img alt="Cap 2018-02-05 09-27-40-142" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-27-40-142-620x213.png" width="620" height="213" /></a></p>
<p><strong>2017  ICT 융합 프로젝트 공모전 입선작</strong></p>
<p><span style="font-size: x-large;"><strong>색종이로 작곡하는 춤추고 노래하는 자동차로봇</strong></span></p>
<p style="text-align: right;"><strong>글 | 숭실대학교 김세현</strong></p>
<p style="text-align: left;">
<p><span style="color: #0000ff;"><strong>1. 심사평</strong></span><br />
<strong>칩센</strong> 작품명을 보았을 때 작곡을 어떻게 하는지, 그 작곡에 대해 어떻게 로봇이 동작하는지가 매우 궁금하였습니다. 첨부한 동영상 및 보고서 내용을 보았을때, 작곡이라기 보다는 어떠한 형태이든지 간에 입력이 이루어 지는 수동적인 (흔히 보는 형태의) 입력과, 입력된 악보에 대해 어떤 방식과 패턴으로 로봇이 움직이는 등에 대한 내용이 매우 부족한 것으로 보입니다. 보고서에서 말한 영유아 및 어린이를 대상으로 한다고 보더라도 음계와 색상을 매칭하는 것 자체가 쉽지 않은 과정으로 보입니다. 작품의 이름 대비 많은 부분이 아쉬운 결과물로 느껴집니다.</p>
<p><strong>뉴티씨</strong> 색상 인식이 인상적인 작품입니다. 실제로 기술을 적용하려면 새로운 암호인증 시스템으로 만들거나, 공장의 불량감지 같은 분야에서 사용이 가능해 보입니다.</p>
<p><strong>위드로봇</strong> 컬러 센서를 음악과 연결한 부분이 참신합니다. 전체적으로 완성도가 높은 작품으로 평가합니다.</p>
<p><span style="color: #0000ff;"><strong>2. 작품 개요</strong></span><br />
개발자가 생각하는 주요 고객 타겟 층은 다음과 같은 세 부류이다.<br />
첫째, 한국의 현대사회는 고령화 시대와 1인 가족 시대로 점점 가게 되면서, 사회적, 경제적, 개인적인 여러 방면에서 다양한 문제들이 함께 발생하고 있다. 개인적인 정서적 문제 중 하나가 바로 ‘외로움’이다. 이에 따라 독거노인들이나 1인 가족들의 적막한 삶에 활력소가 되어주고 외로움을 채워줄 존재가 점점 필요해지고 있다. 그 빈자리를 채우기 위해 주인의 명령에 재롱을 떨며 춤추고 노래하는 손자, 손녀 같은 또는 친구 같은 로봇을 개발하였다.</p>
<p>두 번째 주요 고객층은 영유아 및 어린이들이다. 어린이들에게 색감으로 계이름을 시각적으로 받아들이게 해주고, 로봇이 아이가 직접 만든 색종이 계이름판으로 음악을 만들어 그에 맞춰 춤까지 추는 모습을 보며, 자연스럽게 음악과 로봇에 친숙해질 수 있다. 이는 결과적으로 아이들의 정서 발달 및 로봇과 관련된 가치관 발달에도 큰 도움을 줄 수 있다.</p>
<p>마지막으로, 아직 전자공학이나 로봇공학과 친숙하지 않은 일반인들에게도 그들의 가치관에 대한 긍정적인 효과를 기대할 수 있다. 현실적으로 로봇공학의 발전에 대해 다소 거부감이 있는 일반인들이 많다. 이들에게 로봇이 ‘재롱’을 부리는 모습은 그들의 감성을 자극하여 로봇과 더욱 친숙해질 수 있고 로봇에 대한 호감 이미지를 만드는 데에 기여한다.</p>
<p>이와 같은 세 가지 효과를 기대하며 색상 인식으로 춤추고 노래하는 자동차로봇을 개발하였다.</p>
<p><span style="color: #0000ff;"><strong>3. 작품 설명</strong></span><br />
<span style="background-color: #ffffff; color: #33cccc;"><strong>3.1. 주요 동작 및 특징</strong></span><br />
<span style="color: #00ccff;"><strong> 3.1.1. 주요 동작</strong></span><br />
<strong> Ⅰ. 악보 생성 기능</strong><br />
(1) 컬러센서를 이용한 색상 감별로 악보 생성</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-27-59-998.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34693" alt="Cap 2018-02-05 09-27-59-998" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-27-59-998.jpg" width="620" height="434" /></a></p>
<p>TYPE 29의 컬러센서를 컬러 인식 모드인 MODE 2로 설정하여 컬러센서 자체에서 인식 가능한 검정, 파랑, 초록, 노랑, 빨강, 흰색, 갈색을 인식하여 각 색에 음계를 매치하여 라즈베리파이 내의 buffer에 저장하였다가, 사용자가 색 악보에 따라 작곡한 음악을 듣고자 하면 한 음계 당 500ms 동안 스피커로 각 음계를 출력하며 ‘노래’를 하도록 하였다. 아래 표는 각 색상마다 매치한 계이름과 주파수를 정리한 표이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-07-480.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34694" alt="Cap 2018-02-05 09-28-07-480" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-07-480.png" width="620" height="295" /></a></p>
<p>1-2) 계이름과 1:1 매치되는 숫자로 악보 생성<br />
컬러센서로 인식할 수 있는 색상의 수는 위의 표에서 볼 수 있듯이 7가지로 한정되어있기 때문에, 다양한 음을 사용하는 악보를 만들기에는 부적합하다. 따라서 사용자가 각 계이름에 맞게 미리 매치시켜놓은 숫자들의 나열을 buffer에 입력함으로서 악보를 생성할 수도 있다. Linux의 C 언어에서는 getchar()이나 scan() 종류의 함수와 같은 문자를 입력받는 함수가 따로 없다. 따라서 사용자가 직접 이 기능을 하는 함수를 만들어야 한다. 아래 소스는 getchar() 함수를 구현한 getch 함수 소스코드이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-21-898.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34695" alt="Cap 2018-02-05 09-28-21-898" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-21-898.png" width="620" height="430" /></a><br />
악보 생성은 위와 같이 두 가지 방법으로 가능하지만, 앞으로는 주로 색상 악보를 만들어서 작곡하는 모드를 주로 다룰 것이다.</p>
<p><strong>Ⅱ. 저장된 악보에 맞춰 춤추는 기능</strong><br />
EV3 자동차로봇에 달려있는 4개의 포트에는 자동차 좌측 앞바퀴, 우측 앞바퀴 2개를 연결하는 Large motor 2개와 Medium motor 1개를 연결시켜 직진, 후진, 좌회전 직진, 우회전 직진, 좌회전 후진, 우회전 후진, 팔 올리기, 팔 내리기 등 EV3와 연결된 모터가 할 수 있는 8가지 기능은 각 음계와 매치되어 로봇이 춤을 추게 된다. 각 음계와 연결된 motor 모션은 다음 표와 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-30-230.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34696" alt="Cap 2018-02-05 09-28-30-230" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-30-230.png" width="620" height="269" /></a></p>
<p><strong>Ⅲ. 터치 센서를 이용한 간단한 on-off 기능 탑재</strong><br />
터치 센서란, 단순하게 누르면 1의 값을, 누르지 않으면 0의 값을 유지하는 스위치와 같은 원리의 센서이다. 이 센서를 이용해, 처음 프로그램을 실행하고 한 번 센서를 눌렀을 때 자동차가 직진을 하면서 바닥에 깔린 색종이의 조합인 악보를 컬러센서로 센싱을 하도록 했고, 센싱해야 하는 색종이의 모임이 끝나면 다시 한 번 터치 센서를 눌러야만 저장한 악보대로 노래를 하고 춤을 추도록 제어하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-39-932.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34670" alt="Cap 2018-02-05 09-28-39-932" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-39-932.jpg" width="620" height="429" /></a></p>
<p><span style="color: #33cccc;"><strong>3.1.2. 특징</strong></span><br />
<strong> Ⅰ. 마인드스톰 EV3</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-45-914.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34671" alt="Cap 2018-02-05 09-28-45-914" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-28-45-914.jpg" width="620" height="428" /></a></p>
<p>마인드스톰 EV3란, LEGO사와 MIT 미디어랩의 합작품으로, 로봇을 만들고 프로그래밍을 할 수 있는 블록이다. labVIEW의 블록 코딩을 사용하면 아주 쉽게 코딩이 가능하다. 하지만, 이번 프로젝트에서는 당연히 블록코딩을 사용하지 않았다. EV3의 VM(Virtual machine)에서 실행되는 bytecode라는 것이 있는데, USB, Bluetooth, WiFi를 통해 VM으로 전송이 가능하다. 바이트코드의 목록과 형식은 LEGO MINDSTORMS EV3 Firmware Develop kit를 참고하였다. 바이트 코드는 OP code, parameter, return valude로 구성된다. 각 값들을 정의에 따라 바꾸며 섬세한 EV3 제어가 가능하다.</p>
<p><strong>Ⅱ. 라즈베리파이3로 EV3를 WiFi로 제어</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-30-181.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34672" alt="Cap 2018-02-05 09-30-30-181" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-30-181.png" width="620" height="346" /></a></p>
<p>EV3를 제어하는 MCU로는 라즈베리파이3를 채택하였다. 라즈베리 파이2와는 다르게 3에서는 와이파이 기능이 자체적으로 들어가 있기 때문에 근거리에서 무선으로 EV3 자동차로봇을 제어하는 데에 적합하였다. 이 때, 라즈베리파이라는 외부의 MCU로부터 EV3를 제어하므로 Direct Command 형식으로 명령코드를 작성하였다. Direct Command는 외부에서 EV3로 byte code를 전송할 때 사용하는 형식으로, USB, Bluetooth, WiFi로 전송 가능하며 이 또한 LEGO MINDSTORMS EV3 Communication Developer kit를 참고하였다. 응답으로 Direct reply를 받을 수 있다.</p>
<p>&nbsp;</p>
<p><strong>Ⅲ. 컬러 센서 사용하는 악보 제작</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-35-966.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34673" alt="Cap 2018-02-05 09-30-35-966" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-35-966.jpg" width="620" height="429" /></a></p>
<p>컬러 센서로 색종이의 색깔을 구분하여 악보를 제작할 수 있다. 이 때 프로젝트 환경이었던 실내 장판은 갈색이 아닌 무색(색 없음, value 값 0)으로 컬러 센서가 인식을 하였다. 실제로, 컬러 센서로 색을 인식시킬 때 가장 까다로웠던 색이 바로 갈색인데, 조금 밝은 갈색이면 노란색으로, 조금 어두운 갈색은 검은색으로, 또 약간 붉은 기가 있는 갈색은 빨간색으로 인식하여 컬러센서를 위한 갈색을 찾는 데에 조금 애를 먹었다. 하지만 시중에서 판매되는 색종이로 갈색 값을 어렵지 않게 인식시킬 수 있으므로, 사용자가 사용하는 데에는 큰 무리가 없을 것으로 예상된다. 컬러센서로 인식시킬 색상 악보의 예시는 다음 사진과 같다. 아래 ‘악보’는 조지 윈스턴의 ‘캐논 변주곡’의 앞부분이다. 화살표 방향으로 자동차로봇이 전진하면서 컬러센서로 색상을 인식하고 각 색에 1:1 매칭이 되어있는 숫자로 변환시켜 색종이의 순서대로 저장하게 된다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-43-930.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34674" alt="Cap 2018-02-05 09-30-43-930" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-43-930.png" width="620" height="203" /></a></p>
<p><strong>Ⅳ. 소프트웨어적 발전 : Direct Command를 자동으로 전송하는 함수 및 Direct Reply를 자동으로 수신하는 함수의 알고리즘 개발</strong><br />
Direct Command는 위에서 언급하였듯이 EV3로 bytecode를 전송할 때 사용하는 형식으로, Little Endian을 사용하며 리턴 값으로 사용하는 Global variable의 offset은 align되어야 하며, 커맨드를 보내는 형식 또한 다소 복잡하다. 아래는 Direct Command의 형식을 정리한 그림이다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-50-380.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34675" alt="Cap 2018-02-05 09-30-50-380" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-30-50-380.png" width="620" height="296" /></a></p>
<p>bytecode를 보낼 때마다 이 형식을 지키며 일일이 보내게 되면 굉장히 시간이 많이 걸리고, 복잡하다. 따라서 이번 프로젝트에서 Direct Command를 구조체로 미리 만들어서 함수의 매개변수로 보내면 byte code로 해석하여 EV3로 전송해주는 send_command() 함수를 개발하였다. 또한, Direct Reply 또한 해석하여 shell에 print해주는 read_reply() 함수 또한 개발하였다. 함수의 작성 코드는 다음과 같다.</p>
<p>① send_command 함수</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-02-634.png" rel="lightbox[34454]"><img class="alignnone size-large wp-image-34676" alt="Cap 2018-02-05 09-31-02-634" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-02-634-513x620.png" width="513" height="620" /></a></p>
<p>② read_reply 함수</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-11-014.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34677" alt="Cap 2018-02-05 09-31-11-014" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-11-014.png" width="620" height="351" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-21-164.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34678" alt="Cap 2018-02-05 09-31-21-164" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-21-164.png" width="620" height="447" /></a></p>
<p>이 두 함수는 이 프로젝트뿐만 아니라 byte code를 작성하여 마인드 스톰 EV3를 제어하는 모든 프로젝트에서 아주 유용하게 쓰이게 될 것이다.</p>
<p><span style="color: #33cccc;"><strong>3.2. 전체 시스템 구성</strong></span><br />
<strong>Ⅰ. 소프트웨어적 구성</strong><br />
라즈베리파이와 EV3를 연결하여 명령을 송수신한다. 라즈베리파이와 EV3는 USB 포트로 연결되며, 라즈베리파이의 전원 공급은 EV3의 USB 단자로부터 공급받게 된다. 리눅스 환경에서 와이파이로 라즈베리파이와 ssh로 통신하여 C 프로그래밍으로 춤추고 노래하는 자동차로봇의 알고리즘을 짜고 실행시키게 되면, USB 드라이버는 USB 컨트롤러를 통해 프로그래밍 명령을 전달하게 된다.</p>
<p>이 때 EV3의 특성상, 외부에서 오는 명령은 EV3 전용 Byte code로 작성이 되어있어야 하며, 이 byte code는 EV3의 USB controller를 통해 USB 드라이버로 인식되어 EV3 내부의 가상 머신에 전달된다. USB로 연결된 라즈베리파이와 EV3는 일단 라즈베리파이에서 USB 장치 디바이스 파일을 찾는데, 다른 USB 장치가 없이 EV3만 연결되어있을 때는 절대경로로 /dev/hidraw0 파일을 찾으면 된다. 라즈베리파이에서 해당 디바이스 파일을 읽고 쓰기 위해 open을 할 때도 이 위치의 디바이스 파일을 이용하면 된다. 이 가상머신 위에서 EV3는 라즈베리파이 알고리즘의 명령대로 각 Output 드라이버들에게 명령을 전달하고, 모터 컨트롤러와 스피커에 전기적 신호가 전달되어 명령을 수행하게 된다. EV3와 라즈베리파이를 연동하는 일련의 과정을 도표로 요약하여 작성하면 다음과 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-43-615.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34679" alt="Cap 2018-02-05 09-31-43-615" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-43-615.png" width="620" height="413" /></a></p>
<p><strong>Ⅱ. 하드웨어적 구성</strong><br />
절차적인 하드웨어 구성 도표는 다음과 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-52-696.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34680" alt="Cap 2018-02-05 09-31-52-696" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-31-52-696.png" width="620" height="290" /></a></p>
<p>조립 및 연결이 완료된 라즈베리파이와 EV3의 전체 조감도는 다음과 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-32-02-697.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34681" alt="Cap 2018-02-05 09-32-02-697" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-32-02-697.jpg" width="620" height="433" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-32-05-981.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34682" alt="Cap 2018-02-05 09-32-05-981" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-32-05-981.jpg" width="620" height="433" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-32-14-430.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34683" alt="Cap 2018-02-05 09-32-14-430" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-32-14-430.jpg" width="620" height="433" /></a></p>
<p><span style="color: #33cccc;">3.3. 개발 환경</span><br />
<strong>Ⅰ. 개발 언어</strong><br />
라즈베리파이는 기본적으로 Linux 환경에서 동작한다. 리눅스 환경에서 주로 쓰이는 언어는 C언어와 Python인데, 본 프로젝트에서는 C언어를 사용하였다.</p>
<p><strong>Ⅱ. 사용 시스템</strong><br />
MCU로 라즈베리파이 3를 채택하였다. ssh 통신으로 근거리에 있는 자동차 로봇과 호스트 컴퓨터 사이의 무선 통신을 하는데에 WiFi 기능이 기본적으로 탑재되어있는 라즈베리파이 3가 적합하다고 판단했다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-34-40-081.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34684" alt="Cap 2018-02-05 09-34-40-081" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-34-40-081.jpg" width="620" height="433" /></a></p>
<p><strong>Ⅲ. 사용 툴</strong><br />
Linux Ubuntu OS 기반에서 vim 편집기를 사용하여 개발하였다.</p>
<p><span style="color: #0000ff;"><strong>4. 단계별 제작 과정</strong></span><br />
<strong>Ⅰ. 전체적인 제작 과정</strong><br />
위 프로젝트를 진행하는데 소요된 전체 제작 기간은 2017년 1월 29일부터 2017년 2월 26일까지이다. 1월 말 며칠 동안은 리눅스 및 라즈베리파이에 대해 이론적으로 공부하는 시간을 가졌으며, 실질적으로 춤추고 노래하는 자동차 로봇 프로젝트를 진행하는 데에 소요된 기간은 2월 한 달이다. 따라서 단계별 제작 과정을 2월 한 달 간의 시간의 흐름을 따라 도식적으로 도표로 정리하면 다음과 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-34-47-463.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34685" alt="Cap 2018-02-05 09-34-47-463" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-34-47-463.png" width="620" height="202" /></a></p>
<p><strong>Ⅱ. EV3 로봇 조립</strong><br />
마인드스톰 EV3 키트에 포함되어있는 설명서대로 조립을 진행한다. 그 후 전원을 키고, 데모 프로그램을 실행해보며 제대로 조립을 했는지 확인한다. EV3는 사용자의 목적에 따라 다양한 형태로 조립이 가능한데, 나는 4개의 바퀴가 달린 포크레일 형태로 조립하였다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-34-56-081.jpg" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34686" alt="Cap 2018-02-05 09-34-56-081" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-34-56-081.jpg" width="620" height="435" /></a></p>
<p>그 결과 4개의 바퀴를 위한 large motor 2개, 포크레일의 팔을 제어하기 위한 medium motor 한 개가 조립 시 필요하였다. 특히, 라즈베리파이를 EV3 로봇에 고정시켜야했는데, 이 때 LEGO의 장점이 십분 발휘되었다. 위의 그림 4-1.1에서 확인할 수 있듯이, 라즈베리파이를 EV3 본체의 우측에 고정시키기 위해 여분의 레고 조각들을 이용해 개발자가 라즈베리파이가 고정될 수 있도록 라즈베리파이 둥지를 만들었다.</p>
<p><strong>Ⅲ. 라즈베리파이와의 연동</strong><br />
본 프로젝트에서 사용한 MCU는 라즈베리파이3로, 호스트 컴퓨터와 라즈베리파이 사이의 WiFi를 이용한 ssh 통신이 기본적으로 가능하다. 아래 그림 4-2.1은 호스트 컴퓨터에서 라즈베리파이로 ssh를 이용해 접속한 모습이다. 개발자가 사용한 라즈베리파이의 ip 주소가 192.168.0.10이며 성공적으로 라즈베리파이와 통신이 연결된 것을 확인할 수 있다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-02-196.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34687" alt="Cap 2018-02-05 09-35-02-196" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-02-196.png" width="620" height="317" /></a></p>
<p><strong>Ⅳ. 핵심 알고리즘 개발</strong><br />
알고리즘의 흐름도는 아래 그림 4-3.1과 같다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-08-697.png" rel="lightbox[34454]"><img class="alignnone size-full wp-image-34688" alt="Cap 2018-02-05 09-35-08-697" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-08-697.png" width="620" height="439" /></a></p>
<p>&nbsp;</p>
<p><strong>Ⅴ. 테스트 및 디버깅</strong><br />
컬러 센서가 감지하는 색상은 정확한 편이었지만, 다양한 색상 인식이 필요하고 고정적인 크기의 색상 인식 물체가 필요한 이유로 색종이를 색상 인식 물체로 선정했다. 그런데, 색종이의 밝은 분홍색은 컬러센서가 하얀색으로 인식하고, 색종이의 주황색은 컬러센서가 노란색으로 인식하는 등 조금의 오차가 있었다. 따라서 이러한 부분들을 컬러 센서를 테스트하는 과정에서 컬러 센서가 인식하는 대로 다시 분류하는 작업이 필요했다. 특히 색상 인식이 까다로웠던 색은 갈색이었는데, 밝은 갈색은 노란색, 붉은 갈색은 빨간색, 어두운 갈색은 검정색으로 인식하였다. 다행스럽게도 색종이의 갈색은 한 번의 오류 없이 항상 갈색으로 인식하여 갈색 색종이를 악보로 쓸 수 있었다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-21-917.png" rel="lightbox[34454]"><img class="alignnone size-large wp-image-34689" alt="Cap 2018-02-05 09-35-21-917" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-21-917-491x620.png" width="491" height="620" /></a></p>
<p>라즈베리파이와 EV3를 연결시켜 고정시키는 과정에서 여러 종류의 커넥팅 라인들 또한 많을 수 밖에 없었는데, 이 선들의 무게중심이 EV3 자동차 로봇의 한 쪽으로 극단적으로 쏠리게 되면 자동차가 직진할 때 조금 회전하는 경향이 보였다. 따라서 선들을 묶어서 EV3 본체 중간에 움직이지 않도록 고정시켰다. 그 뒤로는 직진을 할 때 문제가 일어나지 않았다.<br />
색상을 인식한 후 buffer에 저장하는 과정에서 더 빠르고 단순한 방법으로 알고리즘을 개발하기 위해 여러 방법으로 알고리즘을 변형하고 테스트해보았다. 다음 그림 4-1.1은 알고리즘 테스트 과정 중인 모습이다.</p>
<p>가장 많은 방법으로 테스트를 해본 것 중 하나는 바로 무음 처리이다. 프로젝트를 진행하면서 한 가지 해결하지 못한 것은, 첨부 2 또는 첨부 3의 동작 동영상에서 볼 수 있듯이 박자가 쉬는 부분에서는 스피커의 출력 주파수를 0Hz로 설정하고 스피커의 출력 시간 또한 0초로 설정하였음에도 그 타이밍에 ‘툭’하는 소리가 나는 현상이 일어난다. 스피커를 출력하는 동안 무음으로 처리되어야 할 부분에 마치 잡음처럼 들리기도 하여, 이 부분을 해결하지 못한 점이 아쉽다.</p>
<p><span style="color: #0000ff;"><strong>5. 작동 이미지</strong></span></p>
<p><strong><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-32-150.jpg" rel="lightbox[34454]"><img class="alignnone  wp-image-34690" alt="Cap 2018-02-05 09-35-32-150" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-32-150-525x620.jpg" width="600" /></a></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-40-364.jpg" rel="lightbox[34454]"><img class="alignnone  wp-image-34691" alt="Cap 2018-02-05 09-35-40-364" src="http://www.ntrexgo.com/wp-content/uploads/2017/11/Cap-2018-02-05-09-35-40-364.jpg" width="600" /></a></p>
<p><span style="color: #0000ff;"><strong>6. 참고문헌</strong></span><br />
· NCS(임베디드SW구현)기반의 스마트로봇EV3, 남상엽, 2014, 이지테크<br />
· 산딸기 http://www.rasplay.org</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/34454/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[30호]6족 보행 로봇 ‘벅벅이’</title>
		<link>http://www.ntrexgo.com/archives/29420</link>
		<comments>http://www.ntrexgo.com/archives/29420#comments</comments>
		<pubDate>Fri, 15 May 2015 07:39:59 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[30호]]></category>
		<category><![CDATA[ict]]></category>
		<category><![CDATA[공모전]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[우수상]]></category>
		<category><![CDATA[융햡]]></category>
		<category><![CDATA[프로젝트]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=29420</guid>
		<description><![CDATA[디바이스마트매거진 30호 &#124; 최근 산업 현장 외에도 일상생활에서 사람을 도와줄 수 있는 로봇의 필요성이 높아지고 있다. 이러한 요구를 충족시키기 위한 로봇에 있어 이동의 기능은 필수적인 기술이 되었다. ]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/wp-content/uploads/2015/05/Cap-2015-11-30-16-24-59-922.png" rel="lightbox[29420]"><img class="alignnone size-full wp-image-29448" alt="Cap 2015-11-30 16-24-59-922" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/Cap-2015-11-30-16-24-59-922.png" width="620" height="250" /></a></p>
<p><span style="color: #000080;font-size: xx-large;background-color: #ffffff"><strong>6족 보행 로봇 ‘벅벅이’</strong></span></p>
<p style="text-align: right">글 | 고려대학교 과학기술대학 제어계측공학과 류예슬</p>
<p>&nbsp;</p>
<p><span style="color: #ffffff;font-size: medium;background-color: #000080"><strong>심 사 평</strong></span></p>
<p><span style="color: #ffffff;background-color: #0000ff">싱크웍스 </span>시연동영상으로 볼때 작품의 완성도가 높았고, 학생 수준에서 구할 수 있는 재료들을 잘 사용해서 만든 것 같다. 작품을 만들면서 많은 공부가 되었을 것 같다.</p>
<p><span style="color: #ffffff;background-color: #0000ff">JK전자 </span>유선 조이스틱으로 조정하여 단순히 보행만 하는 기능 이외에 보행을 하면서 할 수 있는 부가적인 기능이 추가되었으면 더 좋았을 것 같다. 예를 들면 사람이 갈수 없는 곳을 탐사하여 영상을 전송하는 기능이나, 물건을 집어서 옮기는 기능 등이 된다면 조금 더 실용성이 높아질 것이다. 어쨌든 여러 사람이 아닌 혼자서 기구부 제작과 소프트웨어 개발까지 했다는 것은 쉬운 일은 아니었을 것이다. 마음이 맞는 좋은 파트너와 코웍을 하면 조금 더 실용성이 높은 작품이 나올것 같다.</p>
<p><span style="color: #ffffff;background-color: #0000ff">뉴티씨</span> 매우 잘만든 6족로봇 작품으로 판단된다. 다만, 빠른 이동은 좀 어려운 점이 약간 아쉽다. 미끄러움을 방지하기 위하여, 끝부분에 고무 같은 재질을 사용한 점도 좋은 점으로 착안하였다. 좀 더 잘 만든다면, 구조로봇 같은 형태로도 만들어질 수 있을 것으로 생각되며, 계단 등도 다른 작품처럼 올라갈 수 있을 것으로 생각된다. 기술적인 난이도는 매우 높지도 낮지도 않지만, 전체적인 작품의 완성도가 높은 것으로 판단되며, 기구적인 부분에서도 창의적인 아이디어로 재료 선택 등에서도 무게도 줄이고 잘 만든 것 같다. 향후, 학습하면서 좋은 작품을 만들 수 있을 것으로 기대한다.</p>
<p><span style="color: #ffffff;font-size: medium;background-color: #000080"><strong>작품 개요</strong></span></p>
<p><strong><span style="color: #0000ff">■ 프로젝트 개발 동기</span></strong><br />
최근 산업 현장 외에도 일상생활에서 사람을 도와줄 수 있는 로봇의 필요성이 높아지고 있다. 이러한 요구를 충족시키기 위한 로봇에 있어 이동의 기능은 필수적인 기술이 되었다. 특히 6족 로봇은 오프로드에서도 바퀴로 이동하는 모바일로봇 또는 다른 종류의 보행 로봇보다 안정된 보행을 할 수 있다는 장점을 가졌고, 또한 전쟁, 행성탐사, 무너진 건물 속의 인명탐사 등에 활용 될 수 있다.<br />
하드웨어 및 소프트웨어에 열정이 있는 사람들의 모임인 과 내 학술소모임 다가치(KUCIRA)에서 학술제를 목표로 보행로봇을 프로젝트로 기획하던 중, 보행 로봇에 대한 정보를 수렴한 결과 위와 같은 장점을 가진 6족 로봇이 가장 적절하다 생각되어 개발하게 되었다.</p>
<p><span style="color: #0000ff"><strong>■ 프로젝트 구현 목표</strong></span><br />
· 6족 로봇의 보행 메카니즘과 구조 이해 (전진, 후진, 회전)<br />
· Atmega 128 (MCU) 이해 및 AVR 프로그래밍 이해<br />
· 서보모터의 이해 [fast pwm제어]
· 2축 조이스틱(가변저항)을 이용한 유선제어 [AD Convertor]
<p><span style="color: #0000ff"><strong>■ 제목의 의미</strong></span><br />
이 프로젝트의 가장 큰 특징은 로봇의 다리가 6개라는 점이다. 이 점을 감안하여 6개의 다리를 가진 곤충과 관련된 이름을 지어주려고 하였는데, 첫 프로젝트인 느낌을 살리기 위해 ‘bug’의 ‘벅’을 한국식으로 바꾸어 ‘벅벅이’라 이름을 붙여주게 되었다.</p>
<p><span style="font-size: medium;color: #ffffff;background-color: #000080"><strong>작품 설명</strong></span></p>
<p><span style="color: #0000ff"><strong>■ 주요 동작 및 특징</strong></span><br />
‘벅벅이’의 주요 동작은 보행이다. 로봇의 다리는 6개이고 각 다리 당 2개의 관절을 가진 12관절 구조이다. 몸통과 가까운 모터를 ‘위 관절’이라 하고 바닥과 가까운 모터를 ‘아래 관절’이라고 칭하면, 위 관절은 가고자 하는 방향결정에 중요한 역할을 한다. 아래 관절은 위 관절이 이동을 할 때에는 발을 바닥에서 들어주고 이동을 마친 후에는 바닥으로 발을 찍어주어 바닥의 마찰을 이용하여 이동하게 해주는 역할을 한다.<br />
구현한 보행의 종류는 크게 세 가지이다. 전진, 후진, 좌/우로의 회전이다. 그리고 정육각형 형태의 프레임을 가졌기 때문에 앞뒤 구분이 필요하였다. 이를 위해 led를 삽입하였고 앞뒤 구분의 역할과 동시에 동작에 따라 led가 다른 알고리즘을 수행하게 하였다. 마지막으로 2축 조이스틱을 이용하여 조이스틱의 기울기(위치)에 따라 ‘벅벅이’를 제어하였다.</p>
<p><strong>1. 전진/후진</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-1.jpg" rel="lightbox[29420]"><img class="alignnone size-full wp-image-29428" alt="30 2014 ict (1)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-1.jpg" width="400" height="313" /></a><br />
위 사진처럼 다리의 번호를 1번부터 6번까지로 표현하였다. 위 관절의 모터를 먼저 얘기하면 2번과 6번, 3번, 1번과 5번, 4번 이렇게 각각의 세트를 4개의 MCU PORT에 연결하였다. 아래 관절은 2, 3, 6번 그리고 1, 4, 5번 다리가 또 다른 2개의 PORT에 연결하였다. 이렇게 연결한 이유는 6족 로봇의 보행 매카니즘과 관련이 있다. 동영상으로 시연영상을 보면 바로 파악하기는 어려우나 자세히 보면 모터의 동작 순서는 다음과 같다.<br />
위 관절의 1번+5번 모터를 A, 4번 모터를 B, 2번+6번 모터를 C, 3번 모터를 D라 하고, 아래 관절의 1번+4번+5번 모터를 E, 2번+3번+6번 모터를 F라 하자. 정지 상태에서 위 관절의 모든 모터는 각도를 0˚부터 180˚범위에서 90˚이고, 아래 관절의 모든 모터는 40˚인 상태이다.(위 오른쪽 사진 참고) 전진을 위한 과정은 다음과 같다.</p>
<p>1) 먼저 전진을 위해서는 E모터를 90˚로 해준다. 이것은 먼저 이동할 다리를 움직일 수 있도록 발을 바닥에서 해체시켜주는 것이다. (모터의 RESET(정지)상태는 ABCD모터는 모두 90˚ 이고, EF모터는 모두 40˚이다.)<br />
2) A모터는 110˚, B모터는 75˚가 동시에 되도록 한다.<br />
3) E번 모터를 40˚로 한다. 이것은 발을 바닥으로 내려주는 역할을 한다.<br />
4) F모터를 90˚로 하여 반대편 다리를 든다. (위 관절의 한 세트라도 방향 제어를 할 경우에는 다른 반대쪽 아래 관절의 다리는 들려있어야 한다.)<br />
5) A모터를 70˚B모터는 110˚가 동시에 되도록 한다. 아래 관절의 모터로 인해 발이 바닥에 닿아 있는 상태이기 때문에 마찰에 의하여 로봇이 앞으로 움직이게 된다.<br />
6) 위와 같은 원리로 C모터는 70˚, D모터는 110˚가 동시에 되도록 한다.<br />
7) F모터를 40˚로, E모터를 90˚로 한다.<br />
8) C모터는 110˚, D모터는 80˚가 동시에 되도록 한다. 마찬가지로 F모터로 인해 마찰에 의하여 로봇이 전진하게 된다.</p>
<p>위 과정의 알고리즘은 다음과 같다. 실제 코딩(모터의 분류)은 A, B, C, D, E, F가 아닌 숫자로 되어있지만 위에 그렇게 표현하였기 때문에 바꿔 첨부하였다. Motor(int x, int y)함수는 x번 모터를 y˚만큼 각도변환 시키는 함수이다. delay를 얼마만큼 주는지에 따라 보행 속도가 결정된다.<br />
*후진은 전진과 방향만 반대일 뿐 보행 원리는 같다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>void GOBACK()<br />
{<br />
PORTA=0X00;<br />
Motor(E,90); //들고(1번다리)<br />
delay_ms(230);<br />
Motor(A,110);<br />
Motor(B,75); // 1번다리 회전<br />
delay_ms(230);<br />
Motor(E,40); //1번다리 내리고<br />
delay_ms(230);<br />
Motor(f,90); // 2번다리 들고<br />
delay_ms(230);<br />
Motor(A,70);<br />
Motor(B, 110); //1번다리 반회전<br />
delay_ms(230);<br />
Motor(C,70);<br />
Motor(D,110); // 2번다리 회전<br />
delay_ms(230);<br />
Motor(F,40); //2번다리 내리고<br />
delay_ms(230);<br />
Motor(E,90); //1번다리 들고<br />
delay_ms(230);<br />
Motor(C,110);<br />
Motor(D,80); //2번다리 반회전<br />
}</p>
</div>
<p><strong>2. 좌/우 회전</strong><br />
좌/우 회전의 매카니즘 이해는 전진/후진보다 훨씬 쉽다. 간단하게 말하면 다리를 반으로 나누어 회전하고자하는 방향으로 회전을 시켜주면 된다. 내가 구현한 알고리즘은 회전시킬 다리의 아래 관절을 들고 그 다리를 회전시키고 나머지 반의 다리들도 앞과 같이 해주면 된다. 아래 관절을 이용해 발을 드는 동작과 위 관절을 이용해 다리를 회전시키는 동작 사이의 시간을 줄여줄수록 모션을 좀 더 부드럽게 제어할 수 있다.<br />
아래는 실제 알고리즘이다. 중간에 들어간 read_adc()에 대한 조건문은 뒤에서 조이스틱 파트에서 설명하기로 한다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>//좌우<br />
if(read_adc(1)&gt;900 //오른쪽으로 회전<br />
{<br />
PORTA=0xf0;<br />
Motor(1,90); //들고(1번다리)<br />
delay_ms(100);<br />
Motor(3,110);<br />
Motor(4,110); //1번다리 회전<br />
delay_ms(200);<br />
Motor(1,40); //1번다리 내리고<br />
delay_ms(200);<br />
if(read_adc(1)&gt;=300 &amp;&amp; read_adc(1)&lt;=700)<br />
STOP();<br />
else if(read_adc(1)&gt;900)<br />
{</p>
<p>Motor(2,90); // 2번다리 들고<br />
delay_ms(100);<br />
Motor(3,90);<br />
Motor(4,90); //1번다리 반회전<br />
delay_ms(200);<br />
Motor(5,110);<br />
Motor(6,110); // 2번다리 회전<br />
delay_ms(100);<br />
Motor(2,40); //2번다리 내리고<br />
delay_ms(200);<br />
if (read_adc(1)&gt;=300 &amp;&amp; read_adc(1)&lt;=700)<br />
STOP();<br />
else if(read_adc(1)&gt;900)<br />
{<br />
Motor(1,90); //1번다리 들고<br />
delay_ms(100);<br />
Motor(5,90);<br />
Motor(6,90); //2번다리 반회전<br />
}<br />
</div>
<p><strong>3. 동작에 따른 LED</strong><br />
알고리즘 상의 ‘벅벅이’의 보행종류는 앞서 말했듯이 전진, 후진, 회전으로 나눠진다. 원한다면 각 동작에 다른 led제어구문을 삽입할 수 있다. 나는 로봇의 정지 상태와 동작 상태만을 구분하기 위해 정지 상태에는 8개의 LED가 방향을 바꾸어 가며 순차점등을 하도록 하였고, 동작 상태에서는 눈과 같다는 인상을 심어주기 위해 양 끝 LED만 켜지게 하였다. (이것은 ‘눈’을 연상시키게 함이다.) 실제 알고리즘은 다음과 같다.</p>
<p><strong><span style="color: #808080">정지상태의 LED 동작</span></strong><br />
좀 더 정확한 초 계산을 위해 타이머 normal 모드를 통해 LED를 제어하였다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>Void STOP()<br />
{<br />
if(i&lt;8)<br />
{<br />
if(cnt1&gt;1)<br />
{<br />
PORTA=~(RLED&lt;&lt;i);<br />
i++;<br />
cnt1=0;<br />
}<br />
}<br />
else if(i==8)<br />
{<br />
if(j&lt;8)<br />
{<br />
if(cnt1&gt;1)<br />
{<br />
PORTA=~(LLED&gt;&gt;j);<br />
j++;<br />
cnt1=0;<br />
}<br />
}<br />
else i++;<br />
}<br />
else<br />
{<br />
i=0;<br />
j=0;<br />
}<br />
</div>
<p><span style="color: #808080"><strong>동작상태의 LED 동작</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
EPROTA = 0x7E<br />
</div>
<p>양 끝 LED를 계속 키고 있는 상태를 코딩하는 것은 쉽다. 내가 구성한 회로의 LED의 PORT가 아닌 쪽이 Vcc와 연결되어 있기 때문에 LED와 연결된 PORT의 출력레지스터 설정을 한 후, LOW신호를 흘려주면 그 부분의 LED는 불이 들어오게 된다.<br />
우선 사용한 2축 조이스틱은 두 개의 가변저항으로 만들어진 컨트롤러이다. 먼저 한 축은 보행의 전진, 후진을 제어하고, 나머지 한 축은 좌/우로의 회전을 제어한다. 여기서 사용되는 AVR의 기능은 ADC라는 기능이다.</p>
<p>ADC란 ‘Analog Digital Convertor’라는 줄임말로 아날로그 신호를 디지털로, 혹은 디지털 신호를 아날로그 신호로 바꿔주는 기능이다. 여기서 내가 사용한 것은 아날로그 신호를 디지털 신호로 바꿔준 기능이다. 2축 조이스틱의 방향을 바꿔줄 때마다 가변저항의 값이 변한다. 이것이 바로 아날로그 신호이다. 이런 아날로그 신호를 MCU에 전달해주고 그 신호 값에 따라 코딩한 알고리즘이 구현된다. 이것이 아날로그신호가 디지털 신호로 바뀌는 과정이다. 로봇의 각 모션에 따른 알고리즘은 길기 때문에 위에서 잠깐 봤던 회전 알고리즘에서 설명을 하도록 하겠다.</p>
<p>ADC를 사용하기 위해서는 먼저 그것에 대한 초기 레지스터 설정을 해주어야 한다. 레지스터 설정은 Code Vision의 Wizard (사용하고자 하는 기능의 툴을 제공)을 사용하였다.</p>
<p><a href="http://www.ntrexgo.com/archives/29420/30-ict-05" rel="attachment wp-att-29427"><img class="alignnone  wp-image-29427" alt="30 ict 05" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-ict-05.bmp" width="538" height="283" /></a></p>
<p>레지스터 설정은 간단하게 넘어가고, 아날로그 신호를 디지털 신호로 어떤 식으로 변환하는지에 대해서 살펴보자. 밑의 사진은 ‘좌/우 회전’ 동작에서도 봤던 알고리즘이다. 중간 중간에 read_adc(1)의 값에 따른 조건문이 삽입되어 있다. 이것이 바로 가변저항 즉, 아날로그 신호를 디지털 신호로 변환시킨 값이다.<br />
가변저항의 값에 따라 read_adc(1)의 값이 어떻게 변하는지는 보통 통신을 통해서 정확한 값을 확인한다. 하지만 정확한 값을 받아야 하는 센서를 사용하는 것이 아니고 내가 원하는 지점에서부터 작동하기만 하면 되기 때문에 처음 테스트는 read_adc(1)의 값에 따라 LED를 통해 확인했고 그 값을 토대로 알고리즘을 작성할 수 있었다.<br />
조이스틱을 오른쪽으로 기울였을 때 내가 원하는 위치에서의 adc값은 900이었다. 그 이상일 때 회전하는 알고리즘을 넣어주었고 다시 조이스틱이 가운데로 돌아왔을 때는 정지하는 내용도 중간 중간에 넣어 있다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>//좌우<br />
if(read_adc(1)&gt;900 //오른쪽으로 회전<br />
{<br />
PORTA=0xf0;<br />
Motor(1,90); //들고(1번다리)<br />
delay_ms(100);<br />
Motor(3,110);<br />
Motor(4,110); //1번다리 회전<br />
delay_ms(200);<br />
Motor(1,40); //1번다리 내리고<br />
delay_ms(200);<br />
if(read_adc(1)&gt;=300 &amp;&amp; read_adc(1)&lt;=700)<br />
STOP();<br />
else if(read_adc(1)&gt;900)<br />
{</p>
<p>Motor(2,90); // 2번다리 들고<br />
delay_ms(100);<br />
Motor(3,90);<br />
Motor(4,90); //1번다리 반회전<br />
delay_ms(200);<br />
Motor(5,110);<br />
Motor(6,110); // 2번다리 회전<br />
delay_ms(100);<br />
Motor(2,40); //2번다리 내리고<br />
delay_ms(200);<br />
if (read_adc(1)&gt;=300 &amp;&amp; read_adc(1)&lt;=700)<br />
STOP();<br />
else if(read_adc(1)&gt;900)<br />
{<br />
Motor(1,90); //1번다리 들고<br />
delay_ms(100);<br />
Motor(5,90);<br />
Motor(6,90); //2번다리 반회전<br />
}<br />
</div>
<p>다른 동작들도 아래와 같은 방식의 알고리즘으로 되어있다.</p>
<p><span style="color: #0000ff"><strong>■ 전체 시스템 구성</strong></span><br />
<strong>1. 6족 보행 로봇을 만들기 위한 최소 관절(모터)의 개수 파악</strong><br />
6족 로봇으로 보행하기 위해서는 위의 매커니즘을 이해하면 알 수 있듯이 최소 다리 당 2개 즉, 12개가 필요함을 파악했다.</p>
<p><strong>2. 서보모터 각도 제어</strong><br />
서보모터의 각도를 제어하기 위해서는 모터구동의 원리를 이해할 필요가 있었다. 서보모터는 모터에 흘려주는 Pulse의 주기에 따라 각도가 제어된다. Pulse를 변형시켜주기 위해 타이머의 ‘Fast pwm’기능을 사용하였고, 프레임 제작 전 원하는 각도를 넣었을 때 그 각도가 되도록 하는 실습을 하였다.</p>
<p><strong>3. 프레임 제작 계획</strong><br />
사용하기로 한 모터의 토크는 3kg.cm은 그리 좋은 스펙은 아니다. 그러나 사람들이 만든 여러 블로그를 참고하여 프레임의 무게를 최소화할 수 있다면 문제가 될 부분은 아니었다. 그리하여 가장 프레임의 재료는 100% 포맥스로 정하였다.</p>
<p><strong>4. 보행 매카니즘 파악</strong><br />
모터의 각도제어를 실습하였고, 프레임이 완성된 후 6족 로봇의 보행 매카니즘을 파악하였다. 목표는 전진/후진/좌우로 회전이었기 때문에 제어방법을 가장 효율적으로 하고자 공통된 모터는 묶어 제어하기로 결정하였다.</p>
<p><strong>5. MCU 선정 / 회로구성</strong><br />
MCU는 쓰고자 하는 기능들(I/O, Interrupt, ADC, Timer)을 쓸 수 있는 ‘Atmega128’을 선정하였다. 회로에서는 가장 중요한 전원부는 ‘LM2576’이라는 레귤레이터를 사용하여 구성하였다. 처음에는 ‘LM7805’로 전원부를 구성했었는데, 두 레귤레이터 모두 출력전압을 5V로 바꿔준다는 특징은 같으나 output의 전류에서 차이가 있었다. 7805는 1A까지만 전류가 흐르지만 2576은 3A까지 흐를 수 있는 스펙을 갖고 있다. 그런 이유로 전원부는 시행착오를 거쳐 다시 제작하였다. 전류 값이 중요한 이유는 모터가 병렬로 연결되어 있어 전류가 조금이라도 부족하면 작동이 되지 않기 때문이다.</p>
<p><strong>6. 조이스틱의 원리이해</strong><br />
ADC를 이용하여 조이스틱의 방향에 따라 원하는 대로 제어하는 원리에 대하여 이해하였고 그것을 LED로 먼저 확인한 후, 모터에도 적용시켜 구현할 수 있었다.</p>
<p><span style="color: #0000ff"><strong>■ 개발환경</strong></span><br />
- MCU : Atmega 128<br />
- 개발 언어 : C<br />
- Tool : AVR Studio 및 Code Vision AVR</p>
<p><span style="font-size: medium;color: #ffffff;background-color: #000080"><strong>단계별 제작 과정</strong></span></p>
<p><span style="color: #0000ff"><strong>■ 프레임 제작</strong></span><br />
<strong>1. 제작 전 구상도</strong></p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td><img class="alignnone  wp-image-29431" alt="30 2014 ict (4)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-4.jpg" width="216" height="226" /></td>
<td><img class="alignnone  wp-image-29430" alt="30 2014 ict (3)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-3.jpg" width="229" height="227" /></td>
</tr>
</tbody>
</table>
<p><strong>2. 제작 과정</strong></p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29432" rel="attachment wp-att-29432"><img alt="30 2014 ict (5)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-5.jpg" width="121" height="230" /></a></td>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29433" rel="attachment wp-att-29433"><img alt="30 2014 ict (6)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-6-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td style="text-align: center">1. 재료 구매 (포맥스)</td>
<td style="text-align: center">2. 몸체 제작 (정 6각형 구조)</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29434" rel="attachment wp-att-29434"><img class="alignnone size-full wp-image-29434" alt="30 2014 ict (7)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-7.jpg" width="274" height="207" /></a></td>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29435" rel="attachment wp-att-29435"><img class="alignnone size-full wp-image-29435" alt="30 2014 ict (8)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-8.jpg" width="286" height="208" /></a></td>
</tr>
<tr>
<td style="text-align: center">3. 몸체+모터 제작</td>
<td style="text-align: center">4. 위 관절 제작</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29436" rel="attachment wp-att-29436"><img class="alignnone size-full wp-image-29436" alt="30 2014 ict (9)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-9.jpg" width="288" height="209" /></a></td>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29437" rel="attachment wp-att-29437"><img class="alignnone size-medium wp-image-29437" alt="30 2014 ict (10)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-10-300x200.jpg" width="300" height="200" /></a></td>
</tr>
<tr>
<td style="text-align: center">5. 아래관절 제작</td>
<td style="text-align: center">6. 발 제작 (충분한 마찰을 주기 위함)</td>
</tr>
<tr>
<td style="text-align: center" colspan="2"><a href="http://www.ntrexgo.com/?attachment_id=29438" rel="attachment wp-att-29438"><img class="size-full wp-image-29438 aligncenter" alt="30 2014 ict (11)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-11.jpg" width="364" height="273" /></a></td>
</tr>
<tr>
<td style="text-align: center" colspan="2">7. 프레임 전체 완성</td>
</tr>
</tbody>
</table>
<p><strong>■  하드웨어 제어부 제작</strong></p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29439" rel="attachment wp-att-29439"><img class="alignnone size-full wp-image-29439" alt="30 2014 ict (12)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-12.jpg" width="567" height="274" /></a></td>
</tr>
<tr>
<td style="text-align: center">전원부</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29442" rel="attachment wp-att-29442"><img class="alignnone size-full wp-image-29442" alt="30 2014 ict (15)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-15.jpg" width="567" height="316" /></a></td>
</tr>
<tr>
<td style="text-align: center">모터부</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29440" rel="attachment wp-att-29440"><img class="alignnone size-full wp-image-29440" alt="30 2014 ict (13)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-13.jpg" width="370" height="296" /></a></td>
</tr>
<tr>
<td style="text-align: center">스위치</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29441" rel="attachment wp-att-29441"><img class="alignnone size-full wp-image-29441" alt="30 2014 ict (14)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-14.jpg" width="342" height="296" /></a></td>
</tr>
<tr>
<td style="text-align: center">LED</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/?attachment_id=29443" rel="attachment wp-att-29443"><img class="alignnone size-full wp-image-29443" alt="30 2014 ict (16)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-16.jpg" width="478" height="317" /></a></td>
</tr>
</tbody>
</table>
<p><strong>■  컨트롤러 제작</strong></p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td><a style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;font-size: 13px;line-height: 19px" href="http://www.ntrexgo.com/?attachment_id=29444" rel="attachment wp-att-29444"><img class="alignnone size-full wp-image-29444" alt="30 2014 ict (17)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-17.jpg" width="567" height="353" /></a></td>
</tr>
<tr>
<td style="text-align: center">조이스틱</td>
</tr>
</tbody>
</table>
<p><a href="http://www.ntrexgo.com/?attachment_id=29447" rel="attachment wp-att-29447"><img class="size-full wp-image-29447 aligncenter" alt="30 2014 ict" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict.jpg" width="567" height="376" /></a></p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/?attachment_id=29445" rel="attachment wp-att-29445"><img class="alignnone  wp-image-29445" alt="30 2014 ict (18)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-18.jpg" width="252" height="200" /></a></td>
<td><a href="http://www.ntrexgo.com/?attachment_id=29446" rel="attachment wp-att-29446"><img class="alignnone  wp-image-29446" alt="30 2014 ict (19)" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/30-2014-ict-19.jpg" width="338" height="208" /></a></td>
</tr>
<tr>
<td style="text-align: center">조이스틱(납땜)</td>
<td style="text-align: center">조이스틱과 모드 선택 스위치</td>
</tr>
</tbody>
</table>
<p><strong>■   소스코드</strong></p>
<p><strong><span style="color: #808080">모터의 각도 제어함수</span></strong><br />
<strong></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c01" rel="attachment wp-att-29466"><img class="alignnone size-full wp-image-29466" alt="소스코드01" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드01.jpg" width="226" height="452" /></a></p>
<p><strong><span style="color: #808080">I/O 레지스터 설정</span></strong><br />
<strong></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c02" rel="attachment wp-att-29467"><img class="alignnone size-full wp-image-29467" alt="소스코드02" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드02.jpg" width="214" height="108" /></a></p>
<p><strong><span style="color: #808080">Interrupt 레지스터 설정</span></strong><br />
<strong></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c03" rel="attachment wp-att-29468"><img class="alignnone size-full wp-image-29468" alt="소스코드03" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드03.jpg" width="238" height="105" /></a></p>
<p><strong><span style="color: #808080">Timer 레지스터 설정</span></strong><br />
<strong></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c04" rel="attachment wp-att-29469"><img class="alignnone  wp-image-29469" alt="소스코드04" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드04.jpg" width="295" height="131" /></a></p>
<p><strong><span style="color: #808080">ADC 레지스터 설정</span></strong><br />
<strong></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c05" rel="attachment wp-att-29462"><img class="alignnone size-full wp-image-29462" alt="소스코드05" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드05.jpg" width="147" height="89" /></a></p>
<p><strong><span style="color: #808080">GOSTR() 함수 : 전진</span></strong><br />
<strong></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c06" rel="attachment wp-att-29463"><img class="alignnone  wp-image-29463" alt="소스코드06" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드06.jpg" width="257" height="313" /></a></p>
<p><strong><span style="color: #808080">GOBACK() 함수 : 후진</span></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c07" rel="attachment wp-att-29464"><img class="alignnone  wp-image-29464" alt="소스코드07" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드07.jpg" width="256" height="315" /></a></p>
<p><strong><span style="color: #808080">STOP() 함수 : 정지</span></strong></p>
<p><a href="http://www.ntrexgo.com/archives/29420/%ec%86%8c%ec%8a%a4%ec%bd%94%eb%93%9c01" rel="attachment wp-att-29466"><img class="alignnone size-full wp-image-29466" alt="소스코드01" src="http://www.ntrexgo.com/wp-content/uploads/2015/05/소스코드01.jpg" width="226" height="452" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/29420/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[20호]DIY 프로젝트 공모전 입선작 &#8211; EVALARM 물체회피 기능을 가진 알람카</title>
		<link>http://www.ntrexgo.com/archives/20912</link>
		<comments>http://www.ntrexgo.com/archives/20912#comments</comments>
		<pubDate>Fri, 30 Aug 2013 06:20:18 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[20호]]></category>
		<category><![CDATA[diy]]></category>
		<category><![CDATA[공모전]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[프로젝트]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=20912</guid>
		<description><![CDATA[디바이스마트 매거진 20호 &#124; 일반시계와 알람시계의 가장 큰 차이점은 알람기능 수행 여부의 차이입니다. 그 중 알람기능은 정해진 시간에 맞추어 사용자가 일어날 수 있도록 도와주는 것이 가장 큰 핵심이라고 할 수 있습니다. 하지만 기존의 알람시계는 소리를 잘 듣기위해 곁에 두고 자게 되고, 이로 인해 사용자가 무의식중에 알람을 꺼버려서 지각을 하거나 그 기능을 상실해 버리는 경우가 대부분입니다. 그렇기 때문에 저희 Evalam은 소리가 잘 들리게 끔 곁에 두지만 일어나지 않으면 꺼지지 않게 끔 설계되어 있어 가장 중요하고 큰 기능이 상실되는 것을 막고 이를 재미와 접목시켜 상쾌한 아침을 맞을 수 있도록 만들어졌습니다.]]></description>
				<content:encoded><![CDATA[<table style="width: 620px">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym.jpg" rel="lightbox[20912]"><img class="alignnone size-large wp-image-21089" alt="20Feadiym" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym-620x386.jpg" width="620" height="386" /></a></p>
<p><span style="font-size: medium;color: #800080"><strong>작품설명</strong></span></p>
<p><span style="color: #ff6600"><strong>제작 동기</strong></span></p>
<p><strong style="color: #800080;font-size: medium"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/293260.jpg" rel="lightbox[20912]"><img class="size-medium wp-image-21098 aligncenter" alt="293260" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/293260-300x200.jpg" width="300" height="200" /></a></strong></p>
<p>일반시계와 알람시계의 가장 큰 차이점은 알람기능 수행 여부의 차이입니다. 그 중 알람기능은 정해진 시간에 맞추어 사용자가 일어날 수 있도록 도와주는 것이 가장 큰 핵심이라고 할 수 있습니다. 하지만 기존의 알람시계는 소리를 잘 듣기위해 곁에 두고 자게 되고, 이로 인해 사용자가 무의식중에 알람을 꺼버려서 지각을 하거나 그 기능을 상실해 버리는 경우가 대부분입니다. 그렇기 때문에 저희 Evalam은 소리가 잘 들리게 끔 곁에 두지만 일어나지 않으면 꺼지지 않게 끔 설계되어 있어 가장 중요하고 큰 기능이 상실되는 것을 막고 이를 재미와 접목시켜 상쾌한 아침을 맞을 수 있도록 만들어졌습니다.</p>
<p><span style="color: #ff6600"><strong>유사 작품 | 클로키로보틱 알람시계</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy클로키로보틱.jpg" rel="lightbox[20912]"><img class="size-medium wp-image-21093 aligncenter" alt="20diy클로키로보틱" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy클로키로보틱-300x234.jpg" width="300" height="234" /></a><br />
유동성을 가진다는 측면에서 본 아이디어와 유사한 장점을 가졌지만 가격이 너무 비싸고 장애물들을 피할 수 없기 때문에, 자칫 장롱 밑 등의 폐쇄된 장소에 들어갈 시 분실의 위험이 따른다는 큰 단점이 있습니다.<br />
아이디어는 클로키로보틱 알람시계와 비슷하지만 클로키로보틱 알람시계의 단점인 장애물을 피할 수 없다는 점과 폐쇄된 장소에 들어갈 시 분실의 위험이 따른 점을 개선하도록 설계되어 있습니다. 적외선 센서을 통한 물체 회피와 리모컨 센서를 통한 RC카 제어 등으로 실용성을 높이는 것과 더불어 재미를 위해 제작하게 되었습니다.</p>
<p><span style="color: #ff6600"><strong>작품 기능 및 설명</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-6.png" rel="lightbox[20912]"><img class="wp-image-21119 aligncenter" alt="20Feadiym0 (6)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-6-620x256.png" width="496" height="205" /></a><br />
동작은 RC카와 시계의 기능을 합쳐 놓은 작품입니다.<br />
RC카는 물체 회피(모터), 조정기(수신부), 움직임(거리센서)으로 구성되어 있고, 시계에서는 일반적인 알람과 시계로 구성되어 있습니다. 서로 다른 두 작품을 합쳐 알람이 울릴 경우에 알람을 꺼버리려는 행동을 방지할 수 있도록 설계했습니다.<br />
또한 4개의 센서를 통해 벽이나 물건을 회피하여 작품과 물건을 보호하도록 설계했습니다. 이에 대한 자세한 설명은 후에 하겠습니다.</p>
<p>&nbsp;</p>
<p><span style="color: #800080"><strong><span style="font-size: medium">주요 동작 및 특징</span></strong></span></p>
<p><span style="color: #ff6600"><strong>알람이 울릴 시 전체 시나리오</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0.png" rel="lightbox[20912]"><img class="alignnone size-large wp-image-21113" alt="20Feadiym0" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-620x169.png" width="620" height="169" /></a></p>
<p>4개의 거리 측정 센서로 물체에 감지하는 상황은 총 7가지 경우로 생각해 보았습니다. 그리고 그 상황에 따라 동작은 5가지로 구성했습니다. 먼저 주요 동작 조건을 사진으로 확인해 보겠습니다.</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy평지.jpg" rel="lightbox[20912]"><img class="alignnone  wp-image-21094" alt="20diy평지" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy평지-582x620.jpg" width="188" height="200" /></a></td>
<td>1. 평지에서 사진 : 단순히 알람이 시끄럽게 울리도록 설계했습니다.</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy앞에서-알람잡.jpg" rel="lightbox[20912]"><img class="alignnone  wp-image-21092" alt="20diy앞에서 알람잡" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy앞에서-알람잡-566x620.jpg" width="183" height="200" /></a></td>
<td>2. 앞에서 Evalarm을 잡으려고 할 때 : 앞에서 Evalarm을 잡으려고 할 때 뒤로 움직이도록 설계했습니다.</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy뒤에서-알람잡.jpg" rel="lightbox[20912]"><img class="alignnone  wp-image-21111" alt="20diy뒤에서 알람잡" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy뒤에서-알람잡-508x620.jpg" width="192" height="235" /></a></td>
<td>3. 뒤에서 Evalarm을 잡으려고 할 때 : 앞으로 움직이도록 설계했습니다.</td>
</tr>
<tr>
<td style="text-align: center"><img class="alignnone  wp-image-21091" alt="20diy앞뒤에서 알람잡" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diy앞뒤에서-알람잡-499x620.jpg" width="183" height="228" /></td>
<td>4. 앞뒤에서만 물체가 감지 될 때 : 좌측으로 회전하도록 설계했습니다.</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/네방향.jpg" rel="lightbox[20912]"><img class="alignnone  wp-image-21099" alt="네방향" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/네방향-569x620.jpg" width="191" height="208" /></a></td>
<td>5. 네 방향에서 물체가 감지 될 때 : 빠져나갈 수 있는 틈새를 찾도록 설계했습니다.</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/앞뒤랑-좌측.jpg" rel="lightbox[20912]"><img class="alignnone  wp-image-21108" alt="앞뒤랑 좌측" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/앞뒤랑-좌측-580x620.jpg" width="195" height="208" /></a></td>
<td>6. 앞뒤 그리고 좌측에서 물체가 감지 될 때 :우측으로 회전하도록 설계했습니다.</td>
</tr>
<tr>
<td style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/앞뒤-우측.jpg" rel="lightbox[20912]"><img class="alignnone  wp-image-21107" alt="앞뒤 우측" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/앞뒤-우측-573x620.jpg" width="193" height="208" /></a></td>
<td>7. 앞뒤 그리고 우측에서 물체가 감지 될 때 : 좌측으로 회전하도록 설계했습니다.</td>
</tr>
</tbody>
</table>
<p><span style="color: #ff6600"><strong>설정 시 전체 시나리오 : 시간 수정, 알람 설정, 알람 시간</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-1.png" rel="lightbox[20912]"><img class="wp-image-21114 aligncenter" alt="20Feadiym0 (1)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-1-546x620.png" width="382" height="434" /></a><br />
위와 같은 표처럼 알람 시간과 알람 설정 그리고 시간을 4개의 스위치로 설정할 수 있도록 설계되어 있습니다.</p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/메인.jpg" rel="lightbox[20912]"><img class="alignnone size-medium wp-image-21100" alt="메인" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/메인-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/알람-끔.jpg" rel="lightbox[20912]"><img class="alignnone size-medium wp-image-21105" alt="알람 끔" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/알람-끔-300x225.jpg" width="300" height="225" /></a></td>
</tr>
<tr>
<td style="text-align: center">메인화면</td>
<td style="text-align: center">알람이 꺼진 화면</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/알람킴.jpg" rel="lightbox[20912]"><img class="alignnone size-medium wp-image-21106" alt="알람킴" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/알람킴-300x225.jpg" width="300" height="225" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/시간십초변화.jpg" rel="lightbox[20912]"><img class="alignnone size-medium wp-image-21122" alt="시간십초변화" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/시간십초변화-300x224.jpg" width="300" height="224" /></a></td>
</tr>
<tr>
<td style="text-align: center">알람이 켜진 화면</td>
<td style="text-align: center">시간을 10초로 설정한 화면</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/시간십분변화.jpg" rel="lightbox[20912]"><img class="alignnone size-medium wp-image-21121" alt="시간십분변화" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/시간십분변화-300x224.jpg" width="300" height="224" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/시간열시간변화.jpg" rel="lightbox[20912]"><img class="alignnone size-medium wp-image-21120" alt="시간열시간변화" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/시간열시간변화-300x224.jpg" width="300" height="224" /></a></td>
</tr>
<tr>
<td style="text-align: center">시간을 10분으로 설정한 화면</td>
<td style="text-align: center">시간을 10시간으로 설정한 화면</td>
</tr>
</tbody>
</table>
<p>위와 같은 표처럼 알람 시간과 알람 설정 그리고 시간을 4개의 스위치로 설정할 수 있도록 설계되어 있습니다.</p>
<p><span style="color: #800080;font-size: medium"><strong>전체 시스템 구성</strong></span></p>
<p><span style="color: #ff6600"><strong>하드웨어 구성</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-2.png" rel="lightbox[20912]"><img class="wp-image-21115 aligncenter" alt="20Feadiym0 (2)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-2-620x305.png" width="397" height="195" /></a></p>
<p>TEXT LCD는 7비트로 제어가 가능하도록 설계했으며, 스위치 외부 인터럽트를 사용하여 제어하도록 했습니다. 리모컨 센서는 외부 인터럽트와 타이머 카운트로 인식 받도록 설계했습니다. 적외선 센서는 AD변환을 통해 거리를 측정하도록 설계했습니다.</p>
<p><span style="color: #ff6600"><strong>적외선 센서(L298)</strong></span></p>
<table border="0">
<tbody>
<tr>
<td><a style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif;font-size: 13px;line-height: 19px" href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diyL298데이터시트.jpg" rel="lightbox[20912]"><img class="alignnone size-large wp-image-21095" alt="20diyL298데이터시트" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diyL298데이터시트-620x271.jpg" width="620" height="271" /></a></td>
</tr>
<tr>
<td style="text-align: center">L298 데이터시트</td>
</tr>
<tr>
<td><img class="alignnone size-large wp-image-21123" alt="20fediy03" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20fediy03-620x154.png" width="620" height="154" /></td>
</tr>
<tr>
<td style="text-align: center">모터 입력(설정)에 대한 움직임의 방향</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diyL298데이터시트2.jpg" rel="lightbox[20912]"><img class="alignnone size-large wp-image-21096" alt="20diyL298데이터시트2" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diyL298데이터시트2-620x346.jpg" width="620" height="346" /></a></td>
</tr>
<tr>
<td style="text-align: center">L298의 데이터시트</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diyL298데이터시트3.jpg" rel="lightbox[20912]"><img class="alignnone size-large wp-image-21097" alt="20diyL298데이터시트3" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diyL298데이터시트3-620x439.jpg" width="620" height="439" /></a></td>
</tr>
<tr>
<td style="text-align: center">L298N 부품</td>
</tr>
</tbody>
</table>
<p><span style="color: #ff6600"><strong>사용시스템</strong></span></p>
<p><span style="color: #339966"><span style="text-decoration: underline">1) 리모컨 관련 시스템 및 설명</span></span><br />
리모컨의 데이터 형식은 아래 그림과 같습니다. 처음에 리더 펄스가 나옵니다. D6121(구 삼성, 구 LG) 형식은 리더 펄스의 길이가 13.5msec이고 TC9012(삼성. LG) 형식은 리더 펄스의 길이가 9msec 입니다.<br />
다음에 32 비트의 데이터가 따라 오는데, 처음 2바이트는 커스텀 코드이고, 다음 1바이트는 데이터, 마지막 바이트는 데이터 1의 보수입니다.</p>
<table border="0">
<tbody>
<tr>
<td><img class="alignnone size-large wp-image-21125" alt="20fediy04" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20fediy04-620x278.jpg" width="620" height="278" /></td>
</tr>
<tr>
<td>리모컨의 데이터 형식</td>
</tr>
</tbody>
</table>
<p>각 비트는 1 또는 0을 나타내는데 펄스 폭의 길이로 구별합니다. (아래 그림 참조) 즉, 펄스 폭이 긴 것(A)이 1을 나타내고, 짧은 것(B)은 0을 나타냅니다. 시간은 각각 0.5625 msec와 1.6875 msec입니다.</p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20fediy005.jpg" rel="lightbox[20912]"><img class="alignnone size-large wp-image-21124" alt="20fediy005" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20fediy005-620x278.jpg" width="620" height="278" /></a></td>
</tr>
<tr>
<td>데이터 펄스폭의 길이</td>
</tr>
</tbody>
</table>
<p>아래에 삼성 리모컨(TV, VCR)의 코드 값을 예로 들었습니다. 우리는 이 코드표를 사용하는 것이 아니라, 프로그램을 통해서 이 코드 값을 알아내고(표와 일치하는지에 대한 확인), 알아낸 코드 값을 이용해서 LCD를 제어하도록 하겠습니다. 삼성 리모컨뿐만 아니라 TC9012나 D6121 형식의 리모컨은 어떤 것이나 코드 값을 알아내서 사용하는 것이 목적입니다.</p>
<p><span style="text-decoration: underline;color: #339966">2) 삼성리모컨에 대한 전반적인 데이터 표</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-4.png" rel="lightbox[20912]"><img class="alignnone size-large wp-image-21117" alt="20Feadiym0 (4)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20Feadiym0-4-620x519.png" width="620" height="519" /></a></p>
<p><span style="text-decoration: underline;color: #339966">3) rc카 시스템</span></p>
<table border="0">
<tbody>
<tr>
<td><img class="alignnone  wp-image-21109" alt="20diY RC카" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20diY-RC카-465x620.jpg" width="279" height="372" /></td>
<td><img class="alignnone  wp-image-21128" alt="rc카 윗부분" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/rc카-윗부분-465x620.jpg" width="279" height="372" /></td>
</tr>
</tbody>
</table>
<table border="0">
<tbody>
<tr>
<td><img class="alignnone  wp-image-21126" alt="rc카 뒷부분" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/rc카-뒷부분-620x465.jpg" width="286" height="215" /></td>
<td><img class="alignnone  wp-image-21127" alt="rc카 옆부분(왼)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/rc카-옆부분왼-620x465.jpg" width="286" height="215" /></td>
</tr>
</tbody>
</table>
<table border="0">
<tbody>
<tr>
<td><img class="alignnone  wp-image-21129" alt="20fediy006" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20fediy006.png" width="227" height="144" /></td>
<td>※ 볼게이트의 사용은 무게중심에 의해 앞으로 본체가 쏠리는 것을 방지하는데 도움을 주기 위해 장착하였습니다.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #800080"><strong>단계별 제작 과정</strong></span><br />
단순히 시계에 필요한 시간 변경 그리고 알람 등의 기능을 업그레이드하여 제작했습니다. 그리고 RC카에 필요한 모터 제어와 리모컨 수신 센서 제어를 포함하여 RC카를 제작했습니다. 적외선 센서를 제어하고 기존의 RC카에서 물체를 회피하는 기능을 연구하고 제작했습니다. 마지막으로 물체 회피와 RC카 그리고 시계 이 모든 것을 합친 Evalarm이 제작됐습니다.</p>
<p><span style="color: #800080"><strong> 기타(회로도, 소스코드, 참고문헌 등)</strong></span></p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">소스코드보기</h3><div class="symple-toggle-container">
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>#include &lt;avr/io.h&gt;<br />
#include &lt;avr/interrupt.h&gt;</p>
<p>#define ir_ready 0<br />
#define ir_lead 1<br />
#define ir_data 2<br />
unsigned char ir_rx_data[4];<br />
//voliate<br />
unsigned char ir_state;<br />
unsigned char ir_timer_cnt;<br />
unsigned char ir_bit_cnt;<br />
unsigned char ir_rx_flag=0;<br />
unsigned char ir_rx_temp;</p>
<p>void clock_data_m_change();<br />
void clock_data_p_change();<br />
void alarm_data_m_change();<br />
void alarm_data_p_change();<br />
void ir_car_run();</p>
<p>char moter_data;</p>
<p>void delay_us(unsigned int us)<br />
{<br />
unsigned int i;</p>
<p>for(i=0;i&lt;us;i++){<br />
asm(&#8220;PUSH R0&#8243;);<br />
asm(&#8220;POP R0&#8243;);<br />
asm(&#8220;PUSH R0&#8243;);<br />
asm(&#8220;POP R0&#8243;);<br />
asm(&#8220;PUSH R0&#8243;);<br />
asm(&#8220;POP R0&#8243;);<br />
}<br />
}</p>
<p>void delay_ms(unsigned int ms)<br />
{<br />
unsigned int i;<br />
for(i=0;i&lt;ms;i++){<br />
delay_us(1000);<br />
}<br />
}</p>
<p>#define CUR11 0&#215;02 /* 커서 홈에 위치시키는 명령어 값 */<br />
#define CUR21 0xC0 /* 커서 2라인 1열에 위치시키는 명령어 값 */<br />
#define LCDON 0x0C /* LCD ON 명령어 값 */<br />
#define LCDOFF 0&#215;08 /* LCD OFF 명령어 값 */<br />
#define MODE4 0&#215;20 /* 4비트 인터페이스 설정 */<br />
#define FSET 0&#215;28 /* 기능설정, 4비트 인터페이스, NF=10 : 2행 5&#215;7 폰트 */<br />
#define LCDCLR 0&#215;01 /* LCD 클리어 */<br />
#define MODENT 0&#215;06 /* 엔트리모드 설정, 표시는 이동 않고, AC 증가, 커서 우측 이동 */</p>
<p>typedef unsigned char byte;</p>
<p>void lcd_cmd(unsigned char ch){ /LCD에 명령어값 1바이트 쓰는 서브루틴, ch는 명령어 값 /<br />
unsigned char temp0, temp1;<br />
delay_ms(1); / 약 15msec delay /<br />
DDRA = 0xff; // 포트C를 출력으로<br />
temp0 = ch &amp; 0xf0; / 상위4비트 마스크 /<br />
temp1 = temp0 | 0&#215;04; / 하위 4비트에 0100b(RS=R/W=0, E=1) 써넣기 /<br />
PORTA = temp1; / LCD에 명령어값의 상위 4비트 써넣기 /<br />
temp1 = temp0 &amp; 0xf0; / 하위 4비트에 0000b(RS=R/W=0, E=0) 써넣기 /<br />
PORTA = temp1; / LCD에 입력 불허 /<br />
delay_us(10); / 약 0.01 msec 시간지연 /<br />
temp0 = (ch &lt;&lt; 4) &amp; 0xf0 ; / 하위4비트를 상위로 옮기고 마스크 /<br />
temp1 = temp0 | 0&#215;04 ; / 하위 4비트에 0100b(RS=R/W=0, E=1) 써넣기 /<br />
PORTA = temp1; / LCD에 명령어값의 하위 4비트 써넣기 /<br />
temp1 = temp0 &amp; 0xf0; / 하위 4비트에 0000b(RS=R/W=0, E=0) 써넣기 /<br />
PORTA = temp1; / LCD에 입력 불허 /<br />
}</p>
<p>void lcd_ln11(void){ /* LCD의 1행1열에 커서를 위치시키는 서브루틴 */<br />
lcd_cmd(CUR11);<br />
}</p>
<p>void lcd_dat(unsigned char ch){ /* LCD에 1글자 쓰는 서브루틴, ch는 글자의 아스키 코드 값 */<br />
unsigned char temp0, temp1;<br />
delay_ms(1); /* 약 15msec delay */<br />
DDRA = 0xff; // 포트C를 출력으로<br />
temp0 = ch &amp; 0xf0; /* 상위4비트 마스크 */<br />
temp1 = temp0 | 0&#215;05; /* 하위 4비트에 0101b(RS=1, R/W=0, E=1) 써넣기 */<br />
PORTA = temp1; /* LCD에 DATA값의 상위 4비트 써넣기 */<br />
temp1 = temp0 | 0&#215;01; /* 하위 4비트에 0001b(RS=1, R/W=0, E=0) 써넣기 */<br />
PORTA = temp1; /* LCD에 입력 불허 */<br />
delay_us(10); /* 약 0.01 msec 시간지연 */<br />
temp0 = (ch &lt;&lt; 4) &amp; 0xf0 ; /* 하위4비트를 상위로 옮기고 마스크 */<br />
temp1 = temp0 | 0&#215;05; /* 하위 4비트에 0101b(RS=1, R/W=0, E=1) 써넣기 */<br />
PORTA = temp1; /* LCD에 DATA값의 하위 4비트 써넣기 */<br />
temp1 = temp0 | 0&#215;01; /* 하위 4비트에 0001b(RS=1, R/W=0, E=0) 써넣기 */<br />
PORTA = temp1; /* LCD에 입력 불허 */<br />
}</p>
<p>void lcd_init(void){ /* LCD 초기화 서브루틴 */<br />
delay_ms(15); /* 약 15msec delay */<br />
delay_ms(5);<br />
lcd_cmd(MODE4);<br />
delay_ms(5);<br />
delay_ms(5); /* 약 5msec delay */<br />
lcd_cmd(MODE4); delay_us(100);<br />
delay_ms(5);<br />
lcd_cmd(MODE4);<br />
delay_ms(5);<br />
lcd_cmd(FSET); /* 기능설정, 4비트 인터페이스, NF=10 : 2행 5&#215;7 폰트 */<br />
delay_ms(5);<br />
lcd_cmd(LCDON); /* LCD ON 명령어 값 */<br />
delay_ms(5);<br />
lcd_cmd(LCDCLR); /* LCD Clear 명령어 값 */<br />
delay_ms(5);<br />
lcd_cmd(MODENT); /* 엔트리모드 설정, 표시는 이동 않고, AC 증가, 커서 우측 이동 */<br />
delay_ms(5);<br />
}</p>
<p>void lcd_str(char *str){ /* LCD에 flash에 저장된 문자열을 출력하는 함수 */<br />
unsigned int i=0;<br />
for(i=0;str[i] != 0; i++)<br />
lcd_dat(str[i]);<br />
}</p>
<p>//시간 관련 소스<br />
char s,m,h;<br />
char as,am,ah;<br />
char a_on;//알람</p>
<p>//키관련 소스<br />
char key;<br />
char key_on;<br />
char key_mode;<br />
char key_count;<br />
char key_buffer;</p>
<p>//1s<br />
int us100;<br />
char count_on;</p>
<p>//시간 변경 함수<br />
void clock_count(){<br />
if(key_mode==1){<br />
}else if(key_mode==11){<br />
}else{<br />
if(count_on==1){<br />
s++;<br />
if(s==60){<br />
m++;<br />
s=0;<br />
}<br />
if(m==60){<br />
h++;<br />
m=0;<br />
}<br />
if(h==60){<br />
h=0;<br />
}<br />
count_on=0;<br />
}<br />
}<br />
}</p>
<p>void key_data(){<br />
if(key_on==1){<br />
//일반 모드<br />
if(key_mode==0){<br />
if(key==4){<br />
key_mode=1;//시간 변경 모드<br />
}else if(key==5){<br />
key_mode=2;//알람 시간 변경 모드<br />
}else if(key==6){<br />
key_mode=3;//알람 설정 모드<br />
}else if(key==7){<br />
key_mode=0;<br />
key_count=0;<br />
}<br />
//시간 시분초 결정<br />
}else if(key_mode==1){<br />
if(key==4){<br />
key_count=(key_count+1)%6;//시분초<br />
}else if(key==5){<br />
key_count=(key_count+5)%6;//시분초<br />
}else if(key==6){//시분초 변경 결정<br />
key_mode=11;<br />
key_buffer=key_count;<br />
}else if(key==7){<br />
key_mode=0;<br />
key_count=0;<br />
}<br />
//시간 시분초 변경<br />
}else if(key_mode==11){<br />
if(key==4){<br />
clock_data_p_change();<br />
}else if(key==5){<br />
clock_data_m_change();<br />
}else if(key==6){<br />
key_mode=1;<br />
}else if(key==7){<br />
key_mode=0;<br />
key_count=0;<br />
}<br />
}else if(key_mode==2){<br />
if(key==4){<br />
key_count=(key_count+1)%6;//시분초<br />
}else if(key==5){<br />
key_count=(key_count+5)%6;//시분초<br />
}else if(key==6){//시분초 변경 결정<br />
key_mode=21;<br />
}else if(key==7){<br />
key_count=0;<br />
key_mode=0;<br />
}<br />
//시간 시분초 변경<br />
}else if(key_mode==21){<br />
if(key==4){<br />
alarm_data_p_change();<br />
}else if(key==5){<br />
alarm_data_m_change();<br />
}else if(key==6){<br />
key_mode=2;<br />
}else if(key==7){<br />
key_mode=0;<br />
key_count=0;<br />
}<br />
}else if(key_mode==3){<br />
if(key==4){<br />
a_on=1;<br />
}else if(key==5){<br />
a_on=0;<br />
}else if(key==6){<br />
key_mode=0;<br />
key_count=0;<br />
}else if(key==7){<br />
key_mode=0;<br />
key_count=0;<br />
}<br />
}<br />
key_on=0;<br />
}<br />
}</p>
<p>//시간 시분초 변경<br />
void clock_data_p_change(){<br />
if(key_count==0){<br />
if((s%10)==9){<br />
s=s-9;<br />
}else{<br />
s=s+1;<br />
}<br />
}else if(key_count==1){<br />
if((s/10)==5){<br />
s=s-50;<br />
}else{<br />
s=s+10;<br />
}<br />
}else if(key_count==2){<br />
if((m%10)==9){<br />
m=m-9;<br />
}else{<br />
m=m+1;<br />
}<br />
}else if(key_count==3){<br />
if((m/10)==5){<br />
m=m-50;<br />
}else{<br />
m=m+10;<br />
}<br />
}else if(key_count==4){<br />
if((h/10)==2){<br />
if((h%10)==3){<br />
h=h-3;<br />
}else{<br />
h=h+1;<br />
}<br />
}else{<br />
if((h%10)==9){<br />
h=h-9;<br />
}else{<br />
h=h+1;<br />
}<br />
}<br />
}else if(key_count==5){<br />
if((h%10)&lt;4){<br />
if((h/10)==2){<br />
h=h-20;<br />
}else{<br />
h=h+10;<br />
}<br />
}else{<br />
if((h/10)==1){<br />
h=h-10;<br />
}else{<br />
h=h+10;<br />
}<br />
}<br />
}<br />
}</p>
<p>//시간 시분초 변경<br />
void clock_data_m_change(){<br />
if(key_count==0){<br />
if((s%10)==0){<br />
s=s+9;<br />
}else{<br />
s=s-1;<br />
}<br />
}else if(key_count==1){<br />
if((s/10)==0){<br />
s=s+50;<br />
}else{<br />
s=s-10;<br />
}<br />
}else if(key_count==2){<br />
if((m%10)==0){<br />
m=m+9;<br />
}else{<br />
m=m-1;<br />
}<br />
}else if(key_count==3){<br />
if((m/10)==0){<br />
m=m+50;<br />
}else{<br />
m=m-10;<br />
}<br />
}else if(key_count==4){<br />
if((h/10)==2){<br />
if((h%10)==0){<br />
h=h+3;<br />
}else{<br />
h=h-1;<br />
}<br />
}else{<br />
if((h%10)==0){<br />
h=h+9;<br />
}else{<br />
h=h-1;<br />
}<br />
}<br />
}else if(key_count==5){<br />
if((h%10)&lt;4){<br />
if((h/10)==0){<br />
h=h+20;<br />
}else{<br />
h=h-10;<br />
}<br />
}else{<br />
if((h/10)==0){<br />
h=h+10;<br />
}else{<br />
h=h-10;<br />
}<br />
}<br />
}<br />
}</p>
<p>//시간 시분초 변경<br />
void alarm_data_p_change(){<br />
if(key_count==0){<br />
if((as%10)==9){<br />
as=as-9;<br />
}else{<br />
as=as+1;<br />
}<br />
}else if(key_count==1){<br />
if((as/10)==5){<br />
as=as-50;<br />
}else{<br />
as=as+10;<br />
}<br />
}else if(key_count==2){<br />
if((am%10)==9){<br />
am=am-9;<br />
}else{<br />
am=am+1;<br />
}<br />
}else if(key_count==3){<br />
if((am/10)==5){<br />
am=am-50;<br />
}else{<br />
am=am+10;<br />
}<br />
}else if(key_count==4){<br />
if((ah/10)==2){<br />
if((ah%10)==3){<br />
ah=ah-3;<br />
}else{<br />
ah=ah+1;<br />
}<br />
}else{<br />
if((ah%10)==9){<br />
ah=ah-9;<br />
}else{<br />
ah=ah+1;<br />
}<br />
}<br />
}else if(key_count==5){<br />
if((ah%10)&lt;4){<br />
if((ah/10)==2){<br />
ah=ah-20;<br />
}else{<br />
ah=ah+10;<br />
}<br />
}else{<br />
if((ah/10)==1){<br />
ah=ah-10;<br />
}else{<br />
ah=ah+10;<br />
}<br />
}<br />
}<br />
}</p>
<p>//시간 시분초 변경<br />
void alarm_data_m_change(){<br />
if(key_count==0){<br />
if((as%10)==0){<br />
as=as+9;<br />
}else{<br />
as=as-1;<br />
}<br />
}else if(key_count==1){<br />
if((as/10)==0){<br />
as=as+50;<br />
}else{<br />
as=as-10;<br />
}<br />
}else if(key_count==2){<br />
if((am%10)==0){<br />
am=am+9;<br />
}else{<br />
am=am-1;<br />
}<br />
}else if(key_count==3){<br />
if((am/10)==0){<br />
am=am+50;<br />
}else{<br />
am=am-10;<br />
}<br />
}else if(key_count==4){<br />
if((ah/10)==2){<br />
if((ah%10)==0){<br />
ah=ah+3;<br />
}else{<br />
ah=ah-1;<br />
}<br />
}else{<br />
if((ah%10)==0){<br />
ah=ah+9;<br />
}else{<br />
ah=ah-1;<br />
}<br />
}<br />
}else if(key_count==5){<br />
if((ah%10)&lt;4){<br />
if((ah/10)==0){<br />
ah=ah+20;<br />
}else{<br />
ah=ah-10;<br />
}<br />
}else{<br />
if((ah/10)==0){<br />
ah=ah+10;<br />
}else{<br />
ah=ah-10;<br />
}<br />
}<br />
}<br />
}</p>
<p>void lcd_display(){<br />
if(key_mode==0){<br />
lcd_cmd(0&#215;80);<br />
if(a_on==1){<br />
lcd_str(&#8220;a_on s]&#8221;);<br />
}else{<br />
lcd_str(&#8220;a_off s]&#8221;);<br />
}<br />
lcd_dat(ah/10+0&#215;30);<br />
lcd_dat(ah%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(am/10+0&#215;30);<br />
lcd_dat(am%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(as/10+0&#215;30);<br />
lcd_dat(as%10+0&#215;30);<br />
PORTC=0X00;<br />
lcd_cmd(0xc0);<br />
lcd_str(&#8220;time] &#8220;);<br />
lcd_dat(h/10+0&#215;30);<br />
lcd_dat(h%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(m/10+0&#215;30);<br />
lcd_dat(m%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(s/10+0&#215;30);<br />
lcd_dat(s%10+0&#215;30);<br />
}else if(key_mode==1){<br />
lcd_cmd(0&#215;80);<br />
lcd_str(&#8220;time setting &#8220;);<br />
PORTC=0X00;<br />
lcd_cmd(0xc0);<br />
lcd_dat(h/10+0&#215;30);<br />
lcd_dat(h%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(m/10+0&#215;30);<br />
lcd_dat(m%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(s/10+0&#215;30);<br />
lcd_dat(s%10+0&#215;30);<br />
lcd_dat(&#8216; &#8216;);<br />
if(key_count==0){<br />
lcd_str(&#8220;1s &#8220;);<br />
}else if(key_count==1){<br />
lcd_str(&#8220;10s &#8220;);<br />
}else if(key_count==2){<br />
lcd_str(&#8220;1m &#8220;);<br />
}else if(key_count==3){<br />
lcd_str(&#8220;10m &#8220;);<br />
}else if(key_count==4){<br />
lcd_str(&#8220;1h &#8220;);<br />
}else if(key_count==5){<br />
lcd_str(&#8220;10h &#8220;);<br />
}<br />
}else if(key_mode==11){<br />
lcd_cmd(0&#215;80);<br />
if(key_count==0){<br />
lcd_str(&#8220;time(1s) change &#8220;);<br />
}else if(key_count==1){<br />
lcd_str(&#8220;time(10s) change &#8220;);<br />
}else if(key_count==2){<br />
lcd_str(&#8220;time(1m) change &#8220;);<br />
}else if(key_count==3){<br />
lcd_str(&#8220;time(10m) change &#8220;);<br />
}else if(key_count==4){<br />
lcd_str(&#8220;time(1h) change &#8220;);<br />
}else if(key_count==5){<br />
lcd_str(&#8220;time(10h) change &#8220;);<br />
}<br />
PORTC=0X00;<br />
lcd_cmd(0xc0);<br />
lcd_dat(h/10+0&#215;30);<br />
lcd_dat(h%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(m/10+0&#215;30);<br />
lcd_dat(m%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(s/10+0&#215;30);<br />
lcd_dat(s%10+0&#215;30);<br />
lcd_str(&#8221; &#8220;);<br />
}else if(key_mode==2){<br />
lcd_cmd(0&#215;80);<br />
lcd_str(&#8220;alarm setting &#8220;);<br />
PORTC=0X00;<br />
lcd_cmd(0xc0);<br />
lcd_dat(ah/10+0&#215;30);<br />
lcd_dat(ah%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(am/10+0&#215;30);<br />
lcd_dat(am%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(as/10+0&#215;30);<br />
lcd_dat(as%10+0&#215;30);<br />
lcd_dat(&#8216; &#8216;);<br />
if(key_count==0){<br />
lcd_str(&#8220;1s &#8220;);<br />
}else if(key_count==1){<br />
lcd_str(&#8220;10s &#8220;);<br />
}else if(key_count==2){<br />
lcd_str(&#8220;1m &#8220;);<br />
}else if(key_count==3){<br />
lcd_str(&#8220;10m &#8220;);<br />
}else if(key_count==4){<br />
lcd_str(&#8220;1h &#8220;);<br />
}else if(key_count==5){<br />
lcd_str(&#8220;10h &#8220;);<br />
}<br />
}else if(key_mode==21){<br />
lcd_cmd(0&#215;80);<br />
if(key_count==0){<br />
lcd_str(&#8220;alarm(1s) change &#8220;);<br />
}else if(key_count==1){<br />
lcd_str(&#8220;alarm(10s) change &#8220;);<br />
}else if(key_count==2){<br />
lcd_str(&#8220;alarm(1m) change &#8220;);<br />
}else if(key_count==3){<br />
lcd_str(&#8220;alarm(10m) change &#8220;);<br />
}else if(key_count==4){<br />
lcd_str(&#8220;alarm(1h) change &#8220;);<br />
}else if(key_count==5){<br />
lcd_str(&#8220;alarm(10h) change &#8220;);<br />
}<br />
PORTC=0X00;<br />
lcd_cmd(0xc0);<br />
lcd_dat(ah/10+0&#215;30);<br />
lcd_dat(ah%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(am/10+0&#215;30);<br />
lcd_dat(am%10+0&#215;30);<br />
lcd_dat(&#8216;:&#8217;);<br />
lcd_dat(as/10+0&#215;30);<br />
lcd_dat(as%10+0&#215;30);<br />
lcd_str(&#8221; &#8220;);<br />
}else if(key_mode==3){<br />
lcd_cmd(0&#215;80);<br />
lcd_str(&#8220;alarm setting &#8220;);<br />
PORTC=0X00;</p>
<p>lcd_cmd(0xc0);<br />
if(a_on==0){<br />
lcd_str(&#8220;alarm off &#8220;);<br />
}else if(a_on==1){<br />
lcd_str(&#8220;alarm on &#8220;);<br />
}<br />
}<br />
}</p>
<p>char buzzer=0;<br />
char ir_go=0;<br />
void alarm_oper(void){<br />
if(a_on==1){<br />
if(h==ah){<br />
if(m==am){<br />
if(s==as){<br />
buzzer=1;<br />
ir_go=1;<br />
}<br />
}<br />
}<br />
}<br />
if(buzzer==1){<br />
PORTD|=0X02;<br />
}else{<br />
PORTD&amp;=0Xfd;<br />
}</p>
<p>delay_ms(1);</p>
<p>if(ir_go==1){<br />
ir_car_run();<br />
}<br />
}</p>
<p>char sr,sl,sf,sb;<br />
char ad_data;</p>
<p>void senser(){<br />
ADMUX=0X60; //어느핀 변화시킬건지<br />
ADCSRA=0XC7; //ad 변환 시작<br />
while((ADCSRA&amp;0&#215;10)==0); //변수=AD값 걸림<br />
ad_data=ADCH; //변수값에 저장<br />
if(ad_data&lt;100){<br />
sf=1;<br />
}else{<br />
sf=0;<br />
}<br />
delay_ms(1);<br />
ADMUX=0X61; //어느핀 변화시킬건지<br />
ADCSRA=0XC7; //ad 변환 시작<br />
while((ADCSRA&amp;0&#215;10)==0); //변수=AD값 걸림<br />
ad_data=ADCH; //변수값에 저장<br />
if(ad_data&lt;100){<br />
sb=1;<br />
}else{<br />
sb=0;<br />
}<br />
delay_ms(1);</p>
<p>ADMUX=0X62; //어느핀 변화시킬건지<br />
ADCSRA=0XC7; //ad 변환 시작<br />
while((ADCSRA&amp;0&#215;10)==0); //변수=AD값 걸림<br />
ad_data=ADCH; //변수값에 저장<br />
if(ad_data&lt;100){<br />
sr=1;<br />
}else{<br />
sr=0;<br />
}<br />
delay_ms(1);</p>
<p>ADMUX=0X63; //어느핀 변화시킬건지<br />
ADCSRA=0XC7; //ad 변환 시작<br />
while((ADCSRA&amp;0&#215;10)==0); //변수=AD값 걸림<br />
ad_data=ADCH; //변수값에 저장<br />
if(ad_data&lt;100){<br />
sl=1;<br />
}else{<br />
sl=0;<br />
}<br />
delay_ms(1);<br />
}</p>
<p>void ir_car_run(){<br />
senser();<br />
//전방 물체 감지<br />
if(sf==0){<br />
//전후방 물체 감지<br />
if(sb==0){<br />
//오른쪽 물체 감지<br />
if(sr==0){<br />
//오른쪽으로 회전 7<br />
PORTC=0X9C;<br />
}else{<br />
//왼쪽으로 회전 6 5 4<br />
PORTC=0X6C;<br />
}<br />
}else{<br />
//후방으로 전진 3 0<br />
PORTC=0X5C;<br />
}<br />
}else{<br />
//후방 물체 감지<br />
if(sb==0){<br />
//전방으로 전진 2 0<br />
PORTC=0XAC;</p>
<p>}else{<br />
//오른쪽 물체 감지<br />
if(sr==0){<br />
//전방으로 전진 1<br />
PORTC=0XAC;<br />
}else{<br />
//왼쪽 물체 감지<br />
if(sl==0){<br />
//전방으로 전진 1<br />
PORTC=0XAC;<br />
}else{<br />
//정지 0<br />
PORTC=0X00;<br />
}<br />
}<br />
}<br />
}<br />
}</p>
<p>void putch(unsigned char ch){ /* 한개의 문자를 pc로 송신한다. */<br />
while((UCSR0A &amp; 0&#215;20) == 0);<br />
UDR0 = ch;<br />
UCSR0A |= 0&#215;20; // 문자 송신준비완료<br />
}</p>
<p>char ir_oper;</p>
<p>void ir_remote(){<br />
//RC카<br />
if(ir_rx_flag == 1){//데이터 전송<br />
ir_rx_flag =0;<br />
putch(ir_rx_data[0]);<br />
putch(ir_rx_data[1]);<br />
putch(ir_rx_data[2]);<br />
putch(ir_rx_data[3]);<br />
ir_oper=1;<br />
//rc_data=ir_rx_data[2];<br />
}<br />
if(ir_oper==1){<br />
if(ir_rx_data[2]==0&#215;05){<br />
//전방<br />
PORTC=0XAC;<br />
}else if(ir_rx_data[2]==0&#215;08){<br />
//왼쪽<br />
PORTC=0X9C;<br />
}else if(ir_rx_data[2]==0x0a){<br />
//오른쪽<br />
PORTC=0X6C;<br />
}else if(ir_rx_data[2]==0x0d){<br />
//뒤로<br />
PORTC=0X5C;<br />
}else if(ir_rx_data[2]==0&#215;04){<br />
ir_go=1;<br />
}else{<br />
PORTC=0X00; }<br />
ir_oper=0;<br />
}<br />
}</p>
<p>int main(void){<br />
DDRA = 0Xff; //LCD<br />
DDRC = 0Xff; //모터 구동<br />
DDRD = 0&#215;02; //리모컨 소자<br />
DDRE = 0X0f; //스위치<br />
DDRF = 0X00; //거리 측정 센서</p>
<p>//외무 인터럽트<br />
EICRB = 0XFF;//상승 에지<br />
EICRA = 0XFF;//상승 에지<br />
EIMSK = 0Xf1;//0-초음파,1-리모컨<br />
UBRR0H = 0;<br />
UBRR0L = 103; // baud rate 9600<br />
UCSR0A = 0;<br />
UCSR0B = 0&#215;98;<br />
UCSR0C = 0&#215;06;<br />
//타이머 카운트 100us<br />
TIMSK = 0X02;<br />
TCCR0 = 0X0A;<br />
OCR0 = 200;<br />
SREG = 0X80;<br />
putch(0&#215;03);<br />
lcd_init();<br />
//lcd_ln11();<br />
//lcd_str(&#8220;COME ON&#8221;);<br />
delay_ms(10);<br />
while(1){<br />
//물체 회피 및 부저<br />
alarm_oper();<br />
//리모컨 컨트롤<br />
ir_remote();<br />
//키스위치<br />
key_data();<br />
//LCD<br />
lcd_display();<br />
//시간 카운터<br />
clock_count();<br />
delay_ms(10);<br />
}<br />
}</p>
<p>SIGNAL(INT4_vect){<br />
// lcd_cmd(0&#215;80);<br />
// lcd_str(&#8220;adfag&#8221;);<br />
// delay_ms(3000);<br />
key_on=1;<br />
key=4;<br />
buzzer=0;<br />
ir_go=0;<br />
PORTC=0X00;<br />
}<br />
SIGNAL(INT5_vect){<br />
key_on=1;<br />
key=5;<br />
buzzer=0;<br />
ir_go=0;<br />
PORTC=0X00;<br />
}<br />
SIGNAL(INT6_vect){<br />
key_on=1;<br />
key=6;<br />
buzzer=0;<br />
ir_go=0;<br />
PORTC=0X00;<br />
}<br />
SIGNAL(INT7_vect){<br />
key_on=1;<br />
key=7;<br />
buzzer=0;<br />
ir_go=0;<br />
PORTC=0X00;<br />
}<br />
SIGNAL(TIMER0_COMP_vect){<br />
ir_timer_cnt++;<br />
us100=us100+1;<br />
if(us100==10000){<br />
us100=0;<br />
count_on=1;<br />
}<br />
}</p>
<p>SIGNAL(INT0_vect){<br />
switch(ir_state){<br />
case ir_ready : //오류 데이터<br />
ir_state = ir_lead;<br />
break;<br />
case ir_lead ://시작 관련 데이터<br />
//리드 펄스 데이터가 오면 4.5ms과 0.5ms의 합의 구간인 5ms<br />
//0&#215;30=48, 0&#215;35=53이다<br />
if((ir_timer_cnt&gt;=0&#215;30) &amp;&amp; (ir_timer_cnt&lt;0&#215;35)){<br />
ir_state = ir_data;<br />
}else{<br />
ir_state = ir_state;<br />
}<br />
ir_bit_cnt = 0;<br />
ir_rx_temp = 0;<br />
break;</p>
<p>case ir_data ://진짜 데이터 3번 데이터 활용<br />
if((ir_timer_cnt&gt;=8) &amp;&amp; (ir_timer_cnt&lt;15)){ //0데이터<br />
}else if((ir_timer_cnt&gt;=19) &amp;&amp; (ir_timer_cnt&lt;30)){//1데이터<br />
ir_rx_temp = ir_rx_temp|0&#215;80;<br />
}else { //에러 데이터<br />
ir_state = ir_lead;<br />
break;<br />
}<br />
ir_bit_cnt++;<br />
////8개의 비트가 다 들어 올 경우 데이터화 시킴<br />
if((ir_bit_cnt%8)==0){<br />
ir_rx_data[(ir_bit_cnt/8)-1] = ir_rx_temp;<br />
ir_rx_temp = 0;<br />
if(ir_bit_cnt &gt;= 32){//모든 데이터 다 들어 올 경우<br />
ir_state = ir_ready;<br />
ir_bit_cnt = 0;<br />
ir_rx_flag = 1;//새로운 데이터 인식 변수<br />
}<br />
}<br />
ir_rx_temp = ir_rx_temp&gt;&gt;1;//데이터화 하는 과정<br />
break;<br />
default: break;<br />
}<br />
ir_timer_cnt = 0;<br />
}<br />
</div>
</div></div>
<p><span style="background-color: #3366ff;color: #ffffff">입선을 수상하신 경성대학교 김가희님 외 3분께 진심으로 축하의 말씀을 드립니다. </span><br />
<span style="background-color: #3366ff;color: #ffffff">수상하신 팀에게는 적립금 10만원과 함께 (주)칩센에서 제공해드리는 소정의 경품이 제공되었습니다.</span><br />
<span style="background-color: #3366ff;color: #ffffff">다음호에는 경성대학교 전력 실험실 김민욱 외 4명이 수상한 &#8216;천지인 스위치 광고판&#8217;이 소개될 예정입니다.</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<div id='wpdm_file_6' class='wpdm_file wpdm-only-button'><div class='cont'><div class='btn_outer'><div class='btn_outer_c' style='background-image: url(http://www.ntrexgo.com/wp-content/plugins/download-manager/icon/file_extension_pdf.png);'><a class='btn_left  ' rel='6' title='[20]Feature DIY EVALARM 회로도' href='http://www.ntrexgo.com/?wpdmact=process&did=Ni5ob3RsaW5r'  >Download</a><span class='btn_right'>&nbsp;</span></div></div><div class='clear'></div></div></div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/20912/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[17호]JK전자와 함께하는 ARM 완전정복(3)-3</title>
		<link>http://www.ntrexgo.com/archives/13367</link>
		<comments>http://www.ntrexgo.com/archives/13367#comments</comments>
		<pubDate>Sun, 10 Mar 2013 06:20:23 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[17호]]></category>
		<category><![CDATA[applications]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=13367</guid>
		<description><![CDATA[디바이스마트 매거진 17호 &#124; 3부 3편. 자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부한다면 큰 도움이 될 것입니다.]]></description>
				<content:encoded><![CDATA[<table style="width: 600px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자.jpg" rel="lightbox[13367]"><img class="alignnone  wp-image-13318" alt="jk전자" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자-300x222.jpg" width="192" height="142" /></a></td>
<td><span style="color: #000080"><strong><span style="font-size: large">JK전자와 함/께/하/는 ARM 완전 정복</span></strong></span><span style="color: #666699"><strong><span style="line-height: 19px">Ⅱ.ARM Applications &#8211; 1부</span></strong></span>글 | JK전자</td>
</tr>
</tbody>
</table>
<p><span style="color: #008000;background-color: #ffff99"><strong>4. 개발환경 설정</strong></span></p>
<p><strong><span style="color: #008000">4.1 IAR Workbench 개발환경 설정</span></strong></p>
<p>ARM Simulator 기반의 실습 프로젝트와 유사하지만 디버거 설정 부분과 Pre-include directory 설정 등이 추가됩니다.<br />
<span style="background-color: #ffff00">(1) Create New Project</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK060.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13291" alt="17featureJK060" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK060-620x446.jpg" width="620" height="446" /></a></p>
<p><span style="background-color: #ffff00">(2) Empty project 생성</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK061.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13292" alt="17featureJK061" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK061.jpg" width="408" height="347" /></a></p>
<p><span style="background-color: #ffff00">(3) 프로젝트 파일이름 입력 &#8211; “mini2440_test”</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK062.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13293" alt="17featureJK062" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK062-620x435.jpg" width="620" height="435" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK077.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13308" alt="17featureJK077" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK077-620x428.jpg" width="620" height="428" /></a></p>
<p><span style="background-color: #ffff00">(4) 그룹생성 &#8211; “base”, “testcode”그룹 생성</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK078.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13309" alt="17featureJK078" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK078-620x427.jpg" width="620" height="427" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK079.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13310" alt="17featureJK079" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK079-620x428.jpg" width="620" height="428" /></a></p>
<p><span style="background-color: #ffff00">(5) 소스 파일추가</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK080.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13311" alt="17featureJK080" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK080-620x428.jpg" width="620" height="428" /></a><br />
- “base”그룹 : base 폴더 안의 *.s, *.c 파일들 추가<br />
- “testcode”그룹 : testcode 폴더 안의 *.c 파일들 추가<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK081.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13312" alt="17featureJK081" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK081-620x428.jpg" width="620" height="428" /></a></p>
<p><span style="background-color: #ffff00">(6) 프로젝트 옵션 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK082.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13313" alt="17featureJK082" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK082-620x429.jpg" width="620" height="429" /></a></p>
<p><span style="background-color: #ffff99">(6.1) Target Device 설정 : Samsung S3C2440A로 설정합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK066.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13297" alt="17featureJK066" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK066-620x437.jpg" width="620" height="437" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK067.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13298" alt="17featureJK067" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK067.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(7) Processor Mode 설정 : “ARM”모드로 설정합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK068.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13299" alt="17featureJK068" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK068.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(8) C/C++ Compiler Pre-include 디렉토리 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK084.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13315" alt="17featureJK084" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK084.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(9) Assembler Pre-include 디렉토리 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK085.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13316" alt="17featureJK085" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK085.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(10) Scattor Loading 파일 설정 : 프로젝트 디렉토리에 “mini2440_lnk.icf”파일을 선택합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK083.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13314" alt="17featureJK083" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK083.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(11) Program Start Entry 설정 : “ __program_start”라고 입력합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK070.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13301" alt="17featureJK070" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK070.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(12) 디버깅 정보를 포함하도록 설정합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK071.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13302" alt="17featureJK071" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK071.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(13) Map 파일을 생성하도록 합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK072.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13303" alt="17featureJK072" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK072.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(14) Debugger 정보 설정 : Dirver &#8211; Simulator, Run to main은 반드시 설정 해제합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK073.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13304" alt="17featureJK073" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK073-620x456.jpg" width="620" height="456" /></a></p>
<p><span style="color: #339966"><strong>4.2 JTAG 을 이용한 프로그램 다운로드</strong></span></p>
<p><span style="color: #99cc00"><strong>4.2.1 ARM-JTAG을 이용한 프로그램 다운로드 </strong></span></p>
<p><span style="background-color: #ffff00">(1) ARM-JTAG Standard 버젼 이상을 사용해야 합니다.</span></p>
<p><span style="background-color: #ffff00">(2) IAR 개발환경에서 Debugger를 설정합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK074.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13305" alt="17featureJK074" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK074-620x446.jpg" width="620" height="446" /></a><br />
RDI Driver를 JICE.dll 로 설정합니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK075.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13306" alt="17featureJK075" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK075-620x446.jpg" width="620" height="446" /></a></p>
<p><span style="background-color: #ffff00">(3) Windows7 사용자일 경우 IAR IDE 프로그램과, JICE Server의 실행 환경을 관리자 권한으로 설정합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK048.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13279" alt="17featureJK048" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK048-620x367.jpg" width="620" height="367" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK049.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13280" alt="17featureJK049" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK049-620x430.jpg" width="620" height="430" /></a></p>
<p><span style="background-color: #ffff00">(4) JICE Server 를 실행한 후 Target Detect 를 합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK050.jpg" rel="lightbox[13367]"><img class="alignnone size-full wp-image-13281" alt="17featureJK050" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK050.jpg" width="410" height="400" /></a></p>
<p><span style="background-color: #ffff00">(5) IAR Workbench 에서 “Download and Debugging”을 실행합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK051.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13282" alt="17featureJK051" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK051-620x401.jpg" width="620" height="401" /></a></p>
<p>위와 같은 화면이 나왔으면 정상적으로 실행이 완료된 상태입니다. 참고로 “mini2440_lnk.icf”파일은 S3C2440의 RAM(0&#215;30000000)영역에서 실행이 되도록 되어 있습니다. NOR 플래시에 다운로드해서 실행을 할 수도 있지만 NOR 플래시도 10만번 이상 Erase하게 되면 수명이 다하기 때문에 테스트용으로는 주로 RAM에서 실행되도록 합니다.</p>
<p><span style="background-color: #ffff00">(6) NOR 플래시에 프로그램을 다운로드 하는 방법</span><br />
- “mini2440_lnk.icf”파일에서 “define symbol EXECUTE_IN_SDRAM=1;”부분을 “define symbol EXECUTE_IN_SDRAM=0;”으로 수정합니다.<br />
- IAR 프로젝트를 Rebuild 합니다.<br />
- jcs 스크립트 파일에서 “mini2440_test.bin”파일의 이름과 경로를 수정합니다.<br />
- JICE Commander를 실행 -&gt; Script Run -&gt; “S3C2440_NOR(SST39VF1601)_PROGRAM_WITH_FLASHAGENT.jcs”를 실행합니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK052.jpg" rel="lightbox[13367]"><img class="alignnone size-large wp-image-13283" alt="17featureJK052" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK052-620x215.jpg" width="620" height="215" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-size: small"><strong>■ 이것으로 ARM Applications 1부를 마치며, 다음호에는 아래 내용에 대하여 살펴보도록 하겠습니다.</strong></span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/13367/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[17호]JK전자와 함께하는 ARM 완전정복(3)-2</title>
		<link>http://www.ntrexgo.com/archives/13348</link>
		<comments>http://www.ntrexgo.com/archives/13348#comments</comments>
		<pubDate>Sun, 10 Mar 2013 05:43:18 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[17호]]></category>
		<category><![CDATA[applications]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=13348</guid>
		<description><![CDATA[디바이스마트 매거진 17호 &#124; 3부 2편. 자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부한다면 큰 도움이 될 것입니다.]]></description>
				<content:encoded><![CDATA[<table style="width: 600px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자.jpg" rel="lightbox[13348]"><img class="alignnone wp-image-13318" alt="jk전자" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자-300x222.jpg" width="192" height="142" /></a></td>
<td><span style="color: #000080"><strong><span style="font-size: large">JK전자와 함/께/하/는 ARM 완전 정복</span></strong></span><span style="color: #666699"><br />
<strong><span style="line-height: 19px">Ⅱ.ARM Applications &#8211; 1부</span></strong></span>글 | JK전자</td>
</tr>
</tbody>
</table>
<p><span style="background-color: #ffff99;color: #008000"><strong>2. 어셈블리어 실습</strong></span></p>
<p><span style="color: #339966"><strong>2.1 ARM Simulator 환경 설정</strong></span></p>
<p>IAR ARM용 컴파일러는 가격이 그렇게 싸지는 않습니다. 다행히도 www.iar.com 에서 시간 제한(30일), 사이즈 제한(32Kbyte) 버젼을 다운 받아서 사용해 볼 수 있습니다.</p>
<p><span style="color: #99cc00"><strong>2.1.1 IAR Evaluation 버젼 다운로드</strong></span><br />
- 다운로드 사이트 방문<br />
<a href="http://supp.iar.com/Download/SW/?item=EWARM-EVAL" target="_blank">http://supp.iar.com/Download/SW/?item=EWARM-EVAL</a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK034.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13265" alt="17featureJK034" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK034-620x372.jpg" width="620" height="372" /></a><br />
패키지 사이즈가 약 830MB정도 입니다. 다운 받아서 설치하시기 바랍니다.</p>
<p>다음은 Evaluation 버젼을 다운로드 받기 위한 절차대로 화면을 캡쳐해 놓은 것입니다. 참조하시기 바랍니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK057.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13288" alt="17featureJK057" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK057-620x434.jpg" width="620" height="434" /></a><br />
반드시 “Code size limited”를 선택하시기 바랍니다. 그렇지 않으면 30일 이후에 더이상 IAR 컴파일러를 사용할 수 없게 됩니다.</p>
<p><span style="background-color: #ffff00">(2) IAR Evaluation 버젼 설치 </span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK054.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13285" alt="17featureJK054" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK054-620x387.jpg" width="620" height="387" /></a><br />
설치가 완료되면 마지막에 License 를 입력하는 화면이 나옵니다. 여기에서 “Register with IAR System to get an evaluation license”를 선택하시기 바랍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK055.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13286" alt="17featureJK055" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK055-620x387.jpg" width="620" height="387" /></a><br />
현재 설치된 제품 중에 라이센스가 없는 제품의 리스트가 나옵니다. 선택을 하고 “다음”으로 진행합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK056.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13287" alt="17featureJK056" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK056-620x387.jpg" width="620" height="387" /></a><br />
IAR Evaluation 버젼을 다운받기 위해서 입력했던 Email 주소로 Registeration Confirm 메일이 와있을 것입니다.<br />
Confirm 메일에 있는 Confirm 링크를 클릭하면 “Registration Complete”와 함께 Evaluation License 번호를 알 수가 있습니다. 그 번호를 위의 화면의 빈 칸에 입력하고 나서 “Regiser”버튼을 누르면 잠시 후에 네트워크를 통해서 Evaluation 라이센스 번호를 받게 됩니다. 경우에 따라서 Fail 이라는 메세지가 나올 수도 있습니다. 그때는 “Register”버튼을 다시 한번 클릭해서 재시도해 보시기 바랍니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK058.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13289" alt="17featureJK058" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK058-620x387.jpg" width="620" height="387" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK059.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13290" alt="17featureJK059" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK059-620x387.jpg" width="620" height="387" /></a><br />
모든 설치가 완료된 화면입니다.</p>
<p><span style="color: #99cc00"><strong>2.1.2 ARM Simulator 프로젝트 생성</strong></span><br />
아래 화면대로 따라서 ARM Simulator 기반의 실습 프로젝트를 생성해 보시기 바랍니다.</p>
<p><span style="background-color: #ffff00">(1) Create New Project</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK060.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13291" alt="17featureJK060" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK060-620x446.jpg" width="620" height="446" /></a></p>
<p><span style="background-color: #ffff00">(2) Empty project 생성<strong> </strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK061.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13292" alt="17featureJK061" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK061.jpg" width="408" height="347" /></a></p>
<p><span style="background-color: #ffff00">(3) 프로젝트 파일이름 입력 &#8211; “arm_simulator”</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK062.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13293" alt="17featureJK062" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK062-620x435.jpg" width="620" height="435" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK063.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13294" alt="17featureJK063" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK063-620x447.jpg" width="620" height="447" /></a></p>
<p><span style="background-color: #ffff00">(4) 그룹생성 &#8211; “base”, “testcode”그룹 생성</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK064.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13295" alt="17featureJK064" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK064-620x444.jpg" width="620" height="444" /></a><br />
- “base”그룹 : 2440init_ewarm.s 추가<br />
- “testcode”그룹 : main.c, SegInit.c 추가</p>
<p><span style="background-color: #ffff00">(6) 프로젝트 옵션 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK065.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13296" alt="17featureJK065" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK065-620x445.jpg" width="620" height="445" /></a></p>
<p><span style="background-color: #ffff99">(6.1) Target Device 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK066.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13297" alt="17featureJK066" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK066-620x437.jpg" width="620" height="437" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK067.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13298" alt="17featureJK067" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK067.jpg" width="614" height="474" /></a><br />
Samsung S3C2440A 로 설정합니다.</p>
<p><span style="background-color: #ffff00">(7) Processor Mode 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK068.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13299" alt="17featureJK068" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK068.jpg" width="614" height="474" /></a><br />
“ARM”모드로 설정합니다.</p>
<p><span style="background-color: #ffff00">(8) Scattor Loading 파일 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK069.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13300" alt="17featureJK069" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK069.jpg" width="614" height="474" /></a><br />
프로젝트 디렉토리에 “arm_simulator.icf”파일을 선택합니다.</p>
<p><span style="background-color: #ffff00">(9) Program Start Entry 설정</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK070.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13301" alt="17featureJK070" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK070.jpg" width="614" height="474" /></a><br />
“ __program_start”라고 입력합니다.</p>
<p><span style="background-color: #ffff00">(10) 디버깅 정보를 포함하도록 설정합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK071.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13302" alt="17featureJK071" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK071.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(11) Map 파일을 생성하도록 합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK072.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13303" alt="17featureJK072" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK072.jpg" width="614" height="474" /></a></p>
<p><span style="background-color: #ffff00">(12) Debugger 정보 설정 : Dirver &#8211; Simulator, Run to main은 반드시 설정 해제합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK073.jpg" rel="lightbox[13348]"><img class="alignnone size-large wp-image-13304" alt="17featureJK073" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK073-620x456.jpg" width="620" height="456" /></a></p>
<p><span style="color: #339966"><strong>2.2 Data Processing Instructions</strong></span></p>
<p>2장에서는 ARM Simulator를 활용한 어셈블리어 실습을 해보도록 하겠습니다. 이 내용들은 ARM Architecture Instruction의 이론 부분을 설명할 때 한번씩 나왔던 내용입니다. 여기서는 이론으로 공부했던 내용들을 실제로 ARM Simulator에서 코드를 작성한 후 컴파일하고 실행해서 결과 값을 직접 확인해 보는데 의미가 있습니다.</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="5">
<tbody>
<tr>
<td>R0 = 0&#215;00<br />
R1 = 0&#215;22<br />
R2 = 0&#215;02<br />
R3 = 0&#215;00<br />
R4 = 0&#215;00</td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK000.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13231" alt="17featureJK000" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK000.jpg" width="388" height="150" /></a></td>
</tr>
</tbody>
</table>
<p>레지스터 값이 위와 같을 때 아래 예제들을 차례대로 수행해 보세요.</p>
<p><span style="color: #000000;background-color: #ffff00">(1) AND R0, R0, #0xFF</span><br />
2440init_ewarm.s 파일에 다음과 같이 입력을 합니다.</p>
<table style="width: 620px" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td>SECTION IMAGE_STARTUP:CODE (2)<br />
PUBLIC __program_start<br />
CODE32<br />
__program_start<br />
b ResetHandler<br />
b HandlerUndef ;handler for Undefined mode<br />
b HandlerSWI ;handler for SWI interrupt<br />
b HandlerPabort ;handler for PAbort<br />
b HandlerDabort ;handler for DAbort<br />
b . ;reserved<br />
b HandlerIRQ ;handler for IRQ interrupt<br />
b HandlerFIQ ;handler for FIQ interrupt<br />
ResetHandler<br />
MOV R0, #0&#215;00<br />
MOV R1, #0&#215;22<br />
MOV R2, #0&#215;02<br />
MOV R3, #0&#215;00<br />
MOV R4, #0x00AND R0, R0, #0xFF<br />
ADD R0, R0, #1<br />
ADD R0, R0, R1<br />
LSL R1, R0, #2<br />
SUB R3, R2, R1, LSR R2HandlerFIQ<br />
b .HandlerIRQ<br />
b .HandlerUndef<br />
b .HandlerSWI<br />
b .HandlerDabort<br />
b .HandlerPabort<br />
b .END</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK000.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13231" alt="17featureJK000" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK000.jpg" width="388" height="150" /></a></p>
<p><span style="background-color: #ffff00">(2) ADD R0, R0, #1 ; R0 = R0 + 1 = 0&#215;1</span><br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK001.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13232" alt="17featureJK001" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK001.jpg" width="396" height="148" /></a></p>
<p><span style="background-color: #ffff00">(3) ADD R0, R0, R1 ; R0 = R0 + R1 = 0&#215;01 + 0&#215;22 = 0&#215;23</span><br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK002.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13233" alt="17featureJK002" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK002.jpg" width="406" height="148" /></a></p>
<p><span style="background-color: #ffff00">(4) LSL R1, R0, #2 ; 0&#215;23(100011) LSL #2 = 0x8C(10001100) -&gt; 참고로 왼쪽으로 2번 쉬프트 하면 *4 를 한 것과 같습니다.</span><br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK003.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13234" alt="17featureJK003" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK003.jpg" width="408" height="146" /></a></p>
<p><span style="background-color: #ffff00">(5) SUB R3, R2, R1, LSR R2</span><br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK004.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13235" alt="17featureJK004" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK004.jpg" width="405" height="148" /></a></p>
<p>R3의 값이 0xFFFFFFDF 로 복잡한 값이 나왔습니다. 왜 이런 결과가 나왔을까요? 우선 R1을 오른쪽으로 2번 쉬프트시키면 0&#215;23이 되고 R2(0&#215;02)에서 R1(0&#215;23)을 빼면 결과 값이 -0&#215;21가 되고 이 값을 2의 보수로 표시하면 0xFFFFFFDF가 됩니다.</p>
<p>0&#215;21 = 00000000000000000000000000100001<br />
-0&#215;21 = 11111111111111111111111111011111 &#8211;&gt; 0&#215;21의 2의 보수<br />
참고로 2의 보수를 취하는 방법은 원래의 2진수에서 0-&gt;1, 1-&gt;0 으로 바꾼 후에 1을 더하면 되겠지요.</p>
<p><span style="color: #339966"><strong>2.3 Multiply Instructions</strong></span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>R0 = 0&#215;01<br />
R1 = 0&#215;02<br />
R2 = 0&#215;03<br />
R3 = 0&#215;04</td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK005.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13236" alt="17featureJK005" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK005.jpg" width="405" height="151" /></a></td>
</tr>
</tbody>
</table>
<p>레지스터 값이 위와 같을 때 아래 예제들을 차례대로 수행해보세요.</p>
<p><span style="background-color: #ffff00">(1) MUL R2, R0, R1 ; R2 = R0*R1 = 0&#215;02</span><br />
2440init_ewarm.s 파일에 다음과 같이 입력을 합니다.</p>
<table style="width: 620px" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, 0&#215;01<br />
MOV R1, 0&#215;02<br />
MOV R2, 0&#215;03<br />
MOV R3, 0x04MUL R2, R0, R1<br />
MULS R2, R0, R1<br />
MLA R3, R2, R1, R0</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK006.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13237" alt="17featureJK006" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK006.jpg" width="407" height="148" /></a></p>
<p><span style="background-color: #ffff00">(2) MULS R2, R0, R1 ; R2 = R0*R1 = 0&#215;02</span><br />
MUL 명령과 같은 명령입니다. 하지만 MUL뒤에 “S”가 붙으면 명령어 처리가 끝난 이후에 CPSR의 Flag Field가 연산 결과에 따라서 업데이트가 됩니다.<br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK006.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13237" alt="17featureJK006" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK006.jpg" width="407" height="148" /></a></p>
<p><span style="background-color: #ffff00">(3) MLA R3, R2, R1, R0 ; R3 = R2*R1 + R0</span><br />
참 효율적이네요. 명령어 하나로 곱하기 연산과 더하기 연산을 같이 할 수 있습니다.<br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK007.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13238" alt="17featureJK007" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK007.jpg" width="407" height="150" /></a></p>
<p><span style="color: #339966"><strong>2.4 Load/Store Instructions</strong></span></p>
<p><span style="color: #99cc00"><strong>2.4.1 Pre-index</strong></span><br />
R0 = 0&#215;31000000<br />
R1 = 0&#215;00<br />
R2 = 0&#215;00<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK008.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13239" alt="17featureJK008" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK008.jpg" width="407" height="149" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK009.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13240" alt="17featureJK009" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK009.jpg" width="387" height="181" /></a></p>
<p><span style="background-color: #ffff00">(1) LDR R1, [R0] ; R1 2440init_ewarm.s 파일에 다음과 같이 입력을 합니다.</span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, 0&#215;31000000<br />
MOV R1, 0&#215;0<br />
MOV R2, 0x0LDR R1, [R0]
STR R1, [R0, #4]
STR R1, [R0, #4]!</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK010.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13241" alt="17featureJK010" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK010.jpg" width="408" height="146" /></a></p>
<p><span style="background-color: #ffff00">(2) STR R1, [R0, #4] ; R1</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK011.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13242" alt="17featureJK011" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK011.jpg" width="385" height="120" /></a></p>
<p><span style="background-color: #ffff00">(3) STR R1, [R0, #4]! ; R1</span><br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK012.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13243" alt="17featureJK012" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK012.jpg" width="403" height="150" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK013.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13244" alt="17featureJK013" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK013.jpg" width="388" height="121" /></a></p>
<p><span style="color: #99cc00"><strong>2.4.2 Post-index</strong></span><br />
R0 = 0&#215;31000000<br />
R1 = 0&#215;00<br />
R2 = 0&#215;04<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK014.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13245" alt="17featureJK014" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK014.jpg" width="393" height="148" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK009.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13240" alt="17featureJK009" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK009.jpg" width="387" height="181" /></a></p>
<p><span style="background-color: #ffff00">(1) LDR R1, [R0], R2 ; R1</span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, 0&#215;31000000<br />
MOV R1, 0&#215;0<br />
MOV R2, 0x4LDR R1, [R0], R2<br />
STR R1, [R0], #4</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK015.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13246" alt="17featureJK015" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK015.jpg" width="394" height="149" /></a></p>
<p><span style="background-color: #ffff00">(2) STR R1, [R0], #4 ; R1</span><br />
- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK016.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13247" alt="17featureJK016" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK016.jpg" width="393" height="145" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK017.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13248" alt="17featureJK017" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK017.jpg" width="389" height="120" /></a></p>
<p><span style="color: #339966"><strong>2.5 Load/Store Multiple Instructions</strong></span></p>
<p>R0 = 0x000A<br />
R4 = 0x000B<br />
R5 = 0x000C<br />
R13 = 0xFFF0<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK035.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13266" alt="17featureJK035" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK035.jpg" width="402" height="172" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK036.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13267" alt="17featureJK036" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK036.jpg" width="392" height="170" /></a></p>
<p><span style="background-color: #ffff00">(1) STMIA R13!, {R0,R4-R5}</span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, #0x000A<br />
MOV R4, #0X000B<br />
MOV R5, #0x000C<br />
LDR R13, =0xFFF0STMIA R13!, {R0,R4-R5}</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK042.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13273" alt="17featureJK042" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK042.jpg" width="412" height="166" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK036.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13267" alt="17featureJK036" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK036.jpg" width="392" height="170" /></a></p>
<p><span style="background-color: #ffff00">(2) STMIB R13!, {R0,R4-R5}</span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, #0x000A<br />
MOV R4, #0X000B<br />
MOV R5, #0x000C<br />
LDR R13, =0xFFF0STMIB R13!, {R0,R4-R5}</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK043.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13274" alt="17featureJK043" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK043.jpg" width="402" height="167" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK038.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13269" alt="17featureJK038" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK038.jpg" width="392" height="171" /></a></p>
<p><span style="background-color: #ffff00">(3) STMDA R13!, {R0,R4-R5}</span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, #0x000A<br />
MOV R4, #0X000B<br />
MOV R5, #0x000C<br />
LDR R13, =0xFFF0STMDA R13!, {R0,R4-R5}</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK042.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13273" alt="17featureJK042" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK042.jpg" width="412" height="166" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK039.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13270" alt="17featureJK039" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK039.jpg" width="392" height="171" /></a></p>
<p><span style="background-color: #ffff00">(4) STMDB R13!, {R0,R4-R5}</span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, #0x000A<br />
MOV R4, #0X000B<br />
MOV R5, #0x000C<br />
LDR R13, =0xFFF0STMDB R13!, {R0,R4-R5}</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK041.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13272" alt="17featureJK041" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK041.jpg" width="406" height="171" /></a><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK040.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13271" alt="17featureJK040" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK040.jpg" width="386" height="167" /></a></p>
<p><span style="color: #339966"><strong>2.6 Branch Instructions</strong></span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandlersubsequent<br />
MOV R0, #1<br />
MOV R1, #2<br />
BL func1<br />
ADD R2, R0, R1func1<br />
MOV R0, #3<br />
MOV R1, #4<br />
BL func2<br />
ADD R2, R0, R1<br />
MOV PC, LRfunc2<br />
MOV R0, #5<br />
MOV R1, #6<br />
ADD R2, R0, R1<br />
MOV PC, LR</td>
</tr>
</tbody>
</table>
<p>위의 예제를 실행하면 R2 레지스터에 “3”이 저장이 되지 않습니다. R2 레지스터에 “3”이 저장이 될 수 있도록 예제를 수정해 보시기 바랍니다. 수정한 예제 코드는 아래와 같습니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK018.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13249" alt="17featureJK018" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK018.jpg" width="462" height="374" /></a><br />
서브 함수를 호출 할 경우에는 서브 함수에서 사용하는 레지스터와 LR 레지스터를 반드시 저장한 이후에 사용해야 한다는 것을 알 수 있습니다.</p>
<p><span style="color: #339966"><strong>2.7 Status Register Access Instructions</strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK019.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13250" alt="17featureJK019" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK019.jpg" width="413" height="227" /></a></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MRS R0, CPSR<br />
BIC R0, R0, #0&#215;80 ; 7번 비트를 clear 하면 인터럽트가 활성화 됩니다.<br />
MSR CPSR, R0</td>
</tr>
</tbody>
</table>
<p>- 실행 결과<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK020.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13251" alt="17featureJK020" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK020.jpg" width="411" height="227" /></a></p>
<p><span style="color: #339966"><strong>2.8 Conditional Execution</strong></span></p>
<p>지금까지 배운 모든 어셈블리어들을 활용해서 최종적으로 몇가지 예제를 풀어 보도록 하겠습니다. 예제를 구현하는데에는 여러가지 방법들이 많이 있겠지만 가장 최적화된 어셈블리 명령어를 사용하시기 바랍니다.</p>
<p><span style="background-color: #ffff00">(1) 1 ~ 10을 더하는 최적화된 어셈블리어로 작성해 보세요.</span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R5, #10<br />
MOV R6, #0<br />
loop_sum<br />
ADD R6, R6, R5<br />
SUBS R5, R5, #1<br />
BNE loop_sum ; Not Equal(Z=1)</td>
</tr>
</tbody>
</table>
<p>루프를 사용할 경우에는 거꾸로 도는 것이 효율적입니다.</p>
<p><span style="background-color: #ffff00">(2) 2개 변수 사이의 절대값을 구하세요.</span><br />
- [-2 - 3] 사이의 절대값</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, #-2<br />
MOV R1, #3SUBS R0, R0, R1V<br />
RSBMI R0, R0, #0</td>
</tr>
</tbody>
</table>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK046.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13277" alt="17featureJK046" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK046.jpg" width="612" height="172" /></a></p>
<p>“SUBS R0, R0, R1”명령을 실행했을 때의 그림입니다. R0, CPSR의 “N”Flag를 잘 살펴보시기 바랍니다. 참고로 RSBMI 명령어는 CPSR의 “N”Flag가 Set되어 있을 때 뺄셈을 하는데 SUB 명령과는 연산의 방향이 반대로 수행이 되는 명령어입니다. 그러니까 이번 예제에서는 “#0”에서 “R0”를 빼는 것입니다.</p>
<p>- [3 - 1] 사이의 절대값</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td>ResetHandler<br />
MOV R0, #3<br />
MOV R1, #1SUBS R0, R0, R1<br />
RSBMI R0, R0, #0</td>
</tr>
</tbody>
</table>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK045.jpg" rel="lightbox[13348]"><img class="alignnone size-full wp-image-13276" alt="17featureJK045" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK045.jpg" width="611" height="172" /></a><br />
“SUBS R0, R0, R1”명령을 실행했을 때의 그림입니다. R0, CPSR의 “N”Flag를 잘 살펴 보시기 바랍니다.</p>
<p>3장에서는 우리가 실제로 실습에 사용할 S3C2440 ARM9 개발보드에 대해서 소개하도록 하겠습니다. ARM Simulator에서는 별다른 설정없이도 어셈블리어 실습을 할 수 있었으나 실제 타겟을 사용할 경우에는 개발보드의 메모리 컨트롤러, 부팅과정 등을 제대로 이해하고 있어야 코드 작성이 가능합니다. 실제 개발보드에서 실습을 하기 전에 S3C2440에 대해서 이론적으로 공부해보도록 하겠습니다.</p>
<p>&nbsp;</p>
<p style="text-align: right"><span style="color: #999999"> JK전자와 함께하는 ARM 완전정복(3)-2 에서 계속 됩니다.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/13348/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[17호]JK전자와 함께하는 ARM 완전정복(3)-1</title>
		<link>http://www.ntrexgo.com/archives/13132</link>
		<comments>http://www.ntrexgo.com/archives/13132#comments</comments>
		<pubDate>Sun, 10 Mar 2013 00:42:26 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[17호]]></category>
		<category><![CDATA[applications]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=13132</guid>
		<description><![CDATA[디바이스마트 매거진 17호 &#124; 3부 1편. 자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부한다면 큰 도움이 될 것입니다.]]></description>
				<content:encoded><![CDATA[<table style="width: 600px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13318" alt="jk전자" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자-300x222.jpg" width="192" height="142" /></a></td>
<td><span style="color: #000080"><strong><span style="font-size: large">JK전자와 함/께/하/는 ARM 완전 정복</span></strong></span><span style="color: #666699"><strong><span style="line-height: 19px">Ⅱ.ARM Applications &#8211; 1부</span></strong></span>글 | JK전자</td>
</tr>
</tbody>
</table>
<p><span style="font-size: 13px;line-height: 19px">자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부한다면 큰 도움이 될 것입니다.</span></p>
<p>ARM Architecture 강의에서는 특정 CPU(S3C2440, STM32Fxx) 에 대한 내용 보다는 ARM Core의 이론적인 구조 자체에 대해서 많은 설명을 하였습니다. 이번 강의에서는 Samsung의 ARM9 CPU S3C2440 개발보드를 이용해서 실제 실습을 통해서 ARM에 대해서 공부해 보도록 하겠습니다.<br />
I. ARM Architecture ~ IV. Cortex-M3 Applications 까지 분명 쉽지 않은 지루하고도 먼 여행이 되겠지만 ARM을 공부하는 임베디드 관련 엔지니어라면 언젠가는 한 번은 넘어야 하는 산이라 생각됩니다. 부디 이 자료가 ARM을 정복하는데 조금이라도 도움이 되시길 바랍니다.</p>
<p>&nbsp;</p>
<p><span style="font-size: small;color: #f68412"><strong>강의 전체 로드맵</strong></span></p>
<p>I. ARM Architecture | 임베디드 시스템 개론에 대한 설명과 ARM7, ARM9 의 구조에 대해서 설명합니다.<br />
<span style="color: #808000"><strong>II. ARM Applications | 삼성의 S3C2440(ARM9) 개발보드(S3C2440 Mini 개발보드)를 이용해서 어셈블리어와 UART, GPIO 등을 실습합니다.</strong></span><br />
III. Cortex-M3 Architecture | Cortex-M3의 특징과 구조에 대해서 설명합니다.<br />
IV. Cortex-M3 Applications | STM32F103VCT6 Dragon 개발보드를 이용해서 GPIO, LCD, SPI, UART, MP3, SDIO, I2C 등을 실습합니다.</p>
<p>이 강의 자료에 대한 모든 질의사항은<a href="http://cafe.naver.com/avrstudio" target="_blank"> http://cafe.naver.com/avrstudio</a>의 ARM Architecture Q&amp;A게시판에 글을 남겨 주시거나 jk@deviceshop.net로 메일을 보내주시기 바랍니다. 가급적이면 여러 사람이 질문에 대한 답변을 공유할 수 있도록 네이버 카페 게시판을 이용해주셨으면 합니다. 감사합니다.</p>
<p><span style="font-size: small;color: #f68412"><strong>Ⅱ. ARM Applications 1부 목차</strong></span></p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td>1. Base of Software Engineering<br />
1.1 Memory Endian Formats<br />
1.2 보수 표현<br />
1.3 논리연산<br />
1.4 진수변환<br />
1.5 Data Types<br />
1.6 Aligned &amp; Un-Aligned Data<br />
2. 어셈블리어 실습<br />
2.1 ARM Simulator 환경 설정</td>
<td>2.2 Data Processing Instructions<br />
2.3 Multiply Instructions<br />
2.4 Load/Store Instructions<br />
2.5 Branch Instructions<br />
2.6 Status Register Access Instructions<br />
2.7 Conditional Execution<br />
3.1 S3C2440 CPU<br />
3.2 S3C2440 Features</td>
<td>3. S3C2440 개발보드 소개<br />
3.3 S3C2440 HW IPs<br />
3.4 Memory Controller<br />
3.5 Timer<br />
3.6 UART<br />
3.7 NAND Booting<br />
4. 개발환경 설정<br />
4.1 IAR Workbench 개발환경 설정<br />
4.2 ARM-JTAG 을 이용한 프로그램 다운로드</td>
</tr>
</tbody>
</table>
<p>1장의 내용은 컴퓨터를 전공한 사람이라면 누구나 다 아는 내용이지만 어셈블리어 실습을 하기위해서는 반드시 알아야 하는 내용입니다. 다 아는 내용이겠지만 기억을 되살리는 차원에서 간단하게만 설명 하도록 하겠습니다.</p>
<p><span style="color: #008080;background-color: #ffff99"><strong>1. Base of Software Engineering</strong></span></p>
<p><span style="color: #339966"><strong>1.1 Memory Endian Formats</strong></span></p>
<p>워드 데이터 안에서의 바이트 순서로 크게 빅 엔디언과 리틀 엔디언으로 나눌 수 있습니다. 빅 엔디언은 사람이 숫자를 쓰는 방법과 같이 큰 단위의 바이트가 앞에 오는 방법이고, 리틀 엔디언은 반대로 작은 단위의 바이트가 앞에 오는 방법입니다. 다시 한번 강조하지만 이것은 워드 범위 내에서의 바이트 단위의 순서입니다.<br />
또한 ARM 레지스터에 저장이 될 경우에는 엔디안의 구분이 없고 메모리 접근 측면에서만 구분이 필요합니다.</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><span style="font-size: small">엔디안 종류</span></td>
<td><span style="font-size: small">0&#215;1234</span></td>
<td><span style="font-size: small">0&#215;12345678</span></td>
<td><span style="font-size: small">아키텍쳐</span></td>
</tr>
<tr>
<td><span style="font-size: small">Big-endian</span></td>
<td><span style="font-size: small">12 34</span></td>
<td><span style="font-size: small">12 34 56 78</span></td>
<td><span style="font-size: small">모토로라 등</span></td>
</tr>
<tr>
<td><span style="font-size: small">Little-endian</span></td>
<td><span style="font-size: small">34 12</span></td>
<td><span style="font-size: small">78 56 34 12</span></td>
<td><span style="font-size: small">x86</span></td>
</tr>
</tbody>
</table>
<p>* 몇몇 아키텍처는 빅 엔디언과 리틀 엔디언 중 하나를 선택할 수 있도록 설계되어있고, 이를 바이 엔디언(Bi-endian)이라 부릅니다. PowerPC, DEC 알파, MIPS, PA-RISC, IA-64 등은 바이 엔디언을 사용하는 대표적인 아키텍처입니다. 우리가 공부하고 있는 ARM도 엔디언을 선택해서 사용할 수 있도록 설계되어 있습니다.<br />
x86 아키텍처가 리틀 엔디언을 쓰기 때문에, 오늘날 x86 아키텍처를 사용하는 대부분의 데스크톱 컴퓨터는 리틀 엔디언을 쓰며 이를 &#8220;인텔 포맷&#8221; 이라고 합니다</p>
<p style="padding-left: 30px">Example)<br />
32비트 숫자인 0x2A를 Little-endian으로 표시 하면?<br />
0&#215;00 00 00 2A = 2A 00 00 00</p>
<p><span style="color: #339966"><strong>1.2 보수 표현</strong></span><br />
컴퓨터에서 보수를 사용하는 이유는 무엇일까요? 모든 것이 0과 1로 표현되는 컴퓨터에서 음수를 표현하는데 편리하기 때문에 사용합니다. 물론 이를 이용해서 뺄셈도 합니다. 예를 들면 12-3의 수식을 컴퓨터(ALU)에서 계산을 하면 실제로는 12에서 3을 빼는 것이 아니라 12와 3의 2의 보수(3의 음수표현)를 더해서 계산을 하게 됩니다.</p>
<p><span style="color: #99cc00"><strong>1.2.1 &#8220;1&#8243; 의 보수</strong></span><br />
주어진 이진수의 모든 자리 숫자를 반전(0을 1로, 1을 0으로)시키면 1의 보수를 얻을 수 있습니다.</p>
<p style="padding-left: 30px">8자리의 이진수 01001011(십진수로 75)의 1의 보수를 구하면 아래와 같습니다.<br />
01001011 의 모든 자리의 수를 반전시킨다.<br />
10110100 &#8211;&gt; 1의 보수</p>
<p><span style="color: #99cc00"><strong>1.2.2 &#8220;2&#8243; 의 보수</strong></span><br />
1의 보수를 구한 다음 2진수 &#8220;1&#8243; 을 더하면 됩니다.<br />
8자리의 이진수 01001011(십진수로 75)의 2의 보수를 구하면 아래와 같습니다.</p>
<p style="padding-left: 30px">01001011 의 모든 자리의 수를 반전시킨다.<br />
10110100 &#8211;&gt; 1의 보수</p>
<p style="padding-left: 30px">10110100<br />
+) 00000001 &#8211;&gt; 1의 보수에서 1을 더합니다.<br />
&#8212;&#8212;&#8212;&#8212;&#8212;<br />
10110101 &#8211;&gt; 2의 보수</p>
<p>보수를 구할 때 한 자리가 더 길어질 경우에는 가장 높은 자리의 숫자는 버립니다.</p>
<p><span style="color: #99cc00"><strong>1.2.3 &#8220;2&#8243; 의 보수를 이용한 뺄셈</strong></span></p>
<p style="padding-left: 30px">예제) 100-75를 2의 보수를 이용해서 연산하시요.<br />
100-75는 100+(-75)와 같으므로</p>
<p style="padding-left: 30px">01100100 (10진수 100)<br />
+) 10110101 (10진수 75의 2의 보수)<br />
&#8212;&#8212;&#8212;&#8212;&#8212;<br />
100011001</p>
<p>새로 생긴 가장 높은 자리의 숫자를 빼고 남은 00011001은 십진수로 25와 같으며 이는 계산하려던 식의 결과입니다.</p>
<p style="padding-left: 30px">예제) 10-75를 2의 보수를 이용해서 연산하시요.<br />
10-75는 10+(-75)와 같으므로</p>
<p style="padding-left: 30px">00001010 (10진수 10)<br />
+) 10110101 (10진수 75의 2의 보수)<br />
&#8212;&#8212;&#8212;&#8212;&#8212;<br />
10111111 (이 결과는 음수 : MSB가 1 이므로 다시 2의 보수를 취하면 65 즉 -65)</p>
<p style="padding-left: 30px">10111111 결과는 MSB가 1(음수)이므로 다시 2의 보수를 취해보면 01000001은 십진수로 65와 같으며 이는 계산하려던 식의 결과 -65가 됩니다.</p>
<p><span style="color: #339966"><strong>1.3 논리 연산</strong></span></p>
<p><span style="color: #99cc00"><strong>1.3.1 NOT</strong></span><br />
2진수 각 자리의 값을 반대로 바꾸는 연산입니다. 이 연산은 어떤 값의 보수를 구할 때 효과적으로 사용할 수 있습니다.</p>
<p style="padding-left: 30px">NOT 0111<br />
= 1000</p>
<p>C나 C++에는 &#8220;~&#8221; 연산을 통해 이 값을 구할 수 있습니다.</p>
<p style="padding-left: 30px">x = ~y;</p>
<p><span style="color: #99cc00"><strong>1.3.2 OR</strong></span><br />
두 값의 각 자릿수를 비교해, 둘 중 하나라도 1이 있다면 1을, 아니면 0을 계산합니다.</p>
<p style="text-align: left;padding-left: 30px">0101<br />
OR 0011<br />
= 0111</p>
<p>C/C++에는 “ | ” 연산자가 이 기능을 제공합니다.</p>
<p style="padding-left: 30px">x = y | z;</p>
<p><strong><span style="color: #99cc00">1.3.3 XOR</span> </strong><br />
두 값의 각 자릿수를 비교해, 값이 같으면 0, 다르면 1을 계산합니다.</p>
<p style="padding-left: 30px">0101<br />
XOR 0011<br />
= 0110</p>
<p>C/C++에는 “ ^ ” 연산자가 이 기능을 제공한다.</p>
<p style="padding-left: 30px">x = y ^ z;</p>
<p><span style="color: #99cc00"><strong>1.3.4 AND</strong></span><br />
두 값의 각 자릿수를 비교해, 두 값 모두에 1이 있을 때에만 1을, 나머지 경우에는 0을 계산합니다.</p>
<p style="padding-left: 30px">0101<br />
AND 0011<br />
= 0001</p>
<p>C/C++에는 “ &amp; ” 연산자가 이 기능을 제공한다.</p>
<p style="padding-left: 30px">x = y &amp; z;</p>
<p><span style="color: #339966"><strong>1.4. Shift 연산</strong></span></p>
<p><span style="color: #99cc00"><strong>1.4.1 왼쪽으로 쉬프트(&lt;&lt;)</strong></span><br />
“ &lt;&lt; ” 키워드는 데이터를 왼쪽으로 비트 수만큼 이동시키기 때문에 2의 “이동할 비트수”를 제곱한 값과 데이터가 곱해진 값이 결과 값으로 도출됩니다. 5(b00000101)를 왼쪽으로 3비트 이동시키면 5 &lt;&lt; 3 = 40(b00101000) 즉 5 * 8 한 것과 같은 효과가 나타납니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK023.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13254" alt="17featureJK023" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK023.jpg" width="382" height="191" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="text-align: center">가중치</td>
<td style="text-align: center">128</td>
<td style="text-align: center">64</td>
<td style="text-align: center">32</td>
<td style="text-align: center">16</td>
<td style="text-align: center">8</td>
<td style="text-align: center">4</td>
<td style="text-align: center">2</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">연산전</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
</tr>
<tr>
<td style="text-align: center">연산후</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
</tr>
</tbody>
</table>
<p><span style="color: #99cc00"><strong>1.4.2 오른쪽으로 쉬프트(&gt;&gt;)</strong></span><br />
“&gt;&gt;” 키워드는 데이터를 오른쪽으로 비트 수만큼 이동시키기 때문에 2의 “이동한 비트수”를 제곱한 값으로 데이터를 나눗셈 한 값이 도출됩니다.<br />
40(b00101000)를 오른쪽으로 1비트 이동시키면 40 &gt;&gt; 1 = 20(b00101000) 즉 40/2 한 것과 같은 효과가 있습니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK024.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13255" alt="17featureJK024" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK024.jpg" width="382" height="192" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="text-align: center">가중치</td>
<td style="text-align: center">128</td>
<td style="text-align: center">64</td>
<td style="text-align: center">32</td>
<td style="text-align: center">16</td>
<td style="text-align: center">8</td>
<td style="text-align: center">4</td>
<td style="text-align: center">2</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">연산전</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">2</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
</tr>
<tr>
<td style="text-align: center">연산후</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
</tr>
</tbody>
</table>
<p><span style="color: #99cc00"><strong>1.4.3 부호가 있는 왼쪽 쉬프트 연산(&lt;&lt;)</strong></span><br />
79(b01001111) &lt;&lt; 1 = -98(b10011110)<br />
부호 비트(“1”)와 그 다음 비트(“0”)가 서로 다른 값인 경우 부호가 바뀌고 Overflow가 발생하게 됩니다. 위의 예제에서는 양수에서 음수로 바뀌면서 Overflow가 발생하였습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK025.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13256" alt="17featureJK025" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK025.jpg" width="382" height="191" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td style="text-align: center">가중치</td>
<td style="text-align: center">부호</td>
<td style="text-align: center">64</td>
<td style="text-align: center">32</td>
<td style="text-align: center">16</td>
<td style="text-align: center">8</td>
<td style="text-align: center">4</td>
<td style="text-align: center">2</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">연산전</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">1</td>
<td style="text-align: center">1</td>
<td style="text-align: center">1</td>
</tr>
<tr>
<td style="text-align: center">연산후</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
<td style="text-align: center">0</td>
<td style="text-align: center">1</td>
<td style="text-align: center">1</td>
<td style="text-align: center">1</td>
<td style="text-align: center">1</td>
<td style="text-align: center">0</td>
</tr>
</tbody>
</table>
<p><span style="color: #99cc00"><strong>1.4.4 부호가 있는 오른쪽 쉬프트 연산(&gt;&gt;)</strong></span><br />
여기서 65의 2의 보수를 이용해서 -65를 표현했습니다. -65(b10111111) &gt;&gt; 1 = -33(b11011111)<br />
예를 들어 위의 그림과 같이 “1011 1111” 값을 오른쪽으로 한번 이동하면 왼쪽에 생긴 빈 공간은 최상위 비트인 1 값으로 채워지는 것입니다. 만약 “-160 &gt;&gt; 4v 를 연산하면 -160 의 이진수 값인“1010 0000”가 오른쪽으로 4비트만큼 이동하고, 왼쪽에 생긴 네개의 빈 공간은 최상위 비트인 1 로 채워지므로 연산 결과는 “1111 1010”가 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK026.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13257" alt="17featureJK026" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK026.jpg" width="318" height="192" /></a></p>
<p>&nbsp;</p>
<p><span style="color: #339966"><strong>1.5 Rotate 연산</strong></span></p>
<p>데이터의 모든 비트들을 각각 서로 이웃한 비트의 자리로 옮기고 한 쪽 끝에서 밀려 나가는 비트가 다시 반대편 끝으로 들어오게 되는 연산입니다.</p>
<p><span style="color: #99cc00"><strong>1.5.1 부호 없는(Rotate no carry) 왼쪽 Rotate</strong></span><br />
23(b00010111) ROL 1 = 46(b00101110)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK027.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13258" alt="17featureJK027" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK027.jpg" width="318" height="192" /></a><br />
Left circular shift or rotate</p>
<p><span style="color: #99cc00"><strong>1.5.2 부호 없는(Rotate no carry) 오른쪽 Rotate</strong></span><br />
23(b00010111) ROR 1 = 139(b10001011)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK028.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13259" alt="17featureJK028" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK028.jpg" width="318" height="192" /></a><br />
Right circular shift or rotate</p>
<p><strong><span style="color: #99cc00">1.5.3 부호 있는(Rotate through carry) 왼쪽 Rotate</span> </strong><br />
ROL과 동일하지만 Carry Flag가 최하위 비트로 이동하고, 최상의 비트의 값이 Carry Flag 로 이동됩니다.<br />
23(b00010111) RCL 1 = 47(b00101111)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK029.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13260" alt="17featureJK029" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK029.jpg" width="363" height="192" /></a><br />
Left rotate through carry</p>
<p><span style="color: #99cc00"><strong>1.5.4 부호 있는(Rotate through carry) 오른쪽 Rotate</strong></span><br />
23(b00010111) RCR 1 = 267(b100001011)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK030.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13261" alt="17featureJK030" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK030.jpg" width="359" height="192" /></a><br />
Right rotate through carry<br />
아주 기본적인 내용들이지만 기본적인 것부터 정확하게 알고 있어야 합니다. 주로 데이터 암호화나, 고속의 그래픽 처리 작업 등에서 Shift, Rotate 연산을 많이 사용합니다.</p>
<p><span style="color: #339966"><strong>1.6 진수변환</strong></span></p>
<p>2진수를 16진수로 변환할 때 4자리씩 끊어서 계산하면 편리합니다. 자주 쓰이는 수들의 2진수와 16진수들의 예제들입니다.</p>
<p style="padding-left: 30px">2^4 = 16B = b0001 0000 = 0&#215;10<br />
2^5 = 32B = b0010 0000 = 0&#215;20<br />
2^6 = 64B = b0100 0000 = 0&#215;40<br />
2^7 = 128B = 0&#215;80<br />
2^8 = 256B = b0001 0000 0000 = 0&#215;100<br />
2^10 = 1KB = b0100 0000 0000 = 0&#215;400<br />
2^20 = 1MB = b0001 0000 0000 0000 0000 0000 = 0&#215;100000<br />
2^30 = 1GB = 0&#215;40000000<br />
2^40 = 1TB = 0X10000000000<br />
4KB = 0&#215;1000, 64KB = 0&#215;10000, 1MB = 0&#215;100000</p>
<p style="padding-left: 30px">Ex)<br />
4GB = 4*1GB = 4 * 2^30 = 2^2 * 2^30 = 2^32 = 0&#215;100000000<br />
256KB = 256*1KB = 2^8 * 2^10 = 2^18 = 0&#215;40000<br />
96KB = 64KB + 32KB = 2^6*2^10 + 2^5*2^10 = 0&#215;10000 + 0&#215;3000 = 0&#215;13000<br />
135KB = 128KB + 4KB + 2KB + 1KB = 2^17 + 2^12 + 2^11 + 2^10 = 0&#215;20000 + 0&#215;1000 + 0&#215;800 + 0&#215;400 = 0x21c00</p>
<p><span style="color: #339966"><strong>1.7 Data Types</strong></span></p>
<p>Byte(8 bits)<br />
Halfword(16 bits)<br />
Word (32 bits)<br />
Long Word (64 bits)</p>
<p>- Value ranges</p>
<p>unsigned char val;<br />
<span style="color: #3366ff">0 &lt;= val &lt;= 2^8(255)</span><br />
signed char val;<br />
-128(0&#215;80) &lt;= val &lt;= 127(0x7F)<br />
int(signed 32bit integer) val;<br />
<span style="color: #3366ff">0&#215;8000 0000 &lt;= val &lt;= 7FFFF FFFF</span></p>
<p><span style="color: #339966"><strong>1.8 Aligned &amp; Un-Aligned Data Access</strong></span></p>
<p><span style="color: #99cc00"><strong>1.8.1 Aligned Access</strong></span></p>
<p>(1) Halfword Data Access : 데이터의 주소 값이 짝수이어야 합니다.<br />
(2) Word Data Access : 데이터의 주소 값이 4의 배수이어야 합니다.</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td bgcolor="#E4F7BA">Aligned Data Access</td>
</tr>
<tr>
<td>char buf[100];int *p;<br />
int gVar;p = (int *)&amp;buf[0];<br />
gVar = *p &#8211;&gt; Data Abort 가능성 1p = (int *)&amp;buf[1];<br />
gVar = *p &#8211;&gt; Data Abort 가능성 2</td>
</tr>
</tbody>
</table>
<p>- Data Abort 가능성 2 : buf의 데이터형이 char(8 bit) 이기 때문에 0번째 이후 부터는 4의 배수가 아니기 때문에 Data Abort 가능성이 있습니다.<br />
- Data Abort 가능성 1 : 0번째 인덱스인데 어떻게 보면 Data Abort 가능성이 없는 것처럼 보입니다. 보통은 Linker가 알아서 buf 변수의 할당 주소를 4의 배수에 맞추어 주지만 그렇지 않을 가능성도 있기 때문에 링커에 따라서는 Data Abort 가능성이 있는 것입니다. 그렇다면 Data Abort가 발생하지 않도록 char 배열 buf를 선언하려면 어떻게 해야 할까요? 컴파일러 지시자를 사용해서 char 배열 buf를 강제로 4의 배수로 맞추어 주는 것입니다.</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td bgcolor="#E4F7BA">Aligned Data Access</td>
</tr>
<tr>
<td>#pragma data_alignment = 2 &#8211;&gt; 강제로 4의 배수가 되도록 지시<br />
char buf[100];int *p;<br />
int gVar;p = (int *)&amp;buf[0];<br />
gVar = *p &#8211;&gt; 정상동작p = (int *)&amp;buf[1];<br />
gVar = *p &#8211;&gt; 1번째 배열에서는 여전히 Data Abort 가능성 2</td>
</tr>
</tbody>
</table>
<p>여기서 또 한가지 ARM C언어에서 구조체 선언을 할 때 어떻게 선언하는 것이 효율적인지를 알아 봅시다.</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td colspan="2" bgcolor="#E4F7BA">비 효율적인 구조체 데이터 선언</td>
</tr>
<tr>
<td>struct {<br />
char a;<br />
int b;<br />
short c;<br />
int d;<br />
} gVar;</td>
<td>메모리 배치<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK031.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13262" alt="17featureJK031" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK031.jpg" width="225" height="134" /></a></td>
</tr>
</tbody>
</table>
<p>위의 그림을 보면 총 5byte의 메모리 공간을 낭비하였습니다. 그렇다면 선언 순서를 short c, int b 의 순서를 바꾸면 어떻게 될까요?</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="5">
<tbody>
<tr>
<td colspan="2" bgcolor="#E4F7BA">비 효율적인 구조체 데이터 선언</td>
</tr>
<tr>
<td>struct {<br />
char a;<br />
short c;<br />
int b;<br />
int d;<br />
}gVar;</td>
<td>메모리 배치<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK032.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13263" alt="17featureJK032" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK032.jpg" width="225" height="134" /></a></td>
</tr>
</tbody>
</table>
<p>단지 선언 순서만 바꾸어도 메모리 낭비가 5-byte에서 1-byte로 줄었습니다.</p>
<p><strong><span style="color: #99cc00">1.8.2 Un-Aligned Data Access</span> </strong></p>
<p>(1) ARM Architecture v6 부터 지원됨<br />
(2) ARM Architecture v4T, v5T(E) 등에서 Un-aligned data를 접근하려고 하면 Data Abort가 발생합니다.</p>
<p><em id="__mceDel"><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK033.jpg" rel="lightbox[13132]"><img class="alignnone  wp-image-13264" alt="17featureJK033" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/17featureJK033-620x170.jpg" width="496" height="136" /></a></em></p>
<p>&nbsp;</p>
<p style="text-align: right"><span style="color: #999999">JK전자와 함께하는 ARM 완전정복(3)-2 에서 계속 됩니다.</span><a href="http://wp.me/p3jmc8-3ti" target="_blank"><br />
</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/13132/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[16호]JK전자와 함께하는 ARM 완전정복 2부</title>
		<link>http://www.ntrexgo.com/archives/2515</link>
		<comments>http://www.ntrexgo.com/archives/2515#comments</comments>
		<pubDate>Thu, 10 Jan 2013 07:36:52 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[16호]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=2515</guid>
		<description><![CDATA[디바이스마트 매거진 16호 &#124; 자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부한다면 큰 도움이 될 것입니다. ]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/archives/2867" target="_blank">1부 계속</a></p>
<p>&nbsp;</p>
<p><span style="color: #800000"><strong>7. ARM Instruction Sets</strong></span><a id="1342322528" name="7"></a></p>
<p><span style="color: #ff0000"><strong>7.1 Understanding ARM Instruction set</strong></span><a id="13423225282" name="7.1"></a></p>
<p>ARM Instruction Set은 ARM 명령어들 즉 어셈블리어를 이야기하는 것입니다. 대부분은 C 코드를 이용해서 작업을 합니다만, 어셈블리어도 어느 정도는 숙지하고 있어야 하는 몇가지 이유가 있습니다.</p>
<p>(1) ARM 어셈블리어를 잘 파악하고 있으면 ARM의 구조를 더 잘 이해할 수 있습니다.</p>
<p>(2) 전통적인 ARM의 Startup 코드는 스택이 초기화 되기 전에는 C로 작성을 할 수가 없습니다. 최근 Cortex 계열은 Reset 벡터의 초기 번지가 Stackaddress여서 C코드만으로도 부트로더 작성이 가능합니다.</p>
<p>(3) C컴파일러의 최적화가 아주 잘 되어 있지만, 사람이 주의해서 작성하는 어셈블리 코드보다는 최적화할 수 없습니다.</p>
<p>(4) Debugging in detail (instruction level debugging)</p>
<p>일반적인 ARM 어셈블리어 형식입니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14023.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2623" alt="16FJK14023" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14023-300x134.jpg" width="300" height="134" /></a></td>
</tr>
</tbody>
</table>
<p>· Directive : 어셈블리 코드의 특성을 지정하는 지시어입니다.<br />
· Label : 반드시 Space 없이 첫번째 컬럼에 위치해야 하고, Label 자체가 Address가 됩니다.<br />
· Comment : 주석은 &#8220;;&#8221; 문자 이후로 작성을 하면 됩니다.<br />
· Instructions(ADD, MOV, LDR &#8230;) : 명령어들은 반드시 앞 부분에 적어도 하나 이상의 Space가 있어야 합니다.</p>
<p><span style="color: #ff0000"><strong>7.2 ARM Instruction sets</strong></span><a id="134232252822" name="7.2"></a></p>
<p>ARM Processor는 2가지 명령어 세트를 지원하는데 32bit ARM 명령어와 16bit Thumb 명령어가 있습니다. Thumb 명령어는 모든 ARM 프로세서에서 지원하는 것은 아니고 Thumb 특성을 지원하는 Core에서만 사용이 가능합니다. 최근 Cortex 계열에서는 16bit, 32bit 명령어를 같이 사용할 수 있는 Thumb-2 Instruction도 지원합니다. 심지어 Cortex-M3의 경우에는 Thumb-2 Instruction만 사용이 가능 합니다. 8bit 길이의 Jave Byte Code도 사용할 수 있는데 이것도 Thumb 명령어와 같이 모든 ARM Processor가 지원하는 것은 아닙니다.</p>
<table style="width: 550px" border="1" cellspacing="0" cellpadding="8">
<tbody>
<tr>
<td align="center" bgcolor="#FF6600" height="39">Instruction Type</td>
<td align="center" bgcolor="#FF6600" height="39">Instructions</td>
</tr>
<tr>
<td bgcolor="#FFFFFF" width="192">Data Processing</td>
<td align="left" bgcolor="#FFFFFF" width="654">ADD, ADC, SUB, SBC, RSB, AND, ORR, BIC, MOV, CMP, TEQ, …</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">Multiply</td>
<td align="left" bgcolor="#FFFFFF">MUL, MULS, MLA, SMULL, UMLAL, …</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">Load/Store</td>
<td align="left" bgcolor="#FFFFFF">LDR, LDRB, LDRH, LDRSH, LDM, STR, STRB, STRH, STRSH, STM, …</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">Branch</td>
<td align="left" bgcolor="#FFFFFF">B, BL, BX, BLX, …</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">Status Access</td>
<td align="left" bgcolor="#FFFFFF">MRS, MSR</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">Swap</td>
<td align="left" bgcolor="#FFFFFF">SWP, SWPB</td>
</tr>
<tr>
<td bgcolor="#FFFFFF">Coprocessor</td>
<td align="left" bgcolor="#FFFFFF">MRC, MCR, LDC, STC</td>
</tr>
</tbody>
</table>
<p><span style="color: #ff0000"><strong>7.3 Data Processing Instructions</strong></span> <a id="134232252823" name="7.3"></a></p>
<p><span style="color: #ff6600">(1) Instructions</span></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1488.jpg" rel="lightbox[2515]"><img class="alignnone size-large wp-image-2688" alt="16FJK1488" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1488-620x69.jpg" width="620" height="69" /></a></td>
</tr>
</tbody>
</table>
<p><span style="text-decoration: underline">&lt; Cond &gt;</span><br />
해당 명령의 조건 실행 플래그입니다. 해당 플래그를 통해 명령을 CPSR의 플래그 상태에 따라 선택적으로 실행을 할 수 있습니다. ARM에서 지원하는 굉장히 강력한 기능으로 조건부 실행을 잘 이용하면 분기문을 최대한 줄여 시스템 성능을 향상 시킬 수 있습니다.</p>
<p><span style="text-decoration: underline">&lt; I &gt;</span><br />
Operand 2로 지정되어 있는 부분이 Immediate Operand 인지 아닌지 여부를 나타내는 비트입니다. 즉 25번필드[I] 가 &#8220;0&#8243; 이면 [11 : 0] 가 shifter operand로 동작을 하고 &#8220;1&#8243; 이면 Immediate Operand로 동작합니다. Immediate Operand라 함은, 예를 들어 MOV R0, #0&#215;01234 라고 했을 경우 #0&#215;1234를 가리키는 말입니다.</p>
<p><span style="text-decoration: underline">&lt; Opcode &gt;</span><br />
데이터 프로세싱 명령중 어떤 명령인지를 나타내는 필드입니다. 해당 필드와 명령어는 아래와 같습니다.</p>
<table style="width: 550px" border="1" cellspacing="0" cellpadding="8">
<tbody>
<tr>
<td align="center" bgcolor="#FF6600" height="20">Opcode</td>
<td align="center" bgcolor="#FF6600" height="20">Mnemonic</td>
<td align="center" bgcolor="#FF6600">Meaning</td>
<td align="center" bgcolor="#FF6600">Action</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF" width="69">0000</td>
<td align="center" bgcolor="#FFFFFF" width="107">AND</td>
<td align="left" bgcolor="#FFFFFF" width="190">Logical AND</td>
<td align="left" bgcolor="#FFFFFF" width="444">Rd = Rn AND shifter_operand</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0001</td>
<td align="center" bgcolor="#FFFFFF">EOR</td>
<td align="left" bgcolor="#FFFFFF">Logical Exclusive OR</td>
<td align="left" bgcolor="#FFFFFF">Rd = Rn EOR shifter_operand</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0010</td>
<td align="center" bgcolor="#FFFFFF">SUB</td>
<td align="left" bgcolor="#FFFFFF">Subtract</td>
<td align="left" bgcolor="#FFFFFF">Rd = Rn &#8211; shifter_operand</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0011</td>
<td align="center" bgcolor="#FFFFFF">RSB</td>
<td align="left" bgcolor="#FFFFFF">Reverse subtract</td>
<td align="left" bgcolor="#FFFFFF">Rd = shifter_operand &#8211; Rn</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0100</td>
<td align="center" bgcolor="#FFFFFF">ADD</td>
<td align="left" bgcolor="#FFFFFF">Add</td>
<td align="left" bgcolor="#FFFFFF">Rd = Rn + shifter_operand</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0101</td>
<td align="center" bgcolor="#FFFFFF">ADC</td>
<td align="left" bgcolor="#FFFFFF">Add with carry</td>
<td align="left" bgcolor="#FFFFFF">Rd = Rn + shifter_operand + Carry</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0110</td>
<td align="center" bgcolor="#FFFFFF">SBC</td>
<td align="left" bgcolor="#FFFFFF">Subract with carry</td>
<td align="left" bgcolor="#FFFFFF">Rd = Rn – shifter_operand – NOT(Carry)</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0111</td>
<td align="center" bgcolor="#FFFFFF">RSC</td>
<td align="left" bgcolor="#FFFFFF">Reverse Subract with carry</td>
<td align="left" bgcolor="#FFFFFF">Rd = shifter_operand &#8211; Rn – NOT(Carry)</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1000</td>
<td align="center" bgcolor="#FFFFFF">TST</td>
<td align="left" bgcolor="#FFFFFF">Test</td>
<td align="left" bgcolor="#FFFFFF">Update flags after Rn AND shifer_opernad</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1001</td>
<td align="center" bgcolor="#FFFFFF">TEQ</td>
<td align="left" bgcolor="#FFFFFF">Test Equivalence</td>
<td align="left" bgcolor="#FFFFFF">Update flags after Rn EOR shifer_opernad</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1010</td>
<td align="center" bgcolor="#FFFFFF">CMP</td>
<td align="left" bgcolor="#FFFFFF">Compare</td>
<td align="left" bgcolor="#FFFFFF">Update flags after Rn &#8211; shifer_opernad</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1011</td>
<td align="center" bgcolor="#FFFFFF">CMN</td>
<td align="left" bgcolor="#FFFFFF">Commom</td>
<td align="left" bgcolor="#FFFFFF">Update flags after Rn + shifer_opernad</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1100</td>
<td align="center" bgcolor="#FFFFFF">ORR</td>
<td align="left" bgcolor="#FFFFFF">Logical OR</td>
<td align="left" bgcolor="#FFFFFF">Rd = Rn OR shifter_operand</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1101</td>
<td align="center" bgcolor="#FFFFFF">MOV</td>
<td align="left" bgcolor="#FFFFFF">Move</td>
<td align="left" bgcolor="#FFFFFF">Rd = shifter_operand</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1110</td>
<td align="center" bgcolor="#FFFFFF">BIC</td>
<td align="left" bgcolor="#FFFFFF">Bit clear</td>
<td align="left" bgcolor="#FFFFFF">Rd = Rn AND NOT(shifter_operand)</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1111</td>
<td align="center" bgcolor="#FFFFFF">MVN</td>
<td align="left" bgcolor="#FFFFFF">Move Not</td>
<td align="left" bgcolor="#FFFFFF">Rd = NOT(shifter_operand)</td>
</tr>
</tbody>
</table>
<p><span style="text-decoration: underline">&lt; S &gt;</span><br />
S 비트가 1인 경우는 데이터 프로세싱 명령의 결과가 CPSR에 영향(Rd의 레지스터가 PC인 경우 SPSR의 값으로 CPSR을 복원)을 미칩니다. 즉, 0인 경우에는 CPSR은 변하지 않습니다.</p>
<p><span style="text-decoration: underline">&lt; Rn &gt;</span><br />
ARM 데이터 프로세싱 명령은 그 결과와 첫 번째 오퍼랜드는 항상 레지스터로 지정해야 합니다. Rn은 첫 번째 오퍼랜드를 가리키는 것으로 위에서 Op1으로 표기한 것에 해당합니다. ARM에서 한번에 볼 수 있는 범용 레지스터는 sp, lr, pc 등을 포함해서 r0~r15 까지입니다. 즉, 4bit를 통해 레지스터를 나타내게 됩니다. 해당 필드는 명령에 따라 사용되지 않기도 합니다. MOV나 MVN등이 이에 해당합니다.</p>
<p><span style="text-decoration: underline">&lt; Rd &gt;</span><br />
오퍼레이션의 결과가 저장될 레지스터를 의미합니다. 역시 레지스터를 가리키므로 4bit를 사용하고 모든 명령에서 디폴트로 사용되는 필드. ARM의 데이터 프로세싱 명령의 결과는 항상 레지스터로 들어갑니다.</p>
<p><span style="text-decoration: underline">&lt; Operand 2 &gt;</span><br />
Immediate Operand 혹은 레지스터 Operand 입니다. &lt;I&gt; 필드가 0일 경우 레지스터입니다.</p>
<p><span style="color: #ff6600">(2) Syntax : &lt;operation&gt;{cond}{s} Rd, Rn, operand2</span></p>
<p>·Operand2 is a register<br />
ADD R0, R1, R2</p>
<p>·Operand2 is immediate value<br />
BIC R1, R2, #0xFF</p>
<p>· Operand2 shifted value<br />
ADD R0, R1, R2, LSL #2<br />
SUB R0, R1, R2, LSR R3</p>
<p>·Data movement<br />
MOV R0, R1<br />
MOV R0, #0&#215;1</p>
<p>·Comparisons set flags only<br />
CMP R0, R1<br />
CMP R2, #0&#215;01</p>
<p><span style="color: #ff6600">(3) Immediate value</span></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14007.jpg" rel="lightbox[2515]"><img class="alignnone size-large wp-image-2690" alt="16FJK14007" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14007-620x64.jpg" width="620" height="64" /></a></td>
</tr>
</tbody>
</table>
<p>Immediate value(상수 값)= ROR immed_8 by 2*rot</p>
<p>MOV R0, #0xFF000000<br />
MOV R0, #0&#215;12<br />
MOV R0, #0&#215;104 ; 100000100 &#8211;&gt; permitted<br />
MOV R0, #0&#215;102 ; 100000010 &#8211;&gt; not permitted<br />
MOV R0, #0&#215;12345678 ; 10010001101000101011001111000 &#8211;&gt; not permitted</p>
<p>위의 예제에서 상수 값으로 &#8220;#0&#215;104&#8243;는 사용할 수 있는데 &#8220;#0&#215;102&#8243;, &#8220;#0&#215;12345678&#8243; 값으로 올 수 없는 이유는 무엇일까요?<br />
&#8220;ROR immed_8 by 2*rot&#8221; 의 수식을 잘 살펴 보시기 바랍니다. 어렵다구요? 네, 쉬운 계산이 아닐 수 있습니다.<br />
우선 &#8220;#0&#215;12345678&#8243; 값은 쉽게 판단이 될 것 같은데요. Rotate없이 표현 가능한 값의 범위가 8bit 를 넘었습니다.<br />
&#8220;#0&#215;102&#8243; 는 왜 안될까요? 쉽게 생각하면 8-bit immediate 값을 #rot 값을 2배 한만큼 오른쪽으로 로테이션을(ROR) 해서 Immediate value을 만들 수 있는 값을 반드시 상수로 사용해야 한다는 말입니다. 역시 말로는 잘 설명이 되지 않네요. 아래 그림들을 참조 하시기 바랍니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14006.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2689" alt="16FJK14006" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14006-620x367.jpg" width="502" height="297" /></a></td>
</tr>
</tbody>
</table>
<p>아래 Immediate value의 또 다른 예제 입니다.<br />
MOV r0, #0xfc000003 ; 11111100000000000000000000000011<br />
r0에 상수 값 0xfc000003을 넣는 명령입니다. 해당 값은 8bit 값 0xFF를 32bit로 확장하고 오른쪽으로 6번 Rotate 시킨 값입니다. 그래서 에러가 나지 않습니다.</p>
<p><span style="color: #ff6600">(4) 32-bit Instruction format</span><br />
MOV R0, #1</p>
<p>굉장히 단순한 예제인데요. 위에서 배운 32-bit Instructions 포맷을 분석해 보도록 하겠습니다. 코드를 Disassebly 해보면 &#8220;0xE3A00001(1110 001 1101 0 0000 0000 0000 00000001)&#8221; 입니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1426.jpg" rel="lightbox[2515]"><img class="alignnone size-full wp-image-2626" alt="16FJK1426" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1426.jpg" width="518" height="41" /></a></td>
</tr>
</tbody>
</table>
<p>Instruction 포맷을 다시 한번 살펴보면 아래와 같습니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14008.jpg" rel="lightbox[2515]"><img class="alignnone size-large wp-image-2691" alt="16FJK14008" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14008-620x59.jpg" width="620" height="59" /></a></td>
</tr>
</tbody>
</table>
[31:28] : 1110 &#8211; 7.11 Conditional Execution 에서 배울 예정입니다. 우선은 그냥 &#8220;1110&#8243; 은 Always execution flag 라고 알아 두시기 바랍니다.<br />
[27:25] : 001 &#8211; Operland 2로 지정되어 있는 부분이 Immediate Operand이므로 25번 비트가 &#8220;1&#8243; 입니다.<br />
[24:21] : 1101 &#8211; Opcode &#8220;MOV&#8221; 는 &#8220;1101&#8243; 입니다.<br />
[20] : 0 &#8211; 명령어 Opcode에 &#8220;S&#8221; 가 붙지 않았으므로 CPSR에 영향을 미치는 명령어는 아닙니다.<br />
[19:16] : 0000 &#8211; Rn 부분으로 레지스터 번호를 표현합니다. 만약 &#8220;MOV R2, #1&#8243; 였다면 Rn 이 &#8220;0000&#8243; 이 아니라 &#8220;0010&#8243; 일 것입니다.<br />
[15:12] : 0000 &#8211; Rd 부분이 없으므로 &#8220;0000&#8243; 입니다.<br />
[11:0] : 8bit Immediate value 로서 &#8220;#1&#8243; 에 해당하는 &#8220;00000001&#8243; 입니다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>*참고<br />
MOV R2, #1 명령에 대한 32-bit Instruction 포맷 =<br />
0xE3A02001(1110 001 1101 0 0000 0010 0000 00000001)</p>
</div>
<p><span style="color: #ff6600">(5) Examples</span></p>
<p><strong>R0 = 0&#215;00</strong></p>
<p>R1 = 0&#215;22<br />
R2 = 0&#215;02<br />
R3 = 0&#215;00<br />
R4 = 0&#215;00</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1427.jpg" rel="lightbox[2515]"><img class="alignnone size-full wp-image-2627" alt="16FJK1427" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1427.jpg" width="388" height="150" /></a></td>
</tr>
</tbody>
</table>
<p>레지스터의 값들이 위와 같을때 아래 예제들을 차례대로 수행 했을때의 각각의 레지스터 값은?</p>
<p><strong>AND R0, R0, #0xFF ; 0&#215;00 &amp; 0xff = R0의 값은 변환 없음</strong></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1430.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2630" alt="16FJK1430" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1430-300x81.jpg" width="300" height="81" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1427.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2627" alt="16FJK1427" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1427-300x115.jpg" width="300" height="115" /></a></td>
</tr>
</tbody>
</table>
<p><strong>ADD R0, R0, #1</strong> ; R0 = R0 + 1 = 0&#215;1</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1431.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2631" alt="16FJK1431" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1431-300x101.jpg" width="300" height="101" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1428.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2628" alt="16FJK1428" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1428-300x112.jpg" width="300" height="112" /></a>/td&gt;</td>
</tr>
</tbody>
</table>
<p><strong>ADD R0, R0, R1</strong> ; R0 = R0 + R1 = 0&#215;01 + 0&#215;22 = 0&#215;23</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1430.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2630" alt="16FJK1430" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1430-300x81.jpg" width="300" height="81" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1432.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2632" alt="16FJK1432" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1432-300x109.jpg" width="300" height="109" /></a></td>
</tr>
</tbody>
</table>
<p><strong>LSL R1, R0, #2</strong> ; 0&#215;23(100011) LSL #2 = 0x8C(10001100) -&gt; 참고로 왼쪽으로 2번 쉬프트 하면 *4 를 한것과 같습니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1433.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2633" alt="16FJK1433" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1433-300x67.jpg" width="300" height="67" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1434.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2634" alt="16FJK1434" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1434-300x107.jpg" width="300" height="107" /></a></td>
</tr>
</tbody>
</table>
<p><strong>SUB R3, R2, R1, LSR R2</strong><br />
R3의 값이 0xFFFFFFDF로 복잡한 값이 나왔습니다. 왜 이런 결과가 나왔을까요?<br />
우선 R1을 오른쪽으로 2번 쉬프트 시키면 0&#215;23이 되고 R2(0&#215;02) 에서 R1(0&#215;23) 을 빼면 결과 값이 -0&#215;21가 되고 이 값을 2의 보수로 표시하면 0xFFFFFFDF 가 됩니다.</p>
<p>0&#215;21 = 00000000000000000000000000100001<br />
- 0&#215;21 = 11111111111111111111111111011111<br />
&#8211;&gt; 0&#215;21의 2의 보수</p>
<p>참고로 2의 보수를 취하는 방법은 원래의 2진수에서 0-&gt;1, 1-&gt;0 으로 바꾼 후에 1을 더하면 되겠지요.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1435.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2635" alt="16FJK1435" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1435-300x55.jpg" width="300" height="55" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1436.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2636" alt="16FJK1436" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1436-300x109.jpg" width="300" height="109" /></a></td>
</tr>
</tbody>
</table>
<p><strong>BIC R0, R1, #0xFF00</strong></p>
<p>R1(0x8C) = 0000000010001100</p>
<p>0xFF00(65280) = 1111111100000000</p>
<p>BIC = 0000000010001100 ; 0xFF00 로 bit clear를 해도 R1의 값은 변화가 없네요.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1437.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2637" alt="16FJK1437" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1437-300x74.jpg" width="300" height="74" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1438.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2638" alt="16FJK1438" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1438-300x110.jpg" width="300" height="110" /></a></td>
</tr>
</tbody>
</table>
<p><strong>RSB R0, R1, #0</strong> ; #0 &#8211; R1(0x8C) = 0xFFFFFF74(0x8C 의 2의 보수 값)<br />
RSB 명령어는 SUB와는 반대로 마이너스 연산을 수행합니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1439.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2639" alt="16FJK1439" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1439-300x65.jpg" width="300" height="65" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1440.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2640" alt="16FJK1440" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1440-300x112.jpg" width="300" height="112" /></a></td>
</tr>
</tbody>
</table>
<p><span style="color: #ff0000"><strong>7.4 Multiply Instructions</strong></span><a id="1342322528232" name="7.4"></a></p>
<p><span style="color: #ff6600">(1)Multiply (Accumulate) Syntax</span><br />
MUL{&lt;cond&gt;}{S} Rd, Rm, Rs ; Rd = Rm * Rs<br />
MUA{&lt;cond&gt;}{S} Rd, Rm, Rs, Rn ; Rd = (Rm * Rs) + Rn</p>
<p><span style="color: #ff6600">(2) Examples</span><br />
<strong>R0 = 0&#215;01</strong><br />
<strong>R1 = 0&#215;02</strong><br />
<strong>R2 = 0&#215;03</strong><br />
<strong>R3 = 0&#215;04</strong><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1441.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2641" alt="16FJK1441" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1441-300x111.jpg" width="300" height="111" /></a></p>
<p>레지스터의 값들이 위와 같을 때 아래 예제들을 차례대로 수행했을 때의 각각의 레지스터 값은?</p>
<p><strong>MUL R2, R0, R1</strong> ; R2 = R0*R1 = 0&#215;02</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1443.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2643" alt="16FJK1443" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1443-300x109.jpg" width="300" height="109" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1442.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2642" alt="16FJK1442" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1442-300x64.jpg" width="300" height="64" /></a></td>
</tr>
</tbody>
</table>
<p><strong>MULS R2, R0, R1</strong> ; R2 = R0*R1 = 0&#215;02<br />
MUL 명령과 같은 명령입니다. 하지만 MUL뒤에 &#8220;S&#8221; 가 붙으면 명령어 처리가 끝난 이후에 CPSR의 Flag Field 가 연산 결과에 따라서 업데이트가 됩니다.<br />
자세한 사항은 7.11 Conditional Execution 에서 자세히 다루도록 하겠습니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1443.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2643" alt="16FJK1443" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1443-300x109.jpg" width="300" height="109" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1444.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2644" alt="16FJK1444" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1444-300x76.jpg" width="300" height="76" /></a></td>
</tr>
</tbody>
</table>
<p><strong>MLA R3, R2, R1, R0</strong> ; R3 = R2*R1 + R0</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1446.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2646" alt="16FJK1446" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1446-300x110.jpg" width="300" height="110" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1445.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2645" alt="16FJK1445" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1445-300x82.jpg" width="300" height="82" /></a></td>
</tr>
</tbody>
</table>
<p>참 효율적이네요. 명령어 하나로 곱하기 연산과 더하기 연산을 같이 할 수 있습니다.</p>
<p><strong>SMULL R3, R2, R1, R0</strong> ; R3,R2 = R1*R0</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1447.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2647" alt="16FJK1447" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1447-300x109.jpg" width="300" height="109" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1448.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2648" alt="16FJK1448" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1448-300x93.jpg" width="300" height="93" /></a></td>
</tr>
</tbody>
</table>
<p>부호있는 64비트 곱셈 명령어 입니다. R1*R0 하여 상위 32비트는 R2에 하위 32비트는 R3에 저장합니다.<br />
위에서 부호있는 연산이 나왔는데, 좀더 복잡한 예제를 풀어 보도록 하겠습니다.</p>
<p><strong>R0 = 0xF0000002</strong><br />
<strong>R1 = 0&#215;02</strong><br />
<strong>R2 = 0&#215;00</strong><br />
<strong>R3 = 0&#215;00</strong></p>
<p>초기 레지스터의 값이 위와 같을때 SMULL 연산 이후의 R2, R3 의 값은 어떻게 될까요?<br />
우선 0xF0000002가 음수이기 때문에 연산을 하기 위해서는 2의 보수값(F0000002의 2의 보수 = 0xFFFFFFE)을 먼저 취합니다. 그리고 나서 0xFFFFFFE * 0&#215;02 = 0x1FFFFFFC 를 합니다. 연산이 끝나고 나서 음수를 표현하기 위해서 다시 0x1FFFFFFC 의 2의 보수를 취합니다. 이때 SMULL이 64비트 곱셈 명령어이므로 64비트로 확장합니다. 이렇게 하면 상위 32비트는 0xFFFFFFFF 이고 하위 32비트는 0&#215;04가 됩니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1449.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2649" alt="16FJK1449" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1449-300x112.jpg" width="300" height="112" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1450.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2650" alt="16FJK1450" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1450-300x67.jpg" width="300" height="67" /></a></td>
</tr>
</tbody>
</table>
<p>위의 그림에서 &#8220;MOV R0, #-268435454&#8243; 라고 R0를 초기화하고 있습니다. 이것은 0xf0000002의 값이 음수(최상위 비트가 1이면 음수이죠)이기 때문에 컴파일러에서 알기 쉽도록 음수 10진수로 표현을 해준 것입니다.</p>
<p><span style="color: #ff0000"><strong>7.5 Load/Store Instructions</strong></span><a id="134232252824" name="7.5"></a></p>
<p>Memory의 내용을 레지스터로 이동(Load)하거나 레지스터의 내용을 메모리에 저장(Store) 하는 명령어입니다. 데이터 Access단위에 따라서 아래와 같이 분류됩니다. Load, Store는 ARM 명령어 가운데 가장 많이 사용되는 명령어이며 굉장히 중요합니다. 반드시 숙지 하고 있어야 합니다.<br />
- Word : LDR, STR<br />
- Byte : LDRB, STRB<br />
- Halfword : LDRH, STRH<br />
- Signed byte : LDRSB<br />
- Signed halfword : LDRSH</p>
<p><span style="color: #ff6600">(1) Syntax</span><br />
LDR{cond}{size} Rd, &lt;address&gt;<br />
STR{cond}{size} Rd, &lt;address&gt;</p>
<p><span style="color: #ff6600">(2) Addressing Mode</span><br />
- Pre Index : Rd 레지스터에 데이터를 먼저 이동시킨 후 &lt;address&gt; offset을 증가 혹은 감소합니다.<br />
<strong>R0 = 0&#215;31000000</strong><br />
<strong>R1 = 0&#215;00</strong><br />
<strong>R2 = 0&#215;00</strong></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1461.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2661" alt="16FJK1461" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1461-300x112.jpg" width="300" height="112" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1450.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2650" alt="16FJK1450" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1450-300x67.jpg" width="300" height="67" /></a></td>
</tr>
</tbody>
</table>
<p>레지스터의 값들과 메모리(메모리 배열은 리틀 엔디언) 값이 위와 같을 때 아래 예제들을 차례대로 수행했을 때의 각각의 레지스터와 메모리의 값은?</p>
<p><strong>LDR R1, [R0]</strong> ; R1 &lt;&#8211; M[R0]
<p>R0가 가르키고 있는 0&#215;31000000 번지의 메모리 값은 0&#215;67452301 입니다. 그러므로 LDR 연산 이후에 R1에는 0&#215;67452301 값이 저장됩니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1454.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2654" alt="16FJK1454" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1454-300x107.jpg" width="300" height="107" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1453.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2653" alt="16FJK1453" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1453-300x51.jpg" width="300" height="51" /></a></td>
</tr>
</tbody>
</table>
<p><strong>STR R1, [R0, #4]</strong> ; R1 &lt;&#8211; M[R0+4]
R0가 가르키는 0&#215;31000000 번지에서 4-byte 를 더한 번지의 메모리 위치에 R1(0&#215;67452301) 값을 저장합니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1456.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2656" alt="16FJK1456" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1456-300x93.jpg" width="300" height="93" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1455.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2655" alt="16FJK1455" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1455-300x66.jpg" width="300" height="66" /></a></td>
</tr>
</tbody>
</table>
<p><strong>STR R1, [R0, #4]!</strong> ; R1 &lt;&#8211; M[R0+4], then R0 &lt;&#8211; R0+4</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1458.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2658" alt="16FJK1458" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1458-300x111.jpg" width="300" height="111" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1459.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2659" alt="16FJK1459" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1459-300x93.jpg" width="300" height="93" /></a></td>
</tr>
</tbody>
</table>
<p>R1에 0&#215;31000004번지의 메모리 내용 0&#215;67452301을 저장하고 난 이후에 R0의 레지스터값 + 0&#215;04 를 수행합니다.</p>
<p>예제에서 0&#215;30000000, 0&#215;30000004 번지의 내용이 동일해서 혼동될 수도 있지만 R1에는 R0레지스터값 + 0&#215;04 = 0&#215;30000004 번지의 값이 저장이 된다는 것을 기억하시기 바랍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1463.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2663" alt="16FJK1463" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1463-300x66.jpg" width="300" height="66" /></a></p>
<p>- Post Index: Offset calculation after data transfer</p>
<p><strong>R0 = 0&#215;31000000</strong><br />
<strong>R1 = 0&#215;00</strong><br />
<strong>R2 = 0&#215;04</strong></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1461.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2661" alt="16FJK1461" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1461-300x112.jpg" width="300" height="112" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1452.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2652" alt="16FJK1452" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1452-300x140.jpg" width="300" height="140" /></a></td>
</tr>
</tbody>
</table>
<p>레지스터의 값들과 메모리(메모리 배열은 리틀 엔디언) 값이 위와 같을 때 아래 예제들을 차례대로 수행했을 때의 각각의 레지스터와 메모리의 값은?</p>
<p><strong>LDR R1, [R0], R2</strong> ; R1 &lt;&#8211; M[R0], then R0 &lt;&#8211; R0+R2</p>
<p>R1에 R0가 가르키는 0&#215;31000000번지의 메모리값 0&#215;67452301의 값을 저장하고 나서 R0 = R0(0&#215;31000000) + R2(0&#215;04)가 됩니다. Preindex 방식에서는 R0를 먼저 계산하고 나서 메모리 번지의 값을 R1에 저장하였으나 Postindex 방식에서는 순서가 반대가 됩니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1462.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2662" alt="16FJK1462" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1462-300x113.jpg" width="300" height="113" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1460.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2660" alt="16FJK1460" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1460-300x57.jpg" width="300" height="57" /></a></td>
</tr>
</tbody>
</table>
<p><strong>STR R1, [R0], #4</strong> ; R1 &lt;&#8211; M[R0], then R0 &lt;&#8211; R0+4</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1464.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2664" alt="16FJK1464" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1464-300x110.jpg" width="300" height="110" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1456.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2656" alt="16FJK1456" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1456-300x93.jpg" width="300" height="93" /></a></td>
</tr>
</tbody>
</table>
<p>레지스터 R1의 값 0&#215;67452301을 메모리 0&#215;31000004 번지에 저장을 하고난 이후에 R0 = R0(0&#215;310000004) + 0&#215;04 를 수행합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1457.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2657" alt="16FJK1457" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1457-300x77.jpg" width="300" height="77" /></a></p>
<p><span style="color: #ff6600">(3) Literal Pool</span><br />
32bit의 모든 값을 가질 수 없고 12bit를 가지고 일정 형식에 맞추어서 사용해야 합니다. Immediate value 에서 자세히 설명했던 내용입니다.</p>
<p><strong>MOV R0, #0&#215;12345678</strong> ; illegal (build error)<br />
<strong>LDR R0, =0&#215;12345678</strong> ; legal (build success)<br />
<strong>MOV R0, #0&#215;104</strong> ; legal<br />
<strong>MOV R0, #0&#215;102</strong> ; illegal</p>
<p>위의 예제에서 0&#215;12345678 값을 LDR 명령어를 사용하면 제약 없이 사용이 가능한 것을 알 수 있습니다. LDR 명령어를 사용하는 것이 편해보이기는 하지만 메모리에 접근하기 때문에 속도는 많이 느려지겠지요..</p>
<p><span style="color: #ff0000"><strong>7.6 Load/Store Multiple Instructions</strong></span><a id="1342322528242" name="7.6"></a></p>
<p>LDR, STR 명령어와 기능은 동일 하지만 Rn레지스터 값이 가르키는 메모리 위치에 여러 개 레지스터 값들을 저장할 수 있습니다.</p>
<p><span style="color: #ff6600">(1) Syntax</span><br />
LDM{cond}{addr_mode} Rn{!}, &lt;register_list&gt;{^}<br />
STM{cond}{addr_mode} Rn{!}, &lt;register_list&gt;{^}</p>
<p><span style="color: #ff6600">(2) Addressing Mode</span><br />
- IA : increment after<br />
- IB : increment before<br />
- DA : decrement after<br />
- DB : decrement before</p>
<p><span style="color: #ff6600">(3) Examples</span><br />
-레지스터 값들</p>
<p><strong>R0 = 0x000A</strong><br />
<strong>R4 = 0x000B</strong><br />
<strong>R5 = 0x000C</strong><br />
<strong>R13 = 0xFFF0</strong></p>
<p>STMIA R13!, {R0,R4-R5} 연산의 결과는?<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14013.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2694" alt="16FJK14013" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14013-300x138.jpg" width="300" height="138" /></a></p>
<p>STMIB R13!, {R0,R4-R5} 연산의 결과는?<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14014.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2695" alt="16FJK14014" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14014-300x140.jpg" width="300" height="140" /></a></p>
<p>STMDA R13!, {R0,R4-R5} 연산의 결과는?<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14015.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2696" alt="16FJK14015" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14015-300x138.jpg" width="300" height="138" /></a></p>
<p>STMDB R13!, {R0,R4-R5} 연산의 결과는?<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14016.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2697" alt="16FJK14016" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14016-300x141.jpg" width="300" height="141" /></a></p>
<p>참고로 ARM Compiler는 Stack 동작시 Full Descending Stack 방식으로 동작하고 있습니다. STMDA 명령어와 동일한 방식입니다. 즉 Stack Pointer는 항상 유효한 데이터를 가르키고 있고 주소가 감소하는 방향으로 저장이 됩니다.</p>
<p>- Stack에서 PUSH, STMDB 대신에 아래와 같이 사용이 가능합니다.<br />
STMFD SP!, {R4-R12, LR}</p>
<p>- Stack에서 POP, LDMIA 대신에 아래와 같이 사용이 가능합니다.<br />
LDMFD SP!, {R4-R12, PC}<br />
LDMFD SP!, {R0-R12, PC}^</p>
<p>&#8220;^&#8221; 연산자는 목적지의 레지스터(Rd)가 PC인 경우에 SPSR을 CPSR로 복구까지 하라는 명령입니다.</p>
<p><span style="color: #ff0000"><strong>7.7 Branch Instructions</strong></span><a id="1342322528243" name="7.7"></a></p>
<p>혹시 서브 함수와 서브 프로시져의 차이점을 알고 있나요? 2가지 모두 메인 프로그램 흐름에서 벗어(분기하여)나 특정 작업을 수행하는 것은 동일합니다. 하지만 엄밀하게 차이점을 이야기하면 서브 프로시져는 분기 이후에 분기하기 이전의 흐름으로 되돌아 오지 않고 분기한 주소에서부터 프로그램 수행이 계속될 경우에 사용을 하고 서브 함수는 분기한 주소에서 특정 작업을 수행하다가 분기 이전의 주소로 복귀하여 프로그램을 수행하도록 합니다. 설명이 길어 졌네요. 그림을 통해서 차이점을 구분해 보도록 합시다.</p>
<p><span style="text-decoration: underline">서브 프로시져 호출 시 프로그램 흐름</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14017.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2698" alt="16FJK14017" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14017-300x165.jpg" width="300" height="165" /></a></p>
<p><span style="text-decoration: underline">서브 함수 호출 시 프로그램 흐름</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14018.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2699" alt="16FJK14018" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14018-300x166.jpg" width="300" height="166" /></a></p>
<p><span style="color: #ff6600">(1) Syntax</span><br />
B{L}{cond} &lt;target_addr&gt;<br />
target_addr &lt;&#8211; pc + SignExtended(immed_24)&lt;&lt;2<br />
·여기서 PC는 Pipeline 에서 설명했듯이 Branch Instruction의 주소에서 8을 더한 위치가 됩니다.</p>
<p><span style="color: #ff6600">(2) Branch Range</span><br />
-32MB ~ +32MB<br />
분기 범위가 +- 32MB 까지로 제한이 되는 이유는 2^24 = 16MB &lt;&lt; 2를 하면 64MB이고 이를 +- 로 하면 32MB까지가 되는 것입니다.</p>
<p><span style="color: #ff6600">(3) Examples</span><br />
<strong>B Label</strong><br />
<strong>MOV PC, #0</strong><br />
<strong>MOV PC, LR</strong><br />
레지스터 R15(PC) 에 직접 분기할 주소를 저장하여도 분기가 가능합니다.<br />
<strong>LDR PC, =func</strong><br />
참고로 LDR 명령어를 사용하면 Branch명령어를 사용했을 때보다 1가지 잇점이 있는데 4GB이내에서는 어디든지 분기가 가능하다는 것입니다. Branch 명령어의 분기 range는 -32MB ~ +32MB의 제약이 있습니다. 물론 메모리에서 주소를 읽어와야 하므로 성능면에서는 좋지 않겠지요.</p>
<p><span style="color: #ff6600">(4) 함수 호출(BL)</span><br />
- 함수 호출시<br />
BL func &#8211;&gt; B 명령어와 다른 점은 LR레지스터에 PC-4 의 Address값이 H/W적으로 저장이 됩니다.<br />
- ARM 모드 함수 종료시<br />
MOV PC, LR &#8211;&gt; LR 에는 이미 BL 명령어의 주소 +4 의 값이 저장이 되어 있어 BL 명령어 다음부터 명령을 수행할 수 있도록 합니다.<br />
- Thumb 모드 함수 종료시<br />
BX LR</p>
<p><span style="color: #ff6600">(5) Subsequent Function Calls</span><br />
함수안에서 함수를 다시 호출을 하면 어떤 일이 발생할까요. 예제 코드를 가지고 분석해 보도록 하겠습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14019.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2700" alt="16FJK140" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14019-300x115.jpg" width="300" height="115" /></a></p>
<p>위의 예제에서 서브함수를 호출하고난 이후에 main 루틴에 있는 R2에는 #3이 저장이 되어있어야 합니다. 언뜻 보기에 #11이 저장이 되어있을 것 같습니다.</p>
<p>R0, R1은 func1에서 각각 #3, #4 가 저장이 되고 func2를 거치면서 #5, #6이 저장이 됩니다. 그래서 #11이 될 것이라고 예상이 될 수 있지만 사실은 func1의 ADD 명령어만 반복해서 실행이 될 것입니다. 왜냐하면 main에서 func1으로 branch할때까지는 LR에는 BL명령어 Address+4 가 저장이 되고 func1에서 func2로 분기할 때 다시 LR에는 func2로 분기하는 BL명령어 Address+4가 저장이 되어 최종 func2에서 MOV PC, LR 을 실행하면 func1의 ADD 명령어로 PC가 이동을 하고 다시 func1에서 MOV PC, LR 이 실행되면 LR 값에 의해서 다시 func1의 ADD 명령어가 반복해서 실행이 될 것입니다. 조금 복잡한듯 하지만 잘 따라가 보면 알 수 있습니다. 이 예제에서 알 수있는 것은 서브함수를 호출할 경우에는 서브함수 내에서 반드시 LR과 서브함수에서 사용할 레지스터들을 Stack에 백업을 하고 서브함수에서 복귀전에 다시 Stack에서 복원을 해야 한다는 것을 알 수 있습니다. 그러면 위의 예제를 main 루틴에 있는 R2에 #3이 저장이 되도록 수정을 하면 어떻게 될까요?</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1466.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2666" alt="16FJK1466" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1466.jpg" width="370" height="299" /></a></p>
<p>위의 그림에서 MOV SP, #98304 를 하는 이유는 Stack을 사용하기 위해서 Supervisor 모드의 Stack 포인터를 초기화하는 것입니다. 참고로 Stack 포인터의 주소는 실제 타겟마다 다를 수 있습니다. Stack 포인터는 주로 시스템의 주 메모리에 위치합니다.</p>
<p><span style="color: #ff6600">(7) Veneer</span><br />
베니어라는 용어가 나오네요. 혹시 베니어 합판이라는 말을 들어 보셨나요? 작은 나무 조각들을 겹겹이 붙여서 만든 합판입니다. 여기 나오는 Veneer라는 개념이 흡사 베니어 합판을 만드는 것과 유사한 것 같습니다. 사실 Veneer라는 것은 ARM의 특성은 아니고 컴파일러에서 지원하는 기능입니다. 원래 B, BL 등의 분기 명령어는 -32MB~32MB 범위내에서 분기가 가능하다고 하였습니다. 하지만 아래 그림과 같이 MyFunc2을 호출할 때 컴파일러에서 자동으로 Veneer라는 중간 분기점을 만들어서 32MB 범위를 벗어나도 서브 함수를 호출 가능하도록 만들어 줍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1424.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2624" alt="16FJK1424" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1424-300x69.jpg" width="300" height="69" /></a></p>
<p>위의 기능 이외에도 추가로 아래와 같은 기능이 있습니다.</p>
<p>- ARM to ARM or Thumb to Thumb 으로 분기<br />
: Long branch capability<br />
- ARM to Thumb or Thumb to ARM 으로 분기<br />
: Long branch capability and interworking capability</p>
<p><span style="color: #ff0000"><strong>7.8 Status Register Access Instructions</strong></span><a id="1342322528244" name="7.8"></a></p>
<p><span style="color: #ff6600">(1) Syntax</span><br />
MRS{cond} Rd, CPSR ; CPSR의 값을 Rd 레지스터로 읽어 옵니다.<br />
MRS{cond} Rd, SPSR ; SPSR의 값을 Rd 레지스터로 읽어 옵니다.<br />
MSR{cond} CPSR_&lt;fields&gt;, #&lt;immediate&gt;<br />
MSR{cond} CPSR_&lt;fields&gt;, &lt;Rm&gt; ; Rm 레지스터의 값을 CPSR에 저장합니다.<br />
MSR{cond} SPSR_&lt;fields&gt;, #&lt;immediate&gt;<br />
MSR{cond} SPSR_&lt;fields&gt;, &lt;Rm&gt; ; Rm 레지스터의 값을 SPSR에 저장합니다.<br />
이전에도 설명했지만 CPSR 레지스터의 구조를 다시 한번 확인 바랍니다.</p>
<p><span style="color: #ff6600">(2) Examples</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14020.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2701" alt="16FJK14020" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14020-300x185.jpg" width="300" height="185" /></a><br />
- IRQ 를 Enable 하는 코드 입니다.<br />
아래 명령어들이 수행되는 동안의 CPSR레지스터의 변화 값을 확인해보시기 바랍니다.</p>
<p><strong>MRS R0, CPSR</strong><br />
<strong>BIC R0, R0, #0&#215;80</strong> ; 7번 비트를 clear 하면 인터럽트가 활성화 됩니다.<br />
<strong>MSR CPSR, R0</strong></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1468.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2668" alt="16FJK1468" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1468-300x164.jpg" width="300" height="164" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1467.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2667" alt="16FJK1467" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1467-300x44.jpg" width="300" height="44" /></a></td>
</tr>
</tbody>
</table>
<p>BIC, MSR 명령에 의해서 CPSR의 I 가 &#8220;0&#8243; 으로 변경(Unmask) 되어 Interrupt가 가능하게 되었습니다. 참고로 CPSR_fc 와 CPSR은 같은 레지스터입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1469.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2669" alt="16FJK1469" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1469-300x165.jpg" width="300" height="165" /></a></p>
<p>- IRQ를 Disable 하는 코드 입니다.</p>
<p><strong>MRS R0, CPSR</strong><br />
<strong>ORR R0, R0, #0&#215;80</strong> ; 7번 비트를 set 하면 인터럽트를 사용할 수 없습니다.<br />
<strong>MSR CPSR, R0</strong></p>
<p>간혹 MSR_c, MRS_x 등으로 사용되는 예제들이 있는데 밑줄 다음에 오는 flag의 의미는 아래와 같습니다. 그리고 밑줄 다음의 _c, _x 등은 의미를 명확하게 하기 위해서 사용하는 것일뿐 생략해도 아무 문제가 되지는 않습니다.</p>
<p>c = PSR[7:0]
x = PSR[15:8]
s = PSR[23:16]
F = PSR[31:24]
<span style="color: #ff0000"><strong>7.9 Software Interrupt Instruction</strong></span><a id="1342322528245" name="7.9"></a></p>
<p><span style="color: #ff6600">(1) Syntax</span><br />
SWI{cond} &lt;immed_24&gt;<br />
SEI 명령어는 S/W 적으로 강제적으로 ARM에 IRQ 예외를 발생 시킵니다. 주로 OS에서 User application들이 운영체제 서비스 루틴을 호출할 경우에 특권모드에서 콜하기 위해서 많이 사용됩니다.</p>
<p><span style="color: #ff6600">(2) Examples</span><br />
SWI #0&#215;123456</p>
<p><span style="color: #ff0000"><strong>7.10 SWP Instruction</strong></span><a id="1342322528246" name="7.10"></a></p>
<p><span style="color: #ff6600">(1) Syntax</span><br />
SWP{cond}{B} Rd, Rm, [Rn]
<p><span style="color: #ff6600">(2) Operation</span><br />
Temp &lt;&#8211; [Rn]
[Rn] &lt;&#8211; Rm<br />
Rd &lt;&#8211; Temp</p>
<p><span style="color: #ff6600">(3) Semaphore Instruction</span><br />
명령어 수행중에 인터럽트없이 메모리의 Read, Write 를 할 수 있는 Atomic 동작을 할 수 있습니다. Atomic이라는 용어가 나오는데요, 이것은 어떤 동작을 1개의 오퍼레이션으로 완료하는 것을 의미합니다. 즉 Atomic 오퍼레이션이 수행되는 동안에는 인터럽트가 발생하지 않는 것입니다.</p>
<p><span style="color: #ff6600">(4) Examples</span><br />
<strong>R0 = 0&#215;01</strong><br />
<strong>R1 = 0&#215;02</strong><br />
<strong>R2 = 0&#215;31000000</strong></p>
<p>&nbsp;</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1470.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2670" alt="16FJK1470" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1470-300x158.jpg" width="300" height="158" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1472.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2672" alt="16FJK1472" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1472-300x152.jpg" width="300" height="152" /></a></td>
</tr>
</tbody>
</table>
<p>레지스터의 값들이 위와 같을 때 아래 예제들을 차례대로 수행했을 때의 각각의 레지스터 값은?</p>
<p><strong>SWP R0, R1, [R2]</strong><br />
R2 가 가르키는 주소(0&#215;31000000)의 값 0&#215;78563412의 값이 R0에 저장이 되었고,</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1474.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2674" alt="16FJK1474" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1474-300x154.jpg" width="300" height="154" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1471.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2671" alt="16FJK1471" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1471-300x64.jpg" width="300" height="64" /></a></td>
</tr>
</tbody>
</table>
<p>R1의 값 0&#215;02가 R2가 가르키는 0&#215;31000000 메모리에 저장이 되었습니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1473.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2673" alt="16FJK1473" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1473-300x142.jpg" width="300" height="142" /></a></p>
<p>아래의 예는 바이트 명령어입니다. SWPB 명령어를 사용했을 경우 R0 에는 어떤 값이 저장이 될까요?<br />
<strong>SWPB R0, R1, [R2]</strong></p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1477.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2677" alt="16FJK1477" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1477-300x155.jpg" width="168" height="87" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1475.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2675" alt="16FJK1475" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1475-300x55.jpg" width="300" height="55" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1476.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2676" alt="16FJK1476" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1476.jpg" width="164" height="82" /></a></td>
</tr>
</tbody>
</table>
<p>동작은 SWP와 동일하고 단지 바이트 단위로 SWP가 된다는 것만 다릅니다. 위의 그림들을 참조 하시기 바랍니다.</p>
<p><span style="color: #ff0000"><strong>7.11 Conditional Execution</strong></span><a id="1342322528247" name="7.11"></a></p>
<p>ARM모드 에서 굉장히 강력한 기능으로 명령어들을 특정 조건이 만족했을 때에만 실행시킬 수 있습니다. 이렇게 조건부 실행이 가능하면 성능면에서 아래와 같은 잇점이 있습니다.</p>
<p>- Increase code density<br />
- Decrease the number of branches</p>
<p>Thumb모드에서는 분기명령어 이외에는 이 조건부 실행 기능을 사용할 수 없습니다. 그 이유는 명령어의 길이가 Thumb 모드에서는 16bit로 제한이 되어서 조건부 실행을 할만큼 레지스터 공간이 충분하지 못하기 때문입니다. 그러면 실행 가능한 조건이라는 것은 어떤것들이 있을까요?<br />
ARM명령어 설명할 때 맨처음에 나왔던 그림인데요. 아래 그림을 보고 실행 조건에 대해서 설명하도록 하겠습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14008.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2691" alt="16FJK14008" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14008-620x59.jpg" width="558" height="53" /></a></p>
<p><span style="text-decoration: underline">&lt; Cond &gt;</span></p>
<p>해당 명령의 조건 실행 플래그입니다. 데이터 프로세싱 명령어에도 당연히 포함됩니다. 해당 플래그를 통해 명령을 현재 플래그 레지스터(CPSR)의 상태에 따라 실행 여부를 결정하는데 사용되는 플래그입니다.<br />
ARM 명령어의 길이는 32bit라고 하였습니다. 32bit 중에서 4bit를 조건부 실행을 하는데 할당하고 있습니다. [31:28] bit가 바로 &lt;Cond&gt; 비트입니다.<br />
그리고 &lt;Cond&gt; 필드에 올 수 있는 것들은 아래 표와 같습니다.</p>
<table style="width: 550px" border="1" cellspacing="0" cellpadding="8">
<tbody>
<tr>
<td align="center" bgcolor="#FF6600" height="39">Cond</td>
<td align="center" bgcolor="#FF6600" height="39">Mnemonic</td>
<td align="center" bgcolor="#FF6600">Meaning</td>
<td align="center" bgcolor="#FF6600">Condition flag state</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF" width="69">0000</td>
<td align="center" bgcolor="#FFFFFF" width="107">EQ</td>
<td align="left" bgcolor="#FFFFFF" width="190">Equal</td>
<td align="left" bgcolor="#FFFFFF" width="444">Z = 1</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0001</td>
<td align="center" bgcolor="#FFFFFF">NE</td>
<td align="left" bgcolor="#FFFFFF">Not Equal</td>
<td align="left" bgcolor="#FFFFFF">Z = 0</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0010</td>
<td align="center" bgcolor="#FFFFFF">CS/HS</td>
<td align="left" bgcolor="#FFFFFF">Carry set / unsigned &gt;=</td>
<td align="left" bgcolor="#FFFFFF">C = 1</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0011</td>
<td align="center" bgcolor="#FFFFFF">CC/LO</td>
<td align="left" bgcolor="#FFFFFF">Carry clear / unsigned &lt;</td>
<td align="left" bgcolor="#FFFFFF">C = 0</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0100</td>
<td align="center" bgcolor="#FFFFFF">MI</td>
<td align="left" bgcolor="#FFFFFF">Minus/Negative</td>
<td align="left" bgcolor="#FFFFFF">N = 1</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0101</td>
<td align="center" bgcolor="#FFFFFF">PL</td>
<td align="left" bgcolor="#FFFFFF">Plus/Positive or Zero</td>
<td align="left" bgcolor="#FFFFFF">N = 0</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0110</td>
<td align="center" bgcolor="#FFFFFF">VS</td>
<td align="left" bgcolor="#FFFFFF">Overflow</td>
<td align="left" bgcolor="#FFFFFF">O = 1</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">0111</td>
<td align="center" bgcolor="#FFFFFF">VC</td>
<td align="left" bgcolor="#FFFFFF">No overflow</td>
<td align="left" bgcolor="#FFFFFF">O = 0</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1000</td>
<td align="center" bgcolor="#FFFFFF">HI</td>
<td align="left" bgcolor="#FFFFFF">Unsigned higher</td>
<td align="left" bgcolor="#FFFFFF">C = 1 &amp; Z = 0</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1001</td>
<td align="center" bgcolor="#FFFFFF">LS</td>
<td align="left" bgcolor="#FFFFFF">Unsigned lower or same</td>
<td align="left" bgcolor="#FFFFFF">C = 0 | Z = 1</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1010</td>
<td align="center" bgcolor="#FFFFFF">GE</td>
<td align="left" bgcolor="#FFFFFF">Signed &gt;=</td>
<td align="left" bgcolor="#FFFFFF">N == V</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1011</td>
<td align="center" bgcolor="#FFFFFF">LT</td>
<td align="left" bgcolor="#FFFFFF">Signed &lt;</td>
<td align="left" bgcolor="#FFFFFF">N != V</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1100</td>
<td align="center" bgcolor="#FFFFFF">GT</td>
<td align="left" bgcolor="#FFFFFF">Signed &gt;</td>
<td align="left" bgcolor="#FFFFFF">Z == 0, N == V</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1101</td>
<td align="center" bgcolor="#FFFFFF">LE</td>
<td align="left" bgcolor="#FFFFFF">Signed &lt;=</td>
<td align="left" bgcolor="#FFFFFF">Z == 1 or N! = V</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1110</td>
<td align="center" bgcolor="#FFFFFF">AL</td>
<td align="left" bgcolor="#FFFFFF">Always</td>
<td align="left" bgcolor="#FFFFFF"></td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">1111</td>
<td align="center" bgcolor="#FFFFFF">(NV)</td>
<td align="left" bgcolor="#FFFFFF">Unpredictable</td>
<td align="left" bgcolor="#FFFFFF"></td>
</tr>
</tbody>
</table>
<p>참고로 우리가 지금까지 사용해왔던 MOV, ADD 명령어 뒤에 Mnemonic 없이 사용을 하면 &#8220;Always&#8221; 가 적용되어서 실행이 된 것입니다.</p>
<p><span style="color: #ff6600">(1) Condition Flag Change</span><br />
Condition Flag변경은 Data Processing Instructions에 의해서만 영향을 받으면 명령어 뒤에 &#8220;S&#8221; Prefix를 사용해야만 합니다.<br />
Condition Flag는 CPSR레지스터의 [31:24] 비트 필드에 정의되어 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14012.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2693" alt="16FJK14012" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14012-620x382.jpg" width="446" height="275" /></a></p>
<p>설명이 조금 복잡한가요. 예제를 통해서 살펴 보도록 합시다.</p>
<p><span style="color: #ff6600">(1) Examples1</span><br />
NZCV 플래그가 변화하는 예제들입니다. 여기서 N(Negative), Z(Zero result)까지는 명확한 것 같은데 Carry, Overflower는 어떻게 다른 것일까요?<br />
아래 예제들을 수행하면서 차이점을 비교해보시기 바랍니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1484.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2684" alt="16FJK1484" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1484-300x148.jpg" width="300" height="148" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1481.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2681" alt="16FJK1481" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1481-300x37.jpg" width="300" height="37" /></a></td>
</tr>
</tbody>
</table>
<p>· N : 연산의 결과 R2(0&#215;40000000)의 최상위 비트가 &#8220;1&#8243; 이 아님<br />
· Z : 연산의 결과 R2가 0&#215;0 이 아님<br />
· C : 32-bit 를 넘어섰으므로 Carry가 발생<br />
· V : ARM에서 Overflow 를 검출하는 방식은 MSB 이전 비트에서 발생한 Carry(&#8220;0&#8243; 과 &#8220;1&#8243; 을 더해도 Carry가 발생하지 않았으므로 &#8220;0&#8243;)와 MSB에서 발생한 Carry(&#8220;1&#8243; 과 &#8220;1&#8243; 을 더해서 Carry 가 발생했으므로 &#8220;1&#8243;)의 값이 달라지는 경우에 Overflow가 검출됩니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1485.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2685" alt="16FJK1485" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1485-300x150.jpg" width="300" height="150" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1482.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2682" alt="16FJK1482" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1482-300x38.jpg" width="300" height="38" /></a></td>
</tr>
</tbody>
</table>
<p>· N : 연산의 결과 R2(0&#215;00000000)의 최상위 비트가 &#8220;0&#8243; 이므로 Negative 발생하지 않음<br />
· Z : 연산의 결과 R2가 0&#215;0 이므로 세팅<br />
· C : 32-bit 를 넘어섰으므로 Carry 가 발생<br />
· V : MSB 이전 비트에서 발생한 Carry(&#8220;0&#8243;과 &#8220;0&#8243;을 더해도 Carry가 발생하지 않았으므로 &#8220;0&#8243;)와 MSB에서 발생한 Carry(&#8220;1&#8243; 과 &#8220;1&#8243; 을 더해서 Carry 가 발생했으므로 &#8220;1&#8243;)의 값이 달라지는 경우에 Overflow가 검출됩니다.</p>
<table>
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1486.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2686" alt="16FJK1486" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1486-300x147.jpg" width="300" height="147" /></a></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1483.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2683" alt="16FJK1483" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1483-300x38.jpg" width="300" height="38" /></a></td>
</tr>
</tbody>
</table>
<p>· N : 연산의 결과 R2(0&#215;80000000)의 최상위 비트가 &#8220;1&#8243;이므로 Negative 발생<br />
· Z : 연산의 결과 R2가 0&#215;0 이 아님<br />
· C : 32-bit 를 넘어섰으므로 Carry가 발생<br />
· V : MSB 이전 비트에서 발생한 Carry(&#8220;1&#8243; 과 &#8220;1&#8243; 을 더해서 Carry가 발생했으므로 &#8220;1&#8243;)와 MSB에서 발생한 Carry(&#8220;1&#8243; 과 &#8220;1&#8243; 을 더해서 Carry 가 발생 했으므로 &#8220;1&#8243;)의 값이 다르지 않으므로Overflow가 검출되지 않습니다.</p>
<p><span style="color: #ff6600">(2) Examples2</span><br />
ADD R0, R1, R2 -&gt; does not update the flags( &#8220;S&#8221;Prefix가 없음)<br />
ADDS R0, R1, R2 -&gt; update the flags ( &#8220;S&#8221;Prefix가 있음)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14009.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2692" alt="16FJK14009" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14009-620x173.jpg" width="434" height="121" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>SUBS R2, R1, R0 : SUBS 명령 실행 이후에 CPSR의 condition flag가 업데이트 됩니다.</p>
<p>ADDEQ R3, R1, R0 : condition field 에 Z flag 가 Set 되어 있으면 실행이 되고 그렇지 않으면 NOP(단순히 CPU의 1Clock을 소비) 명령이 실행됩니다.<br />
condition field 에 Z flag 가 Set 되었다는 의미는 R1, R0 의 값이 같아서 R3에 &#8220;0&#8243;이 저장이 되었다는 의미입니다. 참고로 CMP, TST, CMN, TEQ instructions 등의 비교, 검사 명령어들은 &#8220;S&#8221; Prefix가 없이도 CPSR의 condition flag가 업데이트 됩니다.</p>
<p>다음 구문을 Conditional Execution을 사용했을 경우와 안했을 경우로 구분해서 비교해 보세요.</p>
<p>if(a==0) a = a + 1;<br />
else a = a &#8211; 1;</p>
<table style="width: 550px" border="1" cellspacing="0" cellpadding="8">
<tbody>
<tr>
<td align="center" bgcolor="#FF6600" height="39">Non Conditional Execution</td>
<td align="center" bgcolor="#FF6600" height="39">Conditional Execution</td>
</tr>
<tr>
<td align="left" bgcolor="#FFFFFF" width="346">      cmp r0, #0bne AAAadd r0, r0, #1b BBBAAAsub r0, r0, #1BBB</td>
<td align="left" bgcolor="#FFFFFF" width="376">cmp r0, #0addeq r0, r0, #1subne r0, r0, #1</td>
</tr>
<tr>
<td align="left" bgcolor="#FFFFFF">5 instructions1 branch execution</td>
<td align="left" bgcolor="#FFFFFF">3 instructions0 branch execution</td>
</tr>
</tbody>
</table>
<p>조건부 명령을 사용함으로서 instructions을 2개나 줄였고 가장 중요한 것은 branch 명령없이 구현을 했다는 것입니다.<br />
branch 명령은 ARM pipeline을 무너뜨리기 때문에 성능에서 굉장히 치명적입니다.</p>
<p><span style="color: #993300"><strong>8. Thumb Instruction Sets</strong></span><a id="1342322528248" name="8"></a></p>
<p>Thumb 명령어는 ARM 명령어에 비해서 16bit라는 명령어의 길이 때문에 많은 제약이 있습니다. 가장 단점은 조건부 실행 명령을 사용할 수가 없다는 것입니다.<br />
Thumb 명령어는 ARM을 이해하는 있어서 큰 부분을 차지하지는 않다고 생각되기 때문에 간단하게 특성 정도만 확인하고 넘어 가도록 하겠습니다.</p>
<p><span style="color: #ff0000"><strong>8.1 Thumb Instruction 특징</strong></span><a id="1342322528249" name="8.1"></a></p>
<p>(1) 16-bit length instruction set<br />
(2) ARM 명령어보다 코드의 집적도가 높습니다.( about 65% of ARM instruction )<br />
(3) 일반적으로는 32bit ARM명령어 보다는 속도가 느리지만 16bit memory 시스템에서는 그렇지 않을 수도 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1487.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2687" alt="16FJK1487" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1487-620x223.jpg" width="434" height="156" /></a></p>
<p><strong style="color: #ff0000">8.2 Thumb Instruction 제약 사항</strong></p>
<p><a id="13423225282492" name="8.2"></a></p>
<p>· Limited Access to Registers : R0-R7 registers are accessible.<br />
· Narrow Range of Immediate Value<br />
· Not Flexible for Exception Mode<br />
· Exception Handler should be executed in ARM mode. : Exception이 발생하면 항상 ARM 모드로 전환이 됩니다.<br />
· Limited conditional instruction.<br />
· Branch instructions can be executed conditionally.<br />
· Inline Barrel Shifter is not used.</p>
<p><span style="color: #ff0000"><strong>8.3 Thumb, ARM Instruction 비교</strong></span><a id="13423225282493" name="8.3"></a><br />
아래 코드를 ARM 명령어와 Thumb 명령어로 작성하고 비교해보시기 바랍니다.</p>
<p>if(x&gt;=0) return x;<br />
else return -x;</p>
<table style="width: 550px" border="1" cellspacing="0" cellpadding="8">
<tbody>
<tr>
<td align="center" bgcolor="#FF6600" height="39">ARM Instruction</td>
<td align="center" bgcolor="#FF6600" height="39">Thumb Instruction</td>
</tr>
<tr>
<td align="left" bgcolor="#FFFFFF" width="346">abs_rtnCMP r0, #0RSBLT r0, r0, #0MOV pc, lr</td>
<td align="left" bgcolor="#FFFFFF" width="376">abs_rtnCMP r0, #0BGE returnNEG r0 r0returnMOV pc, lr</td>
</tr>
<tr>
<td align="left" bgcolor="#FFFFFF">- Instructions : 3- Size : 12Bytes- 16-bit bus : 6access- 32-bit bus : 3access</td>
<td align="left" bgcolor="#FFFFFF">- Instructions : 4- Size : 8Bytes- 16-bit bus : 4access- 32-bit bus : 4access</td>
</tr>
</tbody>
</table>
<p>위의 표에서 16-bit bus일경우의 access 횟수를 보면 오히려 Thumb 명령어가 효율을 보이기도 합니다.</p>
<p><span style="color: #ff0000"><strong>8.4 ARM/Thumb Interworking</strong></span><a id="13423225282494" name="8.4"></a></p>
<p>ARM 모드와 Thumb 모드를 같이 사용할 수가 있습니다. 하지만 동시에 명령어들을 섞어서 사용할 수 있는 것은 아니고 ARM 모드에서 BX branch명령어에 의해서 Thumb 모드로 전환을 할 수가 있고 다시 Thumb 모드에서 BX 명령어를 이용해서 ARM 모드로 복귀할 수 있습니다.</p>
<p><span style="color: #ff6600">(1) BX</span><br />
Instruction<br />
BX{cond} Rm<br />
CPSR.T &lt;&#8211; Rm[0], PC &lt;&#8211; Rm &amp; 0xFFFFFFFE</p>
<p>BX명령어는 일반 분기명령어와 비슷한 것 같지만 조금 다릅니다. 이유는 32bit ARM 모드에서 Thumb 모드로 전환을 할때 32bit 명령어에서 16bit로 변경되면서 PC의 주소 증가하는 값이 4byte에서 2byte로 바뀌기 때문에 그런 것입니다. 당연히 Thumb 모드에서 ARM 모드로 다시 복귀할 때는 반대의 경우이겠죠? 조금 어렵죠? 예를 들어서 설명하도록 하겠습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1479.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2679" alt="16FJK1479" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1479.jpg" width="418" height="203" /></a></p>
<p>위의 그림에서 붉은 박스를 잘 보시면 armcode 부분은 32비트 코드 사이즈이고, thumbcode 부분은 16비트 길이의 코드 사이즈임을 알 수 있습니다.</p>
<p>0x5C address의 코드 BX, R0 코드가 수행이 되었을 때 레지스터의 상태를 보면 아래와 같습니다.<br />
thumbcode가 시작되는 주소는 0x6C인데, armcode의 &#8220;BX, R0(0x6d)&#8221; 코드에 의해서 0x6C가 아닌 0x6D로 분기하라고 되어 있습니다. 올바르게 수행이 될까요? 물론 잘 수행이 됩니다. 이것의 비밀은 위에서 설명한 &#8220;CPSR.T &lt;&#8211; Rm[0], PC &lt;&#8211; Rm &amp; 0xFFFFFFFE&#8221;에 있습니다.<br />
우선 CPSR.T = 1 로 변경이 되는 것은 Rm(1101101) 의 최하위 비트가 &#8220;1&#8243; 이기 때문입니다. 또한 Rm(1101101) &amp; 0xFFFFFFFE 에 의해서 실제 BX분기 명령어에 의해서 분기되는 주소는 0x6C가 됩니다. BX 명령어에서 Rm(1101101) &amp; 0xFFFFFFFE 해서 분기를 하는 이유는 ARM 모드(32비트)이건 Thumbmode(16비트) 이건 PC의 주소를 항상 2의 배수를 유지하기 위해서 입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1480.jpg" rel="lightbox[2515]"><img class="alignnone size-medium wp-image-2680" alt="16FJK1480" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK1480-300x150.jpg" width="300" height="150" /></a></p>
<p><span style="color: #800000"><strong>9. AAPCS</strong></span><a id="13423225282495" name="9"></a></p>
<p><span style="color: #ff0000"><strong>9.1 Procedure Call Standard for the ARM Architecture</strong></span><a id="13423225282496" name="9.1"></a></p>
<p>쉽게 이야기 하면 ARM에서 서브 루틴을 호출할 때의 레지스터, 스택 사용 방법에 대한 것입니다. 아래 표는 Procedure call시 사용되는 레지스터들을 표로 정리한 것입니다.</p>
<table style="width: 550px" border="1" cellspacing="0" cellpadding="8">
<tbody>
<tr>
<td align="center" bgcolor="#FF6600" height="39">Register</td>
<td align="center" bgcolor="#FF6600" height="39">Synonym</td>
<td align="center" bgcolor="#FF6600">Special</td>
<td align="center" bgcolor="#FF6600">Role in ther procedure call standard</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF" width="69">r15</td>
<td align="center" bgcolor="#FFFFFF" width="107"></td>
<td align="left" bgcolor="#FFFFFF" width="190">PC</td>
<td align="left" bgcolor="#FFFFFF" width="444">Program Count</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r14</td>
<td align="center" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">LR</td>
<td align="left" bgcolor="#FFFFFF">Link Register</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r13</td>
<td align="center" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">SP</td>
<td align="left" bgcolor="#FFFFFF">Stack Pointer</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r12</td>
<td align="center" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">IP</td>
<td align="left" bgcolor="#FFFFFF">The Intra-procedure-call scratch register</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r11</td>
<td align="center" bgcolor="#FFFFFF">v8</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register8</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r10</td>
<td align="center" bgcolor="#FFFFFF">v7</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register7</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r9</td>
<td align="center" bgcolor="#FFFFFF">v6</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register6Platform registerTher meaning of the register is defined by the platform standad</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r8</td>
<td align="center" bgcolor="#FFFFFF">v5</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register5</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r7</td>
<td align="center" bgcolor="#FFFFFF">v4</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register4</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r6</td>
<td align="center" bgcolor="#FFFFFF">v3</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register3</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r5</td>
<td align="center" bgcolor="#FFFFFF">v2</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register2</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r4</td>
<td align="center" bgcolor="#FFFFFF">v1</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Variable register1</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r3</td>
<td align="center" bgcolor="#FFFFFF">a4</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Argument / scratch register4</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r2</td>
<td align="center" bgcolor="#FFFFFF">a3</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Argument / scratch register3</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r1</td>
<td align="center" bgcolor="#FFFFFF">a2</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Argument / scratch register2</td>
</tr>
<tr>
<td align="center" bgcolor="#FFFFFF">r0</td>
<td align="center" bgcolor="#FFFFFF">a1</td>
<td align="left" bgcolor="#FFFFFF"></td>
<td align="left" bgcolor="#FFFFFF">Argument / result / scratch register1</td>
</tr>
</tbody>
</table>
<p>■ 참고로 scratch register들은 서브루틴 호출시 변경이 있을 수 있는 위험이 있는 레지스터입니다. 그러므로 서브루틴 호출시 Stack에 백업한 이후 서브루틴을 호출해야 합니다.</p>
<p>위의 표에서 알수 있는 것은 함수를 호출할 때 함수의 인자 4개까지는 r0 ~ r3에 저장이 되어 호출이 되고 함수에서 return에 의한 결과 값은 r0에 담아서 함수를 호출한 메인 함수로 값을 전달하고 있음을 알수 있습니다. 그럼 함수의 인자가 4개 이상인 경우에는 어떻게 되는 것일까요? 5번째 인자부터는 Stack에 저장한 후 함수에서 POP해서 사용합니다. Stack은 메인 메모리를 사용하므로 가능하면 함수 인자는 4개까지만 사용하는 것이 성능 향상에 도움이 됩니다.</p>
<p><span style="color: #ff0000"><strong> 9.2 Function Parameter Passing</strong></span><a id="13423225282497" name="9.2"></a></p>
<p>void main(void)</p>
<p>{</p>
<p>int sum;</p>
<p>// R0 레지스터에 a+b+c+d+e 의 합이 저장되어 return이 됩니다.</p>
<p>sum = func1(0, 1, 2, 3, 99);</p>
<p>}</p>
<p>int a &#8211;&gt; R0</p>
<p>int b &#8211;&gt; R1</p>
<p>int c &#8211;&gt; R2</p>
<p>int d &#8211;&gt; R3</p>
<p>int e &#8211;&gt; Stack</p>
<p>Return Value &#8211;&gt; R0</p>
<p>int func1(int a, int b, int c, int d, int e)</p>
<p>{</p>
<p>return a+b+c+d+e;</p>
<p>}</p>
<p>위의 C 코드를 Disassembly 해보면 다음과 같습니다. 오른쪽 설명을 참조 하시기 바랍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14022.jpg" rel="lightbox[2515]"><img class="alignnone  wp-image-2622" alt="16FJK14022" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/16FJK14022-571x620.jpg" width="457" height="496" /></a></p>
<p>ARM Architecture 강의에서는 특정 CPU(S3C2440, STM32Fxx)에 대한 내용보다는 ARM Core의 이론적인 구조 자체에 대해서 많은 설명을 하였습니다. 다음 ARM Application 강의에서는 Samsung의 ARM9 CPU S3C2440 개발보드를 이용해 실제 실습을 통하여 ARM에 대해서 공부해 보도록 하겠습니다.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/2515/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[15호]JK전자와 함께하는 ARM 완전정복 1부</title>
		<link>http://www.ntrexgo.com/archives/2867</link>
		<comments>http://www.ntrexgo.com/archives/2867#comments</comments>
		<pubDate>Wed, 24 Oct 2012 18:23:16 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[15호]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=2867</guid>
		<description><![CDATA[디바이스마트 매거진 15호 &#124; 자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부한다면 큰 도움이 될 것입니다. ]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/wp-content/uploads/2012/10/15FJKARM444.jpg" rel="lightbox[2867]"><img class=" wp-image-2886 alignleft" alt="15FJKARM444" src="http://www.ntrexgo.com/wp-content/uploads/2012/10/15FJKARM444-620x465.jpg" width="241" height="181" /></a></p>
<h3><span style="color: #800000">JK전자와 함/께/하/는 ARM 완전 정복</span></h3>
<h3>Ⅰ.ARM Architecture &#8211; 1부</h3>
<p style="text-align: right">글 | JK전자</p>
<p>자료는 ARM을 처음 접하는 입문자로서 S/W 엔지니어 혹은 H/W 엔지니어를 대상으로 하였습니다. 처음에는 Cortex-M3 구조를 목표로 하였으나 전통적인 ARM(주로 ARM7, ARM9)의 구조에 대해서 먼저 이야기한 다음 Cortex-M3 구조에 대해서 하기로 마음을 고쳐 먹었습니다. Cortex-M3도 ARM 이기 때문에 전통적인 ARM의 구조에 대해서 잘 이해하고 Cortex-M3 구조와 비교해 보면서 공부 한다면 큰 도움이 될 것입니다.</p>
<p>ARM Architecture 강의는 특정 CPU(S3C2440, STM32Fxx) 보다는 ARM의 이론적인 구조 자체에 대해서 많은 설명을 하고 있습니다. 하지만 일반적인 ARM의 구조를 잘 이해하면 특정벤더의 CPU도 쉽게 이해할 수 있을 것이라 생각됩니다.</p>
<p>처음에는 주로 임베디스 시스템에 대한 이론을 공부하게 될 것이고 이후에 ARM의 구조, 레지스터, Instructions 등에 대해서 설명해나갈 것입니니다. 이론 설명이 끝나면 실제 타겟 보드를 선정하여 이론으로만 설명했던 내용을 직접 코딩해 보고 타겟에 다운로드하여 결과를 확인하는 실습을 해보도록 하겠습니다.</p>
<p>I. ARM Architecture ~ IV. Cortex-M3 Applications 까지 분명 쉽지 않은 지루하고도 먼 여행이 되겠지만 ARM을 공부하는 임베디드관련 엔지니어라면 언젠가는 한번은 넘어야 하는 산이라 생각됩니다. 부디 이 자료가 ARM을 정복하는데 조금이라도 도움이 되시길 바랍니다.</p>
<h4><span style="color: #000000"><strong>강의 전체 로드맵</strong></span></h4>
<p>I. ARM Architecture | 임베디드 시스템 개론에 대한 설명과 ARM7, ARM9 의 구조에 대해서 설명 합니다.<br />
II. ARM Applications | 삼성의 S3C2440(ARM9) 개발보드(S3C2440 Mini 개발보드)를 이용해서 어셈블리어와 UART, GPIO 등을 실습합니다.<br />
III. Cortex-M3 Architecture | Cortex-M3의 특징과 구조에 대해서 설명합니다.<br />
IV. Cortex-M3 Applications | STM32F103VCT6 Dragon 개발보드를 이용해서 GPIO, LCD, SPI, UART, MP3, SDIO, I2C 등을 실습합니다.</p>
<p>이 강의 자료에 대한 모든 질의사항은 http://cafe.naver.com/avrstudio의 ARM Architecture Q&amp;A게시판에 글을 남겨 주시거나 jk@jkelec.co.kr 로 메일을 보내주시기 바랍니다.<br />
가급적이면 여러 사람이 질문에 대한 답변을 공유 할수 있도록 네이버 카페 게시판을 이용해 주셨으면 합니다. 감사합니다.</p>
<p><span style="color: #800000"><strong>1. 임베디스 시스템 소개</strong></span><a id="1"></a></p>
<p><span style="color: #ff0000"><strong>1.1 Embedded System 이란</strong></span><a id="12" name="1.1"></a><br />
ARM프로세서는 예전에는 주로 경량화된 임베디드 시스템에서 사용되었는데, 최근에는 엄청난 성능으로 무장하여 마이크로소프트사에서도 ARM을 지원하는 등 좀 더 복잡한 사용자 UI가 필요한 분야 (주로 스마트 기기)에까지 그 쓰임새가 확대되었습니다.</p>
<p>Embedded System의 특징을 몇가지로 요약하면 다음과 같습니다.</p>
<p>- 장치에 내장된 Process에 의해 특정한 목적의 기능을 수행하는 하드웨어와 소프트웨어가 조합된 경량화된 시스템<br />
- 입출력 장치를 내장하고 있다.<br />
- Processor 동작은 주로 S/W에 의지해 동작 한다.<br />
- 자동차, 네트워크 장비, Mobile 단말기, 정보가전 등에 응용되고 있다.<br />
- 저전력, 안정성, 저렴함</p>
<p><span style="color: #ff0000"><strong>1.2 Embedded System 구성</strong></span><a id="13" name="1.2"></a><br />
임베디드 시스템은 크게 Hardware와 Software로 구성되어 집니다.</p>
<p><span style="color: #ff6600">(1) Hardware</span><br />
- CPU(Processor)<br />
- Memory 장치 : ROM(NOR), RAM(SDRAM, SRAM), Storage(NAND, SD) &#8230;<br />
- I/O 장치 : Network, LCD, GPIO &#8230;<br />
메모리 중에서 NOR, SDRAM등은 Random access가 가능하나 NAND 메모리의 경우는 Random access가 불가능 하고 CPU 입장에서 Address를 가지고 접근할 수가 없습니다. 그래서 NAND의 경우에는 메모리라고 하기 보다는 저장장치에 가깝습니다. Address를 가지고 Random access가 가능하다면 XIP(Execute In Place)가 가능하여 부팅을 위한 메모리로서 사용이 가능합니다. 최근에는 NAND 메모리만 있어도 부팅이 가능한 디바이스들(S3C6410, S5PV210 등)이 있으나 이것은 NAND 메모리에서 직접 실행되는 것이 아니라 CPU 레벨에서 NAND 메모리의 0번 블럭의 내용을 CPU의 Internal SRAM에 로드시켜서 NAND 메모리에서 부팅이 가능한 것처럼 보여지는 것 입니다. 그래서 CPU의 OM(Operation Mode)등의 포트를 잘보면 NAND 메모리의 동작 Cycle, Size 등을 H/W 적으로 정해주는 부분이 있습니다.</p>
<p><span style="color: #ff6600">(2) Software</span><br />
- System Software : Firmware(OS 개념이 없음), Device Driver(OS 관점)<br />
- RTOS, Embedded OS<br />
- Middleware : Network Stack Protocol, File System &#8230;<br />
- Applications</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM001.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2824" alt="15FJKARM001" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM001.jpg" width="285" height="162" /></a></p>
<p><span style="line-height: 19px">위의 그림에서 System Software는 Device Driver혹은 HAL(Hardware Abstraction Layer, 하드웨어 추상화 계층)이라고도 부릅니다. </span></p>
<p><span style="color: #ff0000"><strong>1.3 Operating System</strong></span><a id="132" name="1.3"></a></p>
<p><span style="color: #ff6600">(1) RTOS (Real-Time OS)</span><br />
- 주어진 임의의 작업에 대해 정해진 시간 내에 수행할 수 있도록 하는 환경을 제공<br />
- 개발시에 주로 운영체제와 Task들이 같이 빌드 됩니다.<br />
- VxWorks, uC/OS, FreeRTOS, pSOS(삼성), Nucleus<br />
RTOS에 대해서는 여러가지 정의가 많이 있지만 예를 들어보면 좀 감이 올것 같습니다. 일반적으로 우리가 사용하는 PC의 경우에 우리가 Excel 등을 실행 시켰을 경우 조금 늦게 실행이 된다고 해서 큰 일이 발생 하지는 않습니다. 실행이 될때까지 조금 기다리면 되겠죠. 하지만 무인자동차를 운행하는 시스템등에서 전방에 장애물이 나타났을 경우 반드시 부딪히기전에 멈춰서거나 피해가야 되겠지요. 어떤 상황(부딪히는 상황)에 대해서 정해진 시간(부딪히기 전)까지는 반드시 응답을 주어야 하는 시스템에서 RTOS등이 필요하게 됩니다.</p>
<p><span style="color: #ff6600">(2) Embedded OS</span><br />
- 여러 복잡한 작업들을 동시에 효율적으로 수행하기 위한 환경 제공<br />
- 이미 동작 중에 있는 운영체제 상에서 새로운 프로세스를 이식 할 수 있다. &#8211;&gt; RTOS에 비해서 Application 개발을 편리하게 할수 있습니다.<br />
- Windows CE, Linux, Android, iOS<br />
Embedded OS는 최근에 스마트폰, 네비게이션 등에 많이 이용되고 있습니다.</p>
<p><span style="color: #800000"><strong>2. Processor</strong></span><a id="13423222" name="2"></a></p>
<p><span style="color: #ff0000"><strong>2.1 CPU</strong></span><a id="13423223" name="2.1"></a></p>
<p><span style="color: #ff6600">(1) CPU (Central Processing Unit)</span><br />
CPU의 구성은 Processor Core + System Bus + Peripherals (H/W IP) + Memory 로 이루어 집니다. 이렇게 CPU안에 주변장치(Peripherals), Memory등을 모두 담고 있는 시스템을 SOC (System-On-Chip) 라고 한다. 아래 그림은 SOC의 한 예이다. 우리가 앞으로 공부하려고 하는 ARM도 바로 Processor Core 중의 한 종류 입니다. Data 버스와 Instruction 버스가 따로 있는 것으로 보아서 하바드 아키텍쳐 구조 입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM002.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2825" alt="15FJKARM002" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM002-620x592.jpg" width="496" height="474" /></a></p>
<p><span style="color: #ff6600">(2) Processor Core</span><br />
- 메모리 장치로 부터 프로그램의 구성 요소인 명령어들을 fetch, decoding, execution 하는 동작을 합니다.<br />
- 레지스터(Register), 연산장치(ALU), 제어장치(Control Unit), 버스(Bus), Cache memory(Optional), MMU(Optional) 등으로 구성 됩니다.<br />
- Processor Core의 종류에는 ARM, MIPS, Intel의 Sandy Bridge 등도 Processor Core의 한 종류 입니다.</p>
<p><span style="color: #ff0000"><strong>2.2 RISC and CISC</strong></span><a id="13423224" name="2.2"></a></p>
<p><span style="color: #ff6600">(1) RISC (Reduced Instruction Set Computer)</span><br />
RISC의 대표 주자는 ARM, MIPS, SunSPARC, IBM PowerPC 등이 있습니다. ARM사의 다음 버젼에서는 64비트를 지원한다고 합니다.<br />
- Same Length for all instruction, big code sizes<br />
단순한 ADD명령이나 복잡한 명령이나 모두 32bit의 동일한 명령어 길이를 가지고 있기 때문에 코드의 집적도가 떨어질 수 밖에 없습니다. 이를 보완하기 위해서 16bit 코드 사이즈를 가지고 Thumb 명령어를 지원하고 있고 Cortex-M 계열에서는 ARM, Thumb명령어의 장점을 취한 Thumb2 명령어를 사용하고 있습니다.<br />
- Simple Hardware, Low Power, Mobile Device 들을 위해서 최적화 되어 있음.<br />
명령어의 길이가 모두 같기 때문에 코드 집적도는 떨어지지만 이 덕분에 H/W 가 단순해지고 전력 소모를 줄일수 있습니다.<br />
- Load Store Architecture, needs many registers<br />
명령어의 개수가 많지 않기 때문에 그에 따라서 레지스터가 좀더 필요하게 되었습니다.</p>
<p><span style="color: #ff6600">(2) CISC (Complex Instruction Set Computer)</span><br />
CISC 대표주자는 Intel x86, Alpha 계열이 있습니다.<br />
- 명령어의 길이가 기능에 따라서 다르기 때문에 복잡한 H/W 처리가 요구 됩니다.<br />
- 수행하는 명령에 따라서 명령어의 사이즈가 다르게 설계 되어 단순한 일을하는 명령어는 코드의 사이즈가 작고 복잡한 일을 수행하는 명령어는 사이크가 큽니다. 이로 인해서 코드 사이즈는 작아 졌으나 각기 다른 사이즈의 명령어를 수행하기 위한 H/W 설계가 복잡해 지고 상대적으로 RISC에 비해 전력 소모가 많아졌습니다.<br />
- 복잡한 작업을 수행하는 다양한 명령어 들이 있기 때문에 RISC에 비해서 많은 레지스터가 필요 하지는 않습니다.</p>
<p><span style="color: #ff0000"><strong>2.3 Register</strong></span></p>
<p>프로세서 코어에 위치하고 있고 프로세서가 접근 가능한 가장 빠른 임시 기억 장치로 ARM 프로세서는 아래과 같은 3가지 종류의 레지스터가 있습니다.</p>
<p><span style="color: #ff6600">(1) General Purpose Register</span> : 프로그램 데이터 처리에 사용됩니다.<br />
<span style="color: #ff6600">(2) Control Register : Stack Pointer, Link Register, Program Counter</span><br />
- Stack Pointer는 현재 프로세스 모드의 Stack의 Top 주소를 가르키고 있습니다.<br />
- Link Register는 서브루틴 분기시 서르부틴을 끝마치고 복귀 할 주소를 가지고 있습니다.<br />
- Program Count는 현재 실행 중인 주소 값입니다.<br />
<span style="color: #ff6600">(3)Program Status Register</span> : Processor 의 상태정보와 ALU의 결과 정보를 저장하고 있습니다.<br />
참고로 일반 레지스터 외에 특별한 레지스터가 있는데 주로 Processor 주위에 있는 주변 장치들을 제어하기 위해서 SFR (Special Function Register) 가 있습니다. 주로 Memory-Mapped 방식으로 접근이 되고 대부분 bit 단위로 제어가 됩니다.(AND, OR, EOR &#8230; ) 그리고 Memory-Mapped 되어 있다는 말은 SFR은 각 레지스터에 해당하는 주소가 정해져 있어 주소를 통해서 접근이 가능 하다는 이야기 입니다. S/W 엔지니어가 ARM 펌웨어 프로그램을 한다고 하면 대부분의 작업이 바로 SFR 레지스터를 세팅하고 제어하는 일입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM003.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2826" alt="15FJKARM003" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM003.jpg" width="254" height="206" /></a></p>
<p>예제로 아래 그림은 ARM9 프로세서중의 하나인 삼성의 S3C2440의 UART제어를 위한 SFR 레지스터 입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM004.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2827" alt="15FJKARM004" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM004-620x472.jpg" width="496" height="378" /></a></p>
<p>ULCON0 레지스터의 경우 0&#215;50000000 번지를 통해서 접근이 가능합니다. 0&#215;50000000 번지의 32Bit 레지스터는 각 비트별로 기능이 나누어져 있습니다. 0 ~ 1 비트는 UART 통신시 WordLength 를 설정할 수 있고, 레지스터별로 각 비트의 기능이 세분화 되어 있습니다.</p>
<p>S3C2440 CPU에서 UART 관련 SFR을 세팅하는 코드를 예를 들면 다음과 같습니다.</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>// S3C2440 CPU의 UART SFR 레지스터의 주소를 정의 합니다.<br />
#define rULCON0 (*(volatile unsigned *)0&#215;50000000) //UART 0 Line control<br />
#define rUCON0 (*(volatile unsigned *)0&#215;50000004) //UART 0 Control<br />
#define rUFCON0 (*(volatile unsigned *)0&#215;50000008) //UART 0 FIFO control<br />
#define rUMCON0 (*(volatile unsigned *)0x5000000c) //UART 0 Modem control<br />
#define rUTRSTAT0 (*(volatile unsigned *)0&#215;50000010) //UART 0 Tx/Rx status<br />
#define rUERSTAT0 (*(volatile unsigned *)0&#215;50000014) //UART 0 Rx error status<br />
#define rUFSTAT0 (*(volatile unsigned *)0&#215;50000018) //UART 0 FIFO status<br />
#define rUMSTAT0 (*(volatile unsigned *)0x5000001c) //UART 0 Modem status<br />
#define rUBRDIV0 (*(volatile unsigned *)0&#215;50000028) //UART 0 Baud rate divisor</p>
<p>// 정의된 SFR 레티스터의 주소에 직접 값을 써 넣을 수 있습니다.<br />
rUFCON0 = 0&#215;0; //UART channel 0 FIFO control register, FIFO disable<br />
rUFCON1 = 0&#215;0; //UART channel 1 FIFO control register, FIFO disable<br />
rUFCON2 = 0&#215;0; //UART channel 2 FIFO control register, FIFO disable<br />
rUMCON0 = 0&#215;0; //UART chaneel 0 MODEM control register, AFC disable<br />
rUMCON1 = 0&#215;0; //UART chaneel 1 MODEM control register, AFC disable</p>
<p>//UART0<br />
rULCON0 = 0&#215;3; //Line control register : Normal,No parity,1 stop,8 bits</p>
</div>
<p><span style="color: #ff0000"> <strong>2.4 ALU (Arithmetic Logic Unit)</strong></span></p>
<p><a id="134232252" name="2.4"></a></p>
<p><span style="color: #ff6600">(1) 산술 연산 수행</span> : ADD, SUB 등 연산 수행<br />
<span style="color: #ff6600">(2) 논리 연산 수행</span> : AND, OR, XOR 등 연산 수행<br />
<span style="color: #ff6600">(3) Program Status Register Update</span> : Negative, Zero, Carry, Overflow, Saturation</p>
<p>Program Status Register Update 기능은 조건부 명령과 관련이 있습니다. 조건부 명령에 관해서는 ARM Instruction 에서 자세히 설명 하도록 하겠습니다.</p>
<p><span style="color: #ff0000"><strong>2.5 Control Unit</strong></span><a id="1342322522" name="2.5"></a></p>
<p><span style="color: #000000">(1) 메모리에서 명령을 인출 합니다.</span><br />
<span style="color: #000000"> (2) 인출된 명령을 분석하여 어떤 명령인지 어떤 레지스터들이 사용되는지를 확인 합니다.</span><br />
<span style="color: #000000"> (3) 명령어 실행에 필요한 제어신호를 만들어 내고 실행 합니다.</span></p>
<p><span style="color: #ff0000"><strong>2.6 Bus</strong></span><a id="1342322523" name="2.6"></a></p>
<p>(1) CPU와 메모리 사이의 데이터 통로<br />
(2) CPU : Bus Master, Memory : Bus Slave<br />
(3) Bus는 Address 버스와 Data 버스가 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM006.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2829" alt="15FJKARM006" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM006-620x405.jpg" width="434" height="284" /></a></p>
<p><span style="color: #fa8072">2.6.1 Von-Neumann Bus</span></p>
<p>CPU와 메모리 사이에 물리적으로 하나의 버스만 존재 합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM007.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2831" alt="15FJKARM007" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM007.jpg" width="382" height="227" /></a></p>
<p><span style="color: #fa8072">2.6.2 Harvard-Architecture Bus</span></p>
<p>CPU와 메모리 사이에 물리적으로 2개 이상의 Bus 존재하여<br />
Von-Neumann Bus 구조에 비해서 CODE, DATA 에 동시에 접근 할 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM008.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2832" alt="15FJKARM008" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM008-620x122.jpg" width="496" height="98" /></a></p>
<p><span style="color: #ff0000"><strong>2.7 Processor 기본 동작</strong></span><a id="1342322524" name="2.7"></a></p>
<p><span style="color: #ff6600">(1) 명령어 인출( Instruction Fetch )</span><br />
명령어를 캐시 혹은 메모리에서 읽어 명령어 파이프 라인에 저장</p>
<p><span style="color: #ff6600">(2) 명령어 해독( Instruction Decoding )</span><br />
어떤 일을 하는 명령어 인지, 어떤 레지스터를 사용하는지 해독</p>
<p><span style="color: #ff6600">(3) 명령어 실행( Instruction Execution )</span><br />
ALU 연산수행 &#8211; 메모리 접근 명령어인 경우 메모리 접근을 위한 주소 계산</p>
<p><span style="color: #ff6600">(4) 메모리 접근( Memory Access )</span><br />
- ALU 연산에 의해 결정된 주소를 사용하여 메모리 접근<br />
- 메모리 접근 명령어가 아닌경우, 결과를 한 사이클 동안 저장</p>
<p><span style="color: #ff6600">(5) 레지스터 쓰기( Register Write Back )</span><br />
- ALU 연산결과를 Regisger 에 기록<br />
- 메모리에서 읽은 값을 Register 에 기록</p>
<p><span style="color: #ff0000"><strong>2.8 Pipeline</strong></span><a id="1342322525" name="2.8"></a></p>
<p>- Cache와 더불어 프로세서의 속도를 획기적으로 개선 하였습니다.<br />
- 하나의 명령어를 여러 개의 독립적인 작업들로 나누어 병렬적으로 실행 합니다.</p>
<p>ARM7의 경우 3단 파이프 라인을 가지고 있는데, 아래 4개의 명령어가 처리되는 과정을 파이프 라인이 있을 경우와 없을 경우로 나누어서 설명하도록 하겠습니다.</p>
<p>JOB1 : MOV R0, #0&#215;1<br />
JOB2 : MOV R1, #0&#215;2<br />
JOB3 : ADD R2, R0, R1<br />
JOB4 : MOV R3, R2</p>
<p><span style="text-decoration: underline"><strong>* 파이프 라인이 없는 시스템</strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM009.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2833" alt="15FJKARM009" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM009-620x181.jpg" width="496" height="145" /></a><br />
파이프 라인이 없는 시스템에서는 4개의 명령어를 수행하는 각 단계별로 3Cycle씩 총 12Cycle을 소모하고 있습니다.</p>
<p><span style="text-decoration: underline"><strong>* 3단 파이프 라인 시스템( ARM7 )</strong></span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM010.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2834" alt="15FJKARM010" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM010-620x183.jpg" width="496" height="146" /></a></p>
<p>3단 파이프 라인이 있는 시스템에서는 4개의 명령어를 수행하는 처음 단계에만 3Cycle을 소모하고 다음 부터는 1Cycle이 소모되어 총 6Cycle을 소모하고 있다. 결과적으로 파이프 라인이 없는 시스템 보다 2배 정도의 성능 향상을 가져 옵니다.</p>
<p>- F(Instruction Fetch), D(Instruction Decoding), E(Instruction Execution)</p>
<p>- 위의 예는 모든 명령어가 캐시에 있어서(그러므로 모든 과정이 1Cycle 이내에 처리) 메인 메모리 접근이 없다는 가정 하에서 수행되는 결과 입니다. 만약 프로세서가 주메모리에 접근해야 하는 일이 발생한다면 추가로 메모리 접근 파이프라인 단계가 필요 하게 됩니다</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM011.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2835" alt="15FJKARM011" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM011-620x550.jpg" width="496" height="440" /></a></p>
<p>지금까지 설명한 프로세서의 기본 동작을 위의 그림(ARM7TDMI Processor Block Diagram)으로 설명을 하면, <span style="color: #ff0000">[1] </span>메모리에서 명령어를 Fetch하여 Instruction Pipeline에 집어 넣고 <span style="color: #ff0000">[2] </span>그 명령어를 Control unit 에서 해독하고 <span style="color: #ff0000">[3]</span>ALU에서 실행, <span style="color: #ff0000">[4]</span>메모리 접근 명령의 경우 메모리 접근할 주소 계산, <span style="color: #ff0000">[5]</span> 그리고 결과를 다시 Register에 Write 하고 있습니다. <span style="color: #ff0000">[2]</span> 에서 Instruction Decoder는 명령어를 읽어서 해석하는 일을 하며, 이에 대하여 Control Unit은 각종 제어 신호를 발생하게 됩니다. 예를 들어 ALU에게 더하기를 하라는 신호를 발생 시킨다던가, 또는 메모리에게 특정 주소를 Read할 수 있도록 신호를 발생시킨다든가 하는 여러 가지 Control signal들 입니다.</p>
<p><span style="color: #800000"><strong>3. 프로세서 성능</strong></span><a id="133" name="3"></a></p>
<p><span style="color: #ff0000"><strong>3.1 CPU 성능 증가 기법들</strong></span><a id="134" name="3.1"></a></p>
<p><span style="color: #ff6600">(1) Clock</span><br />
CPU 성능을 높이는데 가장 일반적인 방법으로 단순히 CPU의 동작 클럭을 높이는 방법이 있습니다. 당연히 같은 작업을 할때 CPU Tick 시간이 빠른 CPU가 그렇지 않은 CPU보다 빠르게 동작을 하겠지요.</p>
<p><span style="color: #ff6600">(2) Execution Optimization</span><br />
아래 내용들은 간단히 개념 정도만 설명하도록 하겠습니다. 각 항목 하나에 대한 이론만 하더라도 분량이 상당할것 같습니다.</p>
<p>- Pipeline : 기본 개념은 하나의 명령어를 여러개의 독립된 작업으로 나누어 병렬적으로 실행. Pipeline은 이전에도 한번 설명 하였습니다.<br />
- Branch prediction(분기예측) : 정상적인 프로그램 흐름에서 분기를 하게되면 Pipeline이 무너지게 되는데 이렇게 되면 다시 Pipeline에 명령어가 적재되어 실행이 되기까지 CPU는 Stall 하게 됩니다. 이를 방지하기 위해서 프로세서가 분기문을 실행하기도 전에 분기 지점을 예측하여 Pipeline을 다시 적재하는 기능 입니다. 물론 분기가 되는 지점을 프로세서에서 100% 예측할수는 없습니다. 예측이 맞으면 좋은거고(Pipeline이 무너지지 않음), 틀렸을 경우에는 원상태로 복구하는 추가 작업이 펄요 합니다. 분기 예측에는 동적예측, 정적 예측 등 여러가지 방법이 있습니다.</p>
<p>- Out-of-order execution</p>
<p>Address: Instructions<br />
0&#215;0004 : a = b + c<br />
0&#215;0008 : d = a + b<br />
0x000c : z = x + y</p>
<p>위의 예제에서 보통 프로세서는 0&#215;0004 번지부터 순차적으로 0&#215;0008, 0x000c 번지로 실행이 되는데, 자세히 보면 0&#215;0008번지는 &#8220;a&#8221;, &#8220;b&#8221; 와 연관이 있기 때문에 0&#215;0004번지가 반드시 먼저 실행이 완료가 될때까지 기다린 이후에 실행이 되어야 합니다. CPU입장에서 보면 일을 하지 못하는 유휴한 시간이 되겠지요. 하지만 0x000c 번지 처럼 이전의 실행내용과 무관하다면 0&#215;0008번지 보다 먼저 실행이 될수도 있게 하는 것입니다. 물론 소프트웨어 개발자 입장에서는 이러한 문제에 신경쓰지 않아도 시스템에서 알아서 해주죠. 이것을 S/W 개발자가 모두 생각하면서 작업을 해야 한다면 엄두가 나지 않겠죠..</p>
<p><span style="text-decoration: underline">- Superscalar</span></p>
<p>CPU는 한 클럭에 하나씩의 명령어를 처리하게 되어있습니다. 이를 개선해서 동시, 혹은 한 사이클 미만으로 둘 이상의 명령어를 처리하는 방식으로 슈퍼스칼라 등의 방식이 나왔으며, 이는 파이프라인을 나누어 휴지 상태의 하드웨어를 활용하도록 하는 방식을 사용합니다. 이처럼 병렬연산 구조는 겹치지 않는 명령어를 병렬로 동시 진행함으로서 프로세서의 내부에서 작동을 대기하며 휴지 상태로 있는 파트를 줄임으로서 작업효율을 높여 연산 속도를 향상시키는 것에 목적이 있습니다. 명령어 스케줄을 H/W에 의존합니다. Multi-ALU 기능으로 한 클럭에 여러 명령어 들을 fetch 해서 동시에 여러 명령어 들을 실행 시킬 수 있어 CPI(Clock per Instruction)가 1보다 작아 질수도 있음. 데이터 의존성, 자원 의존성, 프로시저 의존성이 존재하는 경우에는 동시에 실행되어서는 안됩니다. 도입한 에로는 IBM RS/6000, DEC 21064, Intel i960CA 등이 있습니다.</p>
<p><span style="text-decoration: underline">- VLIW (Very Long Instruction Word)</span></p>
<p>VLIW는 ILP(Instruction Level Parallelism)를 최대한 활용해서 병렬 연산을 진행하며, 이를 하나의 긴 명령어 형식 내에 동시에 실행될 수 있는 명령어(연산 코드 및 오퍼랜드)들을 여러 개 포함시킴으로써 각명령어 단위를 인출해 실행할 때 마다 여러 연산이 동시에 실행되도록 하는 방식 입니다. 명령어 코드는 길지만 하나로 취급되기 때문에 인출과 해독은 하나의 회로에 의해 이루어지고, 각 연산의 실행 사이클만 여러 개의 유니트(ALU를 비롯한 Function unit)들로 나누어져 동시에 처리되게 된다. 컴파일러단에서 명령어의 배치가 이루어 지는 방식입니다. 하나의 명령어 코드의 길이가 128, 256, 512 비트단위로 구성되어 질수 있습니다. VLIW를 도입한 예로 TI C6000 Series, ATI GPU core, Intel Itanium 등이 있습니다.</p>
<p>Superscalar와 VLIW가 비슷하게 생각 되어질 수 있는데, <strong>슈퍼스칼라</strong>(superscalar)는 CPU 내에 파이프라인을 여러 개 두어 명령어를 동시에 실행하는 기술입니다. 명령어를 동시에 실행 시키기 위해서 ALU가 여러개 있어야 합니다. VLIW는 1개의 긴 명령어 안에 여러개의 명령어들을 인출하여 동시에 실행하는 기술입니다.</p>
<p><span style="color: #ff6600">(3) Cache</span><br />
CPU 성능을 높이는 방법으로 요즈음 디부분의 CPU들은 Cache를 사용합니다.<br />
캐시가 생겨나게된 배경은 일반적으로 프로그램은 한번 참조했던 명령어나 데이터는 다시 참조 할 가능성이 높다는 데서 기인 합니다. 이를 참조의 지역성 이라고 합니다. 참조할 데이터가 가까운주소의 영역에 있는 특성을 공간적 지역성(Spatial locality)라 하고 최근에 참조했던 주소를 다시 참조할 가능성이 높은 특성을 시간적 지역성(Temporal locality) 이라고 합니다. 이러한 특성을 가지고 캐시의 블럭은 최근에 참조했던 주소의 데이터를 블럭단위로 SRAM 캐시 공간에 저장을 해서 CPU에서 속도가 느린 메인메모리의 접근을 최소화 하도록 합니다.</p>
<p><span style="color: #ff0000"><strong>3.2 CPU Clock 증가의 한계점</strong></span><a id="1342" name="3.2"></a></p>
<p><span style="color: #ff6600">(1) Clock</span><br />
2000년도 중반 이후 CPU의 클록 속도는 더 이상 급격하게 증가하고 있지 않음. 클록 속도가 증가하면 전력 소비및 누설전류 증가와 함께 심한 발열이 발생하고 이로인해 복잡한 쿨릭 시스템 설계가 필요해 집니다. 예전의 Pentium 싱글코어 CPU들의 쿨링팬을 생각하면 발열등이 어느정도 인지 짐작이 갑니다.</p>
<div class="symple-box YELLOW none" style="text-align:left; width:100%;"> 
<p><strong>참고. Moore’s Law</strong></p>
<p>1965년에 발표 되었고, 그 의미는 &#8220;마이크로칩의 가격은 18개월 마다 절반으로 하락&#8221; 하고<br />
&#8220;마이크로칩의 성능은 18개월 마다 2배로 발전한다.&#8221; 는 의미이다.<br />
2000년도 중반까지 법칙이 맞아 왔으나 최근에는 성능이 2배로 발전한다는 법칙은 한계점에 도달하고 있다.</p>
</div>
<p>&nbsp;</p>
<p><strong>3.3 Multi Core Processor</strong></p>
<p><a id="134232" name="3.3"></a></p>
<p>(1) Hyper Threading<br />
- 하나의 CPU에서 2개 이상의 Thread를 병렬적으로 수행 시킴. 엄밀히 이야기 하면 Multi Core Process는 아닙니다.<br />
- Hyper threaded CPU는 추가적인 레지스터들 및 하드웨어가 필요 함</p>
<p>(2) Multi Core<br />
- 하나의 CPU 내부에 두 개 이상의 Processor 코어를 두어 각각의 Processor에서 프로그램을 수행 시킵니다.<br />
- Homogeneous : 동일한, 균질의 &#8211; 똑같은 종류의 CPU를 여러개 가지고 있음<br />
- Heterogeneous :  이종혼합(CPU+GPU) &#8211; 인텔 울트라북 등 에서 사용하는 CPU들</p>
<p>(3) Memory Wall<br />
- Core 개수가 많을 수록 한 코어가 메모리를 사용할 수 있는 기회가 적어짐.<br />
- Core의 개수가 8개 이상 증가되면, 오히려 메모리 대역폭 성능이 감소됨</p>
<p>(4) Parallel Programming<br />
- Multi Core 시스템에서 성능을 높이기 위해서는 병렬 프로그래밍 효율에 달려 있음(The Free Lunch is Over)<br />
- 인간의 보편적인 사고를 뛰어 넘어야 하는 어려움<br />
- 컴파일러의 성능이 그다지 뛰어나지 못함</p>
<div class="symple-box yellow none" style="text-align:left; width:100%;"> 
<p>참고. The Free Lunch is Over</p>
<p>A fundamental turn toward concurrency in software.<br />
</div>
<p>예전에는 소프트웨어 개발자들이 멀티코어등을 신경쓰지 않고 개발을 해도 하드웨어 성능이 급격하게 발달이 되어 소프트웨어 성능이 개선되었으나 최근에는 무어의 법칙에도 한계점이 도달했고 마이크로 프로세서의 성능 개선의 방법으로 멀티코어쪽으로 진화하고 있어, 개발자들이 소프트웨어 성능을 개선하기 해서는 동시성등을 고려하여 개발을 해야 하지만, 이것은 쉬운 문제가 아닙니다.</p>
<p>- Refer to<br />
Dr. Dobb’s Journal, 30(3), March 2005</p>
<p>http://www.gotw.ca/publications/concurrency-ddj.htm</p>
[/symple_box]
<p>&nbsp;</p>
<p><span style="color: #800000"><strong>4. Embedded Software</strong></span></p>
<p><span style="color: #ff0000"><strong>4.1 Machine &amp; Language</strong></span></p>
<p><strong></strong><span style="color: #ff6600">(1) 기계어( Machine Code )</span><br />
- Processor (CPU)가 이해하는 0과 1로 이루어진 디지털 신호<br />
- Processor 제조사마다 코드 방식이 모두 다름<br />
- 개발자가 기계어를 사용하여 프로그램 하는 것은 거의 불가능 : 예전에는 기계어로 직접 프로그램을 했다고 하는 분들도 계시는데 필자는 그런 정도의 세대는 아니어서 해보지는 못했지만, 생각만 해도 머리가 지끈 아파 오네요.</p>
<p><span style="color: #ff6600">(2) 어셈블리어( (Assembly Code )</span><br />
- 기계어 작성의 불편함을 극복하기 위해서 Processor 제조사에서 정의함.<br />
- 처리속도가 기계어와 같음( 기계어와 1:1 로 매칭 )<br />
- Processor Core 마다 어셈블리 코드가 다름 : ARM, MIPS, x86 명령어들 ..<br />
- 가독성( Readability ) 이 기계어보다 훨씬 좋지만 여전히 보통이 개발자에게는 쉽지 않음</p>
<p><span style="color: #ff6600">(3) C Language</span><br />
- Assembly 명령어들의 단점을 극복한 언어<br />
- 임베디스 S/W 개발에 가장 많이 이용됨<br />
- 어셈블리보다 가독성이 매우좋고 관리가 편함<br />
- 구조적, 모듈화 프로그래밍 가능<br />
- 어셈블리처럼 하드웨어 직접제어 가능</p>
<p><span style="color: #ff0000"><strong>4.2 컴파일러</strong></span><a id="1342322528" name="4.2"></a></p>
<p><span style="color: #ff6600">(1) C언어 번역기</span><br />
- C로 표현된 언어를 어셈블리로 번역하고 오브젝트 파일로 변환 시킨다.<br />
- 사용하려는 Processor코어에 맞는 컴파일러를 사용해야 함<br />
- C로 표현된 프로그램을 ARM코어 CPU 에서 동작시키기 위해서는 ARM 컴파일러를 사용 해야 함. 보통은 x86 PC에서 개발(코딩) 한후 ARM용 컴파일러를 이용해서 컴파일을 한후 타겟이 되는 ARM CPU 에 다운로드(퓨징) 하여 실행 시킴. x86 PC에서 사용하는 ARM용 컴파일러를 Cross Compiler 라고 함. ARM용 크로스 컴파일러로는 KEIL MDK, IAR Workbench(EWARM), ADS, RVDS, ARM용 GCC(주로 리눅스 개발환경에서 사용) 등이 있음.</p>
<p><span style="color: #ff6600">(2) 오브젝트 파일</span><br />
- 어셈블리 코드 섹션, 데이터 섹션<br />
- 디버깅 정보<br />
- 심볼 정보</p>
<p><span style="color: #ff0000"><strong>4.3 어셈블러</strong></span><a id="1342322529" name="4.3"></a><br />
어셈블리 언어를 기계어(오브젝트 파일)로 변환 합니다. 어셈블러와 어셈블리 언어를 혼동하면 안됩니다. 어셈블리 언어는 코드를 작성하는 언어이고, 어셈블러는 작성된 어셈블리 언어를 기계어로 변환 시키는 역할을 합니다.</p>
<p><span style="color: #ff0000"><strong>4.4 Linker</strong></span><a id="13423225210" name="4.4"></a><br />
- 여러 코드및 데이터 섹션들에 미리 정의된 주소를 할당합니다.<br />
- 이미 빌드된 라이브러리들이 함께 사용 될 수 있습니다.<br />
- 링크 작업시 같은 속성의 섹션들(.text, .ro, .rw)을 같이 묶어주는 작업도 합니다.</p>
<p>여기까지 컴파일러, 어셈블러, 링커등 각각이 하는 일들을 살펴 보았습니다. 그렇다면 컴파일하고, 어셈블하고, 링크작업까지 완료가 되면 생성되는 실행가능한 Binary 는 어떤 구조로 해서 만들어 지는 것일까요. 아래 그림을 통해서 알아 보도록 하겠습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM012.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2836" alt="15FJKARM012" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM012-620x352.jpg" width="347" height="197" /></a></p>
<p>*.c 파일을 컴파일 하면 *.s 파일이 생성되고 *.s 파일을 어셈블 하면 *.o 파일이 생성이 되고 *.o 파일들과 다른 라이브러리 파일들(*.a) 을 Link 시키면 실행 가능한 bin 파일이 생성이 됩니다.<br />
그러면 Linker는 여러개의 *.o 파일들을 어떻게 묶어서 bin 파일을 생성하는 걸까요? 이것을 알려면 *.o 파일의 구조와 링크스크립트 파일에 대해서 알아야 합니다. 링크스크립트 파일은 나중에 다시 이야기 하도록 하고 우선 *.o 파일에 대해서만 자세히 보도록 합시다.<br />
아래 일반적이 *.c 파일이 있습니다. 각 변수들과 함수들이 메모리 상에 어떻게 자리를 잡는지 RO, RW, ZI 영역으로 구분해 보세요. 참고로 0 으로 초기화 되거나 값이 할당되지 않은 변수는 ZI(Zero-initialized) 영역, 초기값이 전역 변수는 RW(read-write) 영역, 코드나 변경 불가능한 변수는 RO(Read only) 영역으로 할당이 됩니다.<br />
RW, ZI, RO는 GCC 등에서는 각각 .data, .bss, .constdata + .text 로 불리기도 합니다. 즉 RW = .data, ZI = .bss, RO = .constdata + .text 가 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM038.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2869" alt="15FJKARM038" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM038.jpg" width="200" height="279" /></a></p>
<p>정답은 아래와 같습니다. 아래 오른쪽 그램에 있는 표의 내용이 바로 C코드가 컴파일 되어 오브젝트(*.O) 파일의 구성이 되는 것입니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM013.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2837" alt="15FJKARM013" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM013-620x287.jpg" width="446" height="207" /></a><br />
여기서 중요한 사실은 함수, 전역변수, static 변수는 자기만의 주소를 가지며 Map 파일에 Symbol 형태로 나타나며, Local 변수는 자기만의 주소를 갖지 못합니다.<br />
Symbol들이 자기만의 고유 주소를 갖고 있기 때문에 다른 파일의 함수들에서도 직접 access가 가능한 이유 이기도 합니다.</p>
<p><strong> 5. ARM Processor</strong><a id="13423225210" name="5"></a></p>
<p>4장까지는 학교다닐때 한번씩은 들어 밨음직한 내용으로 다소 지루한 내용이었던 같습니다. 이제 5장부터 본격적으로 ARM 에 대해서 공부해 보도록 하겠습니다. ARM(영국회사) 사는 architecture core 및 system core 를 License 해주는 IP 회사 입니다. 직접 반도체를 제조하여 판매하는 것이 아니라 설계한 프로세서를 반도체 회사에 Hard Macrocell(수정불가) 또는 Synthesizable core(일부 수정 가능) 로 제공 합니다. 반도체 제조회사에서는 ARM사로 부터 제공받은 ARM core와 주변 장치를 추가하여 SOC를 만들어 사용자에게 판매하거나 자체 제품에 사용 합니다.</p>
<p>참고로 아래 내용들은 최근 ARM사의 연혁 입니다. Cortex-M3(2004년), M0(2009년), M4(2010년), 등을 발표한 년도 등을 알수가 있네요.</p>
<h4><strong>2012</strong></h4>
<ul>
<li>ARM, Gemalto and G&amp;D <a href="http://www.arm.com/about/newsroom/arm-gemalto-giesecke-devrient-form-joint-venture-deliver-next-generation-security.php" target="_self">form joint venture</a> to deliver next-generation mobile security</li>
<li>First Windows RT (Windows on ARM) devices revealed</li>
<li>ARM, AMD, Imagination, MediaTek and Texas Instruments founding members of <a href="http://hsafoundation.com/" target="_self">Heterogeneous System Architecture (HSA) Foundation</a></li>
<li>ARM and TSMC work together on FinFET process technology for next-generation 64-bit ARM processors</li>
<li>ARM forms first UK forum to create technology blueprint “Internet of Things” devices</li>
<li>ARM named one of <a href="http://www.britainstopemployers.co.uk/BritainsTopEmployers/BritainsTopEmployers2012/C/tabid/5862/C/1248/ARM.aspx" target="_self">Britain’s Top Employers</a></li>
<li>MIT Technology Review named ARM in its list of <a href="http://www.technologyreview.com/tr50/2012/" target="_self">50 Most Innovative Companies</a></li>
</ul>
<h4><strong>2011</strong></h4>
<ul>
<li>ARM ranked #12 in FastCompany’s <a href="http://www.fastcompany.com/most-innovative-companies/2011/profile/arm.php" target="_self">50 Most Innovative Companies</a></li>
<li>WIRED magazine named Warren East in the UK’s Most Influential Leaders</li>
<li>ARM CEO Warren East makes Barron’s list of the <a href="http://online.barrons.com/article/SB50001424052970204582404576214641280640346.html" target="_self">World’s Top 30 CEOs</a></li>
<li>ARM was again included in the <a href="http://www.ftse.com/Indices/FTSE4Good_Index_Series/index.jsp" target="_self">FTSE4Good Index</a>, designed to measure the performance of companies that meet globally-recognized corporate responsibility standards</li>
<li>ARM granted <a href="http://www.queensawardsmagazine.com/winners2011" target="_self">Queen’s Award</a> for Enterprise (Innovation Category)</li>
<li><a href="http://www.arm.com/community/partners/display_company/rw/company/microsoft/">Microsoft</a> unveils <a href="http://www.arm.com/community/partners/display_product/rw/ProductId/5740/" target="_self">Windows on ARM </a>at CES 2011</li>
<li><a href="http://www.arm.com/community/partners/display_company/rw/company/ibm-international-business-machines/">IBM</a> and ARM collaborate to provide comprehensive design platforms down to 14nm</li>
<li>ARM and <a href="http://www.arm.com/community/partners/display_company/rw/company/united-microelectronics-corporation/">UMC</a> extend partnership into 28nm</li>
<li><a href="/products/processors/cortex-a/cortex-a7.php" target="_self">Cortex-A7 </a>processor launched</li>
<li><a href="/products/processors/technologies/biglittleprocessing.php" target="_self">Big.LITTLE </a>processing announced, linking <a href="/products/processors/cortex-a/cortex-a15.php" target="_self">Cortex-A15</a> and Cortex-A7 processors</li>
<li><a href="/products/processors/instruction-set-architectures/index.php" target="_self">ARMv8</a> architecture unveiled at TechCon</li>
<li><a href="http://www.arm.com/community/partners/display_company/rw/company/applied-micro-circuits-corporation-amcc/">AMP</a> announce license and plans for first ARMv8-based processor</li>
<li>ARM <a href="/products/multimedia/mali-graphics-hardware/mali-t658.php" target="_self">Mali-T658 </a>GPU launched</li>
<li>ARM expands <a href="http://www.arm.com/about/newsroom/media-alert-arm-expands-r.php" target="_self">R&amp;D presence in Taiwan </a>with Hsinchu Design Center</li>
<li>ARM and <a href="http://www.arm.com/community/partners/display_company/rw/company/avnet-inc/">Avnet</a> launch <a href="/about/newsroom/avnet-electronics-marketing-and-arm-launch-embedded-software-store.php" target="_self">Embedded Software Store </a>(ESS)</li>
<li>ARM, <a href="http://www.arm.com/community/partners/display_company/rw/company/cadence-design-systems/">Cadence</a> and <a href="http://www.arm.com/community/partners/display_company/rw/company/taiwan-semiconductor-manufacturing-corp/">TSMC</a> tape out first 20nm Cortex-A15 multicore processor</li>
</ul>
<h4>2010</h4>
<ul>
<li>Giesecke &amp; Devrient secure mobile payments announcement via <a href="/products/processors/technologies/trustzone.php" target="_blank">ARM TrustZone</a> and G&amp;D&#8217;s Mobicore technologies</li>
<li>ARM launches <a href="/products/processors/cortex-m/cortex-m4-processor.php" target="_blank">Cortex-M4 processor </a>for high performance digital signal control</li>
<li>ARM together with key Partners form Linaro to speed rollout of Linux based devices</li>
<li><a href="/about/newsroom/microsoft-licenses-arm-architecture.php" target="_blank">Microsoft </a>becomes ARM Architecture Licensee</li>
<li><a href="/about/newsroom/arm-and-tsmc-sign-long-term-strategic-agreement.php" target="_blank">ARM &amp; TSMC</a> sign long-term agreement to achieve optimized Systems-on-Chip based on ARM processors, extending down to 20nm</li>
<li>ARM extends performance range of processor offering with the <a href="/products/processors/cortex-a/cortex-a15.php" target="_blank">Cortex-A15 MPCore processor</a></li>
<li><a href="/products/multimedia/mali-graphics-hardware/index.php" target="_blank">ARM Mali</a> becomes the most widely licensed embedded GPU architecture</li>
<li><a href="/products/multimedia/mali-graphics-hardware/mali-t604.php" target="_blank">ARM Mali-T604 </a>Graphics Processing Unit introduced providing industry-leading graphics performance with an energy-efficient profile</li>
<li>ARM announces <a href="/about/newsroom/arm-announces-corelink-400-system-ip-to-unleash-high-performance-cpu-and-gpu-systems.php" target="_self">Corelink 400 series </a>of AMBA 4 protocol-compliant system IP</li>
</ul>
<h4>2009</h4>
<ul>
<li>ARM announces 2GHz capable <a href="/products/processors/cortex-a/cortex-a9.php" target="_self">Cortex-A9</a> dual core processor implementation</li>
<li>ARM invests in Japanese software vendor eSOL to develop enhanced platforms for next-generation automotive electronics</li>
<li>ARM launches its smallest, lowest power, most energy efficient processor, <a href="/products/processors/cortex-m/cortex-m0.php" target="_self">Cortex-M0</a></li>
<li>ARM Ltd. receives Best Companies accreditation</li>
<li>ARM extends its leadership in media processing by acquiring Logipard AB</li>
</ul>
<h4>2008</h4>
<ul>
<li>ARM announces 10 billionth processor shipment</li>
<li>ARM wins Britain&#8217;s Top Employer Award 2008 from crf.com</li>
<li>ARM announces Industry First silicon-on-Insulator Physical IP for IBM&#8217;s 45nm SOI Foundry</li>
<li><a href="/products/multimedia/mali-graphics-hardware/mali-200.php" target="_self">ARM Mali-200 GPU</a> Worlds First to achieve Khronos Open GL ES 2.0 conformance at 1080p HDTV resolution</li>
</ul>
<h4>2007</h4>
<ul>
<li>Five billionth ARM Powered processor shipped to the mobile device market</li>
<li>ARM Cortex-M1 processor launched – the first ARM processor designed specifically for implementation on FPGAs</li>
<li>AMBA Adaptive Verification IP launched</li>
<li>RealView Profiler for Embedded Software Analysis introduced</li>
<li>ARM unveils Cortex-A9 processors for scalable performance and low-power designs</li>
<li>ARM Introduces SecurCore SC300 Processor For Smart Card Applications</li>
<li>Warren East, CEO, wins Orange Business Leader of the Year Award</li>
</ul>
<h4>2006</h4>
<ul>
<li>IEEE honors ARM with its 2006 Corporate Innovation Recognition award.</li>
<li>ARM Cortex-A8 processor recognized as &#8220;Best In 2005&#8243; by four leading electronics industry publications</li>
</ul>
<h4>2005</h4>
<ul>
<li>ARM listed by Electronic Business as one of the ten most significant companies in electronics over the past 30 years</li>
<li>ARM acquired Keil Software</li>
<li>ARM Cortex-A8 processor announced</li>
<li>ARM launched DesignStart Program</li>
</ul>
<h4>2004</h4>
<ul>
<li>ARM acquired Artisan Components Inc.</li>
<li>The ARM Cortex family of processors, based on the ARMv7 architecture, is announced. The ARM Cortex-M3 is announced in conjunction, as the first of the new family of processors</li>
<li>ARM Cortex-M3 processor announced, the first of a new Cortex family of processor cores</li>
<li>NEON media acceleration technology announced</li>
<li>ARM technology licensed to Aplix, Atheros, Broadcom, CSR, Kawasaki, NEC, Socle, Sony Ericsson, Thomson, Toshiba, Samsung and ZRRT</li>
<li>ARM acquired Axys Design Automation</li>
<li>MPCore multiprocessor launched, the first integrated multiprocessor</li>
<li>OptimoDE technology launched, the groundbreaking embedded signal processing core</li>
</ul>
<p><span style="color: #ff0000"><strong>5.1 ARM 프로세서의 종류</strong></span><br />
ARM Processor에 대해서 나름대로 정리를 해본 것입니다. 이 표와 다르게 분류를 하는 사람들도 있습니다. 이것은 제 개인적인 판단에 의한 분류 입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM022.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2846" alt="15FJKARM022" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM022-620x388.jpg" width="446" height="279" /></a><br />
Cortex 프로세서 이전의 ARM Processors들을 전통적인 ARM으로 분류 하였고 Cortex-M, R 시리즈 까지는 기존의 uCOM시장의 프로세서들을 겨냥한 저가이면서 Realtime 프로세서 시장을 겨냥한 프로세서 이고, A 프로파일 부터는 고성능의 Application을 구현하는 프로세서로 분류 하였습니다.</p>
<p><span style="color: #f08080">5.1.1 ARM7 Processor</span></p>
<p><span style="color: #ff6600">(1) ARM7TDMI Core</span><br />
- RISC Architecture (ARM v4T)<br />
- 3 stage pipelining<br />
- Hard macrocell<br />
- 32-bit ARM/16-bit Thumb Instructions<br />
- Unified bus architecture( 폰노이만 버스 구조)<br />
- ARM720T = ARM7TDMI + MMU + Cache(8KB Unified) + WB + AMBA<br />
- S3C44B0 등</p>
<p><span style="color: #ff6600">(2) ARM7TDMI Block Diagram</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM023.jpg" rel="lightbox[2867]"><img alt="15FJKARM023" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM023-620x455.jpg" width="446" height="328" /></a></p>
<p><span style="color: #f08080">5.1.2 ARM9 Processor</span></p>
<p><span style="color: #ff6600">(1) ARM9TDMI Core</span><br />
- RISC Architecture (ARM v4T)<br />
- 5 stage pipelining -&gt;<br />
Improved clock frequency<br />
- Harvard Bus Architecture<br />
- Simultaneous access to instruction and data memory<br />
- Hard macrocell</p>
<p>- 32-bit ARM/16-bit Thumb Instructions<br />
- ARM920T = ARM9TDMI + Dual Caches + MMUs + WB + AMBA + PA TAG RAM<br />
- S3C2440, S3C2443 등</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM024.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2848" alt="15FJKARM024" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM024-620x428.jpg" width="496" height="342" /></a></p>
<p>앞의 ARM7과 달리 명령어 버스와 데이터 버스가 구분이 되어 있는것을 알수 있습니다. 여기서 약간 생소한 용어가 보이는데요, Write back PA TAG RAM 이 뭘까요?<br />
이 용어를 설명하기 위해서는 먼저 캐시 메모리의 2가지 동작 방식을 알아야 합니다. Cache메모리의 내용을 주메모리에 Write할때, Write-through 방식과 Write-back 방식이 있습니다. Write-through방식은 캐시 메모리의 내용이 업데이트 될때 주 메모리에도 동시에 업데이트가 되는 방식이고 Write-back 방식은 캐시메모리의 내용이 업데이트 되어도 바로 주 메모리에 반영이 되는 것이 아니라 Write back PA TAG RAM 에서 잠시 저장해 두었다가 블록 단위로 CPU가 쉬고 있는 동안에 주 메모리에 업데이트 하는 방식 입니다. Write Buffer는 Write-throuh 방식일 경우에 Data Cache의 내용을 주 메모리에 Write 하기 전에 Buffer 역할을 해주고, Write back PA TAG RAM은 Write-back 방식을 경우에 Data Cache의 내용을 잠시 보관하고 있다가 주 메모리에 Write를 해주는 역할을 합니다.</p>
<p><span style="color: #f08080">5.1.3 ARM11 Processor</span></p>
<p><span style="color: #ff6600">(1) ARM1176JZ(F)-S Core</span><br />
- ARM v6 Architecture<br />
- Improved Multimedia Performance<br />
-  2x faster MPEG4 encode/decode<br />
-  SIMD(Single Instruction, Multiple Data) Instructions : 단일 명령으로 다중 데이터를 처리하는 것을 말합니다.<br />
- Improved Real-Time Performance<br />
Fast Exception/Interrupt Handling<br />
Vector Interrupt Controller -&gt; Reduced Interrupt Latency<br />
New Stack and Processor Mode Change Instructions<br />
- Improved Memory Interface<br />
Un-aligned Data Access<br />
Mixed-Endian<br />
8 stages pipeline<br />
Higher clock frequency<br />
9 stages pipeline for ARM1152T2(F)-S<br />
Separate load-store and arithmetic pipelines<br />
Branch prediction (static &amp; dynamic)<br />
Return Stack</p>
<p>- Other features<br />
High Performance Integer Processor<br />
Physically-tagged caches<br />
Jazelle technology<br />
VFP (Vector Floating Point)<br />
Non Blocking<br />
HUM (Hit Under Miss)<br />
ARM TrustZone Technology<br />
Thumb-2 Instruction<br />
Intelligent Energy Manger (IEM) Technology</p>
<p>- S3C6400, S3C6410 ..</p>
<p><span style="color: #f08080">5.1.4 ARM Cortex Families</span></p>
<p><span style="color: #ff6600">(1) A profile (ARMv7-A) : Application Profile</span><br />
- For sophisticated, high-end applications running open and complex operating systems<br />
- ARM, Thumb, Thumb-2 instruction sets<br />
- S5PC100, S5PV210, OMAP3530 ..</p>
<p><span style="color: #ff6600">(2)R profile (ARMv7-R) : Real-time Profile</span><br />
- For real-time system<br />
- ARM, Thumb, Thumb-2 instruction sets</p>
<p><span style="color: #ff6600">(3) M profile (ARMv7-M) : Microcontroller Profile</span><br />
- For cost-sensitive and microcontroller applications<br />
- Thumb-2 instruction set only<br />
- STM32F 시리즈</p>
<p>공교롭게도 새로 발표된 Cortex 패밀리의 Profile의 첫번째 이름이 A.R.M 으로 회사 이름과 동일 하네요. 우연의 일치 인가요?</p>
<p><span style="color: #ff0000"><strong>5.2 ARM Processor 선택</strong></span></p>
<p>- Embedded real-time Processor<br />
Embedded real-time systems for storage, automotive body and powertrain,<br />
industrial and networking applications<br />
- Application Processor<br />
Devices running open operating systems including Linux, Palm OS, Symbian OS and Windows CE in wireless, consumer entertainment and digital imaging applications<br />
- Secure Processor<br />
Smart cards, SIM cards and payment terminals</p>
<p>위와 같이 전문적으로 분류 할 수도 있게지만 결국 현업에서의 프로세서 선택의 가장 큰 기준은 가격대비 성능일 것입니다. 실제 구현하려고 하는 프로젝트를 구현 할 수 있는 가장 낮은 Cost의 프로세서를 선택 할 것이기 때문 입니다. 현장 에서는 Money, Money 해도 싼게 최고죠. 여기서 또 한가지 S/W 개발자의 입장에서 생각해 보면 개발의 난이도일 것입니다. 전통적인 ARM에 해당하는 ARM7, ARM9, ARM11 프로세서들은 RAM, ROM을 CPU외부에 위치 시킵니다. 이러한 이유(CPU, 제품마다 주소와 초기화 코드등이 틀려짐)때문에 코드의 호환성( 사용하는 메모리 뱅크와 메모리의 용량, 종류에 따라서 소스 레벨의 코드가 달라짐)이 매우 떨어지고 부트로더 등을 직접 작성 해야 합니다. 이에 반해서 Cortex-M, R 프로파일의 코어들은 CPU내부에 RAM, ROM을 가지고 있고 Address 또한 같은 코어를 사용하는 CPU들은 모두 동일 하게 사용됩니다. 그래서 컴파일러(개발 IDE) 수준에서 부트로더를 제공 할 수도 있습니다. 실제로 대부분의 상용 컴파일러 들은 개발자가 부트로더 코드를 작성하지 않아도 기본으로 제공하고 있습니다.</p>
<p><span style="color: #800000"><strong>6. ARM Architecture</strong></span></p>
<p><span style="color: #ff0000"><strong>6.1 ARM based system</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM029.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2853" alt="15FJKARM029" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM029-620x385.jpg" width="496" height="308" /></a></p>
<p>위의 블럭도는 ARM Core에 대한 블럭도는 아니고 붉은색 부분의 ARM Core를 이용해서 구현한 CPU의 한 예 입니다.</p>
<p><span style="color: #ff0000"><strong>6.2 ARM Operating Modes</strong></span></p>
<p><span style="color: #ff6600">(1) 7개의 Processor Mode가 존재</span><br />
User, FIQ, IRQ, Supervisor, Abort Mode, Undefined, System Mode</p>
<p><span style="color: #ff6600">(2) Operating Mode 변경은 Hardware 및 Software로 가능 합니다.</span><br />
ARM 프로세서에 전원이 인가 되면 SVC 모드에서 시작이 되고 인터럽트, 익셉션 등이 발생하면 상황에 맞추어서 H/W 적으로 Operating Mode 가 변경이 되거나 S/W 적으로는 SWI 명령어에 의해서 SVC 모드로 진입 할 수도 있습니다.<br />
ARM Core에는 왜 이렇게 여러가지 동작 모드가 존재하는 것일까요? 아마도 아키텍쳐 차원에서 소프트웨어의 보안및 동작을 지원 하기 위해서일 것입니다. 가령 OS 설계시 커널 S/W 는 모든 권한을 가지고 수행 하도록 하고, User 어플리케이션은 제한된 권한을 가지고 수행을 하도록 설계 한다면 어플리케이션 프로세서는 모든 권한이 없는 User Mode 에서 동작 시키고 나머지 커널및 디바이스 드라이버들은 권한이 있는 나머지 모드(Supervisor, System Mode)에서 실행 시키도록 할 수 있습니다. 물론 이러한 기능은 S/W 적으로도 구현이 불가능한 것은 아니지만 구현을 위해서는 더 많은 노력이 필요할 것입니다.<a href="http://www.ntrexgo.com/wp-admin/post.php?post=2867&amp;action=edit&amp;message=10#"><br />
</a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM030.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2854" alt="15FJKARM030" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM030-620x224.jpg" width="558" height="202" /></a></p>
<p>- CPSR Register를 Privilege Mode 에서 S/W 로 변경 가능, User Mode에서 변경하면 Undefined Instruction Exception 이 발생 합니다.</p>
<p>- ARM Core에 전원이 인가되면 최초에는 Supervisor 모드로 동작을 합니다. 처음에 권한이 없는 모드로 시작을 하면 Privilege Mode로 전환 할 방법이 없겠죠.<br />
- 각 모드는 별개의 Stack영역과 Banked Register 영역을 가지고 있습니다.</p>
<p>위에서 여러가지 모드가 많이 있지만 언제 어떤 모드를 반드시 써야만 하는 규칙이 있는 것은 아니고, 일반 적인 권고 사항일 뿐입니다. 대부분 OS를 운영하지 않는 단순한 펌웨어 레벨의 코드들은 초기 부팅시 설정된 Supervisor 만 사용하는 경우도 많이 있습니다. 위의 표를 보면 mode는 크게 Privileged modes와 Unprivileged mode 로 나눌 수 있습니다. 2가지 mode 구분의 차이는</p>
<p>(1) Privileged Mode (특권 모드)는 IRQ나 FIQ등의 Interrupt의 사용 가능 유무를 직접 설정 할 수 있습니다.</p>
<p>(2) Privileged Mode는 자기들끼리 서로 Mode 변경이 자유자재로 가능 합니다만, Normal Mode는 자기 스스로 Privileged Mode로 Mode의 변경이 불가능 합니다.</p>
<p>그것은 예를 들어, SYS ↔ FIQ, IRQ ↔ SVC과 같이 Privileged Mode → Normal Mode (USR)은 가능하지만, USR → Privileged Mode로의 변경은 불가능 합니다. 아주 중요한 사실입니다. 기억해 주세요.<br />
결국 Privileged Mode는 자기들 멋대로 Mode에 관한 한 자유롭게 왔다 갔다 할 수 있지만, USER Mode는 가능하지 않습니다.</p>
<p>FIQ, IRQ, Abort, Undef 모드는 이후의 장에서 좀더 자세히 설명 하도록 하고 System mode, User mode, Supervisor (SVC) mode 에 대해서 먼저 설명 하도록 하겠습니다.<br />
User Mode는 Application Program을 Execution 하는 Mode이고, System Mode는 Privileged Operating system task가 실행되는 mode이고, Supervisor mode는 보호된 Operating system(커널등) 에서 주로 사용되는 mode 입니다.</p>
<p><span style="color: #ff0000"><strong>6.3 ARM Registers</strong></span><a id="13423225210252" name="6.3"></a></p>
<p><span style="color: #fa8072">6.3.1 Normal Registers</span></p>
<p>앞 시간에 레지스터는 임시로 데이터를 보관하고, 연산에 사용되고, 프로그램 제어에 사용되는 접근속도가 가장빠른 임시 기억장치 라고 설명을 하였습니다.</p>
<p>ARM Core를 잘 이해하기 위해서는 ARM Core에 내장되어 있는 기본 Register들이 어떻게 구성되어 있고, 사용되는지를 잘 알아야 합니다. Register들은 Core가 사용할 수 있는 저장 매체 중에서 가장 빠른 속도를 자랑하며, ARM의 동작은 모두 Register들을 어떻게 사용하는냐에 따라서 동작을 제어 할 수 있습니다. 결국 ARM 프로세서를 사용 한다는 것은 아래 Register들을 가지고 연산을 하며 주 메모리와 메모리 매핑된 주변 장치들을 제어하기 위해서 Load, Store 하는 것입니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM031.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2855" alt="15FJKARM031" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM031-620x371.jpg" width="496" height="297" /></a><br />
위의 레지스터 그림을 보면 ARM 동작모드별로 구분이 되어 있고, 동작 모드에 따라서 파란색 박스로 한번 더 구분이 되어 있는것을 볼 수 있습니다. 파란색 박스로 되어 있는 레지스터들을 뱅크드 레지스터라고 합니다. 그러니까 힌색박스의 레지스터는 동작 모드에 상관 없이 공통으로 사용되어지고 파란색 박스의 뱅크드된 레지스터는 동작 모드별로 독립적으로 사용 가능하다는 것입니다. 말로만 해서는 잘 이해가 되지 않지요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM037.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2861" alt="15FJKARM037" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM037-620x535.jpg" width="434" height="375" /></a></p>
<p>한가지 예를 들어서 설명을 하도록 하겠습니다. CPU에 최초 전원이 인가되어 SVC 모드로 동작을 하다가 FIQ인터럽트가 발생 하였을 경우 레지스터 상태는 아래와 같습니다.<br />
FIQ로 전환이 되면 R8 ~ R14까지는 FIQ전용 레지스터가 사용이 됩니다. 이말은 FIQ모드에서 R8 ~ R14는 SVC모드에서의 R8 ~ R14와는 다른 레지스터 입니다. 즉 SVC모드에서 FIQ가 발생이 되었을때 문맥(Context) 보존을 위해서 R8 ~ R14는 저장을 하지 않아도 FIQ모드에서 R8 ~ R14는 마음대로 사용해도 됩니다. CPSR레지스터도 FIQ, SVC 모드에서 각각 존재 합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM032.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2856" alt="15FJKARM032" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM032-407x620.jpg" width="293" height="446" /></a></p>
<p>여기서 문맥(Context)이라는 용어가 나오는데, 문맥이라는 의미가 무엇일까요?</p>
<p>S/W 입장에서 생각해 보면 프로그램이 순서대로 실행이 되다가 어떤 순간에 ISR이 발생을 하면 원래의 프로그램 실행을 잠시 중단하고 ISR 서비스 루틴으로 이동하게 됩니다. 이때 ISR서비스 루틴으로 이동을 하는것을 문맥의 전환이라고 하는데요 ISR 서비스 루틴으로 이동하고 나서 ISR서비스를 마치고 원래의 프로그램이 계속해서 실행이 되어야 하는데 만약 ISR서비스 루틴에서 특정 레지스터들(R0 ~ R12)을 사용하였다면 그 값들이 변동이 된상태에서 원래의 프로그램이 실행되던 위치로 돌아와서 계속 실행을 하게 되면 원하지 않던 결과가 나올 수 있습니다. 이런한 이유 때문에 문맥의 보존을 위해서 ISR 서비스 루틴으로 이동을 하기 전에 ISR에서 사용될 레지스터들을 스택에 임시로 저장을 하고 ISR루틴을 빠져나오기 전에 스택에 저장되어 있던 레지스터들을 다시 복원시켜 줍니다.</p>
<p>ISR 서비스 루틴으로 이동하는 것을 문맥의 전환이라 하고</p>
<p>ISR 루틴에서 사용 할 레지스터들을 임시로 스택에 저장하였다가 ISR루틴의 수행을 마치고 복귀하기전에 저장해 두었던 레지스터들을 원래의 값으로 복원하는 것을 문맥 보존 이라고 합니다.</p>
<p>아 ~~ 설명이 길어 지고야 말았네요. 이것도 간단하게 예를 들어서 다시 설명을 하도록 하지요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM033.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2857" alt="15FJKARM033" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM033.jpg" width="344" height="138" /></a></p>
<p>위의 그림에서 &#8220;MOV R1, #2&#8243; 명령 이후에 Interrupt가 발생하지 않았다면 R2에서 #3이 들어가 있어야 하나  ISR 서비스 루틴에서  R0, R1을 #0으로 변경하여 ISR 루틴 복귀 후  R2에는 #0이 들어가 있습니다. 이것은 원래의 원하던 프로세스 흐름이 아닙니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM027.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2851" alt="15FJKARM027" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM027-620x191.jpg" width="496" height="153" /></a></p>
<p>위의 그림에서는 스택을 이용해서 ISR 서비스 루틴에서 문맥 저장(PUSH)과 복원(POP)을 하고 있어<br />
Interrupt가 발생하여 문맥전환(Context Switch &#8211; ISR 서비스 루틴으로 이동)이 일어난 후에도<br />
복귀 하였을때 R2에는 정상적으로 #3이 들어가 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM034.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2858" alt="15FJKARM034" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM034.jpg" width="332" height="123" /></a></p>
<p>위의 예제는 FIQ 인터럽트가 발생 했을 경우이 예제 입니다. R10에 저장되는 값은 몇일까요 ?</p>
<p>정답은 #3이 들어가 있겠죠. 왜냐하면 FIQ 모드에서 사용되는 F8 ~ R14는 뱅크드 되어 있어서 Normal루틴에서 사용되는 R8 ~ R12와는 별개의 레지스터 이기 때문에 FIQ 모드에서 R8 ~ R12 는 문맥저장과 복원을 하지 않아도 되는것 입니다. 하지만 FIQ 모드에서도 R0 ~ R7 를 사용한다면 문맥 저장과 복원을 해야 겠지요.</p>
<p>이해가 가시나요. ARM 위의 3가지 경우에 대해서 직접 코드를 입력해서 테스트 해보도록 하세요. 어셈블리어로 코드를 작성 할때 아주 중요한 내용 입니다.</p>
<p><span style="color: #fa8072">6.3.2 Special Registers</span></p>
<p>ARM 레지스터들중에서 R0 ~ R12 까지는 일반 연산, 임시 저장 장소등으로 사용이 되고 R13 ~ R15까지는 조금 특별한 의미를 가지고 있습니다. 그리고 CPSR(Current Program Status Register) 이라는 상태 레지스터도 있습니다.</p>
<p><span style="color: #ff9900">(1) R13</span><br />
- Stack Pointer(SP)<br />
- ARM 동작 모드별로 스택 포인터를 가르키고 있습니다.<br />
- R13(SP)는 ARM 동작 모드별로 뱅크드 되어 있는 레지스터 입니다.</p>
<p><span style="color: #ff9900">(2) R14</span><br />
- Link Register(LR)<br />
- 함수 호출시 리턴될 주소를 가지고 있음<br />
- R14(LR)는 ARM 동작 모드별로 뱅크드 되어 있는 레지스터 입니다.</p>
<p>함수 호출시 복귀할 주소를 저장하기 위해서 레지스터 까지 1개를 할당했는데 어떤 장점이 있을까요 ?<br />
여러번 분기(BL)하는 경우가 아닌 한번만 분기(BL) 하는 경우라면, 함수 에서 원래의 주소로 복귀할때 스택을 사용하지 않고 R14 레지스터를 사용함으로써, 그 속도에서 이익을 얻게 되는 것입니다.</p>
<p><span style="text-decoration: underline">* 스택 접근 = 메인 메모리 접근 = 느림</span></p>
<p>레지스터는 CPU가 접근 할 수 있는 가장 빠른 고속의 메모리 저장 공간 이라고 생각하면 되겠습니다.</p>
<p><span style="color: #ff9900">(3) R15</span><br />
- Program Counter(PC)<br />
- PC를 사용하여 메모리에서 명령어를 Fetch<br />
- R15(PC)는 프로세서 모드에 상관없이 하나의 R15를 가지고 있음( ARM 동작모드별로 뱅크드 되어 있지 않습니다.)</p>
<p><span style="color: #ff9900">(4) CPSR</span><br />
- Program Status Register (CPSR)<br />
- CPSR은 ARM 동작 모드별로 뱅크드 되어 있는 레지스터 입니다.<br />
- 프로세서 모드가 변경이 되면 하드웨어적으로 변경되기 이전의 CPSR 복사본이 SPSR( Saved Program Status Register &#8211; CPSR의 뱅크드 레지스터) 에 저장이 됩니다.<br />
- User, System 모드를 제외하고 각 동작 모드마다 하나씩 존재 합니다.</p>
<p>아래 그림이 좀 복잡해 보이기는 하지만 CPSR도 32bit 레지스터일 뿐입니다. 지금부터 하나씩 파혜쳐 보도록 하지요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM026.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2850" alt="15FJKARM026" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM026-620x367.jpg" width="496" height="294" /></a></p>
<p>앞에 NZCVQ는 Flag field라고 해서, 뭔가 연산한 후에 set되는 register입니다. 이 field는 방금 처리된 ALU의 연산 결과의 상태를 나타냅니다.</p>
<p align="left">1) N : Negative &#8211; 연산결과가 마이너스인 경우에 set 됩니다.</p>
<p align="left">2) Z : Zero &#8211; 연산결과가 0인 경우에 set 되요.</p>
<p align="left">3) C : Carry &#8211; 연산결과에 자리 올림이 발생한 경우에 set 됩니다.</p>
<p align="left">4) V : oVerflow : 연산의 결과가 overflow 났을 경우에 set되는데, Over flow라는건 넘치는 경우니까 원래 가져야 하는 Range보다 결과 값이 큰 경우가 그 경우에 해당됩니다.</p>
<p align="left">이것의 필요성은 ARM의 철학이기도 한데, ARM core는 Opcode를 Memory에서 가져오자 마자 (Fetch) 이를 무조건 실행하는 것이 아니라 Condition flag인 NZCV를 보고 바로 앞 opcode의 실행결과를 보고 실행할지 말지를 결정할 수 있습니다.<br />
Default는 AL &#8220;Always&#8221; , condition과 관계없이 항상 실행 하는 것입니다. Control Field에 대해서는 우선 여기까지 설명을 하고, ARM Instruction에서 좀더 자세히 예를 들어서 설명을 하도록 하겠습니다.</p>
<p>Control Field의 7번 비트인 &#8220;I&#8221; 을 1로 마스킹을 하면 인터럽트가 발생 하지 않습니다. 인터럽트를 받아 들이기 위해서는 0으로 Clear 해야 합니다.</p>
<p>마찬가지로 Control Field의 6번 비트인 &#8220;F&#8221; 을 1로 마스킹을 하면 Fast 인터럽트가 발행 하지 않습니다. Fast 인터럽트를 받아 들이기 위해서는 0으로 Clear 해야 합니다. 마지막으로 5번 비트인 &#8220;T&#8221; 모드가 있습니다. ARM Core는 초기 부팅시에는 무조건 ARM 모드(5번 비트의 &#8220;T&#8221; 가 0으로 설정 됨)에서 시작이 되고 경우에 따라서 Thumb mode로 전환을 할 수가 있습니다. Thumb mode에 대해서는 이후의 장에서 다시 설명을 하도록 하겠습니다. 앞절에서 ARM에는 7가지의 동작 모드가 있다고 하였는데, 이 동작 모드들에 따라서 위의 표와 이 CPSR의 하위 5bit(Mode bits)의 값들이 설정이 됩니다.</p>
<p><span style="color: #ff0000"><strong>6.4 ARM Exceptions</strong></span><a id="134232252102522" name="6.3"></a></p>
<p>Exception 이란 무엇일 까요? 사전적인 의미로는 &#8220;예외&#8221; 라고 되어 있습니다. 하지만 우리는 지금 ARM을 공부하고 있기 때문에 좀더 ARM 적인 표현을 한다면, 외부 요청이나 프로그램 오류로 인해 코드의 정상적인 흐름을 벗어나는 동작 이라고 설명을 하겠습니다. 코드의 정상적인 흐름을 벗어난다는 이갸기는 PC(R15)의 주소가 바뀌게 되는 것입니다. 아래 그림은 Exception 중에서 IRQ 예외 상황이 발생했을 경우에 Exception 처리 흐름의 기본적인 예제 입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM027.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2851" alt="15FJKARM027" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM027-620x191.jpg" width="496" height="153" /></a></p>
<p>PC의 0&#215;1004를 실행하고 나서 IRQ 예외 상황이 발행을 하게 되면 코드의 정상적인 흐름을 잠시 중단하고 IRQ 예외상항을 처리해 주어야 합니다. 여기서 IRQ예외 상황을 처리해 주는 루틴을 Exception Handler하고 합니다. Exception Handler 에서는 7가지 예외 상황(여기 예에서는 IRQ 예외)에 맞는 적절한 처리를 하고 Exception이 발생하기 이전으로 복귀하면 됩니다. Exception Handler에서 한가지 주의 할 사항은 Exception이 발생하기 이전으로 복귀하기 전에 반드시 문맥을 복원하고 복귀 해야 합니다.<br />
그리고 위의 그림에서는 편의상 IRQ 예외 처리를 위해서 0&#215;3000번지로 코드의 흐름이 변경되었지만 실제로 ARM에서는 IRQ 가 발생하면 코드의 흐름이(PC) 0&#215;00000018 로 H/W 적으로 변경이 되고 0&#215;00000018 에서는 다시 실제로 예외 사항을 처리하는 Exception Handler 함수로 분기하는 방식으로 처리가 됩니다.<br />
0&#215;00000018 번지를 Exception Vector라고 하고<br />
ARM에서는 7가지의 Excepton이 존재하는데 이러한 예외 상황이 발행을 하면 각 예외 상황에 따라서 미리 할당된 주소에 있는 ARM 명령어가 수행이 됩니다.</p>
<p>아래 표는 ARM에서의 7가지의 Excepton 에 대하여 주소와 각 Exception에 할당된 정해진 Vector 주소 입니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM028.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2852" alt="15FJKARM028" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM028-620x207.jpg" width="496" height="166" /></a><br />
Exception의 종류와 앞에서 배웠던 ARM 동작 모드와의 관계를 혼동해서는 안됩니다. 예외 상황이 발생하면 그에 따라서 H/W 적으로 ARM 동작 모드가 변경이 되는 것입니다. Priority는 같은 시간에 다수의 예외 상황이 발행하게 되면 우선순위가 높은 놈이 먼저 발생을 하겠지요.</p>
<p>보통 Vector주소는 0&#215;00 번지에서 32bit(4Byte)단위로 증가 하는데, High Vecotr로 설정이 되면 시작 주소가 0xFFFF0000가 됩니다. Windows CE에서는 High Vector를 사용한다고 합니다.</p>
<p><span style="color: #ff6600">(1) Reset</span><br />
ARM Core에 전원을 인가하는 등에서 발행<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM014.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2838" alt="15FJKARM014" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM014-620x177.jpg" width="434" height="124" /></a></p>
<p>(2) Undefined Instruction<br />
ARM Processor 에서 정의되지 않은 명령어 등을 실행 하는 경우에 발생<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM039.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2875" alt="15FJKARM039" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM039-620x209.jpg" width="434" height="146" /></a><br />
Return 이라고 되어 있는 항목은 Exception Handler 수행을 마치고 원래의 프로그램 흐름으로 복귀할때, R14에 H/W적으로 들어가는 복귀 주소에 따라서 달라지게 됩니다. 각 Exception 종류에 따라서 R14에 들어가는 복귀 주소가 달라 지므로 주의 해야 합니다.</p>
<p align="left"><span style="color: #ff6600">(3) Software Interrupt</span></p>
<p align="left">비 특권모드에서 특권 모드로 진입하기 위해서 Software Interrupt 명령어를 실행한 경우 발생</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM016.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2840" alt="15FJKARM016" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM016-620x235.jpg" width="434" height="165" /></a></p>
<p><span style="color: #ff6600">(4) Prefetch Abort</span><br />
Illegal 주소에서 명령어를 가져와서 실행 하려는 경우에 발생<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM018.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2842" alt="15FJKARM018" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM018-620x207.jpg" width="434" height="145" /></a></p>
<p><span style="color: #ff6600">(5) Data Abort</span><br />
Illegal 주소에 Data를 쓰거나 읽기 동작을 시도하는 경우에 발생<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM019.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2843" alt="15FJKARM019" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM019-620x306.jpg" width="434" height="214" /></a></p>
<p><span style="color: #ff6600">(6) IRQ</span><br />
ARM Processor 외부에서 인터럽트를 요청한 경우에 발생<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM020.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2844" alt="15FJKARM020" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM020-620x243.jpg" width="434" height="170" /></a></p>
<p><span style="color: #ff6600">(7) FIQ</span><br />
ARM Processor 왼부에서 Fast 인터럽트를 요청한 경우에 발생<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM021.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2845" alt="15FJKARM021" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM021-620x238.jpg" width="434" height="167" /></a><br />
Exception Handler를 종료하고 원래의 프로세스 흐름으로 복귀하는 Return 명령어의 공통점은 SUBS, MOVS 등으로 끝에 &#8220;S&#8221; 접미사가 따라 붙습니다. &#8220;S&#8221; 접미사의 의미는 Destination 레지스터가 만약 PC(R15) 라면 SPSR을 CPSR로 복원 하라는 의미의 접미사 입니다. 물론 이러한 과정은 H/W 적으로 이루어 집니다.</p>
<p>아래 그림은 IRQ 발생시 처리하는 절차 입니다. 위에서 언급했던 내용들과 비교해 보시기 바랍니다.<br />
프로그램의 정상적인 흐름에서 0&#215;1004번지 명령어 처리중에 IRQ 예외가 발생하면 0&#215;1004 번지의 명령어 수행이 완료가 된 이후에 IRQ 예외의 Exception Vector인 0&#215;0018번지로 PC가 이동을 하고 0&#215;0018번지에서 실제로 IRQ 예외처리 핸들러 함수가 있는 번지로 다시 이동을 한다음 예외처리를 완료하고 다시 IRQ 예외가 발생한 다음 번지의 명령어가 있는 곳으로 &#8220;SUBS PC, LR, #4&#8243; 에 의해서 복귀해서 IRQ 예외가 발생하지 않은것처럼 계속해서 Normal 루틴이 실행이 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM06.jpg" rel="lightbox[2867]"><img class="alignnone size-large wp-image-2830" alt="15FJKARM06" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM06-620x283.jpg" width="620" height="283" /></a></p>
<p>위에서 한가지 설명을 빠뜨린 것이 있는데, IRQ 예외가 일어나면 H/W 적으로는 다음과 같은 일이 발생을 합니다.</p>
<p><span style="color: #ff6600">(1) CPSR 백업</span> : SPSR_irq = CPSR_svc<br />
<span style="color: #ff6600">(2) ARM 모드로 전환( 예외상황에서는 항상 ARM 모드로 수행이 됨)</span> : CPSR.T = 0<br />
<span style="color: #ff6600">(3) CPSR MODE 를 IRQ 모드로 변경</span> : CPSR[4:0] = 0b10010<br />
<span style="color: #ff6600">(4) IRQ 모드 마스킹(인터럽트가 Disable 됨)</span> : CPSR.I = 1<br />
<span style="color: #ff6600">(5) R14_irq = PC + #8</span><br />
<span style="color: #ff6600">(6) PC = 0&#215;18( IRQ Vector address)</span></p>
<p>(5)번 항목에서 LR(R14)에 PC + #8이 들어가는 이유는 특정 번지의 명령어가 수행될때 IRQ가 발생을 하면 Execution &#8211; Fetch &#8211; Decode 의 Pipe line 에서 보면 Execution 단계에서 실제 PC는 현재 실행중인 명령어의 Fetch(+4), Decode(+8) 단계가 실행이 되고 있기때문에 LR에는 PC + #8 번지의 값이 들어 가게 됩니다. 하지만 IAR, KEIL, ADS 등의 컴파일러 등에서는 IRQ발생시 LR레지스터 값을 조사해보면 LR의 값이 PC + #8 가 아니고 LR = PC 의 값과 동일하다고 표시 됩니다. 이것은 컴파일러 사용자의 혼동을 피하기 위해서 이렇게 표시를 하고 있는것 같습니다.</p>
<p><span style="color: #ff0000"><strong>6.5 Exception 과 Interrupt의 차이</strong></span><a id="134232252102523" name="6.5"></a></p>
<p>Exception과 Interrupt는 무엇이 다를까요. 경우에 따라서는 비슷한 의미 일수도 있습니다. 하지만 몇가지 다른점이 있습니다.</p>
<p><span style="color: #ff6600">(1) Exception</span><br />
- 특정 명령어 실행에 의한 오류시 발생<br />
- 클록에 동기 적으로 발생됨 : Exception은 주로 Core내부에서 발생하기 때문에 Core의 클럭에 동기적으로 발생을 합니다.<br />
- 메모리 접근 오류, 디버깅 중단점, divide by zero&#8230; 등<br />
- 넓게 생각하면 Exception은 IRQ를 포함한다고 생각해도 됩니다.</p>
<p><span style="color: #ff6600">(2) Interrupt</span><br />
- Processor 의 명령어 실행과 관계없이 Processor 외부에서 주로 발생 &#8211;&gt; 클록에 비동기 적으로 발생 할수도 있음</p>
<p><span style="color: #ff0000"><strong>6.6 ARM에서의 Interrupt system</strong></span><a id="134232252102524" name="6.6"></a></p>
<p>ARM Cortex시리즈 이전의 전통적인 ARM Core에는 인터럽트로 받아 드릴 수 있는 방식은 IRQ, FIQ 2가지 밖에 없습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM036.jpg" rel="lightbox[2867]"><img class="alignnone  wp-image-2860" alt="15FJKARM036" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/15FJKARM036-620x165.jpg" width="496" height="132" /></a></p>
<p>위의 그림은 ARM9 Core의 인터럽트 블럭도 입니다. Interrupt Controller 와 Physical Interrupts 소스는 ARM Core 내부의 블럭이 아닙니다. Interrupt Controller 와 Physical Interrupts 부분은 ARM Core를 이용해서 설계한 S3C2440등의 CPU 블럭 입니다. 다시한번 말씀드리지만 ARM Core에는 IRQ나 FIQ냐만을 받아 들일 수 있습니다. Interrupt Controller는 CPU Vendor에 의해서 다르게 디자인 될수도 있습니다.</p>
<p><a href="http://www.ntrexgo.com/archives/2515" target="_blank"><strong>2부 계속</strong></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/2867/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[14호] 2011 캡스톤 디자인 공모전 우수상- 보행보조기구 2부</title>
		<link>http://www.ntrexgo.com/archives/1686</link>
		<comments>http://www.ntrexgo.com/archives/1686#comments</comments>
		<pubDate>Tue, 25 Sep 2012 09:21:19 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[14호]]></category>
		<category><![CDATA[공모전]]></category>
		<category><![CDATA[매거진]]></category>
		<category><![CDATA[캡스톤]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=1686</guid>
		<description><![CDATA[디바이스마트 매거진 14호 &#124; 보조기구는 고관절 이하가 전부 마비된 환자부터, 근력이 부족한 사람들까지 폭넓게 이용이 가능한 보행보조기구이다. 기존 보행기 타입인 부분 마비 장애인이나 노약자들이 직접 밀어야 하는 형태의 보행보조기구의 단점을 개선하고 모터, 센서 등을 사용하여 보다 자연스러운 움직임과 자유롭게 움직일 수 있도록 하는 기구를 설계, 제작한다.]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.ntrexgo.com/archives/1678" target="_blank"><span style="color: #666699"><span style="color: #666699"><b>1부 보러 가기</b></span></span></a></p>
<p>&nbsp;</p>
<p><span style="color: #800000"><strong>4. 제어부</strong></span></p>
<p><span style="color: #ff6600"><strong>4.1 작동 프로세스</strong></span><br />
<span style="color: #ff9900"><strong>4.1.1 작동 프로세스 개요</strong></span></p>
<p><a style="line-height: 19px" href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef02.jpg" rel="lightbox[1686]"><img class="size-large wp-image-1768 aligncenter" alt="2011capstonef02" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef02-620x267.jpg" width="620" height="267" /></a></p>
<p>RF MODEM A3007B는 UART 통신 방식을 지원하므로 목발의 MCU와 UART 방식의 통신을 한다. 목발의 MCU는 목발 밑에 부착된 스위치가 ON이 되거나 일어서기/앉기 스위치가 ON이 될 경우에 RF Modem이 해당 모드에 맞는 신호를 보내도록 한다. RF Modem 간의 통신을 통해 메인 MCU가 신호를 받아들이면 RS485 통신 방식을 사용하여 2개의 모터컨트롤러가 작동될 수 있도록 한다. RS485는 1:n의 통신방식을 지원하기 때문에 2개의 통신포트를 가지고도 여러 개의 통신을 할 수 있다. 메인 MCU의 UART0 포트는 RF Modem의 수신부와, UART1의 포트는 2개의 컨트롤러와 각각 연결된다.</p>
<p style="text-align: center"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef03.jpg" rel="lightbox[1686]"><img class=" wp-image-1769 aligncenter" alt="2011capstonef03" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef03-620x342.jpg" width="434" height="239" /></a></p>
<p>기존목발에 스위치를 부착하여 양 목발이 순차적으로 ON 상태가 되면 모터가 작동하여 걸음이 가능하도록 설계한다. 스위치와 모터의 연결은 RF Modem을 사용한 무선통신으로, 보행에 방해가 되지 않게 한다.</p>
<p><span style="color: #ff9900"><strong>4.1.2 걷기</strong></span></p>
<p>양 목발이 동시에 땅을 짚을 경우, 4점 보행법으로 작동한다. 고관절부의 엉치뼈에 장착된 모터가 1차로 구동이 되어 허벅지 부분을 들어 올려주며, 순차적으로 무릎 부분의 모터가 구동을 시작하여 무릎을 일정한 각도까지 굽혀준다. 허벅지 부분의 모터 구동이 잠시 멈추면 무릎 부분의 모터가 작동하여 보행이 가능한 일정각도까지 무릎을 펴줌과 동시에 장애인은 목발에 하중을 싣고 몸을 앞으로 숙여 발바닥이 땅에 닿도록 한다. 한쪽 발바닥이 발바닥에 고정되고 목발에 일정한 압력이 다시 가해지면 반대쪽 발이 같은 원리로 구동을 시작한다.</p>
<p><span style="color: #ff9900"><strong>4.1.3 앉기/일어나기</strong></span></p>
<p>의자에 앉거나 일어나는 경우는 목발에 부착된 별도의 스위치를 사용하여 구동하도록 한다. 스위치를 사용하여 앉는 경우엔 무릎부의 모터가 중심이 되기 때문에 걸을 때에 비해 큰 각도로 회전하며, 엉치뼈 부분의 모터가 추가적으로 회전하여 허리를 숙이게 함으로써 의자에 앉는 것이 가능하게끔 한다.</p>
<p>일어나는 경우, 모터가 앉는 경우와 반대로 회전하여 일어서는 것을 도와준다. 이 때, 사용자는 최대한 목발에 의지해 몸의 무게중심을 앞으로 쏠리게 하여 무릎부분 관절에 가해지는 힘을 분산시키도록 한다.</p>
<p><span style="color: #ff6600"><strong>4.2 회로도</strong></span></p>
<p><span style="color: #ff9900"><strong>4.2.1 전원부</strong></span></p>
<table width="580" align="center">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef54.jpg" rel="lightbox[1686]"><img class=" wp-image-1771 alignnone" alt="2011capstonef54" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef54-620x238.jpg" width="558" height="214" /></a></td>
</tr>
</tbody>
</table>
<p><span style="color: #ff9900"><strong>4.2.2 스위치 및 LED</strong></span></p>
<div align="center">
<table width="580">
<tbody>
<tr>
<td>
<div id="attachment_1770" class="wp-caption alignnone" style="width: 198px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef53.jpg" rel="lightbox[1686]"><img class=" wp-image-1770    " alt="스위치 및 LED회로" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef53.jpg" width="188" height="287" /></a><p class="wp-caption-text">스위치 및 LED회로</p></div></td>
<td>
<div id="attachment_1773" class="wp-caption alignnone" style="width: 249px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef56.jpg" rel="lightbox[1686]"><img class=" wp-image-1773 " alt="외부 스위치 회로" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef56-265x300.jpg" width="239" height="270" /></a><p class="wp-caption-text">외부 스위치 회로</p></div></td>
</tr>
</tbody>
</table>
</div>
<p><span style="color: #ff9900"><strong>4.2.3 RF Modem 회로</strong></span></p>
<table width="580" align="center">
<tbody>
<tr>
<td>
<div id="attachment_1772" class="wp-caption alignnone" style="width: 405px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef55.jpg" rel="lightbox[1686]"><img class="size-full wp-image-1772" alt="RF 송수신 회로" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef55.jpg" width="395" height="249" /></a><p class="wp-caption-text">RF 송수신 회로</p></div></td>
</tr>
</tbody>
</table>
<p><span style="color: #ff6600"><strong>4.3 작동 소스</strong></span></p>
<p>사용 프로그램 | ATMEL사에서 제공하는 AVR Studio프로그램을 사용.<br />
4.3.1 RF Modem(송신부)</p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">RF Modem 송신부(앉기/일어나기) 소스보기</h3><div class="symple-toggle-container">
<p>#include &lt;avr/io.h&gt;<br />
#include &lt;util/delay.h&gt;</p>
<p>// RF로 송신 할 값을 캐릭터 함수로 설정<br />
//HEAD(0xAA,0xBB, OP code(주파수 311/송신 12 + 송신할 문자)<br />
char RF_FREQ_SET[5]={0xAA,0xBB,3,1,1}; //주파수 세팅<br />
char RF_TX0_STAND[6]={0xAA,0xBB,1,2,1,1}; //일어서기 모드<br />
char RF_TX0_SIT[6]={0xAA,0xBB,1,2,7,7}; //앉기 모드<br />
char RF_TX0_WALK[6]={0xAA,0xBB,1,2,5,5}; //걷기 모드<br />
void TX0_CH(char ch){ while(!(UCSR0A&amp;0&#215;20)); UDR0=ch; }<br />
int main(void) //메인 함수 구문<br />
{<br />
char i; //캐릭터함수 i 설정<br />
DDRA=0xFF; DDRF=0&#215;00; DDRE=2;<br />
//PORTA 출력, PORTF 출력 TXD0 PORTE.1<br />
UCSR0A=0; UCSR0B=0&#215;18; UCSR0C=6; UBRR0H=0;<br />
UBRR0L=103;<br />
// UART0 통신관련 레지스터 설정 , BAUD RATE 9600bps<br />
_delay_ms(100);<br />
// RF 주파수 세팅<br />
for(i=0;i&lt;5;i++)TX0_CH(RF_FREQ_SET[i]);<br />
_delay_ms(1000);<br />
while(1)<br />
{<br />
//delay();<br />
if((PINF&amp;0&#215;04)==0&#215;00) // PORTF에 연결된 2번 스위치를 누르면<br />
{<br />
for(i=0;i&lt;6;i++)TX0_CH(RF_TX0_STAND[i]); //STAND값 송신<br />
_delay_ms(1000);<br />
}<br />
if((PINF&amp;0&#215;10)==0&#215;00) // PORTF에 연결된 4번 스위치를 누르면<br />
{<br />
for(i=0;i&lt;6;i++)TX0_CH(RF_TX0_SIT[i]); //SIT 값 송신<br />
_delay_ms(1000);<br />
}<br />
if((PINF&amp;0&#215;01)!=0&#215;00) // PORTF에 연결된 1번 스위치를 누르면<br />
{<br />
for(i=0;i&lt;6;i++)TX0_CH(RF_TX0_WALK[i]); //WALK 값 송신(left_on)<br />
_delay_ms(1000); }<br />
while(PINF&amp;1); // 누르고 있는 동안은 한 번만 함수 호출<br />
}<br />
}</p>
</div></div>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">RF Modem 송신부 소스보기</h3><div class="symple-toggle-container">
<p>#include &lt;avr/io.h&gt;<br />
#include &lt;util/delay.h&gt;</p>
<p>// RF로 송신 할 값을 캐릭터 함수로 설정<br />
//HEAD(0xAA,0xBB, OP code + (주파수 311/송신 12 + 송신할 문자)<br />
char RF_FREQ_SET[5]={0xAA,0xBB,3,1,1}; //주파수 세팅<br />
char RF_TX0_WALK[6]={0xAA,0xBB,1,2,4,4}; //걷기 모드<br />
void TX0_CH(char ch){ while(!(UCSR0A&amp;0&#215;20)); UDR0=ch; }<br />
int main(void) //메인 함수 구문<br />
{<br />
char i; //캐릭터함수 i 설정<br />
DDRA=0xFF; DDRF=0&#215;00; DDRE=2;<br />
//PORTA 출력, PORTF 출력 TXD0 PORTE.1<br />
UCSR0A=0; UCSR0B=0&#215;18; UCSR0C=6; UBRR0H=0; UBRR0L=103;<br />
// UART0 레지스터 설정 , BAUD RATE 9600bps<br />
_delay_ms(100); //딜레이 1초<br />
for(i=0;i&lt;5;i++)TX0_CH(RF_FREQ_SET[i]);<br />
// i의 숫자가 0에서 4까지 커지는 동안 RF는 주파수 세팅<br />
_delay_ms(1000);<br />
while(1)<br />
{</p>
<p>if((PINF&amp;0&#215;01)!=0&#215;00) // PORTF에 연결된 1번 스위치를 누르면<br />
{<br />
for(i=0;i&lt;6;i++)TX0_CH(RF_TX0_WALK[i]); //WALK 값 송신(right_on)<br />
_delay_ms(1000); }<br />
while(PINF&amp;1); // 누르고 있는 동안은 한 번만 함수 호출<br />
}<br />
}</p>
</div></div>
<p><span style="font-size: 13px;line-height: 19px">4.3.2 RF modem(수신부) :main MCU</span></p>
<div class="symple-toggle"><h3 class="symple-toggle-trigger">RF Modem 수신부 소스보기</h3><div class="symple-toggle-container">
<p>#include &lt;avr/io.h&gt;<br />
#include &lt;avr/interrupt.h&gt;<br />
#include &lt;util/delay.h&gt;<br />
#include &lt;stdio.h&gt;<br />
typedef unsigned char BYTE;<br />
#define BAUD_HIGH 00 //baudrate가 high일때 설정<br />
#define BAUD_LOW_M 8 // 모터의 bps는 115200으로 설정<br />
#define BAUD_LOW_RF 103 // RF모뎀의 bps는 9600으로 설정<br />
#define ALL_FLAG_CLEAR 0&#215;00<br />
#define USATR_RECEIVER_ENABLE 0&#215;10<br />
#define USATR_TRANSMITTER_ENABLE 0&#215;08<br />
#define USATR_CHARACTER_SIZE 0&#215;06<br />
//TXD, RXD 설정<br />
#define RXC_FLAG 0&#215;80<br />
#define TXC_FLAG 0&#215;20<br />
#define COM1 1<br />
//<br />
static int uart_putchar(char c, FILE *stream);<br />
static FILE mystdout=FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);<br />
volatile BYTE movement;<br />
volatile char RF_FREQ_SET[5]={0xAA,0xBB,3,1,1}; //RF 주파수 세팅<br />
volatile int MODE, right_on=0, left_on=0, standing=0, sitting=0;<br />
//<br />
void TX0_CH(char ch){ while(!(UCSR0A&amp;0&#215;20)); UDR0=ch; } // UART0 송신 함수<br />
//<br />
ISR(USART0_RX_vect){ // Interrupt Service Routine<br />
char ch;<br />
ch=UDR0; //UDR0의 값을 ch에 저장<br />
if(ch==7)sitting=1; // 만약 ch가 7이면 sitting ==1<br />
else if(ch==1)standing=1; // ch가 1이면 standing ==1<br />
else if(ch==4)right_on=1; // ch가 4이면 right_on ==1<br />
else if(ch==5)left_on=1; //ch가 5이면 left_on ==1<br />
}<br />
//<br />
void initialize_serial(void){ // initialize_serial 함수 정의<br />
UBRR1H=BAUD_HIGH; UBRR1L=BAUD_LOW_M; // UDR1 레지스터 설정<br />
UCSR1A=ALL_FLAG_CLEAR; //<br />
UCSR1B=USATR_RECEIVER_ENABLE | USATR_TRANSMITTER_ENABLE;<br />
UCSR1C=USATR_CHARACTER_SIZE;<br />
}<br />
//<br />
static int uart_putchar(char c, FILE *stream){<br />
if(c==’\n’) uart_putchar(‘\r’, stream);<br />
if(MODE==COM1){ loop_until_bit_is_set(UCSR1A, UDRE); UDR1=c; }<br />
return 0;<br />
}<br />
//<br />
void TX1_CH(char ch){ while(!(UCSR1A&amp;0&#215;20)); UDR1=ch; }<br />
// UART1의 송신함수<br />
//<br />
void setting(){ // 모터 세팅 함수<br />
unsigned volatile char i;<br />
BYTE SendBuff[256]={0};<br />
PORTA=0xff;<br />
MODE=COM1;<br />
// 컨트롤러 세팅값 (SS2000,2000, Ss200,200, SM0202, PE0001 .. ) 전송<br />
// 모터 컨트롤러에 각각 채널 1,2로 값을 전송함<br />
// 0&#215;01 :１번 컨트롤러ID 0&#215;02 : 2번 컨트롤러 ID<br />
memset(SendBuff,0,sizeof(BYTE)*256); //초기화<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”SS2000,2000!”); _delay_ms(1); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”Ss200,200!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”SM0202!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PE0001!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”SS2000,2000!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”Ss200,200!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”SM0202!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PE0002!”); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1000);</p>
<p>_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
}<br />
//<br />
void standing_M(){ // 모터의 일어나기 동작을 정의<br />
unsigned volatile char i;<br />
BYTE SendBuff[256]={0};<br />
MODE=COM1;<br />
//위치 제어 PA 명령어를 사용하여 위치값 전송<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA5200000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA4800000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1000);</p>
<p>_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(10000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA5200000,5500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA4800000,4500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);<br />
memset(SendBuff,0,sizeof(BYTE)*256);</p>
<p>_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(1000000);<br />
_delay_ms(100000);<br />
_delay_ms(10000);<br />
_delay_ms(100000);<br />
_delay_ms(10000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);</p>
<p>SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA4800000,5500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(1);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA5200000,4500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(100);</p>
<p>}<br />
//<br />
void walking_M(){ // 모터의 걷기 동작을 정의<br />
unsigned volatile char i; // 캐릭터 함수 i 설정<br />
BYTE SendBuff[256]={0};<br />
PORTA=0&#215;00; // PORTA의 LED가 꺼짐<br />
MODE=COM1;<br />
_delay_ms(100);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA5200000,5500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);</p>
<p>_delay_ms(1000);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA5200000,5100000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);</p>
<p>_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA5200000,5500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);</p>
<p>_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA4800000,5500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);</p>
<p>_delay_ms(100);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA4700000,4500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);</p>
<p>_delay_ms(100);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA4700000,5000000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);</p>
<p>_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA5200000,4500000!”); _delay_ms(100); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]);</p>
<p>_delay_ms(10);<br />
}</p>
<p>//<br />
void sit_M(){ // 앉기 동작 정의<br />
unsigned volatile char i;<br />
BYTE SendBuff[256]={0};<br />
PORTA=0&#215;00;<br />
MODE=COM1;<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA4800000,5500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA5200000,4500000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);</p>
<p>_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(100000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
_delay_ms(10000);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA4800000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA5200000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);</p>
<p>_delay_ms(100000); _delay_ms(100000); _delay_ms(100000); _delay_ms(100000);<br />
_delay_ms(100000); delay_ms(100000); _delay_ms(100000); _delay_ms(10000);<br />
_delay_ms(100000); _delay_ms(100000); _delay_ms(100000); _delay_ms(1000);<br />
_delay_ms(1000); _delay_ms(10000);</p>
<p>memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;01; sprintf(&amp;SendBuff[1],”PA5000000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);<br />
memset(SendBuff,0,sizeof(BYTE)*256);<br />
SendBuff[0]=0&#215;02; sprintf(&amp;SendBuff[1],”PA5000000,5000000!”); _delay_ms(10); i=0; while(SendBuff[i])TX1_CH(SendBuff[i++]); _delay_ms(10);<br />
}<br />
//<br />
int main(void){<br />
char i;<br />
left_on=right_on=sitting=standing=0;<br />
DDRA=0xff;<br />
DDRE=2;<br />
DDRG=0b11000000;<br />
UCSR0A=0; UCSR0B=0&#215;98; UCSR0C=6; UBRR0H=0; UBRR0L=103;<br />
//UART0 레지스터 설정, BAUD RATE 9600bps<br />
PORTA=0xff;<br />
initialize_serial(); //초기화<br />
_delay_ms(1);<br />
stdout=&amp;mystdout;<br />
_delay_ms(1000);<br />
for(i=0;i&lt;5;i++)TX0_CH(RF_FREQ_SET[i]); //RF 주파수 세팅<br />
_delay_ms(1000);<br />
sei(); //인터럽트 허용<br />
while(standing==0); //standing==1이 될 때 까지 대기<br />
while(left_on==0); //right_on 과 left_on 둘다 1이 될 때까지 대기<br />
PORTA=0&#215;00;<br />
setting(); // 모터 세팅 호출<br />
_delay_ms(10000);<br />
_delay_ms(10000);<br />
standing_M(); //딜레이 후 일어서는 동작 호출<br />
while(1){<br />
//left_on과 right_on이 둘다 1이라면 걷기 동작 호출<br />
left_on==0;<br />
if((left_on&amp;right_on)==1){<br />
walking_M(); left_on=0; right_on=0; } //함수 호출 후 left_on=0으로 초기화<br />
//sitting==1이 되면 앉기 동작 호출<br />
if(sitting==1){<br />
sit_M(); sitting=0;<br />
}<br />
}<br />
return 0;<br />
}</p>
<p><span style="font-size: 13px;line-height: 19px"></div></div></span></p>
<p><span style="color: #993300"><strong>5. 제작 과정</strong></span></p>
<p><span style="color: #ff6600"><strong>5.1 부품 사진</strong></span></p>
<p><span style="color: #ff9900"><strong>5.1.1 설계부</strong></span></p>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1777" class="wp-caption alignnone" style="width: 423px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef60.jpg" rel="lightbox[1686]"><img class=" wp-image-1777 " alt="135 브라켓" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef60.jpg" width="413" height="276" /></a><p class="wp-caption-text">135 브라켓</p></div></td>
</tr>
</tbody>
</table>
<p>허벅지 관절부와 무릎 관절부 발목을 잇고, 지탱해주면서 몸에 최대한 밀접하게 붙게 하는 뼈대 브라켓이다.</p>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1778" class="wp-caption alignnone" style="width: 411px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef61.jpg" rel="lightbox[1686]"><img class=" wp-image-1778   " alt="베벨기어박스" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef61-620x405.jpg" width="401" height="263" /></a><p class="wp-caption-text">베벨기어박스</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1779" class="wp-caption alignnone" style="width: 226px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef62.jpg" rel="lightbox[1686]"><img class=" wp-image-1779  " alt="Base plate(고 관절부)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef62-300x225.jpg" width="216" height="162" /></a><p class="wp-caption-text">Base plate(고 관절부)</p></div></td>
<td>
<div id="attachment_1780" class="wp-caption alignnone" style="width: 174px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef63.jpg" rel="lightbox[1686]"><img class="size-full wp-image-1780" alt="모터 크라켓" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef63.jpg" width="164" height="151" /></a><p class="wp-caption-text">모터 크라켓</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1781" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef64.jpg" rel="lightbox[1686]"><img class=" wp-image-1781 " alt="허리 관절면" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef64-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">허리 관절면</p></div></td>
<td>
<div id="attachment_1782" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef65.jpg" rel="lightbox[1686]"><img class=" wp-image-1782 " alt="Base plate(무릎 관절부)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef65-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">Base plate(무릎 관절부)</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1783" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef66.jpg" rel="lightbox[1686]"><img class=" wp-image-1783 " alt="모터 브라켓" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef66-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">모터 브라켓</p></div></td>
<td>
<div id="attachment_1757" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef67.jpg" rel="lightbox[1686]"><img class=" wp-image-1757 " alt="무릎 관절면" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef67-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">무릎 관절면</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1758" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef68.jpg" rel="lightbox[1686]"><img class=" wp-image-1758 " alt="기어" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef68-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">기어</p></div></td>
<td>
<div id="attachment_1759" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef69.jpg" rel="lightbox[1686]"><img class=" wp-image-1759 " alt="Gear Box(하단 기어 중심 고정부)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef69-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">Gear Box(하단 기어 중심 고정부)</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1760" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef70.jpg" rel="lightbox[1686]"><img class=" wp-image-1760 " alt="Gear Box(측면 기어 중심 고정부)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef70-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">Gear Box(측면 기어 중심 고정부)</p></div></td>
<td>
<div id="attachment_1761" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef71.jpg" rel="lightbox[1686]"><img class=" wp-image-1761 " alt="Gear Box(옆면 고정부)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef71-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">Gear Box(옆면 고정부)</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1762" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef72.jpg" rel="lightbox[1686]"><img class=" wp-image-1762 " alt="Shaft(하단 기어)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef72-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">Shaft(하단 기어)</p></div></td>
<td>
<div id="attachment_1763" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef73.jpg" rel="lightbox[1686]"><img class=" wp-image-1763 " alt="Shaft(측면기어)" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef73-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">Shaft(측면기어)</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1764" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef74.jpg" rel="lightbox[1686]"><img class=" wp-image-1764 " alt="로터 플랜지" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef74-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">로터 플랜지</p></div></td>
<td>
<div id="attachment_1767" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef77.jpg" rel="lightbox[1686]"><img class=" wp-image-1767 " alt="렉 플레이트" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef77-300x212.jpg" width="210" height="148" /></a><p class="wp-caption-text">렉 플레이트</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1765" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef75.jpg" rel="lightbox[1686]"><img class=" wp-image-1765 " alt="풋 플레이트" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef75-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">풋 플레이트</p></div></td>
<td>
<div id="attachment_1766" class="wp-caption alignnone" style="width: 220px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef76.jpg" rel="lightbox[1686]"><img class=" wp-image-1766 " alt="2011capstonef76" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef76-300x225.jpg" width="210" height="158" /></a><p class="wp-caption-text">힌지 핀</p></div></td>
</tr>
</tbody>
</table>
<p><span style="color: #ff9900"><strong>5.1.2 제어부</strong></span></p>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1809" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef79.jpg" rel="lightbox[1686]"><img class="size-thumbnail wp-image-1809  " alt="90W" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef79-150x150.jpg" width="150" height="150" /></a><p class="wp-caption-text">90W</p></div></td>
<td>
<div id="attachment_1810" class="wp-caption aligncenter" style="width: 160px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef80.jpg" rel="lightbox[1686]"><img class="size-thumbnail wp-image-1810 " alt="150W" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef80-150x150.jpg" width="150" height="150" /></a><p class="wp-caption-text">150W</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1811" class="wp-caption aligncenter" style="width: 308px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef82.jpg" rel="lightbox[1686]"><img class="wp-image-1811  " alt="모터 컨트롤러" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef82-620x348.jpg" width="298" height="167" /></a><p class="wp-caption-text">모터 컨트롤러</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1812" class="wp-caption alignnone" style="width: 310px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef83.jpg" rel="lightbox[1686]"><img class="size-medium wp-image-1812" alt="MOXA 232 to 485 컨버터" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef83-300x167.jpg" width="300" height="167" /></a><p class="wp-caption-text">MOXA 232 to 485 컨버터</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1813" class="wp-caption alignnone" style="width: 310px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef84.jpg" rel="lightbox[1686]"><img class="size-medium wp-image-1813" alt="RF 모뎀을 부착시킨 AVR 보드" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef84-300x180.jpg" width="300" height="180" /></a><p class="wp-caption-text">RF 모뎀을 부착시킨 AVR 보드</p></div></td>
</tr>
</tbody>
</table>
<p><span style="color: #ff9900"><strong>5.2 조립 사진</strong></span></p>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1814" class="wp-caption alignnone" style="width: 226px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef85.jpg" rel="lightbox[1686]"><img class=" wp-image-1814  " alt="직접 제어한 기어 박스 내부" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef85-300x225.jpg" width="216" height="162" /></a><p class="wp-caption-text">직접 제어한 기어 박스 내부</p></div></td>
<td>
<div id="attachment_1815" class="wp-caption alignnone" style="width: 170px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef86.jpg" rel="lightbox[1686]"><img class=" wp-image-1815   " alt="목발 바닥에 부착한 스위치" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef86-277x300.jpg" width="160" height="173" /></a><p class="wp-caption-text">목발 바닥에 부착한 스위치</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1816" class="wp-caption alignnone" style="width: 407px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef87.jpg" rel="lightbox[1686]"><img class=" wp-image-1816  " alt="모터와 컨트롤러 연결 사진" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef87-620x348.jpg" width="397" height="222" /></a><p class="wp-caption-text">모터와 컨트롤러 연결 사진</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1807" class="wp-caption alignnone" style="width: 177px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef78.jpg" rel="lightbox[1686]"><img class="size-medium wp-image-1807" alt="고관절부 착용 사진" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef78-167x300.jpg" width="167" height="300" /></a><p class="wp-caption-text">고관절부 착용 사진</p></div></td>
<td>
<div id="attachment_1817" class="wp-caption alignnone" style="width: 177px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef81.jpg" rel="lightbox[1686]"><img class="size-medium wp-image-1817" alt="발목부분 착용 사진" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef81-167x300.jpg" width="167" height="300" /></a><p class="wp-caption-text">발목부분 착용 사진</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1808" class="wp-caption alignnone" style="width: 407px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef89.jpg" rel="lightbox[1686]"><img class=" wp-image-1808  " alt="보드를 부착한 목발" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef89-620x465.jpg" width="397" height="298" /></a><p class="wp-caption-text">보드를 부착한 목발</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1823" class="wp-caption alignnone" style="width: 208px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef91.jpg" rel="lightbox[1686]"><img class=" wp-image-1823 " alt="조립완성한 사진 1" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef91-247x300.jpg" width="198" height="240" /></a><p class="wp-caption-text">조립완성한 사진 1</p></div></td>
<td>
<div id="attachment_1824" class="wp-caption alignnone" style="width: 221px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef90.jpg" rel="lightbox[1686]"><img class=" wp-image-1824 " alt="조립완성한 사진 2" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef90-264x300.jpg" width="211" height="240" /></a><p class="wp-caption-text">조립완성한 사진 2</p></div></td>
</tr>
</tbody>
</table>
<p><span style="color: #ff6600"><strong>5.3 제작 과정</strong></span></p>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1820" class="wp-caption alignnone" style="width: 456px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef16.jpg" rel="lightbox[1686]"><img class=" wp-image-1820  " alt="브래드보드 시험 중인 Atmega128" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef16-620x287.jpg" width="446" height="207" /></a><p class="wp-caption-text">브래드보드 시험 중인 Atmega128</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1821" class="wp-caption alignnone" style="width: 456px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef17.jpg" rel="lightbox[1686]"><img class=" wp-image-1821  " alt="송신 테스트 중인 A3007B과 직접 만들었던 회로의 실험 모습" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef17-620x282.jpg" width="446" height="203" /></a><p class="wp-caption-text">송신 테스트 중인 A3007B과 직접 만들었던 회로의 실험 모습</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1822" class="wp-caption aligncenter" style="width: 456px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef131.jpg" rel="lightbox[1686]"><img class=" wp-image-1822  " alt="착용 후 모습" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef131-620x251.jpg" width="446" height="181" /></a><p class="wp-caption-text">착용 후 모습</p></div></td>
</tr>
</tbody>
</table>
<table class=" aligncenter">
<tbody>
<tr>
<td>
<div id="attachment_1819" class="wp-caption alignnone" style="width: 456px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef14.jpg" rel="lightbox[1686]"><img class=" wp-image-1819  " alt="착용 후 일어나는 과정" src="http://www.ntrexgo.com/wp-content/uploads/2013/03/2011capstonef14-620x520.jpg" width="446" height="374" /></a><p class="wp-caption-text">착용 후 일어나는 과정</p></div></td>
</tr>
</tbody>
</table>
<p><span style="color: #993300"><strong>6. 결론</strong></span></p>
<p><span style="color: #ff6600"><strong>6.1 설계 쪽 실패과정 &amp; 해결방안</strong></span></p>
<p>전체적인 기구부가 커지는 것을 막기 위해 모듈1의 베벨기어박스를 사용하였으나, 소형 베벨기어였기 때문에 큰 토크에서 견디는 힘이 부족했다. 기구부만 작동시키는 데에는 큰 무리가 가해지지 않았으나 사람이 착용하고 구동한 경우, 앉기 동작에서 문제가 발생하였다. 사람이 의자에 앉는 경우 하중이 뒤로 자연스레 쏠리는 것을 미처 계산하지 못한 바람에 기어 이빨이 손상된 일이 있었다.</p>
<p>따라서 무릎에 가해지는 토크를 보다 잘 견딜 수 있도록 기존보다 큰 2.5 모듈의 베벨기어로 바꾸었다. 결과적으로 이빨의 크기가 커져서 전체적인 기어박스 및 기구부의 크기도 덩달아 커졌지만 상대적으로 견딜 수 있는 토크의 크기도 커졌다.</p>
<p><span style="color: #ff6600"><strong>6.2 제어 쪽 실패과정 &amp; 해결방안</strong></span></p>
<p>ATmega128 보드를 직접 만들기 위해 브래드 보드에 꽂아 실험할 수 있는 UST-MPB-ATmega128 제품을 이용하여 기본적인 회로들을 확인하였다. 납땜을 하기 전 RF 모뎀 회로를 체크하기 위해 브래드 보드로 전원 회로 및 기본적인 송수신 회로를 작성한 후, PCB에 납땜을 하였다. 기본적인 RF 회로 및 스위치 회로는 납땜을 하여 확인을 하였으나, max232 회로 등이 제대로 작동을 하지 않았으며 잦은 브래드 보드 실험 및 전원 회로부에서 꼬인 회로들로 인해 대부분이 쇼트가 나서 max232의 회로를 확인할 수가 없었다. 보드를 다시 제작하려 했으나, 시간상의 문제로 보드를 다시 만들 수 없다고 판단하여 보드 옆에 회로 판이 부착된 개발보드 기능의 AVR 모듈을 이용하였다. 이 AVR 보드에 RF modem 회로 및 필요한 스위치 회로만 추가로 납땜을 해서 필요한 보드를 완성하였다.</p>
<p>기존의 통신방식은 RS232통신을 이용하는 것이어서 추가의 회로가 필요하지 않았지만 후에 RS485로 통신방식을 바꾸면서 RS485와 관련된 회로가 필요하게 되었다. SN75176이란 IC를 사용하여 통신을 할 생각이었으나, 추가적인 회로를 납땜하는 것보다 컨버터를 이용하는 편이 효율적이라 판단하여 MOXA사의 TCC-80 이라는 RS232 to RS485 컨버터를 사용하였다.</p>
<p>구동 프로세스가 목발에 연결된 스위치에 힘을 가하면 목발 쪽 RF가 메인보드에 신호를 송신하고 이러한 RF신호 2개가 메인보드에 수신되어야만 모터가 작동하는 것이라서 컨트롤러 2개, RF modem까지 총 3개의 통신포트가 필요했다. 모터 제어부와 RF 제어부를 따로 작업하다보니 UART방식과 RS232 통신 방식이 충돌이 날거라는 것을 고려하지 못하였다. 그 문제점을 해결하기 위해 메인 MCU를 2개 사용하는 것으로 진행하였었다. MCU를 2개 사용하여 연동하는 것보다 1:n의 통신이 가능한 RS485방식을 택하는 게 효율적이라 판단하였고, 이를 통해 포트 2개로 2개의 컨트롤러 RF modem까지 3개의 통신을 해결할 수 있게 되었다.</p>
<p><span style="color: #ff6600"><strong>6.3. 결론</strong></span></p>
<p>무릎 부분에 힘이 많이 걸리는 것을 고려하여 무릎부 기어를 2.5 베벨 기어로 선정하였고 통신방식은 RS485방식을 선택하여 보드의 개수를 줄일 수 있었다. 실제적인 작동의 경우 기구부만으로 앉고 일어서기 및 걷기 동작은 구현이 가능하며, 현재 사람이 착용한 채 동작을 구현하는 것은 부분적으로 가능하다. 앉기 및 일어서기 동작의 경우 사람이 착용한 채 동작을 구현할 수 있었으나, 걷기 동작의 경우 기구부를 착용하는 팀원이 아직 목발 사용에 익숙치 않아 걷기 움직임이 조금 부자연스러운 관계로 일반적인 걸음걸이의 형태로 각도를 제어하였다. 사람마다 걸음걸이 방식이 조금씩 다르기 때문에 팀원의 목발사용 연습과 함께 차후에 구현할 팀원의 걸음걸이에 맞춰 시연할 예정이다.</p>
<p><span style="color: #993300"><strong>7. 팀원 소개 및 역할 분담</strong></span></p>
<p>이수영 : 해석 및 RF 통신</p>
<p>홍준호 : 가공 및 조립</p>
<p>정그림 : 해석 및 3D Modeling</p>
<p>한솔 : 모터 제어</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/1686/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
