<?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; arm</title>
	<atom:link href="http://www.ntrexgo.com/archives/tag/arm/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>[18호]JK전자와 함께하는 ARM 완전정복(4)-2</title>
		<link>http://www.ntrexgo.com/archives/13757</link>
		<comments>http://www.ntrexgo.com/archives/13757#comments</comments>
		<pubDate>Fri, 10 May 2013 04:22:34 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[18호]]></category>
		<category><![CDATA[applications]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=13757</guid>
		<description><![CDATA[디바이스마트매거진 18호 &#124; ARM Architecture 강의에서는 특정 CPU(S3C2440, STM32Fxx) 에 대한 내용 보다는 ARM Core의 이론적인 구조 자체에 대해서 많은 설명을 하였습니다. 이번 강의에서는 Samsung의 ARM9 CPU S3C2440 개발보드를 이용해서 실제 실습을 통해서 ARM에 대해서 공부해 보도록 하겠습니다.]]></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[13757]"><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></p>
<p><strong style="line-height: 19px"><span>Ⅱ.ARM Applications &#8211; 2부</span></strong></p>
<p>글 | JK전자</td>
</tr>
</tbody>
</table>
<p><span style="color: #00ccff"><strong>(7) Stack Pointer 초기화</strong></span></p>
<p>각 프로세서 모드별(7개 동작모드)로 Processor Mode를 전환하면서 Stack을 초기화해야 합니다. 이전 강좌인 ARM Architecture의 ARM Register 부분을 다시 보시면 R13(SP)는 각 동작 모드별로 뱅크 되어 있는 레지스터임을 확인 할 수 있습니다. 여기서 주의해야 할 점은 User Mode Stack은 제일 마지막에 초기화해야 합니다. 왜 그럴까요? User Mode는 비특권 모드이므로 한번 User Mode로 진입을 하여 SWI 명령등을 사용하지 않으면 다시 특권 모드로 진입을 할 수 없어서 다른 Processor Mode의 Stack Pointer를 초기화할 수가 없습니다. 이런 이유로 해서 User Mode의 Stack Pointer를 제일 마지막에 초기화하도록 해야 합니다.</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #ff0000">;function initializing stacks </span><br />
<span style="color: #ff0000">InitStacks </span><br />
<span style="color: #ff0000">;Don&#8217;t use DRAM,such as stmfd,ldmfd&#8230;&#8230; </span><br />
<span style="color: #ff0000">;SVCstack is initialized before </span><br />
<span style="color: #ff0000">;Under toolkit ver 2.5, &#8216;msr cpsr,r1&#8242; can be used instead of &#8216;msr cpsr_cxsf,r1&#8242; </span><br />
<span style="color: #ff0000">mrs r0,cpsr </span><br />
<span style="color: #ff0000">bic r0,r0,#MODEMASK </span><br />
<span style="color: #ff0000">orr r1,r0,#UNDEFMODE|NOINT </span><br />
<span style="color: #ff0000">msr cpsr_cxsf,r1 ;UndefMode </span><br />
<span style="color: #ff0000">ldr sp,=UndefStack</span><span style="color: #ff0000">orr r1,r0,#ABORTMODE|NOINT </span><br />
<span style="color: #ff0000">msr cpsr_cxsf,r1 ;AbortMode </span><br />
<span style="color: #ff0000">ldr sp,=AbortStack</span><span style="color: #ff0000">orr r1,r0,#IRQMODE|NOINT </span><br />
<span style="color: #ff0000">msr cpsr_cxsf,r1 ;IRQMode </span><br />
<span style="color: #ff0000">ldr sp,=IRQStack</span><span style="color: #ff0000">orr r 1,r0,#FIQMODE|NOINT </span><br />
<span style="color: #ff0000">msr cpsr_cxsf,r1 ;FIQMode </span><br />
<span style="color: #ff0000">ldr sp,=FIQStack ;// 아래(System Mode Stack) 부분 추가 함.</span><span style="color: #ff0000">bic r0,r0,#MODEMASK|NOINT </span><br />
<span style="color: #ff0000">orr r1,r0,#SYSMODE </span><br />
<span style="color: #ff0000">msr cpsr_cxsf,r1 ;SYSMode </span><br />
<span style="color: #ff0000">ldr sp,=SYSStack</span><span style="color: #ff0000">bic r0,r0,#MODEMASK|NOINT </span><br />
<span style="color: #ff0000">orr r1,r0,#SVCMODE </span><br />
<span style="color: #ff0000">msr cpsr_cxsf,r1 ;SVCMode </span><br />
<span style="color: #ff0000">ldr sp,=SVCStack</span><span style="color: #ff0000">;USER mode has not be initialized. We use always SVC mode.</span><span style="color: #ff0000">mov pc,lr ;The LR register won&#8217;t be valid if the current mode is not SVC mode.</span></td>
</tr>
</tbody>
</table>
<p><strong style="color: #00ccff">(8) Segment Initialization</strong></p>
<p>ROM Binary가 만들어 지고 나서 프로그램이 실행되기 위해서는 반드시 RAM이 있어야 합니다. Segment Initialization은 RAM에서 프로그램이 올바른 데이터를 가지고 실행될 수 있도록 RAM 영역에 전역변수의 초기값들을 저장하는 일을 합니다. 좀 더 자세한 사항은 이전 강좌인 ARM Architecture 4.4 Linker 부분을 참조하시기 바랍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm042.jpg" rel="lightbox[13757]"><img class="alignnone  wp-image-13728" alt="18feajkarm042" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm042-620x239.jpg" width="496" height="191" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm043.jpg" rel="lightbox[13757]"><img class="alignnone  wp-image-13729" alt="18feajkarm043" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm043-620x120.jpg" width="496" height="96" /></a></p>
<p>위의 그림에서 왼쪽이 ROM Binary 이고 오른쪽이 RAM 영역입니다.<br />
- .data : C언어 등에서 선언한 전역변수들의 초기값이 저장되어 있는 영역입니다.<br />
- .bss : 0으로 초기화 되는 영역입니다. 초기값을 지정하지 않은 전역변수등이 여기에 해당합니다.<br />
- .textrw : 컴파일러에 의해 생성된 RAM에서 실행되는 함수들 입니다.</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>#pragma segment = &#8220;.bss&#8221;<br />
#pragma segment = &#8220;.data&#8221;<br />
#pragma segment = &#8220;.data_init&#8221;<br />
#pragma segment = &#8220;.rodata&#8221;<br />
#pragma segment = &#8220;.textrw&#8221;<br />
#pragma segment = &#8220;.textrw_init&#8221;<br />
#pragma segment = &#8220;CSTACK&#8221;<br />
void InitSegment()<br />
{<br />
unsigned int k, n;<br />
unsigned char *pdst, *psrc;//<br />
// initialize zero-initialized segment<br />
//<br />
n = (unsigned int)__section_end(&#8220;.bss&#8221;) &#8211; (unsigned int)__section_begin(&#8220;.bss&#8221;);<br />
pdst = (unsigned char *)__section_begin(&#8220;.bss&#8221;);for(k=0; k&lt;n; k++)<br />
{<br />
*(pdst + k) = 0;<br />
}<br />
//<br />
// initialize non-zero-initialized segment<br />
//<br />
n = (unsigned int)__section_end(&#8220;.data_init&#8221;) &#8211; (unsigned int)__section_begin(&#8220;.data_init&#8221;);<br />
pdst = (unsigned char *)__section_begin(&#8220;.data&#8221;);<br />
psrc = (unsigned char *)__section_begin(&#8220;.data_init&#8221;);<br />
for(k=0; k&lt;n; k++)<br />
{<br />
*(pdst + k) = *(psrc + k);<br />
}//<br />
// initialize segment for ram-function<br />
//<br />
n = (unsigned int)__section_end(&#8220;.textrw_init&#8221;) &#8211; (unsignedint)__section_begin(&#8220;.textrw_init&#8221;);<br />
pdst = (unsigned char *)__section_begin(&#8220;.textrw&#8221;);<br />
psrc = (unsigned char *)__section_begin(&#8220;.textrw_init&#8221;);<br />
for(k=0; k&lt;n; k++)<br />
{<br />
*(pdst + k) = *(psrc + k);<br />
}return;<br />
}</td>
</tr>
</tbody>
</table>
<p><strong style="color: #00ccff">(9) main 함수로 이동</strong></p>
<p>EXTERN main<br />
ldr pc, =main</p>
<p>드디어 모든 Stack초기화와 Segment 초기화 과정을 끝내고 C 함수를 호출할 수 있게 되었습니다. 이제부터는 C 코드를 이용해서 각 디바이스들을 테스트할 수 있게 되었네요.</p>
<p>&nbsp;</p>
<p><span style="color: #3366ff"><strong>5.2 GPIO Output(LED On/Off)</strong></span></p>
<p>LED를 컨트롤 하기 위해서는 포트를 Output으로 설정한 후에 GPIO(General Purpose Input Output) 포트에 Low or High를 출력하면 됩니다. 아래 회로도는 우리가 실습에 사용하고 있는 Mini2440의 LED 회로도입니다. 4개의 LED가 있는데 각 LED는 GPB5 ~ 8 에 연결이 되어 있습니다. 그렇다면 LED1을 켜기 위해서 GPB5 포트에 Low(0)로 해야 할까요? 아니면 High(1)로 해야 할까요? 정답은 LED의 한쪽 끝이 VDD33V에 연결이 되어 있기 때문에 Low로 설정해야 전류의 흐름이 발생하여 LED가 켜지게 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm045.jpg" rel="lightbox[13757]"><img class="alignnone  wp-image-13731" alt="18feajkarm045" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm045-620x370.jpg" width="496" height="296" /></a><br />
<span style="text-decoration: underline">실험예제</span><br />
LED1, LED2는 On을 하고, LED3, LED4는 Off 시켜 봅니다.<br />
<span style="color: #33cccc">(1) GPBCON 레지스터에 GPB5 ~ GPB8을 Output으로 설정합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm014.jpg" rel="lightbox[13757]"><img class="size-full wp-image-13697 alignleft" alt="18feajkarm014" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm014.jpg" width="453" height="580" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #808080">// GPB5 Output</span><br />
<span style="color: #808080">(*(volatile unsigned *)0&#215;56000010) = (*(volatile unsigned *)0&#215;56000010) &amp; ~(0&#215;3 &lt;&lt; 10);</span><br />
<span style="color: #808080">(*(volatile unsigned *)0&#215;56000010) = (*(volatile unsigned *)0&#215;56000010) | (0&#215;1 &lt;&lt; 10);</span><span style="color: #808080">// GPB6 Output</span><br />
<span style="color: #808080">rGPBCON = rGPBCON &amp; ~(0&#215;3 &lt;&lt; 12);</span><br />
<span style="color: #808080">rGPBCON = rGPBCON | (0&#215;1 &lt;&lt; 12);</span><span style="color: #808080">// GPB7 Output</span><br />
<span style="color: #808080">rGPBCON = rGPBCON &amp; ~(0&#215;3 &lt;&lt; 14);</span><br />
<span style="color: #808080">rGPBCON = rGPBCON | (0&#215;1 &lt;&lt; 14);</span><span style="color: #808080">// GPB8 Output</span><br />
<span style="color: #808080">rGPBCON = rGPBCON &amp; ~(0&#215;3 &lt;&lt; 16);</span><br />
<span style="color: #808080">rGPBCON <span style="line-height: 19px">= rGPBCON | (0&#215;1 &lt;&lt; 16);</span></span></td>
</tr>
</tbody>
</table>
<p><span style="color: #33cccc">(2) GPBDAT 레지스터의 GPB5, GPB6을 Low로, GPB7, GPB8을 High로 세팅합니다.</span></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #808080">// LED1 On</span><br />
<span style="color: #808080">rGPBDAT = rGPBDAT &amp; ~(0&#215;1 &lt;&lt; 5);</span><br />
<span style="color: #808080">// LED2 On</span><br />
<span style="color: #808080">rGPBDAT = rGPBDAT &amp; ~(0&#215;1 &lt;&lt; 6);</span><br />
<span style="color: #808080">//rGPBDAT = rGPBDAT | (0&#215;1 &lt;&lt; 6);</span><br />
<span style="color: #808080">// LED3 Off</span><br />
<span style="color: #808080">rGPBDAT = rGPBDAT | (0&#215;1 &lt;&lt; 7);</span><br />
<span style="color: #808080">// LED4 Off</span><br />
<span style="color: #808080">rGPBDAT = rGPBDAT | (0&#215;1 &lt;&lt; 8);</span></td>
</tr>
</tbody>
</table>
<p>diag.c &#8211; led_test()</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>// GPB5 Output<br />
(*(volatile unsigned *)0&#215;56000010) = (*(volatile unsigned *)0&#215;56000010) &amp; ~(0&#215;3 &lt;&lt; 10);<br />
(*(volatile unsigned *)0&#215;56000010) = (*(volatile unsigned *)0&#215;56000010) | (0&#215;1 &lt;&lt; 10);// GPB6 Output<br />
rGPBCON = rGPBCON &amp; ~(0&#215;3 &lt;&lt; 12);<br />
rGPBCON = rGPBCON | (0&#215;1 &lt;&lt; 12);// GPB7 Output<br />
rGPBCON = rGPBCON &amp; ~(0&#215;3 &lt;&lt; 14);<br />
rGPBCON = rGPBCON | (0&#215;1 &lt;&lt; 14);// GPB8 Output<br />
rGPBCON = rGPBCON &amp; ~(0&#215;3 &lt;&lt; 16);<br />
rGPBCON = rGPBCON | (0&#215;1 &lt;&lt; 16);// LED1 On<br />
rGPBDAT = rGPBDAT &amp; ~(0&#215;1 &lt;&lt; 5);<br />
// LED2 On<br />
rGPBDAT = rGPBDAT &amp; ~(0&#215;1 &lt;&lt; 6);// LED3 Off<br />
rGPBDAT = rGPBDAT | (0&#215;1 &lt;&lt; 7);<br />
// LED4 Off<br />
rGPBDAT = rGPBDAT | (0&#215;1 &lt;&lt; 8);</td>
</tr>
</tbody>
</table>
<p><span style="text-decoration: underline">소스코드 분석</span></p>
<p>(*(volatile unsigned *)0&#215;56000010) = (*(volatile unsigned *)0&#215;56000010) &amp; ~(0&#215;3 &lt;&lt; 10);<br />
GPBCON 레지스터의 주소가 0&#215;50000010입니다. 0&#215;3(b11)을 왼쪽으로 10번 쉬프트를 하면 b110000000000이고 이것을 &#8220;~&#8221; (Bit clear) 시키면 GPB5[11:10] 부분이 &#8220;00&#8243; 으로 Clear 됩니다.</p>
<p>(*(volatile unsigned *)0&#215;56000010) = (*(volatile unsigned *)0&#215;56000010) | (0&#215;1 &lt;&lt; 10);<br />
0&#215;1(b01)을 왼쪽으로 10번 쉬프트를 하면 b010000000000 이고 이것을 &#8220;|&#8221; (OR) 시키면 GPB5[11:10] 부분이 &#8220;01&#8243; 으로 Output 설정됩니다.</p>
<p>소스 코드중에 volatile 이라는 것을 사용하고 있습니다. 이것은 컴파일러 최적화에서 제외되는 효과가 있습니다.</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>컴파일러 최적화 전</td>
<td>컴파일러 최적화 전</td>
</tr>
<tr>
<td>int a = 0; // 전역 변수<br />
int b = 0; // 전역 변수<br />
int i; // 로컬 변수for(i=0;i&lt;100;i++)<br />
b = b + a * 100;</td>
<td>int a = 0; // 전역 변수<br />
int b = 0; // 전역 변수<br />
int i; // 로컬 변수for(i=0;i&lt;100;i++)<br />
b = b + 0; // a * 100;</td>
</tr>
</tbody>
</table>
<p>위의 코드에서 오른쪽 코드처럼 개발자가 의도하지 않게 컴파일러에 의해 최적화가 되어 &#8220;a*100&#8243; 부분을 최적화하여 b 변수에 항상 0으로 저장이 되도록 할 수도 있습니다. 물론 일반적인 상황에서는 아무 문제가 되지 않지만 for 루프 수행중에 외부 인터럽트가 발생하여 인터럽트 서비스 루틴에서 a의 값을 0이 아닌 다른 값으로 변하게 한 후 다시 for 루프를 수행하면 개발자는 b에 0이 아닌 다른값이 저장되기를 기대하고 있겠지만 최적화된 코드에서는 b에 항상 0 이 저장이 되어 있을 것입니다. 이것은 개발자가 의도한 결과가 아닙니다. 이런 현상을 방지하기 위해서는 변수 a 를 volatile로 선언을 하면 됩니다. 특히나 SFR 레지스터 등에 값을 세팅하는 작업을 한다면 항상 volatile 로 선언을 해서 사용하는 것이 좋습니다.</p>
<p><span style="color: #3366ff"><strong>5.3 GPIO Input( KEY Input) &#8211; Polling</strong></span></p>
<p>LED를 켰을 때와 반대로 이번에는 GPIO포트를 이용해서 입력을 받아 보도록 하겠습니다. 포트에서 입력을 받기 위해서는 포트를 Input으로 설정한 후에 GPIO(General Purpose Input Output) 포트를 읽으면 됩니다. 6개의 KEY가 있는데 우리는 INT11, INT13에 연결되어 있는 K2, K3에 대해서 폴링 방식으로 입력을 감지해 보도록 하겠습니다. 참고로 폴링 방식이란 코드에서 무한 루프를 돌면서 특정 행위를 하는 것을 말합니다. 이번 경우에는 Key가 눌러졌는지를 감시하는 것이겠지요. 폴링과 다른 방식으로는 인터럽트 방식이 있습니다. 다음 절에서 공부하게 될 내용입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm044.jpg" rel="lightbox[13757]"><img class="alignnone  wp-image-13730" alt="18feajkarm044" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm044-620x268.jpg" width="496" height="214" /></a></p>
<p><span style="text-decoration: underline">실험예제</span><br />
K2, K3 를 읽어서 KEY가 눌러져 있으면 LED2, LED3 를 On으로 하고, 눌러져 있지 않으면 Off로 설정해봅시다.</p>
<p><span style="color: #33cccc">(1) GPGCON 레지스터에 GPG3, GPG5를 Input으로 설정합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm015.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13698" alt="18feajkarm015" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm015.jpg" width="459" height="452" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #808080">// KEY3, GPG5 Input</span><br />
<span style="color: #808080">rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 10); </span><br />
<span style="color: #808080">// KEY2, GPG3 Input</span><br />
<span style="color: #808080">rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 6);</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(2) GPGDAT 레지스터의 GPG3, GPG5를 읽어서 &#8220;0&#8243; 이면 KEY가 눌린 상태이고, &#8220;1&#8243; 이면 KEY가 눌러지지 않은 상태입니다.</span></p>
<p>diag.c &#8211; key_test()</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>// KEY3, GPG5 Input<br />
rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 10);<br />
// KEY2, GPG3 Input<br />
rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 6);while(1)<br />
{<br />
if( (rGPGDAT &amp; (0&#215;1 &lt;&lt; 3)) == 0 ) // KEY2 pressed<br />
// LED2 On<br />
rGPBDAT = rGPBDAT &amp; ~(0&#215;1 &lt;&lt; 6);<br />
else<br />
// LED2 Off<br />
rGPBDAT = rGPBDAT | (0&#215;1 &lt;&lt; 6);<br />
if( (rGPGDAT &amp; (0&#215;1 &lt;&lt; 5)) == 0 ) // KEY3 pressed<br />
// LED3 On<br />
rGPBDAT = rGPBDAT &amp; ~(0&#215;1 &lt;&lt; 7);<br />
else<br />
// LED3 Off<br />
rGPBDAT = rGPBDAT | (0&#215;1 &lt;&lt; 7);Delay(80);<br />
};</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong style="color: #3366ff">5.4 GPIO Input( KEY Input) &#8211; Interrupt</strong></p>
<p>이번에는 인터럽트 방식으로 K2, K3 입력을 감지해보도록 하겠습니다. 인터럽트 방식은 폴링방식보다 효율적이기는 하지만 좀 더 복잡합니다. 여기서 효율적이라고 하는 것은 CPU사용을 효과적으로 한다는 것이지 폴링방식보다 빠르다는 말은 아닙니다. 인터럽트 방식은 인터럽트 요청이 왔을때 인터럽트 서비스 루틴으로 분기할 때까지 지연시간이 있어 폴링 방식보다 느릴 수 있습니다. 하지만 폴링방식처럼 계속 루프를 돌면서 대기하지 않아도 되기 때문에 CPU활용면에서는 효율적입니다.</p>
<p><span style="text-decoration: underline">실험예제</span><br />
K2, K3를 읽어서 KEY가 눌러져 있으면 LED2, LED3를 On으로 하고 눌러져 있지 않으면 Off로 설정해봅시다.</p>
<p><span style="color: #33cccc">(1) GPGCON 레지스터에 GPG3, GPG5를 EINT(0&#215;2)으로 설정합니다.</span></p>
<p><span style="color: #33cccc"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm017.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13700" alt="18feajkarm017" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm017.jpg" width="450" height="235" /></a></span></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #808080">// KEY3, GPG5 EINT13</span><br />
<span style="color: #808080">rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 10);</span><br />
<span style="color: #808080">rGPGCON = rGPGCON | (0&#215;2 &lt;&lt; 10);</span><span style="color: #808080">// KEY2, GPG3 EINT11</span><br />
<span style="color: #808080">rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 6); </span><br />
<span style="color: #808080">rGPGCON = rGPGCON | (0&#215;2 &lt;&lt; 6);</span></td>
</tr>
</tbody>
</table>
<p><span style="color: #33cccc">(2) EXTINT1 레지스터에 EINT11, EINT13을 Falling Edge로 설정합니다.</span></p>
<p><strong>Extintn(External Interrupt Control Register n)</strong></p>
<p>The 8 external interrupts can be requested by various signaling methods. The EXTINT register configures configures the signaling method between the level trigger and edge trigger for the extemal interrupt request, and also configuress the signal polarity.<br />
To recognize the level interrupt, the valid logic level on EXTINTn pin must be retained for 40ns at least because of the noise filter.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm018.jpg" rel="lightbox[13757]"><img class="alignnone size-large wp-image-13701" alt="18feajkarm018" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm018-388x620.jpg" width="388" height="620" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #808080">// set eint13 falling edge trigger </span><br />
<span style="color: #808080">rEXTINT1 &amp;= ~(0&#215;7 &lt;&lt; 20);</span><br />
<span style="color: #808080">rEXTINT1 |= (0&#215;2 &lt;&lt; 20);</span><span style="color: #808080">// set eint11 falling edge trigger</span><br />
<span style="color: #808080">rEXTINT1 &amp;= ~(0&#215;7 &lt;&lt; 12);</span><br />
<span style="color: #808080">rEXTINT1 |= (0&#215;2 &lt;&lt; 12);</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(3) EINTPEND 레지스터의 Pending bit를 Clear 합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm019.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13702" alt="18feajkarm019" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm019.jpg" width="452" height="305" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #808080">// clear eint 11,13</span><br />
<span style="color: #808080">rEINTPEND |= (1 &lt;&lt; 11)|(1 &lt;&lt; 13);</span></td>
</tr>
</tbody>
</table>
<p>&#8220;It is cleard by writing 1&#8243; 이라는 문구가 보이는데요. 무슨 의미 일까요? 일반적으로 우리가 SFR 레지스터를 설정할 때에 아래와 같이 먼저 Bit를 Clear 시키고 Set 하는 2단계 과정을 거치게 됩니다.</p>
<p>rEXTINT1 &amp;= ~(0&#215;7 &lt;&lt; 20);<br />
rEXTINT1 |= (0&#215;2 &lt;&lt; 20);</p>
<p>하지만 인터럽트 서비스 루틴 안에서는 이것 조차도 비효율적일수 있고 Atmoic Operation이 아니기 때문에 Pending Clear를 하는 과정에서 새로운 인터럽트가 발생할 경우에 새로운 인터럽트가 지연될 수도 있습니다.</p>
<p>rEINTPEND |= (1 &lt;&lt; 11)|(1 &lt;&lt; 13);</p>
<p>이러한 이유로 위와 같이 &#8220;1&#8243; 을 써넣어서 바로 Pending을 Clear 할 수 있도록 한 것입니다.</p>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(4) EINTMASK 레지스터에서 Interrupt를 Enable 합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm020.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13703" alt="18feajkarm020" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm020.jpg" width="451" height="446" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #808080">// enable eint 11,13</span><br />
<span style="color: #808080">rEINTMASK &amp;= ~((1 &lt;&lt; 11)|(1 &lt;&lt; 13));</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(5) SRCPND 레지스터의 Pending bit를 Clear 합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm021.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13704" alt="18feajkarm021" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm021.jpg" width="450" height="139" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rSRCPND = (0&#215;1&lt;&lt;5); // Clear pending bit</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(6) INTPND 레지스터의 Pending bit를 Clear 합니다.</span><br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm022.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13705" alt="18feajkarm022" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm022.jpg" width="448" height="299" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rINTPND = (0&#215;1&lt;&lt;5); // Clear pending bit</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(7) EINT 인터럽트 서비스 루틴의 함수 포인터를 설정합니다.</span></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>pISR_EINT8_23 = (U32)isr_eint_8_23;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(8) INTMSK에서 EINT8_23 의 인터럽트를 Enable 합니다.</span><br />
<strong>INTERRUPT MASK(INTMSK) REGISTER</strong><br />
This register also has 32 bits each of which is related to an interrupt source. If a specific bit is set to 1, the CPU does not service the interrupt request from the corresponding interrupt source(note that even in such a case, the corresponding bit of SRCPND register is set to 1). If the mask bit is 0, the interrupt request can be serviced.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm023.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13706" alt="18feajkarm023" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm023.jpg" width="455" height="289" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rINTMSK &amp;= ~((0&#215;1&lt;&lt;5));</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(9) Startup코드의 IRQ Exception에서 인터럽트 번호를 확인하고 인터럽트 서비스 루틴으로 분기합니다.</span></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>IsrIRQ<br />
sub sp,sp,#4 ;reserved for PC &#8211;&gt; 1<br />
stmfd sp!,{r8-r9} ; &#8211;&gt; 2<br />
ldr r9,=INTOFFSET ; &#8211;&gt; 3<br />
ldr r9,[r9] ; &#8211;&gt; 4<br />
ldr r8,=HandleEINT0 ; &#8211;&gt; 5<br />
add r8,r8,r9,lsl #2 ; &#8211;&gt; 6<br />
ldr r8,[r8] ; &#8211;&gt; 7<br />
str r8,[sp,#8] ; &#8211;&gt; 8<br />
ldmfd sp!,{r8-r9,pc} ; &#8211;&gt; 9</td>
</tr>
</tbody>
</table>
<p>▶ 1 : 스택포인터를 1 감소하여 빈 공간을 만듭니다. 인터럽트 핸들러 함수의 주소값이 저장될 공간입니다.<br />
▶ 2 : r8, r9를 사용하고 복원해야 하므로 stack에 저장합니다. stmfd는 먼저 어드레스를 감소하고 저장하므로 1에서 만들어진 빈공간은 그대로 남아 있습니다.<br />
▶ 3, 4 : INTOFFSET을 r9에 로드합니다.<br />
▶ 5 : HandleEINT0를 r8에 로드합니다. HandleEINT0는 Startup 코드의 아래 부분에 정의되어 있습니다.<br />
▶ 6,7 : HandleEINT0 + INTOFFSET*4의 수식이 됩니다. INTOFFSET 레지스터에는 발생한 인터럽트 소스의 Offset 값이 들어있는 레지스터입니다.</p>
<p>우리는 EINT8_23을 이용할 것이기 때문에 INTOFFSET 레지스터에는 5가 저장되어 있을 것입니다. 그러므로 HandleEINT0 + 5*4 즉 HandleEINT8_23의 주소가 됩니다.<br />
소스코드에서 key_test_eint() 함수에서 pISR_EINT8_23 = (U32)isr_eint_8_23; 의 코드를 삽입하면 EINT8_23 인터럽트가 발생하면 isr_eint_8_23 함수로 분기를 하게 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm024.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13707" alt="18feajkarm024" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm024.jpg" width="451" height="469" /></a><br />
▶ 8 : str r8,[sp,#8] 에 의해서 맨 처음에 Stack의 빈공간을 만들어 두었던 곳으로 인터럽트 핸들러 함수의 포인터 주소값을 저장합니다.<br />
▶ 9 : r8, r9 를 Stack에서 복원하고 pc 에 인터럽트 핸들러 함수의 주소가 저장이 되어 실제로 인터럽트 핸들러 함수가 실행이 됩니다.</p>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(10) 인터럽트 서비스 루틴에서 GPGDAT 레지스터의 GPG3, GPG5를 읽어서 &#8220;0&#8243; 이면 KEY가 눌린 상태이고, &#8220;1&#8243; 이면 KEY 눌러지지 않은 상태입니다.</span></p>
<p>지금까지 설명한 인터럽트 관련 설정들을 S3C2440 인터럽트 컨트롤러 블럭도와 비교해서 보시기 바랍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm046.jpg" rel="lightbox[13757]"><img class="alignnone size-large wp-image-13732" alt="18feajkarm046" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm046-620x278.jpg" width="620" height="278" /></a><br />
Interrupt MODE도 IRQ/FIQ 설정을 해야 하지만 S3C2440의 기본 인터럽트 설정 값이 IRQ 이기 때문에 생략하였습니다.<br />
외부 인터럽트 1개를 서비스 받기 위해서 정말 많은 과정이 필요 하네요. ARM Applications 이후에 하게될 Cortex-M3 Architecture 부분에서도 인터럽트 서비스에 대해서 설명을 할텐데, 그때 Cortex-M3가 얼마나 간결하고 효율적인지 비교해 보시기 바랍니다.</p>
<p>diag.c &#8211; key_test_eint()</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>__irq __arm void isr_eint_8_23(void)<br />
{<br />
if(rINTPND==BIT_EINT8_23)<br />
{<br />
ClearPending(BIT_EINT8_23);<br />
if(rEINTPEND&amp;(1&lt;&lt;11))<br />
{<br />
rEINTPEND |= 1 &lt;&lt; 11;<br />
rGPBDAT = rGPBDAT ^ (0&#215;1 &lt;&lt; 6); // toggle<br />
}<br />
if(rEINTPEND&amp;(1&lt;&lt;13))<br />
{<br />
rEINTPEND |= 1 &lt;&lt; 13;<br />
rGPBDAT = rGPBDAT ^ (0&#215;1 &lt;&lt; 7); // toggle<br />
}<br />
}<br />
}<br />
void key_test_eint(void)<br />
{// KEY3, GPG5 EINT13<br />
rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 10);<br />
rGPGCON = rGPGCON | (0&#215;2 &lt;&lt; 10);<br />
// KEY2, GPG3 EINT11<br />
rGPGCON = rGPGCON &amp; ~(0&#215;3 &lt;&lt; 6);<br />
rGPGCON = rGPGCON | (0&#215;2 &lt;&lt; 6);// set eint13 falling edge trigger<br />
rEXTINT1 &amp;= ~(0&#215;7 &lt;&lt; 20);<br />
rEXTINT1 |= (0&#215;2 &lt;&lt; 20);// set eint11 falling edge trigger<br />
rEXTINT1 &amp;= ~(0&#215;7 &lt;&lt; 12);<br />
rEXTINT1 |= (0&#215;2 &lt;&lt; 12);// clear eint 11,13 &#8211;&gt; clear by writing &#8220;1&#8243; test<br />
rEINTPEND |= (1 &lt;&lt; 11)|(1 &lt;&lt; 13);// enable eint 11,13<br />
rEINTMASK &amp;= ~((1 &lt;&lt; 11)|(1 &lt;&lt; 13));<br />
rSRCPND = (0&#215;1&lt;&lt;5); // Clear pending bit &#8211;&gt; clear by writing &#8220;1&#8243; test<br />
rINTPND = (0&#215;1&lt;&lt;5); // Clear pending bit &#8211;&gt; clear by writing &#8220;1&#8243; testpISR_EINT8_23 = (U32)isr_eint_8_23;<br />
// Enable EINT8_23 Interrupt<br />
rINTMSK &amp;= ~((0&#215;1&lt;&lt;5));}</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong><span style="color: #3366ff">5.5 Timer</span></strong></p>
<p>임베디드 시스템에서 Timer는 가장 중요하고 필수적인 요소중의 하나로 OS에서 Task 스케줄링을 위해서 사용되기도 합니다. 전자액자, 차량용 블랙박스 등의 응용 어플리케이션에서도 특정 시간 이후에 인터럽트를 발생시켜 정해진 일을 수행하는 경우등 응용분야는 무수히 많습니다.<br />
시간 이야기가 나와서 이야기 하는데 CPU의 클럭 속도가 1Hz 라는 것은 무엇을 의미하는 것일까요? 이것은 1초에 1번의 Tick이 발생한다는 것입니다. 아주 정확한 것은 아니지만 캐시가 있는 시스템에서 캐시 Hit(캐시에서 데이터 혹은 명령어를 가지고 올 경우)일 경우에 1초에 1개의 명령어를 수행한다는 것과 같습니다. S3C2440이 400MHz 로 동작한다면 1초에 4억번의 Tick이 발생하는 것입니다. 정말 어마어마 하지요. 상상해 보세요. 요즘 최신 스마트폰들은 2GHz CPU이면서 그것도 듀얼 코어입니다. 아래는 시간과 주파수 사이의 관계입니다. Timer 설정하는데 이정도는 알고 있어야 합니다. 잘 기억하시기 바랍니다.</p>
<p>- 1sec = 1,000ms = 1,000,000us = 1,000,000,000ns<br />
- 1Hz = 1KHz = 1MHz = 1GHz</p>
<p><span style="text-decoration: underline">실험예제</span><br />
S3C2440 CPU의 내장된 Timer4를 이용해서 1초에 한번씩 Timer 인터럽트를 발생시켜 LDE2를 Blink(On/Off) 하는 실험을 해보도록 하겠습니다.</p>
<p><span style="color: #33cccc">(1) TCFG0 레지스터의 Timer4 Prescaler를 15로 설정합니다.</span></p>
<p><strong>Timer CONFIGURATION REGISTER0 (TCFG0)</strong><br />
Timer input clock Frequency = PCLK/{prescaler value+1}/{divider value}<br />
{prescaler value} = 0~255<br />
{divider value} = 2,4,8,16</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm025.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13708" alt="18feajkarm025" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm025.jpg" width="451" height="244" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>// Timer4 Prescaler = 15<br />
rTCFG0 = 0&#215;0;<br />
rTCFG0 = (15 &lt;&lt; 8);</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(2) TCFG1 레지스터의 Timer4 Divider를 1/2 로 설정합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm026.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13709" alt="18feajkarm026" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm026.jpg" width="453" height="337" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>// Timer4 Divider = 2<br />
rTCFG1 = 0&#215;0;<br />
rTCFG1 = (0&#215;0 &lt;&lt; 16);</td>
</tr>
</tbody>
</table>
<p>위와 같이 설정하면 Datasheet 에 있는 아래 공식에 의해서</p>
<p>Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}<br />
Timer input clock Frequency = 50000000/(15+1)/2 = 1562500</p>
<p>위의 계산식의 의미는 Timer4의 클럭이 1초에 1562500번 발생 한다는 의미입니다. 그러므로 Timer4 buffer count(TCNTB4)를 15625 로 설정해 주면 10ms마다 Auto Reload(Timer Overflow)가 되어 인터럽트가 발생하게 됩니다. 물론 간단하게 TCNTB4를 1562500로 설정해 주면 1초에 한번 발생하는 인터럽트를 만들 수 있겠지만, 안타깝게도 S3C2440의 타이머는 16비트 타이머이므로 최대 값으로 0xFFFF(65535) 이상을 사용할 수가 없습니다.</p>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(3) TCNTB4 레지스터에 Timer4 buffer count를 15625로 설정합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm027.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13710" alt="18feajkarm027" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm027.jpg" width="454" height="147" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>// buffer count<br />
rTCNTB4 = 15625; // interrupt resolution 10msec</td>
</tr>
</tbody>
</table>
<p><span style="color: #33cccc">(4) TCON 레지스터에 Update TCNTB4와 Auto Reload를 설정합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm028.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13711" alt="18feajkarm028" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm028.jpg" width="453" height="245" /></a></p>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(5) TCON 레지스터를 설정하여 Timer를 Start 시킵니다.</span></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>// Start Timer 4<br />
rTCON |= (1&lt;&lt;20);</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(6) TCON에서 Manual Update를 해제하고 INTMSK에서 인터럽트 마스크를 Clear 시킵니다.</span></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>// clean manual update<br />
rTCON &amp;= ~(1&lt;&lt;21);// Enable interrupt<br />
rINTMSK &amp;= ~(0&#215;1&lt;&lt;14);</td>
</tr>
</tbody>
</table>
<p>이렇게 하면 Timer4 인터럽트가 10msec마다 한번씩 발생하게 됩니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm040.jpg" rel="lightbox[13757]"><img class="alignnone size-large wp-image-13726" alt="18feajkarm040" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm040-620x343.jpg" width="620" height="343" /></a><br />
diag.c &#8211; timer4_test()</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>__irq __arm void isr_timer4(void)<br />
{<br />
rSRCPND = BIT_TIMER4; //Clear pending bit<br />
rINTPND = BIT_TIMER4;// Timer가 10msec 마다 발생하므로 1초에 한번씩 toggle 시키기 위해서<br />
if( ++one_seconds_var == 100 )<br />
{<br />
rGPBDAT = rGPBDAT ^ (0&#215;1 &lt;&lt; 6); // toggle LED2<br />
one_seconds_var = 0;<br />
}void timer4_test(void)<br />
{/*<br />
Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}<br />
{prescaler value} = 0~255<br />
{divider value} = 2, 4, 8, 16<br />
period = (prescaler value + 1) * (divider value) * buffer count / PCLK = 10 ms<br />
e.g.; PCLK = 50 Mhz<br />
10 ms = (15 + 1) * 2 * 15625 / (50000 * 1000)<br />
15626 = 10 ms * (50000 * 1000) / 2 / (15 + 1)<br />
*/// Timer4 Prescaler = 15<br />
rTCFG0 = 0&#215;0;<br />
rTCFG0 = (15 &lt;&lt; 8);// Timer4 Divider = 2<br />
rTCFG1 = 0&#215;0;<br />
rTCFG1 = (0&#215;0 &lt;&lt; 16); // Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value} // 50000000/(15+1)/2 = 1562500 &#8211;&gt; 1초에 발생하는 Timer Tick// buffer count<br />
rTCNTB4 = 15625; // interrupt resolution 10msecrTCON = rTCON &amp; ~(0xffffff) | 0&#215;1&lt; rTCON = rTCON | (1 &lt;&lt; 22); // Auto reloadpISR_TIMER4 = (int)isr_timer4;// Start Timer 4<br />
rTCON |= (1&lt;&lt;20);// clean manual update<br />
rTCON &amp;= ~(1&lt;&lt;21);// Enable interrupt<br />
rINTMSK &amp;= ~(0&#215;1&lt;&lt;14);</p>
<p>}</td>
</tr>
</tbody>
</table>
<p>여기서 잠깐! 일반함수와 &#8220;__irq __arm&#8221; 가 있는 함수의 차이점은 무엇일까요?</p>
<p><span style="text-decoration: underline">일반 함수의 Return 부분</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm039.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13725" alt="18feajkarm039" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm039.jpg" width="525" height="71" /></a></p>
<p><span style="text-decoration: underline">ISR 함수의 Return 부분</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm048.png" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13769" alt="18feajkarm048" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm048.png" width="524" height="121" /></a><br />
ISR 함수는 ARM Architecture에서 배운대로 Return을 SUBS PC,LR,#4로 하고 있습니다. 잘 기억이 나지 않으시면 ARM Architecture 자료에서 Pipeline과 Interrupt 부분을 다시 보시기 바랍니다.</p>
<p><span style="color: #3366ff"><strong>5.6 PWM Buzzer</strong></span></p>
<p>Buzzer, LED 등의 밝기 조정 등에 응용할 수 있습니다.</p>
<p><span style="text-decoration: underline">실험예제</span><br />
Buzzer을 울리도록 하고 외부 인터럽트 방식으로 Key K2를 누르면 주파수를 10Hz 올리고 K3를 누르면 10Hz 주파수가 내려가도록 해봅시다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm049.png" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13768" alt="18feajkarm049" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm049.png" width="404" height="268" /></a></p>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(1) GPBCON 레지스터에서 GPB0를 TOUT0(Timer0 Output)으로 설정합니다.</span></p>
<p><span style="color: #33cccc"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm029.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13712" alt="18feajkarm029" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm029.jpg" width="454" height="242" /></a></span></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rGPBCON &amp;= ~0&#215;3; // set GPB0 as tout0, pwm output<br />
rGPBCON |= 0&#215;2;</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(2) TCFG0 레지스터의 Timer0 Prescaler를 15로 설정합니다.</span></p>
<p><strong>PWM TIMER CONTROL REGISTERS</strong><br />
<strong>TIMER CONFIGURATION REGISTER0 (TCFG0)</strong><br />
Timer input clock Frequency = PCLK /{prescaler value+1} / {divider value}<br />
{prescaler value} = 0~255<br />
{divider value} = 2, 4, 8, 16</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm030.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13713" alt="18feajkarm030" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm030.jpg" width="453" height="258" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rTCFG0 &amp;= ~0xff;<br />
rTCFG0 |= 15; // prescaler = 15+1</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(3) Timer0의 Divider 를 1/8 로 설정합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm031.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13714" alt="18feajkarm031" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm031.jpg" width="453" height="98" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rTCFG1 &amp;= ~0xf;<br />
rTCFG1 |= 2; // mux = 1/8</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(4) Timer0의 Count buffer register, compare buffer register를 설정합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm032.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13715" alt="18feajkarm032" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm032.jpg" width="451" height="262" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rTCNTB0 = (Pclk&gt;&gt;7)/buzzer_freq;<br />
rTCMPB0 = rTCNTB0&gt;&gt;1; // rTCNTB0/2</td>
</tr>
</tbody>
</table>
<p>여기까지 설정을 하면 아래와 같이 1KHz의 주파수가 만들어집니다.</p>
<p>Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}<br />
Timer input clock Frequency = 50000000/(15+1)/8 = 390625 → 1초에 발생하는 Timer Tick</p>
<p>50000000Hz(PCLK) &gt;&gt; 7 = 390625 → 결국은 1초에 1번 1Hz값, buzzer_freq(1000)으로 나누어 주면 TCNTBn은 1KHz가 됩니다.</p>
<p>추가로 TCMPBn은 TCNTBn/2로 하면 최종적으로 1KHz인 Timer0(TOUT0)으로 1KHz인 PWM 파형이 출력됩니다.</p>
<p>&nbsp;</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm050.png" rel="lightbox[13757]"><img class="alignnone  wp-image-13767" alt="18feajkarm050" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm050.png" width="519" height="221" /></a></p>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(5) Timer0를 Start 시킵니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm033.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13716" alt="18feajkarm033" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm033.jpg" width="452" height="298" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rTCON &amp;= ~0x1f;<br />
rTCON |= 0xb; //disable deadzone, auto-reload, inv-off, update TCNTB0&amp;TCMPB0, start timer 0<br />
rTCON &amp;= ~2; //clear manual update bit</td>
</tr>
</tbody>
</table>
<p>diag.c &#8211; pwm_buzzer_test()</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>__irq __arm void isr_eint_8_23(void)<br />
{if(rINTPND==BIT_EINT8_23)<br />
{<br />
ClearPending(BIT_EINT8_23);if(rEINTPEND&amp;(1&lt;&lt;11)) // KEY2<br />
{<br />
rEINTPEND |= 1 &lt;&lt; 11;<br />
rGPBDAT = rGPBDAT ^ (0&#215;1 &lt;&lt; 6); // LED2 togglebuzzer_freq += 100;<br />
pwm_buzzer_test();<br />
}<br />
if(rEINTPEND&amp;(1&lt;&lt;13)) // KEY3<br />
{<br />
rEINTPEND |= 1 &lt;&lt; 13;<br />
rGPBDAT = rGPBDAT ^ (0&#215;1 &lt;&lt; 7); // LED3 togglebuzzer_freq -= 100;<br />
pwm_buzzer_test();<br />
}<br />
}<br />
}void pwm_buzzer_test(void)<br />
{<br />
rGPBCON &amp;= ~0&#215;3; // set GPB0 as tout0, pwm output<br />
rGPBCON |= 0&#215;2;rTCFG0 &amp;= ~0xff;<br />
rTCFG0 |= 15; // prescaler = 15+1rTCFG1 &amp;= ~0xf;<br />
rTCFG1 |= 2; // mux = 1/8// Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}<br />
// 50000000/(15+1)/8 = 390625 &#8211;&gt; 1초에 발생하는 Timer Tick// PCLK = 50000000Hz &gt;&gt; 7 = 390625 &#8211;&gt; 결국은 1초에 1번 1Hz 값이다.<br />
// buzzer_freq(1000) 으로 나누어 주면 1KHz가 된다.<br />
rTCNTB0 = (PCLK&gt;&gt;7)/buzzer_freq;rTCMPB0 = rTCNTB0&gt;&gt;1; // rTCNTB0/2</p>
<p>rTCON &amp;= ~0x1f;<br />
rTCON |= 0xb; //disable deadzone, auto-reload, inv-off, update TCNTB0&amp;TCMPB0, start timer 0<br />
rTCON &amp;= ~2; //clear manual update bit<br />
}</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong style="color: #3366ff">5.7 UART</strong></p>
<p>임베디드 프로그램에서 Timer와 함께 UART도 필수적인 인터페이스입니다. 개발초기에 디버그 모니터용으로 활용하기도 하고 개발이 완료된 이후에는 제품의 Setting, Firmware 업그레이드 등에도 활용합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm051.png" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13771" alt="18feajkarm051" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm051.png" width="348" height="242" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm052.png" rel="lightbox[13757]"><img class="alignnone  wp-image-13770" alt="18feajkarm052" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm052.png" width="565" height="303" /></a></p>
<p><span style="text-decoration: underline">실험예제</span><br />
UART0를 PC와 115200bps Baudrate로 통신(RX, TX)을 하는 Echo server로 만들어 봅시다.</p>
<p><span style="color: #33cccc">(1) GPH2를 TXD로 GPH3을 RXD로 설정하고, GPH의 Pullup을 Disable 합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm034.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13717" alt="18feajkarm034" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm034.jpg" width="453" height="341" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rGPHCON &amp;= ~( (0&#215;3 &lt;&lt; 6) | (0&#215;3 &lt;&lt; 4) );<br />
rGPHCON |= ( (0&#215;2 &lt;&lt; 6) | (0&#215;2 &lt;&lt; 4) );<br />
rGPHUP = 0x7ff; // The pull up function is disabled GPH[10:0]</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(2) UART0의 FIFO Buffer를 Disable 합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm035.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13718" alt="18feajkarm035" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm035.jpg" width="455" height="446" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rUFCON0 = 0&#215;0; //UART channel 0 FIFO control register, FIFO disable</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(3) UART0의 Auto Flow Control을 Disable 합니다.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm036.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13719" alt="18feajkarm036" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm036.jpg" width="452" height="460" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rUMCON0 = 0&#215;0; //UART chaneel 0 MODEM control register, AFC disable</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(4) UART Line Control Regier 설정</span> <span style="color: #33cccc">(Normal Mode, No Parity, One Stop Bit, Word Length = 8)</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm037.jpg" rel="lightbox[13757]"><img class="alignnone size-large wp-image-13720" alt="18feajkarm037" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm037-437x620.jpg" width="437" height="620" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rULCON0 = 0&#215;3; //Line control register : Normal,No parity,1 stop,8 bits</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(5) UART Control Regier 설정</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm038.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13721" alt="18feajkarm038" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm038.jpg" width="451" height="906" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rUCON0 = (0&#215;0 &lt;&lt; 10) | (0&#215;1 &lt;&lt; 6) | (0&#215;0 &lt;&lt; 5) | (0&#215;0 &lt;&lt; 4) | (0&#215;1 &lt;&lt; 2) | (0&#215;1 &lt;&lt; 0);</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #33cccc">(6) UART Baudrate Divisor Register 설정</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm047.jpg" rel="lightbox[13757]"><img class="alignnone size-full wp-image-13764" alt="18feajkarm047" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm047.jpg" width="451" height="211" /></a></p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>rUBRDIV0 = ( (int)(Pclk/16./baud+0.5) -1 ); //Baud rate divisior register 0 value = 26</td>
</tr>
</tbody>
</table>
<p>UBRDIV = (int)( UART clock / ( buad rate x 16) ) -1<br />
( UART clock : PCLK, FCLK/n or UEXTCLK )</p>
<p>우리는 UART Clock으로 PCLK 50MHz(50000000)을 사용하고 있으므로 계산식은 다음과 같습니다.</p>
<p>UBRDIV = ( PCLK / (115200*16) ) &#8211; 1 = 26</p>
<p>diag.c &#8211; uart0_test()</p>
<table style="border-collapse: collapse;width: 600px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>void uart0_send_byte(int data)<br />
{<br />
while(!(rUTRSTAT0 &amp; 0&#215;2)); //Wait until THR is empty.<br />
Delay(10);<br />
WrUTXH0(data);}void uart0_test(unsigned int baud)<br />
{<br />
rGPHCON &amp;= ~( (0&#215;3 &lt;&lt; 6) | (0&#215;3 &lt;&lt; 4) );<br />
rGPHCON |= ( (0&#215;2 &lt;&lt; 6) | (0&#215;2 &lt;&lt; 4) );rGPHUP = 0x7ff; // The pull up function is disabled GPH[10:0]rUFCON0 = 0&#215;0; //UART channel 0 FIFO control register, FIFO disable<br />
rUMCON0 = 0&#215;0; //UART chaneel 0 MODEM control register, AFC disable//UART0<br />
rULCON0 = 0&#215;3; //Line control register : Normal,No parity,1 stop,8 bitsrUCON0 = (0&#215;0 &lt;&lt; 10) | (0&#215;1 &lt;&lt; 6) | (0&#215;0 &lt;&lt; 5) | (0&#215;0 &lt;&lt; 4) | (0&#215;1 &lt;&lt; 2) | (0&#215;1 &lt;&lt; 0);rUBRDIV0 = ( (int)(Pclk/16./baud+0.5) -1 ); //Baud rate divisior register 0 value = 26while(!(rUTRSTAT0 &amp; 0&#215;4)); //Wait until tx shifter is empty.uart0_send_byte(&#8216;E&#8217;);<br />
uart0_send_byte(&#8216;c&#8217;);<br />
uart0_send_byte(&#8216;h&#8217;);<br />
uart0_send_byte(&#8216;o&#8217;);<br />
uart0_send_byte(&#8216;\r&#8217;);<br />
uart0_send_byte(&#8216;\n&#8217;);while(1)<br />
{<br />
Delay(10);<br />
while(!(rUTRSTAT0 &amp; 0&#215;1)); //Receive data ready<br />
uart0_send_byte((*(volatile unsigned char *)0&#215;50000024));<br />
}</p>
<p>}</td>
</tr>
</tbody>
</table>
<p>위의 코드는 터미널창에 &#8220;Echo&#8221; 를 Display 하고 터미널에서 입력한 문자를 바로 Echo 하여 다시 터미널 창에 표시하게 됩니다.</p>
<p>&nbsp;</p>
<p><span style="background-color: #ffff00"><strong>이것으로 ARM Applications 4부를 마치며, </strong></span><br />
<span style="background-color: #ffff00"><strong>다음호에서는 III. Cortex-M3 Architecture에 대하여 살펴보도록 하겠습니다. </strong></span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/13757/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[18호]JK전자와 함께하는 ARM 완전정복(4)-1</title>
		<link>http://www.ntrexgo.com/archives/13612</link>
		<comments>http://www.ntrexgo.com/archives/13612#comments</comments>
		<pubDate>Fri, 10 May 2013 02:37:10 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[18호]]></category>
		<category><![CDATA[applicationes]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=13612</guid>
		<description><![CDATA[디바이스마트매거진 18호 &#124; ARM Architecture 강의에서는 특정 CPU(S3C2440, STM32Fxx) 에 대한 내용 보다는 ARM Core의 이론적인 구조 자체에 대해서 많은 설명을 하였습니다. 이번 강의에서는 Samsung의 ARM9 CPU S3C2440 개발보드를 이용해서 실제 실습을 통해서 ARM에 대해서 공부해 보도록 하겠습니다.]]></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[13612]"><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></p>
<p><span style="color: #666699"><strong><span style="line-height: 19px">Ⅱ.ARM Applications &#8211; 2부</span></strong></span></p>
<p>글 | 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 2부 목차</strong></span></p>
<p>5. S3C2440 개발보드 실습<br />
5.1 S3C2440 Startup 코드 분석<br />
5.2 GPIO Output(LED On/Off)<br />
5.3 GPIO Input(KEY Input) &#8211; Polling<br />
5.4 GPIO Input(KEY Input) &#8211; Interrupt<br />
5.5 TIMER<br />
5.6 PWM Buzzer<br />
5.7 UART</p>
<p>5장에서는 우리가 실습에 사용할 Mini2440 개발보드를 가지고 지금까지 이론으로만 공부했던 어셈블리어와 C언어를 이용해서 주변 장치들을 제어하는 실습을 해보도록 하겠습니다. 실제 타켓보드에 내가 작성한 프로그램을 다운로드하여 동작을 확인하는 일은 항상 가슴이 설레입니다.</p>
<p><span style="color: #0000ff"><strong>5. S3C2440 개발보드 실습</strong></span></p>
<p><span style="color: #3366ff"><strong>5.1 S3C2440 Startup 코드 분석</strong></span><br />
ARM 개발보드의 부트코드(Startup)에는 지금까지 이론으로 배웠던 내용들이 거의 모두 포함이 되어 있습니다. 부트 코드만 잘 분석해도 CPU의 50% 이상은 알고 있다고 해도 과언이 아닙니다. 부트코드 기능을 간략하게 요약해 보면 아래와 같습니다.</p>
<p>- Clock &amp; Power Initialization<br />
- Setup each exception handler<br />
- Memory (SDRAM) Initialization<br />
- Peripheral Initialization<br />
- Stack Initialization for each Processor Mode<br />
- Interrupt Handler Setup<br />
- Segment Initialization<br />
- Jump to User Application</p>
<p>이제부터 부팅이 되는 순서대로 실제 코드를 분석해 보도록 하겠습니다.</p>
<p><span style="background-color: #ffffff;color: #00ccff"><strong>(1) Exception Vector Table</strong></span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #ff0000">__program_start</span><br />
<span style="color: #ff0000"> b ResetHandler</span><br />
<span style="color: #ff0000"> b HandlerUndef ;handler for Undefined mode</span><br />
<span style="color: #ff0000"> b HandlerSWI ;handler for SWI interrupt</span><br />
<span style="color: #ff0000"> b HandlerPabort ;handler for PAbort</span><br />
<span style="color: #ff0000"> b HandlerDabort ;handler for DAbort</span><br />
<span style="color: #ff0000"> b . ;reserved</span><br />
<span style="color: #ff0000"> b HandlerIRQ ;handler for IRQ interrupt</span><br />
<span style="color: #ff0000"> b HandlerFIQ ;handler for FIQ interrupt</span></td>
</tr>
</tbody>
</table>
<p>CPU에 전원이 인가되면 처음으로 시작되는 Vector Table (0&#215;0000 0000)입니다.</p>
<p><span style="color: #00ccff"><strong>(2) Watchdog Disable</strong></span><br />
Watchdog가 무엇일까요? 직역을 하면 &#8220;지키는 개&#8221; 이런 뜻이네요. Watchdog는 보통 S/W적으로 설정한 시간동안 Kick(집지키는 개를 한번씩 차주어야 잠을 자지 않겠죠.)을 해주지 않으면 CPU를 Reset 시키는 기능으로 주로 사용합니다. 왜 이런 기능이 필요한 걸까요? 우리가 자주 사용하는 스마트폰을 예로 들어 보도록 하겠습니다. 스마트폰 사용중에 어떤 App을 실행시켰는데 그 이후로 스마트폰이 그 App때문에 터치도 되지않고, 전원 버튼도 입력이 되지 않게 먹통이 되었다고 가정을 하면 배터리를 분리시킨 후 다시 연결하는 방법 이외에는 방법이 없습니다. 이때 만약 Watchdog가 활성화 되어 있다면 스마트폰이 먹통이 되는 순간 S/W적으로 설정한 시간동안 Kick이 없으면 스마트폰이 Reset(재부팅)이 되어 다시 사용할 수 있는 상태가 될 것입니다. 배터리를 분리하는 것보다는 낫겠죠.<br />
그리고 부트코드에서 Watchdog Disable 하는 것은 부팅이 완료되기도 전에 Watchdog에 의해서 CPU가 Reset이 되는 것을 방지하기 위해서 하는 것입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm001.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13684" alt="18feajkarm001" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm001.jpg" width="455" height="421" /></a></p>
<p>0&#215;5300 0000 번지의 SFR 레지스터를 제어하면 WTCON을 설정할 수 있습니다. 실제로는 5번 비트만 &#8220;0 = Disable&#8221; 해도 됩니다.</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #ff0000">ResetHandler</span><br />
<span style="color: #ff0000"> ldr r0,=WTCON ;watch dog disable</span><br />
<span style="color: #ff0000"> ldr r1,=0&#215;0</span><br />
<span style="color: #ff0000"> str r1,[r0]</span></td>
</tr>
</tbody>
</table>
<p><strong style="color: #00ccff">(3) Interrupt Disable</strong></p>
<p>부팅 중에 예측하지 못하는 인터럽트가 발생하지 않도록 Disable 하는 것이 안전합니다.</p>
<p>CPSR.I(1), CPSR.F(1) : 부팅 시에 &#8220;1&#8243; 로 마스킹 되어 있습니다.</p>
<p>- S3C2440 CPU Level의 Interrupt Controller를 Disable 합니다.<br />
Interrupt Mask Register<br />
Interrupt SubMask Register</p>
<p>아래 그림은 S3C2440 CPU의 인터럽트 컨트롤러 블럭도입니다. “S3C2440 CPU Level 의 Interrupt Controller를 Disable” 한다는 것은 아래 블럭도에서 바로 “SUBMASK”, “MASK”를 Disable(“1” 로 Mask) 한다는 것입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm041.jpg" rel="lightbox[13612]"><img class="alignnone size-large wp-image-13727" alt="18feajkarm041" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm041-620x172.jpg" width="620" height="172" /></a></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm002.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13685" alt="18feajkarm002" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm002.jpg" width="482" height="273" /></a></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #ff0000">ldr r0,=INTMSK </span><br />
<span style="color: #ff0000"> ldr r1,=0xffffffff ;all interrupt disable</span><span style="color: #ff0000">str r1,[r0] ldr r0,=INTSUBMSK </span><br />
<span style="color: #ff0000"> ldr r1,=0x3ff ;all sub interrupt disable </span><br />
<span style="color: #ff0000"> str r1,[r0]</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #00ccff"><strong>(4) PLL 설정</strong></span><br />
우리가 사용하는 S3C2440 Mini 개발보드는 외부 Crystal로 12MHz를 사용합니다.<br />
Input Frequency가 12MHz 일때, FCLK:HCLK:PCLK = 400MHz : 100MHz : 40MHz, 즉 1:4:8 비율로 분주가 되도록 설정합니다.</p>
<p><span style="color: #33cccc">(4.1) Clock Divider Control Register(CLKDIVIN) 설정</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm003.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13686" alt="18feajkarm003" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm003.jpg" width="455" height="93" /></a></p>
<p>&nbsp;</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm004.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13687" alt="18feajkarm004" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm004.jpg" width="454" height="381" /></a></p>
<p>CLKDIV_VAL 값이 “b00101”으로 세팅이 되어 있어서 FCLK:HCLK:PCLK = 1:4:8 비율로 분주가 되도록 설정이 됩니다.<br />
최종적으로는 12MHz의 입력주파수를 받아서 동작 주파수가 400MHz가 되도록 설정합니다.</p>
<p><span style="color: #33cccc">(4.2) UPLL Control Register(USB CLK) 설정</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm005.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13688" alt="18feajkarm005" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm005.jpg" width="451" height="218" /></a><br />
Upll = (m * Fin) / (p * 2s)<br />
m = (MDIV + 8), p = (PDIV + 2), s = SDIV</p>
<p>Fin = FCLK 입력으로 들어오는 Crystal 주파수 12MHz<br />
UPLL = ((56+8)*12) / ((2+2)*2*2) = 48MHz</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm006.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13689" alt="18feajkarm006" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm006.jpg" width="453" height="152" /></a><br />
UPLL은 USB컨트롤러에서 사용할 CLK으로 결국은 12MHz Crystal 입력을 받아서 48MHz를 만들어서 사용하고 있습니다.</p>
<p><span style="color: #33cccc">(4.3) MPLL Control Register(Main CLK) 설정</span></p>
<p>Mpll = (2 * m * Fin) / (p * 2s)<br />
m = (MDIV + 8), p = (PDIV + 2), s = SDIV<br />
MPLL = (2*(92+8)*12) / ((1+2)*2*1) = 400MHz</p>
<p>MPLL은 결국은 12MHz Crystal 입력을 받아서 FCLK = 400MHz, HCLK = 100MHz, PCLK = 50MHz를 만들어서 사용하고 있습니다. HCLK과 PCLK의 계산은 CLKDIV 레지스터 설정을 FCLK:HCLK:PCLK = 1:4:8 비율로 분주비를 설정했기 때문에 자동으로 계산이 됩니다.<br />
- 참조로 PLL 계산 방식은 S3C2440 Datasheet를 참조하시기 바랍니다.</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>l<span style="color: #ff0000">dr r0,=CLKDIVN ; 0x4C000014</span><br />
<span style="color: #ff0000"> ldr r1,=CLKDIV_VAL ; CLKDIV_VAL=5 &#8212;&gt; 1:4:8</span><br />
<span style="color: #ff0000"> str r1,[r0]</span><span style="color: #ff0000">;Configure UPLL</span><br />
<span style="color: #ff0000"> ldr r0,=UPLLCON ; 0x4C000008</span><br />
<span style="color: #ff0000"> ldr r1,=((U_MDIV&lt;&lt;12)+(U_PDIV&lt;&lt;4)+U_SDIV) ; U_MDIV=56, U_PDIV=2, U_SDIV=2</span><br />
<span style="color: #ff0000"> str r1,[r0]</span><span style="color: #ff0000">;Configure MPLL</span><br />
<span style="color: #ff0000"> ldr r0,=MPLLCON</span><br />
<span style="color: #ff0000"> ldr r1,=((M_MDIV&lt;&lt;12)+(M_PDIV&lt;&lt;4)+M_SDIV) </span><br />
<span style="color: #ff0000"> str r1,[r0]</span></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong><span style="color: #00ccff">(5) Internal Bus Mode</span></strong></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td>     <span style="color: #ff0000">bl MMU_SetAsyncBusMode</span></td>
</tr>
</tbody>
</table>
<p>- Synchronous : Core Clock System Clock(HCLK)에 동기화 되어 사용</p>
<p>- Asynchronous : System Clock(HCLK)과 관계없이 Free Running Clock(FCLK)을 이용</p>
<p>우리는 FCLK을 이용할 것이기 때문에 MMU_SetAsyncBusMode 함수를 호출하였습니다.</p>
<p><span style="color: #00ccff"><strong>(6) Memory System 초기화</strong></span><br />
시스템에 연결된 FLASH, SDRAM, I/O Device 등과 같은 장치들을 제어하기 위해서 Memory Controller를 초기화해야 합니다.</p>
<p>- Access Timing<br />
- Data Bus Width<br />
- Wait Cycle<br />
- Refresh Rate<br />
- Bank Memory Size</p>
<p>소스 코드들이 꽤 알아먹기 힘든 코드들이네요. 복잡해 보이지만 하는 일은 BWSCON 주소의 SFR에 SMRDATA의 4Byte(32-bit) 데이터들을 루프를 돌면서 Write 하는 것입니다.</p>
<p>- SMRDATA : 메모리 컨트롤러 SFR에 기록할 내용들을 4Byte 길이로 해서 테이블 형태로 데이터를 순차적으로 가지고 있습니다.<br />
- BWSCON : S3C2440 메모리 컨트롤러의 SFR 주소입니다.</p>
<p>소스 파일의 memcfg.inc에 다음과 같이 정의되어 있습니다.<br />
;BWSCON<br />
DW8 EQU (0&#215;0)<br />
DW16 EQU (0&#215;1)<br />
DW32 EQU (0&#215;2)</p>
<p>WAIT EQU (0&#215;1&lt;&lt;2)<br />
UBLB EQU (0&#215;1&lt;&lt;3)</p>
<p>B1_BWSCON EQU (DW32)<br />
B2_BWSCON EQU (DW16)<br />
B3_BWSCON EQU (DW16+WAIT+UBLB)<br />
B4_BWSCON EQU (DW16) ; N.C.<br />
B5_BWSCON EQU (DW16) ; N.C.<br />
B6_BWSCON EQU (DW32) ; MINI2440 SDRAM (K4S281632C)-2M*16bit*4Bank*2, SDRAM(K4S561632C) 32MBx2, 32-bit<br />
B7_BWSCON EQU (DW32) ; N.C.</p>
<p>SMRDATA의 맨 첫번째 데이터들이 무엇을 의미하는 것일까요?</p>
<p>(0+(B1_BWSCON&lt;&lt;4)+(B2_BWSCON&lt;&lt;8)+(B3_BWSCON&lt;&lt;12)+(B4_BWSCON&lt;&lt;16)+(B5_BWSCON&lt;&lt;20)+(B6_BWSCON&lt;&lt;24)+(B7_BWSCON&lt;&lt;28)) &#8211;&gt; (0+(0&#215;2&lt;&lt;4)+(0&#215;1&lt;&lt;8)+(0xD&lt;&lt;12)+(0&#215;1&lt;&lt;16)+(0&#215;1&lt;&lt;20)+(0&#215;2&lt;&lt;24)+(0&#215;2&lt;&lt;28))</p>
<p>상위 비트부터 살펴보도록 하겠습니다.</p>
<p>- (0&#215;2&lt;&lt;28) = DW7[29:28] = Bank7에는 어떤 Memory 디바이스도 연결되어 있지 않습니다. 사실은 무의미한 코드입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm007.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13690" alt="18feajkarm007" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm007.jpg" width="451" height="172" /></a><br />
- (0&#215;2&lt;&lt;24) = DW6[25:24] = Bank6은 SDRAM이 연결되어 있는 메모리 뱅크입니다. 데이터 라인은 32bit(2b10) 입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm008.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13691" alt="18feajkarm008" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm008.jpg" width="452" height="90" /></a></p>
<p>- (0&#215;1&lt;&lt;20) = DW5[21:20] = N.C(Not connected)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm009.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13692" alt="18feajkarm009" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm009.jpg" width="453" height="87" /></a><br />
- (0&#215;1&lt;&lt;16) = DW4[17:16] = N.C(Not connected)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm010.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13693" alt="18feajkarm010" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm010.jpg" width="454" height="96" /></a><br />
- (0xD&lt;&lt;12) = ST3[15], WS3[14], DW3[13:12] = 16-bit DM9000 Ehternet 컨트롤러 설정입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm011.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13694" alt="18feajkarm011" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm011.jpg" width="451" height="200" /></a></p>
<p>- (0&#215;1&lt;&lt;8) = DW2[9:8] = N.C(Not connected)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm012.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13695" alt="18feajkarm012" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm012.jpg" width="450" height="98" /></a><br />
- (0&#215;2&lt;&lt;4) = DW1[5:4] = N.C(Not connected)</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm013.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13696" alt="18feajkarm013" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm013.jpg" width="453" height="145" /></a><br />
- (0&#215;0) = DW0[2:1] = Read only 영역으로 OM[1:0] 핀에 의해서 결정됩니다. 우리가 사용하는 개발보드는 16bit Data width의 NOR Flash 입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm013.jpg" rel="lightbox[13612]"><img class="alignnone size-full wp-image-13696" alt="18feajkarm013" src="http://www.ntrexgo.com/wp-content/uploads/2013/05/18feajkarm013.jpg" width="453" height="145" /></a><br />
나머지 데이터 설정값들도 Datasheet를 참조해서 분석해 보시기 바랍니다.</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="10">
<tbody>
<tr>
<td><span style="color: #ff0000">;Set memory control registers </span><br />
<span style="color: #ff0000">ldr r0,=SMRDATA </span><br />
<span style="color: #ff0000">ldr r1,=BWSCON ; 0&#215;48000000 </span><br />
<span style="color: #ff0000">add r2, r0, #52 ;End address of SMRDATA </span><br />
<span style="color: #ff0000">L5 </span><br />
<span style="color: #ff0000">ldr r3, [r0], #4 </span><br />
<span style="color: #ff0000">str r3, [r1], #4 </span><br />
<span style="color: #ff0000">cmp r2, r0 </span><br />
<span style="color: #ff0000">bne L5</span><span style="color: #ff0000">.</span><br />
<span style="color: #ff0000">.</span><br />
<span style="color: #ff0000">.</span><br />
<span style="color: #ff0000">LTORG</span><br />
<span style="color: #ff0000">SMRDATA DATA</span><br />
<span style="color: #ff0000">DCD (0+(B1_BWSCON&lt;&lt;4)+(B2_BWSCON&lt;&lt;8)+(B3_BWSCON&lt;&lt;12)+(B4_BWSCON&lt;&lt;16)+(B5_BWSCON&lt;&lt;20)+(B6_BWSCON&lt;&lt;24)+(B7_BWSCON&lt;&lt;28))</span><br />
<span style="color: #ff0000">DCD ((B0_Tacs&lt;&lt;13)+(B0_Tcos&lt;&lt;11)+(B0_Tacc&lt;&lt;8)+(B0_Tcoh&lt;&lt;6)+(B0_Tah&lt;&lt;4)+(B0_Tacp&lt;&lt;2)+(B0_PMC)) ;GCS0</span><br />
<span style="color: #ff0000">DCD ((B1_Tacs&lt;&lt;13)+(B1_Tcos&lt;&lt;11)+(B1_Tacc&lt;&lt;8)+(B1_Tcoh&lt;&lt;6)+(B1_Tah&lt;&lt;4)+(B1_Tacp&lt;&lt;2)+(B1_PMC)) ;GCS1</span><br />
<span style="color: #ff0000">DCD ((B2_Tacs&lt;&lt;13)+(B2_Tcos&lt;&lt;11)+(B2_Tacc&lt;&lt;8)+(B2_Tcoh&lt;&lt;6)+(B2_Tah&lt;&lt;4)+(B2_Tacp&lt;&lt;2)+(B2_PMC)) ;GCS2</span><br />
<span style="color: #ff0000">DCD ((B3_Tacs&lt;&lt;13)+(B3_Tcos&lt;&lt;11)+(B3_Tacc&lt;&lt;8)+(B3_Tcoh&lt;&lt;6)+(B3_Tah&lt;&lt;4)+(B3_Tacp&lt;&lt;2)+(B3_PMC)) ;GCS3</span><br />
<span style="color: #ff0000">DCD ((B4_Tacs&lt;&lt;13)+(B4_Tcos&lt;&lt;11)+(B4_Tacc&lt;&lt;8)+(B4_Tcoh&lt;&lt;6)+(B4_Tah&lt;&lt;4)+(B4_Tacp&lt;&lt;2)+(B4_PMC)) ;GCS4</span><br />
<span style="color: #ff0000">DCD ((B5_Tacs&lt;&lt;13)+(B5_Tcos&lt;&lt;11)+(B5_Tacc&lt;&lt;8)+(B5_Tcoh&lt;&lt;6)+(B5_Tah&lt;&lt;4)+(B5_Tacp&lt;&lt;2)+(B5_PMC)) ;GCS5</span><br />
<span style="color: #ff0000">DCD ((B6_MT&lt;&lt;15)+(B6_Trcd&lt;&lt;2)+(B6_SCAN)) ;GCS6</span><br />
<span style="color: #ff0000">DCD ((B7_MT&lt;&lt;15)+(B7_Trcd&lt;&lt;2)+(B7_SCAN)) ;GCS7</span><br />
<span style="color: #ff0000">DCD ((REFEN&lt;&lt;23)+(TREFMD&lt;&lt;22)+(Trp&lt;&lt;20)+(Trc&lt;&lt;18)+(Tchr&lt;&lt;16)+REFCNT)</span><br />
<span style="color: #ff0000">DCD 0&#215;32 ;SCLK power saving mode, BANKSIZE 128M/128M DCD 0&#215;30 ;MRSR6 CL=3clk</span><br />
<span style="color: #ff0000">DCD 0&#215;30 ;MRSR7 CL=3clk</span><br />
<span style="color: #ff0000">DATA</span></td>
</tr>
</tbody>
</table>
<p style="text-align: right"><span style="color: #999999">JK전자와 함께하는 ARM 완전정복(4)-2 에서 계속 됩니다.</span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/13612/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>로봇 암 NT-RobotARM-RC</title>
		<link>http://www.ntrexgo.com/archives/8701</link>
		<comments>http://www.ntrexgo.com/archives/8701#comments</comments>
		<pubDate>Fri, 05 Apr 2013 01:36:14 +0000</pubDate>
		<dc:creator>NTRexLAB</dc:creator>
				<category><![CDATA[일반 주행로봇]]></category>
		<category><![CDATA[arm]]></category>
		<category><![CDATA[robot]]></category>
		<category><![CDATA[robot arm]]></category>
		<category><![CDATA[로봇암]]></category>
		<category><![CDATA[암]]></category>
		<category><![CDATA[엔티렉스]]></category>
		<category><![CDATA[연구소]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=8701</guid>
		<description><![CDATA[소형 로봇 암입니다. 소형이고, 일반적인 RC 서보 모터를 사용하기 때문에 큰 힘을 내지는 못하지만, 학습용이나 각 종 이벤트로는 괜찮을 듯 합니다.

&#160;
먼저 위 로봇암은 NT-RobotARM-RC로, RC서보모터 6개와 6개의 서보모터 동작을 위해 NT-SERVO-16CH-1[판매페이지바로가기], NT-USB2UART[관련글바로가기]를 포함하고 있습니다. 이 제품은 학생들의 학습용도의 사용을 위해 완성품과 조립품으로 각각 판매되는 제품입니다. 물론 나머지 제어코드는 사용자가 직접 MCU를 이용해 꾸미도록 되어있습니다.
NT-RobotARM-Motion-Frame입니다. 이 기구는 큰 힘을 받는 부분이 아니라, 상대적으로 단촐하게 꾸며져 있어요

&#160;
그리고, 이 모델은 그냥 조립형으로만 판매되고 있습니다.
그리고, 또, 별도로, 로봇암의 끝단의 Gripper만 판매하기도 하는데요.

&#160;
이 부분은 꼭 로봇 암이 아니라 학생들이 많이 자작하는 소형 주행로봇의 끝단에 장착해서 많은 응용분야가 있을것같아 별도 판매를 하고 있습니다.
저희 로봇-암을  주행로봇 3총사...]]></description>
				<content:encoded><![CDATA[<p>소형 로봇 암입니다. 소형이고, 일반적인 RC 서보 모터를 사용하기 때문에 큰 힘을 내지는 못하지만, 학습용이나 각 종 이벤트로는 괜찮을 듯 합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/0018.jpg" rel="lightbox[8701]"><img class="size-full wp-image-8702 aligncenter" alt="001" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/0018.jpg" width="457" height="438" /></a></p>
<p>&nbsp;</p>
<p>먼저 위 로봇암은 NT-RobotARM-RC로, RC서보모터 6개와 6개의 서보모터 동작을 위해 NT-SERVO-16CH-1[<a href="http://devicemart.co.kr/goods/view.php?seq=15626" target="_blank">판매페이지바로가기</a>], NT-USB2UART[<a href="http://www.ntrexgo.com/archives/6894" target="_blank">관련글바로가기</a>]를 포함하고 있습니다. 이 제품은 학생들의 학습용도의 사용을 위해 완성품과 조립품으로 각각 판매되는 제품입니다. 물론 나머지 제어코드는 사용자가 직접 MCU를 이용해 꾸미도록 되어있습니다.</p>
<div class="symple-box red none" style="text-align:center; width:100%;"> 
<a href="http://devicemart.co.kr/goods/view.php?seq=15953" target="_blank">NT-RobotARM-RC 완성품 판매페이지 바로가기</a><br />
<a href="http://devicemart.co.kr/goods/view.php?seq=15898" target="_blank">NT-RObotARM-RC 조립품 판매페이지 바로가기</a><br />
</div>
<p>NT-RobotARM-Motion-Frame입니다. 이 기구는 큰 힘을 받는 부분이 아니라, 상대적으로 단촐하게 꾸며져 있어요</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/0027.jpg" rel="lightbox[8701]"><img class="size-full wp-image-8703 aligncenter" alt="002" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/0027.jpg" width="470" height="442" /></a></p>
<p>&nbsp;</p>
<p>그리고, 이 모델은 그냥 조립형으로만 판매되고 있습니다.</p>
<div class="symple-box red none" style="text-align:center; width:100%;"> 
<a href="http://devicemart.co.kr/goods/view.php?seq=19072" target="_blank">NT-RobotARM-Motion-Frame 판매페이지 바로가기</a><br />
</div>
<p>그리고, 또, 별도로, 로봇암의 끝단의 Gripper만 판매하기도 하는데요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/0035.jpg" rel="lightbox[8701]"><img class="size-full wp-image-8704 aligncenter" alt="003" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/0035.jpg" width="516" height="412" /></a></p>
<p>&nbsp;</p>
<p>이 부분은 꼭 로봇 암이 아니라 학생들이 많이 자작하는 소형 주행로봇의 끝단에 장착해서 많은 응용분야가 있을것같아 별도 판매를 하고 있습니다.</p>
<div class="symple-box red none" style="text-align:center; width:100%;"> 
<a href="http://devicemart.co.kr/goods/view.php?seq=15899" target="_blank">NT-ARM-GRIPPER 판매페이지 바로가기</a><br />
</div>
<p>저희 로봇-암을  주행로봇 3총사 [<a href="http://www.ntrexgo.com/archives/8194" target="_blank">관련글 바로가기</a>] 에 적용하면</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/0053.jpg" rel="lightbox[8701]"><img class="size-full wp-image-8705 aligncenter" alt="005" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/0053.jpg" width="388" height="369" /></a></p>
<p>&nbsp;</p>
<p>이런 형태도 가능하구요. 또, 주행로봇 TANK시리즈[<a href="http://www.ntrexgo.com/archives/6544" target="_blank">관련글 바로가기</a>] 에 연결하시면,</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/04/0062.jpg" rel="lightbox[8701]"><img class="size-full wp-image-8706 aligncenter" alt="006" src="http://www.ntrexgo.com/wp-content/uploads/2013/04/0062.jpg" width="489" height="404" /></a></p>
<p>&nbsp;</p>
<p>이렇게 사용하실 수도 있습니다.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/8701/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>
	</channel>
</rss>
