<?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; jk전자</title>
	<atom:link href="http://www.ntrexgo.com/archives/tag/jk%ec%a0%84%ec%9e%90/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>[20호]JK전자와 함께하는 ARM 완전정복(6)-1</title>
		<link>http://www.ntrexgo.com/archives/20915</link>
		<comments>http://www.ntrexgo.com/archives/20915#comments</comments>
		<pubDate>Fri, 30 Aug 2013 06:29:52 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[20호]]></category>
		<category><![CDATA[ARM완전정복]]></category>
		<category><![CDATA[Feature]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=20915</guid>
		<description><![CDATA[디바이스마트 매거진 20호 &#124; 이번 파트에서는 STM32F103VC Dragon 개발보드 + 3.2 터치 LCD 가 부착된 실제 개발보드를 가지고 이론으로만 공부했던 내용을 실제 예제를 통해서 하나씩 배워나가보도록 하겠습니다. ]]></description>
				<content:encoded><![CDATA[<table style="width: 620px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자.jpg" rel="lightbox[20915]"><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>&nbsp;</p>
<p>Ⅳ. Cortex-M3 Applications</p>
<p>&nbsp;</p>
<p>글 | JK전자</td>
</tr>
</tbody>
</table>
<p>ARM Architecture에서 많은 내용을 다루어서 Cortex-M3의 이론적인 부분은 그나마 짧게 끝난 것 같습니다. 이번 파트에서는 STM32F103VC Dragon 개발보드 + 3.2 터치 LCD 가 부착된 실제 개발보드를 가지고 이론으로만 공부했던 내용을 실제 예제를 통해서 하나씩 배워나가보도록 하겠습니다. 예제들은 주로 Cortex-M3 Core 부분에 해당하는 부분을 다룰 것입니다. 처음에는 LCD, MP3 등의 디바이스 제어 예제도 진행하려고 했으나 이 부분들은 Cortex-M3의 공통된 부분도 아니고 디바이스에 따라서 많은 내용이 달라지기 때문에 STM32F10x 시리즈의 자체 기능과 Dragon 개발보드에 연결된 기본 예제들만 다루도록 하겠습니다. 추후 모든 디바이스들에 대한 예제들은 시간이 허락한다면 STM32 응용에 대한 강좌로 진행해 보도록 하겠습니다.</p>
<p><span style="background-color: #ff6600;color: #ffffff"><strong>강의 전체 로드맵</strong></span></p>
<p>I. ARM Architecture | 임베디드 시스템 개론에 대한 설명과 ARM7, ARM9 의 구조에 대해서 설명합니다.<br />
II. ARM Applications | 삼성의 S3C2440(ARM9) 개발보드(S3C2440 Mini 개발보드)를 이용해서 어셈블리어와 UART, GPIO 등을 실습합니다.<br />
III. Cortex-M3 Architecture | Cortex-M3의 특징과 구조에 대해서 설명합니다.<br />
<span style="color: #0000ff">IV. Cortex-M3 Applications | STM32F103VCT6 Dragon 개발보드를 이용해서 GPIO, LCD, SPI, UART, MP3, SDIO, I2C 등을 실습합니다.</span></p>
<p>이 강의 자료에 대한 모든 질의사항은 http://cafe.naver.com/avrstudio의 ARM Architecture Q&amp;A게시판에 글을 남겨주시거나 jk@deviceshop.net로 메일을 보내주시기 바랍니다. 가급적이면 여러 사람이 질문에 대한 답변을 공유할 수 있도록 네이버 카페 게시판을 이용해주셨으면 합니다. 감사합니다.</p>
<p><strong><span style="background-color: #ff6600;color: #ffffff">Ⅳ. Cortex-M3 Applications 목차</span></strong></p>
<p>1. STM32F10x Overview<br />
1.1 STM32F10x Block Diagram<br />
1.2 STM32F10x Memory Map<br />
1.3 STM32F10x Boot Modes<br />
1.4 STM32F10x GPIO<br />
2. STM32F103VC Dragon개발보드 소개<br />
2.1 Features<br />
3. Examples<br />
3.1 GPIO Output without SDK<br />
3.2 GPIO Output with SDK<br />
3.3 GPIO Output with BitBand<br />
3.4 GPIO Input &#8211; Polling<br />
3.5 GPIO Input &#8211; Interrupt<br />
3.6 General Purpose Timer<br />
3.7 Systick &#8211; Delay<br />
3.8 Systick &#8211; Interrupt<br />
3.9 USART &#8211; Polling<br />
3.10 USART &#8211; Interrupt<br />
3.11 USART &#8211; Name Card<br />
3.12 Interrupt Priority1<br />
3.13 Interrupt Priority2<br />
3.14 Power Management &#8211; Sleep<br />
3.15 Power Management &#8211; Stop<br />
3.16 Power Management &#8211; StandBy<br />
3.17 Mode Privilege<br />
3.18 USART Monitor Program</p>
<p><strong><span style="background-color: #ff6600;color: #ffffff">1. STM32F10x Overview</span></strong></p>
<p><span style="color: #ff6600"><strong>1.1 STM32F10x Block Diagram</strong></span></p>
<p>Cortex-M3 Core를 Based로 하여 ICode, DCode, System Bus와 연결이 되어 있는 것을 볼 수 있습니다. Cortex-M3 Core는 ARM사에서 라이센싱한 것이고 아래의 그림에서 Vendor Defined Specfic 부분은 ST Microeclectonics사에서 구현한 것입니다. Bus Matrix를 통해서 AHB system bus와 Cortex-M3 Core가 연결되어 있고 APB1, APB2 bus가 AHB bus에 연결되어 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-49.png" rel="lightbox[20915]"><img class="alignnone  wp-image-21152" alt="20feajk 49" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-49-620x576.png" width="496" height="461" /></a></p>
<p><span style="color: #ff6600"><strong>1.2 STM32F10x Memory Map</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-50.png" rel="lightbox[20915]"><img class="alignnone  wp-image-21153" alt="20feajk 50" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-50-620x549.png" width="496" height="439" /></a><br />
Cortex-M3의 메모리 맵은 Architecture Defined 되어 있고, 4GB의 메모리 공간을 Access 할 수 있습니다. Architecture 차원에서 Memory Map이 정의되어 있기 때문에 같은 Cortex-M3를 기반으로한 CPU들 사이에서는 S/W 개발과 포팅을 쉽게 할 수 있습니다. 그리고 Memory Map에서 유심히 봐야할 부분은 Bit-Band region이 존재하고 있는 영역입니다.</p>
<p>-STM32F103VC CPU의 Memory layout<br />
0&#215;0800.0000 ~ 0&#215;0801.FFFF (FLASH)<br />
0&#215;2000.0000 ~ 0&#215;2000.BFFF (SRAM)<br />
0&#215;4000.0000 ~ 0&#215;4002.3FFF<br />
(Peripheral Memory Map)<br />
0xE000.0000 ~ 0xE00F.FFFF<br />
(Cortex-M3 Internal Peri.)</p>
<p><span style="color: #ff6600"><strong>1.3 STM32F10x Boot Modes</strong></span></p>
<p>STM32F 시리즈의 CPU는 3가지 모드로 부팅할 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-7.png" rel="lightbox[20915]"><img class="alignnone  wp-image-21155" alt="20feajk (7)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-7-620x229.png" width="496" height="183" /></a><br />
- User Flash memory : 일반적인 Normal booting입니다. STM32F CPU의 Internal Flash(0&#215;0 or 0&#215;8000000)에서 부팅을 하는 것입니다.<br />
- System memory : STM32F CPU의 Internal System memory를 이용해서 부팅을 합니다. 이 모드로 부팅을 하면 CPU에 있는 내부 부트로더에 의해서 USART0가 초기화되고 ST 사에서 제공하는 ST Flashloader 프로그램을 이용해서 bin(or hex) 실행 이미지를 User Flash memory 영역에 다운로드 할 수 있습니다. JTAG 장비가 없을 경우 USART0을 이용해서 프로그램을 퓨징할 때 유용하게 사용할 수 있습니다.<br />
- Embedded SRAM : Internal RAM에서 부팅을 시작하게 합니다. 이렇게 하려면 Startup 코드에서 Vector Table offset 위치를 RARM에 위치하도록 Register 설정을 해주어야 합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-8.png" rel="lightbox[20915]"><img class="alignnone  wp-image-21156" alt="20feajk (8)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-8-620x245.png" width="496" height="196" /></a><br />
위의 그림은 우리가 실습에 사용할 Dragon 개발보드의 BOOT 모드 회로도입니다.</p>
<p><strong><span style="background-color: #ff6600;color: #ffffff"> 2. STM32F103VC Dragon 개발보드 소개</span></strong></p>
<p><span style="color: #ff6600"><strong>2.1 Features</strong></span></p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td colspan="2"><strong><span style="color: #ff6600">C</span><span style="color: #ff0000">PU Module &#8211; STM32 Rabbit CPU 모듈 사용</span></strong></td>
</tr>
<tr>
<td>CPU</td>
<td>STM32F103VCT6 Cortex-M3 Core(LQFP-100)</td>
</tr>
<tr>
<td>SRAM</td>
<td>32KB internal SRAM</td>
</tr>
<tr>
<td>Flash</td>
<td>128KB internal Flash memory</td>
</tr>
<tr>
<td>ISP</td>
<td>1 x ISP 모드 전환 점퍼</td>
</tr>
<tr>
<td>UART</td>
<td>1 x UART( UART0)</td>
</tr>
<tr>
<td>LEDs</td>
<td>1 x User LED, 1 x Power LED</td>
</tr>
<tr>
<td>Reset Button</td>
<td>1 x Reset Button</td>
</tr>
<tr>
<td>JTAG</td>
<td>20Pin JTAG interface</td>
</tr>
<tr>
<td>Size(WxH)</td>
<td>68.4mm x 69.1mm(W x H)</td>
</tr>
<tr>
<td>확장포트</td>
<td>STM32F103VCT6의 모든 포트가 2 x 2.54mm으로 나와 있습니다.</td>
</tr>
</tbody>
</table>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td colspan="2"><span style="color: #ff0000"><strong>Bottom Board &#8211; Hardware Features</strong></span></td>
</tr>
<tr>
<td>전원</td>
<td>5V DC 전원(외경:5.5mm, 내경:2mm), USB, USB to Serial 포트를 통해서 전원공급 가능</td>
</tr>
<tr>
<td>RS232</td>
<td>1 x USB2Serial 포트 내장<br />
1 x DB9 시리얼 포트 ( MAX232 )</td>
</tr>
<tr>
<td>USB</td>
<td> x USB 2.0 Full speed</td>
</tr>
<tr>
<td>LCD</td>
<td>1 x 2.4, 4.3, 7.0 inch TFT 터치 LCD 인터페이스<br />
1 x 1602 Char LCD 인터페이스<br />
1 x 12864 그래픽 LCD 인터페이스</td>
</tr>
<tr>
<td>MP3</td>
<td>1 x VS1003B SPI Interface</td>
</tr>
<tr>
<td>RF</td>
<td>1 x nRF24L01 SPI Interface</td>
</tr>
<tr>
<td>AHRS</td>
<td>1 x AHRS Sensor Interface</td>
</tr>
<tr>
<td>LEDs</td>
<td>3 x User LED, 1 x Power LED</td>
</tr>
<tr>
<td>Buttons</td>
<td>5 x User Button, 1 x Wakeup Button</td>
</tr>
<tr>
<td>CAN</td>
<td>1 x CAN ( VP230 )</td>
</tr>
<tr>
<td>RS485</td>
<td>1 x RS485 ( SP3485 )</td>
</tr>
<tr>
<td>SD Memory</td>
<td>1 x 4bit SD memory card interface</td>
</tr>
<tr>
<td>Adjustable Resiter</td>
<td>1 x ADC test</td>
</tr>
<tr>
<td>EEPROM</td>
<td>1 x IIC EEPROM</td>
</tr>
<tr>
<td>Backup Battery</td>
<td>1 x Backup battery holder</td>
</tr>
<tr>
<td>Buzzer</td>
<td>1 x Buzzer</td>
</tr>
<tr>
<td>ADC</td>
<td>2 x ADC Input( ADC12 In8, In9 )</td>
</tr>
<tr>
<td>DAC</td>
<td>1 x DAC</td>
</tr>
<tr>
<td>Size(WxH)</td>
<td>155 x 110 mm</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong><span style="color: #ffffff;background-color: #ff6600">3. 프로그램 다운로드 방법</span></strong></p>
<p><span style="color: #ff6600"><strong>3.1 JTAG을 이용한 다운로드 방법</strong></span></p>
<p><span style="color: #33cccc"><strong>3.1.1 ST-Link/V2</strong></span></p>
<p><span style="color: #99cc00"><strong>(1) ST-Link USB Driver Download and install</strong></span><br />
- http://www.st.com/web/en/catalog/tools/PF258167</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-2.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21247" alt="20feajk (2)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-2-620x421.jpg" width="620" height="421" /></a></p>
<p><span style="color: #99cc00"><strong>(2) ST-Link Utility Download and install</strong></span><br />
- http://www.st.com/web/en/catalog/tools/PF258168</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-4.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21249" alt="20feajk (4)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-4-620x419.jpg" width="620" height="419" /></a></p>
<p><strong><span style="color: #99cc00">(3) ST-Link/V2 Utility Program 설치</span></strong><br />
- STM32 ST-LINK Utility_v2.5.0.exe</p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-5.jpg" rel="lightbox[20915]"><img alt="20feajk (5)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-5-620x472.jpg" width="620" height="472" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-6.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21251" alt="20feajk (6)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-6-620x472.jpg" width="620" height="472" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-7.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21252" alt="20feajk (7)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-7-620x472.jpg" width="620" height="472" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-8.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21253" alt="20feajk (8)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-8-620x472.jpg" width="620" height="472" /></a></td>
</tr>
</tbody>
</table>
<p><strong style="color: #99cc00">(4) ST-Link/V2 USB 드라이버 설치</strong></p>
<p>- ST-Link_v2_usbdriver.exe</p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-9.jpg" rel="lightbox[20915]"><img alt="20feajk (9)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-9-620x472.jpg" width="620" height="472" /></a></td>
</tr>
<tr>
<td style="text-align: center"> ▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-10.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21255" alt="20feajk (10)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-10-620x472.jpg" width="620" height="472" /></a></td>
</tr>
<tr>
<td style="text-align: center"> ▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-11.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21256" alt="20feajk (11)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-11-620x472.jpg" width="620" height="472" /></a></td>
</tr>
<tr>
<td style="text-align: center"> ▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-12.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21257" alt="20feajk (12)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-12-620x472.jpg" width="620" height="472" /></a></td>
</tr>
<tr>
<td style="text-align: center"> ▼</td>
</tr>
<tr>
<td> <a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/14.png" rel="lightbox[20915]"><img class="size-large wp-image-21264 aligncenter" alt="14" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/14.png" width="514" height="392" /></a></td>
</tr>
</tbody>
</table>
<p>- Windows7 의 경우 장치 드라이버가 자동으로 설치되지 않을 경우에 드라이버 소프트웨어 업데이트를 수행합니다.</p>
<table style="width: 620px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-13.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21258" alt="20feajk (13)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-13-620x368.jpg" width="620" height="368" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-14.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21259" alt="20feajk (14)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-14-620x521.jpg" width="620" height="521" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-15.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21260" alt="20feajk (15)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-15-620x449.jpg" width="620" height="449" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-16.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21261" alt="20feajk (16)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-16-620x449.jpg" width="620" height="449" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-17.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21262" alt="20feajk (17)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-17-620x449.jpg" width="620" height="449" /></a></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="color: #99cc00"><strong>(4) ST-Link/V2 Firmware upgrade</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-51.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21198" alt="20feajk (51)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-51-620x402.jpg" width="620" height="402" /></a></p>
<p><span style="color: #99cc00"><strong>(</strong><strong><span style="color: #99cc00">5</span>) Program Fusing with ST-Link/V2</strong></span><br />
ST-Link/V2의 20핀 JTAG Cable을 Dragon 개발보드의 CPU 모듈에 있는 20핀 JTAG 박스 헤더에 연결하고 ST-Link Utility에서 &#8220;Mode Setting&#8221; 메뉴에서 &#8220;SWD&#8221; 모드로 설정합니다. 일반적으로는 STM32F 시리즈에서 &#8220;JTAG&#8221; 모드로 설정해도 되지만 Dragon 개발보드에서는 JTAG 핀의 일부를 LCD 제어시 사용하고 있기 때문에 반드시 &#8220;SWD&#8221; 모드로 설정해야 합니다. 그리고 Connect Target 을 실행합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-52.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21199" alt="20feajk (52)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-52-620x398.jpg" width="620" height="398" /></a><br />
다운로드 할 bin 파일을 선택합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-53.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21200" alt="20feajk (53)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-53-620x396.jpg" width="620" height="396" /></a><br />
- 참고로 IAR 컴파일러 환경에서는 bin 파일을 생성하기 위해서는 Ouput Converter에서 아래 그림과 같이 Binary파일 생성 옵션을 설정해 주어야 bin 파일이 생성됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-18.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21244" alt="20feajk (18)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-18-620x456.jpg" width="620" height="456" /></a><br />
- Download &amp; Verify를 실행합니다.</p>
<p>- IAR, KEIL등의 개발 환경과 직접 연동을 하지 않을 경우에는 ST-Link Utility를 이용해서 실행 binary를 다운로드 받을 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-54.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21201" alt="20feajk (54)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-54-620x397.jpg" width="620" height="397" /></a></p>
<p><span style="color: #99cc00"><strong>(6) EWARM Debug Environment &#8211; ST-Link/V2</strong></span><br />
- Debugger에서 Driver를 ST-Link를 선택합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-18.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21244" alt="20feajk (18)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-18-620x456.jpg" width="620" height="456" /></a><br />
- ST-Link 설정에서 &#8220;SWD&#8221; 모드로 설정을 합니다.<br />
- ST-Link/V2 제품은 IAR에서 사용할 경우 6.20 이상부터 연동을 할 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-49.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21196" alt="20feajk (49" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-49-620x404.jpg" width="620" height="404" /></a></p>
<p><strong><span style="color: #33cccc">3.1.2 ARM-JTAG</span></strong><br />
<span style="color: #99cc00"><strong>(1) ARM-JTAG Utility 설치</strong></span></p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-59.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21206" alt="20feajk (59)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-59-620x429.jpg" width="620" height="429" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-60.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21207" alt="20feajk (60)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-60-620x429.jpg" width="620" height="429" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-61.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21208" alt="20feajk (61)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-61-620x429.jpg" width="620" height="429" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-62.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21209" alt="20feajk (62)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-62-620x429.jpg" width="620" height="429" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-63.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21210" alt="20feajk (63)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-63-620x429.jpg" width="620" height="429" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-64.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21211" alt="20feajk (64)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-64-620x398.jpg" width="620" height="398" /></a></td>
</tr>
</tbody>
</table>
<p><span style="color: #99cc00"><strong>(2) JICE Server 프로그램 실행</strong></span><br />
- ARM-JTAG의 20핀 JTAG Cable을 Dragon 개발보드의 CPU 모듈에 있는 20핀 JTAG 박스 헤더에 연결 하고 JICE Server 프로그램을 실행합니다.<br />
<a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-65.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21212" alt="20feajk (65)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-65-620x398.jpg" width="620" height="398" /></a></p>
<p>연결이 정상적이라면 Core ID를 읽어옵니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-66.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21213" alt="20feajk (66)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-66-620x604.jpg" width="620" height="604" /></a></p>
<p>Core ID가 읽어지지 않는다면 아래와 같이 JICE Server를 설정해 보시기 바랍니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-67.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21214" alt="20feajk (67)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-67-620x604.jpg" width="620" height="604" /></a></p>
<p><span style="color: #99cc00"><strong>(3) JICE Configuration</strong></span><br />
- Debug Port Configuration</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-68.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21215" alt="20feajk (68)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-68-620x604.jpg" width="620" height="604" /></a></p>
<p>- Tap Configuration</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-67.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21214" alt="20feajk (67)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-67-620x604.jpg" width="620" height="604" /></a></p>
<p><span style="color: #99cc00"><strong>(4) JICE Commander</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-70.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21217" alt="20feajk (70)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-70-620x604.jpg" width="620" height="604" /></a></p>
<p><span style="color: #99cc00"><strong>(5) Easy Flashloader 설정</strong></span><br />
STM32F103VC(STM32F10xxC) or STM32F103ZE(STM32F10xxE) 중에서 선택합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-71.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21218" alt="20feajk (71)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-71-620x447.jpg" width="620" height="447" /></a><br />
- 다운로드할 Binary 설정</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-72.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21219" alt="20feajk (72)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-72-620x447.jpg" width="620" height="447" /></a><br />
- Start Download 를 실행하면 먼저 Flash를 Erase하고 나서 선택한 바이너리 파일을 다운로드합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-73.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21220" alt="20feajk (73)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-73-620x447.jpg" width="620" height="447" /></a></p>
<p>&nbsp;</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-74.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21221" alt="20feajk (74)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-74-620x446.jpg" width="620" height="446" /></a></p>
<p><span style="color: #99cc00"><strong>(6) EWARM Debug Environment &#8211; ARM-JTAG</strong></span><br />
- Debugger에서 Driver를 RDI로 선택합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-75.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21222" alt="20feajk (75)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-75-620x455.jpg" width="620" height="455" /></a><br />
- RDI 드라이버를 설정합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-76.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21223" alt="20feajk (76)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-76-620x455.jpg" width="620" height="455" /></a><br />
- Easy Flashloader에서 &#8220;Flash Download Before Debugging&#8221; 을 체크합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-74.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21221" alt="20feajk (74)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-74-620x446.jpg" width="620" height="446" /></a><br />
- IAR 개발환경에서 &#8220;Download and Debugging&#8221;을 시작하면 &#8220;Check Flash Download State!&#8221; 실행창이 나오게 되고 JICE Commander에서 다운로드가 정상적으로 이루어 졌다면 &#8220;PASS&#8221; 버튼을 클릭합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-77.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21224" alt="20feajk (77)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-77-620x403.jpg" width="620" height="403" /></a><br />
- IAR 개발환경에서 Debugging 화면</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-78.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21225" alt="20feajk (78)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-78-620x403.jpg" width="620" height="403" /></a><br />
ARM-JTAG의 사용에 경우 Windows7 환경에서 보다 자세한 환경 설정은 아래 URL을 참조하시기 바랍니다.</p>
<p><a href="http://www.jkelec.co.kr/img/jtag/arm/armjtag/arm_jtag_manual.html" target="_blank"> http://www.jkelec.co.kr/img/jtag/arm/armjtag/arm_jtag_manual.html</a></p>
<p><span style="color: #ff6600"><strong>3.2 STM32F 시리즈의 internal ISP(UART0)를 이용한 방법</strong></span></p>
<p>STM32F 시리즈의 CPU들은 별도의 JTAG 장비없이 내장 ISP 기능을 이용해서 bin 파일을 다운로드 할 수 있습니다.</p>
<p><span style="color: #99cc00"><strong>(1) ISP 모드로 진입</strong></span><br />
다운로드 모드로 진입하기 위해서는 아래 그림과 같이 Boot0 점퍼를 ISP라고 되어 있는 위치에 세팅하고 PC와 연결합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-3.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21248" alt="20feajk (3)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-3-620x212.jpg" width="620" height="212" /></a><br />
Dragon Bottom 보드가 있을 경우에는 Bottom 보드의 UART 포트에 연결을 하면 됩니다. Dragon Bottom 보드에는 PL2303 USB to Serial 포트가 내장되어 있습니다.</p>
<p><span style="color: #99cc00"><strong>(2) PL2303 USB to Serial 드라이버 설치</strong></span><br />
- PL2303_Prolific_DriverInstaller_v1210.exe</p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-1.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21246" alt="20feajk (1)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-1-620x400.jpg" width="620" height="400" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-55.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21202" alt="20feajk (55)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-55-620x396.jpg" width="620" height="396" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-56.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21203" alt="20feajk (56)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-56-620x400.jpg" width="620" height="400" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-57.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21204" alt="20feajk (57)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-57-620x253.jpg" width="620" height="253" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-58.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21205" alt="20feajk (58)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-58-620x400.jpg" width="620" height="400" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-79.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21226" alt="20feajk (79)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-79-620x400.jpg" width="620" height="400" /></a></td>
</tr>
</tbody>
</table>
<p><span style="color: #99cc00"><strong>(3) &#8220;STMicroelectronics flash loader.exe&#8221; 프로그램을 설치하고 실행합니다.</strong></span><br />
- Parity : &#8220;Even&#8221; , Baud Rate : &#8220;115200&#8243; 으로 설정</p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-80.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21227" alt="20feajk (80)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-80-620x448.jpg" width="620" height="448" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-81.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21228" alt="20feajk (81)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-81-620x447.jpg" width="620" height="447" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-83.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21230" alt="20feajk (83)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-83-620x447.jpg" width="620" height="447" /></a></td>
</tr>
</tbody>
</table>
<p>- Binary or Hex 파일을 선택하고 보통은 &#8220;Erase necessary pages&#8221; 를 선택하면 됩니다.</p>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-82.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21229" alt="20feajk (82)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-82-620x390.jpg" width="620" height="390" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-84.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21231" alt="20feajk (84)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-84-620x448.jpg" width="620" height="448" /></a></td>
</tr>
<tr>
<td style="text-align: center">▼</td>
</tr>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-85.jpg" rel="lightbox[20915]"><img class="alignnone size-large wp-image-21232" alt="20feajk (85)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-85-620x447.jpg" width="620" height="447" /></a></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><a title="이어서 계속됩니다. " href="http://www.ntrexgo.com/archives/21271" target="_blank">이어서 계속 됩니다. &gt;&gt;&gt;</a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/20915/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[20호]JK전자와 함께하는 ARM 완전정복(6)-2</title>
		<link>http://www.ntrexgo.com/archives/21271</link>
		<comments>http://www.ntrexgo.com/archives/21271#comments</comments>
		<pubDate>Fri, 30 Aug 2013 06:28:42 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[20호]]></category>
		<category><![CDATA[ARM완전정복]]></category>
		<category><![CDATA[featrure]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[디바이스마트]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=21271</guid>
		<description><![CDATA[디바이스마트 매거진 20호 &#124; 이번 파트에서는 STM32F103VC Dragon 개발보드 + 3.2 터치 LCD 가 부착된 실제 개발보드를 가지고 이론으로만 공부했던 내용을 실제 예제를 통해서 하나씩 배워나가보도록 하겠습니다. ]]></description>
				<content:encoded><![CDATA[<table style="width: 620px" border="0">
<tbody>
<tr>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/05/jk전자.jpg" rel="lightbox[21271]"><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>Ⅳ. Cortex-M3 Applications</p>
<p>&nbsp;</p>
<p>글 | JK전자</td>
</tr>
</tbody>
</table>
<p><a title="[20호]JK전자와 함께하는 ARM 완전정복(6)-1 보러가기" href="http://www.ntrexgo.com/archives/20915" target="_blank">이어서 계속 됩니다. &gt;&gt;&gt;</a></p>
<p><span style="color: #ffffff;background-color: #ff6600"><strong>4. Examples</strong></span></p>
<p><strong><span style="color: #ff6600">4.1 GPIO Output without SDK</span></strong></p>
<p>STM32F 시리즈에는 ST사에서 제공하는 CPU Datasheet를 보지 않더라도 함수 이름만 보고서도 따라할 수 있을 정도의 아주 훌륭한 Library가 있습니다. 하지만 우리는 처음에는 STM32F CPU의 레지스터들을 더 잘 이해하기 위해서 SDK 라이브러리를 사용하지 않고 직접 SFR 레지스터드를 설정하는 방법으로 해보도록 하겠습니다.<br />
첫번째 예제로 Dragon 개발보드의 Bottom 보드에 있는 LED들 중에서 LED2, LED4는 On, LED3는 Off 시키는 예제를 해보도록 하겠습니다.</p>
<p><span style="color: #99cc00"><strong>(1) Dragon 개발보드의 LED 회로</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-9.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21157" alt="20feajk (9)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-9-620x325.png" width="496" height="260" /></a></p>
<p>회로를 보면 LED를 켜기 위해서는 GPIO포트를 High로 하면 LED가 켜지도록 되어 있습니다.</p>
<p><span style="color: #99cc00"><strong>(2) Peripheral Bus</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-10.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21158" alt="20feajk (10)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-10-620x326.png" width="496" height="261" /></a><br />
GPIOE는 APB2 버스에 연결되어 있으므로 APB2 버스의 GPIOE 포트의 Clock을 Enable시켜주어야 합니다.</p>
<p><span style="color: #99cc00"><strong>(3) STM32 Peripheral Boundary Address : 0&#215;4002 1000 (STM32F103 Reference Guide Page 50)</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-11.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21159" alt="20feajk (11)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-11-620x128.png" width="434" height="90" /></a></p>
<p><span style="color: #99cc00"><strong>(4) RCC_APB2ENR Boundary Address : 0&#215;4002 1000 + 0&#215;18 (STM32F103 Reference Guide Page 119)</strong></span></p>
<p><img class="alignnone size-large wp-image-21160" alt="20feajk (12)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-12-620x231.png" width="620" height="231" /></p>
<p><span style="color: #99cc00"><strong>(5) RCC_APB2ENR Boundary Address : 0&#215;4002 1018 (STM32F103 Reference Guide Page 142)</strong></span><br />
- GPIOE Port Enable : (*(volatile unsigned *)0&#215;4002 1018) |= 0&#215;01 &lt;&lt; 6</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-13.png" rel="lightbox[21271]"><img class="alignnone size-large wp-image-21161" alt="20feajk (13)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-13-620x239.png" width="620" height="239" /></a></p>
<p><span style="color: #99cc00"><strong>(6) GPIOE Port Boundary address : 0&#215;4001 1800 ( STM32F103 Reference Guide Page 51 )</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-14.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21162" alt="20feajk (14)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-14-620x206.png" width="446" height="149" /></a></p>
<p><span style="color: #99cc00"><strong>(7) GPIO and AFIO register maps (STM32F103 Reference Guide Page 188)</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-15.png" rel="lightbox[21271]"><img class="alignnone size-large wp-image-21163" alt="20feajk (15)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-15-620x286.png" width="620" height="286" /></a></p>
<p><span style="color: #99cc00"><strong>(8) GPIOE_CRL Register Boundary address : 0&#215;4001 1800</strong></span><br />
- GPIOE Port2, 3, 4를 Output push-pull로 설정</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-16.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21164" alt="20feajk (16)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-16-591x620.png" width="532" height="558" /></a></p>
<p><span style="color: #99cc00"><strong>(9) GPIOE_BSRR(Set/Reset) Register Boundary address : 0&#215;4001 1810</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-17.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21165" alt="20feajk (17)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-17-620x345.png" width="496" height="276" /></a><br />
BSRR 레지스터는 GPIO Set or Reset 전용 레지스터입니다. 0 ~ 15비트는 Set 전용이고 16 ~ 31비트는 Reset 레지스터입니다.<br />
LED2(GPIOE2), LED4(GPIOE4) 포트를 Set하기 위해서는 BSRR 레지스터의 2, 4번 비트를 1로 만들면 됩니다. &#8220;0&#8243;을 Write했을때 &#8220;No action&#8221; 이라고 되어 있는 부분은 일반적으로 레지스터의 특정 비트를 Set or Clear하기 위해서는 LDR, Bit 조작, STR의 3단계가 필요한데, 이러한 Feature가 지원이 되면 Bit 조작 다음에 바로 STR 명령어에 의해서 레지스터 비트 조작이 가능하게 됩니다.</p>
<p><span style="color: #99cc00"><strong>(10) GPIOE_BRR(Reset) Register Boundary address : 0&#215;4001 1814</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-18.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21166" alt="20feajk (18)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-18-620x269.png" width="496" height="215" /></a><br />
GPIO Reset 전용 레지스터를 이용해서 GPIOE3을 Reset 합니다.<br />
(*(volatile unsigned *) 0&#215;40011814) = (0&#215;1 &lt;&lt; 3); // PE3 Off</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void led_test_wo_sdk(void)<br />
{<br />
// APB2 Clock enable<br />
// Reference Page 47, 50, 119, 142<br />
// APB2 peripheral GPIOE clock enable register (RCC_APB2ENR)<br />
(*(volatile unsigned *)0&#215;40021018) |= 0&#215;01 &lt;&lt; 6;<br />
// General Purpose output push-pull<br />
// Reference Page 51, 188, 166<br />
// GPIOE_CRL<br />
(*(volatile unsigned *)0&#215;40011800) &amp;= ~(0xf &lt;&lt; 8);<br />
(*(volatile unsigned *)0&#215;40011800) &amp;= ~(0xf &lt;&lt; 12);<br />
(*(volatile unsigned *)0&#215;40011800) &amp;= ~(0xf &lt;&lt; 16);</p>
<p>// PE2, 3, 4 Ouput mode configuration<br />
// Reference Page 51, 188, 166<br />
// GPIOE_CRL<br />
(*(volatile unsigned *)0&#215;40011800) |= (0&#215;3 &lt;&lt; 8); // PE2 Ouput Mode 50MHz<br />
(*(volatile unsigned *)0&#215;40011800) |= (0&#215;3 &lt;&lt; 12); // PE3 Ouput Mode 50MHz<br />
(*(volatile unsigned *)0&#215;40011800) |= (0&#215;3 &lt;&lt; 16); // PE4 Ouput Mode 50MHz<br />
// Reference Page 168<br />
// GPIOE_BSRR<br />
(*(volatile unsigned *)0&#215;40011810) = (0&#215;1 &lt;&lt; 2); // PE2 On<br />
// GPIOE_BSRR<br />
(*(volatile unsigned *)0&#215;40011810) = (0&#215;1 &lt;&lt; 4); // PE4 On<br />
// GPIOE_BRR<br />
(*(volatile unsigned *)0&#215;40011814) = (0&#215;1 &lt;&lt; 3); // PE3 Off</p>
<p>}</p>
</div>
<p><span style="color: #ff6600"><strong>4.2 GPIO Output with SDK</strong></span></p>
<p><strong><span style="color: #99cc00">(1) 첫번째 예제와 동일한 동작을 하는데 이번에는 ST사에서 제공한 SDK 라이브러리를 이용해서 해보도록 하겠습니다.</span></strong></p>
<p><span style="color: #99cc00"><strong>(2) 프로젝트와 stm32f10x_conf.h 파일 수정</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/11/73.png" rel="lightbox[21271]"><img class="alignnone size-large wp-image-21278" alt="73" src="http://www.ntrexgo.com/wp-content/uploads/2013/11/73-620x304.png" width="620" height="304" /></a><br />
GPIO 라이브러리를 사용하기 위해서는 프로젝트에 stm32f10x_gpio.c 파일을 추가 하고 stm32f10x_conf.h 에서 stm32f10x_gpio.h 를 include 해야 합니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>예제 전체 코드</p>
<p>void led_test_wt_sdk(void)<br />
{</p>
<p>// Define GPIO Init structure<br />
GPIO_InitTypeDef GPIO_InitStructure;<br />
// APB2 Clock enable<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);</p>
<p>/* Configure the GPIOE ports for output*/<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;<br />
GPIO_Init(GPIOE, &amp;GPIO_InitStructure);</p>
<p>GPIO_SetBits(GPIOE, GPIO_Pin_2); // LED2 On<br />
GPIO_ResetBits(GPIOE, GPIO_Pin_3); // LED3 Off<br />
GPIO_SetBits(GPIOE, GPIO_Pin_4); // LED4 On</p>
<p>}</p>
</div>
<p>별도의 설명을 하지 않아도 함수의 이름만 봐도 쉽게 코드를 이해할 수 있습니다.</p>
<p><span style="color: #ff6600"><strong>4.3 GPIO Output with BitBand</strong></span></p>
<p><strong><span style="color: #99cc00">(1) 예제 2번과 동일한 작업을 하는데, 이번에는 Bitband를 이용해서 해보도록 하겠습니다.</span></strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-19.png" rel="lightbox[21271]"><img class="alignnone size-large wp-image-21167" alt="20feajk (19)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-19-620x269.png" width="620" height="269" /></a><br />
Peripheral 영역의 Bitband 영역을 이용해야하기 때문에 Bitband base 영역은 0&#215;40000000이 되고 Bitword base는 0&#215;42000000 이 됩니다.<br />
Bitband 영역의 계산식을 다시 한번 상기하면서 소스코드를 분석해 보시기 바랍니다. GPIOE의 ODR 레지스터를 이용해서 구현하였습니다.<br />
bit_word_offset = (byte_offset x 32) + (bit_number × 4)<br />
bit_word_addr = bit_band_base + bit_word_offset</p>
<p>// GPIOE_ODR : 0x4001180C<br />
// 2,3,4 Bit : PE2, PE3, PE4</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>#define PERI_BASE 0&#215;40000000<br />
#define PERI_BB_BASE 0&#215;42000000</p>
<p>void led_test_wt_bitband(void)<br />
{</p>
<p>// Define GPIO Init structure<br />
GPIO_InitTypeDef GPIO_InitStructure;</p>
<p>// APB2 Clock enable<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);</p>
<p>/* Configure the GPIOE ports */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;<br />
GPIO_Init(GPIOE, &amp;GPIO_InitStructure);</p>
<p>(*(volatile unsigned *)(PERI_BB_BASE + (0x4001180C-PERI_BASE)*32 + 2*4)) = 0&#215;1; // PE2 On<br />
(*(volatile unsigned *)(PERI_BB_BASE + (0x4001180C-PERI_BASE)*32 + 3*4)) = 0&#215;0; // PE3 On<br />
(*(volatile unsigned *)(PERI_BB_BASE + (0x4001180C-PERI_BASE)*32 + 4*4)) = 0&#215;1; // PE4 On</p>
<p>}</p>
</div>
<p><span style="color: #ff6600"><strong>4.4 GPIO Input &#8211; Polling</strong></span><br />
Dragon 개발보드에 있는 버튼 입력을 Polling 방식으로 처리해 보도록 하겠습니다.</p>
<p><span style="color: #99cc00"><strong>(1) BTN2가 눌리면 LED2를 ON 시키고, BTN2가 눌리지 않은 상태면 LED2를 Off 합니다. 동일한 방법으로 BTN3, BTN4 에도 적용 합니다. </strong></span><span style="color: #99cc00"><strong>그리고 BTN1을 누르면 테스트를 종료 합니다.</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-87.jpg" rel="lightbox[21271]"><img class="alignnone  wp-image-21234" alt="20feajk (87)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-87-537x620.jpg" width="376" height="434" /></a></p>
<p>BTN 회로를 보면 버튼이 눌리지 않았을때는 VCC에 연결이 되어 High 상태이고 버튼이 눌리면 GND에 연결이 되면서 Low 상태가 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-21.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21169" alt="20feajk (21)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-21.png" width="391" height="206" /></a></p>
<p><span style="color: #99cc00"><strong>(2) GPIOC 그룹을 사용하기 위해서는 APB2 버스의 GPIOC 그룹의 Clock을 Enable 해야 합니다.</strong></span></p>
<p><span style="color: #99cc00"><strong>(3) GPIOC1, 2, 3을 Input floating으로 설정합니다. </strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void key_input_test_polling_wt_sdk(void)<br />
{</p>
<p>// Define GPIO Init structure<br />
GPIO_InitTypeDef GPIO_InitStructure;</p>
<p>// APB2 Clock enable for LED<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);</p>
<p>// APB2 Clock enable for KEY<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);</p>
<p>/* Configure the GPIOE ports for output*/<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;<br />
GPIO_Init(GPIOE, &amp;GPIO_InitStructure);</p>
<p>/* Configure the GPIOC ports for input */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;<br />
GPIO_Init(GPIOC, &amp;GPIO_InitStructure);</p>
<p>while(1)<br />
{</p>
<p>// BTN1<br />
if( (!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0 )) )<br />
{<br />
break;<br />
}</p>
<p>// BTN2<br />
if( (!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_1 )) )<br />
{<br />
GPIO_SetBits(GPIOE, GPIO_Pin_2); // LED2 On<br />
}<br />
else<br />
{<br />
GPIO_ResetBits(GPIOE, GPIO_Pin_2); // LED2 Off<br />
}</p>
<p>// BTN3<br />
if( (!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2 )) )<br />
{<br />
GPIO_SetBits(GPIOE, GPIO_Pin_3); // LED3 On<br />
}<br />
else<br />
{<br />
GPIO_ResetBits(GPIOE, GPIO_Pin_3); // LED3 Off<br />
}</p>
<p>// BTN4<br />
if( (!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3 )) )<br />
{<br />
GPIO_SetBits(GPIOE, GPIO_Pin_4); // LED4 On<br />
}<br />
else<br />
{<br />
GPIO_ResetBits(GPIOE, GPIO_Pin_4); // LED4 Off<br />
}<br />
}</p>
<p>}</p>
</div>
<p><span style="color: #ff6600"><strong>4.5 GPIO Input &#8211; Interrupt</strong></span><br />
이번에는 BTN 입력을 폴링 방식이 아닌 인터럽트 방식으로 구현해 보도록 하겠습니다.</p>
<p><strong><span style="color: #99cc00">(1) BTN2를 한번 누르면 LED2를 On 시키고, 다시 BTN2를 누르면 LED2를 Off 합니다.</span></strong></p>
<p><strong><span style="color: #99cc00">(2) BTN 입력을 Falling Edge에서 검출되도록 설정합니다.</span></strong><br />
Falling Edge에서 검출한다는 것은 KEY Down에서 인터럽트가 발생하도록 한다는 것이죠. KEY Up을 검출하기 위해서는 Rising Edge 에서 검출되도록 설정하면 됩니다.</p>
<p><span style="color: #99cc00"><strong>(3) PC1 포트의 인터럽트 입력을 받으려면 외부 인터럽트 1번에 연결해야 합니다. 당연히 PC2는 외부 인터럽트 2번에 연결해야 하겠죠</strong>.</span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-22.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21170" alt="20feajk (22)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-22.png" width="492" height="558" /></a></p>
<p><span style="color: #99cc00"><strong>(4) 인터럽트 레지스터 설정</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-23.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21171" alt="20feajk (23)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-23.png" width="482" height="217" /></a></p>
<p><span style="color: #99cc00"><strong>(5) SDK 라이브러리 추가</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-89.jpg" rel="lightbox[21271]"><img class="alignnone size-large wp-image-21236" alt="20feajk (89)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-89-620x364.jpg" width="620" height="364" /></a></p>
<p><span style="color: #99cc00"><strong>(6) 인터럽트 우선순위</strong></span><br />
STM32에서 인터럽트 우선순위 비트는 8비트중에서 상위 4비트만 사용합니다. 4비트 중에서 이번 예제에서는 Priority group 2를 사용해서 Group 우선순위 2비트 Sub 우선순위 2비트를 사용하도록 설정합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-90.jpg" rel="lightbox[21271]"><img class="alignnone  wp-image-21237" alt="20feajk (90)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-90-620x392.jpg" width="496" height="314" /></a></p>
<p><span style="color: #99cc00"><strong>(7) 인터럽트 서비스 흐름도</strong></span><br />
외부 인터럽트가 발생해서 인터럽트 핸들러 함수로 분기하기까지의 과정을 도식화 해보았습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-91.jpg" rel="lightbox[21271]"><img class="alignnone  wp-image-21238" alt="20feajk (91)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-91-620x346.jpg" width="496" height="277" /></a></p>
<p><span style="color: #99cc00"><strong>(8) 예제 코드 작성 순서</strong></span><br />
□ APB2 Clock enable for LED<br />
□ APB2 Clock enable for KEY<br />
□ Configure the GPIOE ports for output<br />
□ Configure the GPIOC ports for input<br />
□ Configure EXTI to generate an interrupt on falling edge<br />
□ EXTIPR : pending 여부및 pending clear(1:pending clear)<br />
□ ICPR : pending clear Cortex-M3</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void key_input_test_interrupt(void)<br />
{<br />
EXTI_InitTypeDef EXTI_InitStructure;<br />
NVIC_InitTypeDef NVIC_InitStructure;</p>
<p>// Define GPIO Init structure<br />
GPIO_InitTypeDef GPIO_InitStructure;</p>
<p>// APB2 Clock enable for LED<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);<br />
// APB2 Clock enable for KEY<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);</p>
<p>// for Interrupt<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);<br />
/* Configure the GPIOE ports for output*/<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;<br />
GPIO_Init(GPIOE, &amp;GPIO_InitStructure);</p>
<p>/* Configure the GPIOC ports for input */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;<br />
GPIO_Init(GPIOC, &amp;GPIO_InitStructure);</p>
<p>/* Connect EXTI */<br />
// External Interrupt configuration register1 (AFIO_EXTICR1)<br />
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource1);</p>
<p>/* Configure EXTI1 to generate an interrupt on falling edge */<br />
EXTI_InitStructure.EXTI_Line = EXTI_Line1;<br />
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;<br />
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;<br />
EXTI_InitStructure.EXTI_LineCmd = ENABLE;<br />
EXTI_Init(&amp;EXTI_InitStructure);<br />
// 2 bit for pre-emption priority, 2 bits for subpriority<br />
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);</p>
<p>NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;<br />
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<br />
NVIC_Init(&amp;NVIC_InitStructure);</p>
<p>/* Clear EXTI Line Pending Bit */<br />
// STM32F10x Pending Register : 0&#215;40010400 + 0&#215;14<br />
EXTI_ClearITPendingBit(EXTI_Line1);</p>
<p>/* Enable the Key EXTI line Interrupt */<br />
// Cortex-M3 Interrupt Clear-Pending Register : 0xE000E280-0xE000E29C<br />
NVIC_ClearPendingIRQ(EXTI1_IRQn);<br />
}<br />
void EXTI1_IRQHandler(void)<br />
{<br />
if(EXTI_GetITStatus(EXTI_Line1) != RESET)<br />
{<br />
EXTI_ClearITPendingBit(EXTI_Line1);</p>
<p>// Blink<br />
GPIOE-&gt;ODR ^= (0&#215;1 &lt;&lt; 2);<br />
}<br />
}</p>
</div>
<p><span style="color: #ff6600"><strong>4.6 General Purpose Timer</strong></span></p>
<p>임베디드 시스템에서 Timer는 가장 중요하고 필수적인 요소로 OS에서 Task스케줄링을 위해서 사용되기도 하고, 전자액자, 차량용 블랙박스 등의 응용 어플리케이션에서도 특정 시간 이후에 인터럽트를 발생시켜 정해진 일을 수행하는 경우 등 응용분야는 무수히 많습니다.</p>
<p><strong>■ 참고 ■</strong><br />
CPU의 클럭 속도가 1Hz 라는 것은 무엇을 의미하는 것일까요?<br />
이것은 1초에 1번의 Tick이 발생한다는 것임. STM32가 72MHz 로 동작한다면 1초에 7천 2백만번의 Tick이 발생하는 것</p>
<p>이번 예제에서는 STM32 CPU에 내장된 Timer2를 이용해서 1초에 한번씩 Timer 인터럽트를 발생시켜 LDE2, LED3를 Toggle(On/Off 를 반복하는것)하는 실험을 해보도록 하겠습니다.</p>
<p><strong>■ 참고 ■</strong><br />
1sec = 1,000ms = 1,000,000us = 1,000,000,000ns<br />
1Hz = 1KHz = 1MHz = 1GHz</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-26.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21174" alt="20feajk (26)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-26-620x395.png" width="496" height="316" /></a></p>
<p><span style="color: #99cc00"><strong>(1) STM32F CPU의 타이머 종류</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-27.jpg" rel="lightbox[21271]"><img class="alignnone  wp-image-21175" alt="20feajk (27)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-27-620x447.jpg" width="496" height="358" /></a></p>
<p><span style="color: #99cc00"><strong>(2) Timer Clock</strong></span><br />
Timer2는 APB1 버스에 연결되어 있습니다. APB1 버스의 최대 동작 속도는 36MHz이지만 위의 그림을 잘 보면 APB1의 Prescaler가 1이 아니면 PB1 Clock x2를 하고 있습니다. 그러므로 Timer2가 APB1에 연결되어 있지만 Timer2에 공급되는 Clock은 72MHz가 됩니다. 주의해서 보지 않으면 Timer2에 공급되는 Clock이 36MHz라고 착각할 수 있습니다.</p>
<p><span style="color: #99cc00"><strong>(3) 프로젝트와 stm32f10x_conf.h 파일 수정</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-93.jpg" rel="lightbox[21271]"><img class="alignnone  wp-image-21240" alt="20feajk (93)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-93-620x310.jpg" width="496" height="248" /></a></p>
<p><span style="color: #99cc00"><strong>(4) 예제 코드 작성 순서</strong></span><br />
□ APB1 Clock enable for TIM2<br />
□ GPIO Init for LED<br />
□ Configure the TIM2 interrupt<br />
□ Time base configuration<br />
□ TIM2 Enable<br />
□ TIM2 interrupt enable</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>예제 전체 코드</p>
<p>void gpio_init_led(void)<br />
{<br />
// Define GPIO Init structure<br />
GPIO_InitTypeDef GPIO_InitStructure;</p>
<p>// APB2 Clock enable<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);</p>
<p>/* Configure the GPIOE ports for output*/<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;<br />
GPIO_Init(GPIOE, &amp;GPIO_InitStructure);<br />
}<br />
void gpio_init_key(void)<br />
{<br />
// Define GPIO Init structure<br />
GPIO_InitTypeDef GPIO_InitStructure;</p>
<p>// APB2 Clock enable for KEY<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);</p>
<p>// for Interrupt<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);</p>
<p>/* Configure the GPIOC ports for input */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;<br />
GPIO_Init(GPIOC, &amp;GPIO_InitStructure);<br />
}</p>
<p>void TIM2_IRQHandler(void)<br />
{<br />
if(TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET )<br />
{<br />
// Also cleared the wrong interrupt flag in the ISR<br />
TIM_ClearFlag(TIM2, TIM_FLAG_Update);<br />
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // Clear the interrupt flag</p>
<p>// Blink<br />
GPIOE-&gt;ODR ^= (0&#215;1 &lt;&lt; 2);<br />
GPIOE-&gt;ODR ^= (0&#215;1 &lt;&lt; 3);<br />
}<br />
}<br />
void timer2_test(void)<br />
{<br />
NVIC_InitTypeDef NVIC_InitStructure;<br />
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;</p>
<p>/* TIM2 clock enable */<br />
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);</p>
<p>gpio_init_led();</p>
<p>/* Enable the TIM2 global Interrupt */<br />
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;<br />
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<br />
NVIC_Init(&amp;NVIC_InitStructure);</p>
<p>// TIM2CLK = 72 MHz( APB1은 원래 36MHz 인데 분주를 해서 사용하므로 36*2 = 72MHz 가 된다. )<br />
// 시간의 기본단위 :S(초)&#8211;&gt;nS.uS.mS.S.<br />
// 72000000/60000=1200 즉 1초에 1200번 클럭이 발생하므로<br />
// ARR 레지스터를 1199+1 번에 한번 인터럽트가<br />
// 발생하도록 설정하면 1초에 한번 인터럽트가 발생된다.<br />
/* Time base configuration */<br />
TIM_TimeBaseStructure.TIM_Period = 1200-1; // ARR(Auto reload register)<br />
TIM_TimeBaseStructure.TIM_Prescaler = 60000-1;<br />
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;<br />
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;<br />
TIM_TimeBaseInit(TIM2, &amp;TIM_TimeBaseStructure);</p>
<p>TIM_ARRPreloadConfig(TIM2, ENABLE);<br />
TIM_Cmd(TIM2, ENABLE);</p>
<p>/* TIM IT enable */<br />
TIM_ITConfig(TIM2, TIM_IT_Update , ENABLE);<br />
}</p>
</div>
자주 사용하는 LED, KEY포트를 초기화하는 함수 gpio_init_led, gpio_init_key를 만들어서 호출하였습니다.</p>
<p><span style="color: #ff6600"><strong>4.7 Systick &#8211; Delay</strong></span></p>
<p>SysTick Timer를 이용해서 1us Delay 함수를 구현하자. delay_ms 함수를 이용하여 LED2, LED3을 1초 간격으로 Toggle(On/Off) 해 봅시다.</p>
<p><span style="color: #99cc00"><strong>(1) System Control Space</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-28.png" rel="lightbox[21271]"><img class="alignnone size-large wp-image-21176" alt="20feajk (28)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-28-620x217.png" width="620" height="217" /></a><br />
System timer인 SysTick은 System Control Space 영역에 위치하고 있습니다.</p>
<p><span style="color: #99cc00"><strong>(2) SysTick Control and Status Register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-29.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21177" alt="20feajk (29)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-29.png" width="496" height="388" /></a><br />
이번에는 SysTick 인터럽트는 사용하지 않을 예정이며, CLKSOURCE는 core clock(72MHz)을 그대로 사용할 것입니다.</p>
<p><span style="color: #99cc00"><strong>(3) Systick Reload Register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-30.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21178" alt="20feajk (30)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-30.png" width="496" height="329" /></a><br />
Systick Current Value Register를 보면 Systick Timer는 24비트 타이머라는것을 알 수 있습니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>예제 전체 코드</p>
<p>// 1us delay 함수<br />
void delay_us (const uint32_t usec)<br />
{<br />
RCC_ClocksTypeDef RCC_Clocks;</p>
<p>/* Configure HCLK clock as SysTick clock source */<br />
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);<br />
RCC_GetClocksFreq(&amp;RCC_Clocks);<br />
// Set SysTick Reload(1us) register and Enable<br />
// usec * (RCC_Clocks.HCLK_Frequency / 1000000) &lt; 0xFFFFFFUL &#8212; because of 24bit timer<br />
// RCC_Clocks.HCLK_Frequency = 72000000<br />
// Systick Reload Value Register = 72<br />
// 72 / 72000000 = 1us<br />
SysTick_Config(usec * (RCC_Clocks.HCLK_Frequency / 1000000));</p>
<p>// SysTick Interrupt Disable<br />
SysTick-&gt;CTRL &amp;= ~SysTick_CTRL_TICKINT_Msk ;</p>
<p>// Until Tick count is 0<br />
while (!(SysTick-&gt;CTRL &amp; SysTick_CTRL_COUNTFLAG_Msk));<br />
}<br />
// 1ms delay 함수<br />
void delay_ms (const uint32_t msec)<br />
{<br />
delay_us(1000 * msec);<br />
}<br />
void systick_test_delay(void)<br />
{<br />
gpio_init_led();<br />
gpio_init_key();</p>
<p>while(1)<br />
{<br />
// BTN1<br />
if( (!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0 )) )<br />
{<br />
break;<br />
}</p>
<p>delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);<br />
delay_ms(100);</p>
<p>// Blink<br />
GPIOE-&gt;ODR ^= (0&#215;1 &lt;&lt; 2);<br />
GPIOE-&gt;ODR ^= (0&#215;1 &lt;&lt; 3);<br />
}<br />
}</p>
</div>
72MHz 클럭을 가지는 24Bit SysTick 타이머로는 1초 Delay를 만들어 낼 수 없기 때문에 100msec delay 함수를 10번 호출하여 구현하였습니다.</p>
<p><span style="color: #ff6600"><strong>4.8 Systick &#8211; Interrupt</strong></span></p>
<p>SysTick Timer를 이용해서 100msec 간격으로 SysTick_Handler 인터럽트를 발생시키고 LED2, LED3을 Toggle(On/Off) 해 봅시다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void SysTick_Handler(void)<br />
{<br />
// Blink<br />
GPIOE-&gt;ODR ^= (0&#215;1 &lt;&lt; 2);<br />
GPIOE-&gt;ODR ^= (0&#215;1 &lt;&lt; 3);<br />
}<br />
void systick_test_interrupt(void)<br />
{<br />
RCC_ClocksTypeDef RCC_Clocks;</p>
<p>gpio_init_led();</p>
<p>/* Configure HCLK clock as SysTick clock source */<br />
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);<br />
RCC_GetClocksFreq(&amp;RCC_Clocks);</p>
<p>/* Setup SysTick Timer for 100 msec interrupts */<br />
if (SysTick_Config(RCC_Clocks.HCLK_Frequency / 10))<br />
{<br />
/* Capture error */<br />
while (1);<br />
}<br />
}</p>
</div>
SysTick_Config 함수 안에서 기본으로 SysTick 인터럽트를 Enable 하고 있기 때문에 다른 설정을 하지 않아도 SysTick_Handler 인터럽트 핸들러로 진입합니다.<br />
이전 SysTick Delay 예제에서는 인터럽트가 발생하지 않도록 하기 위해서,<br />
SysTick-&gt;CTRL &amp;= ~SysTick_CTRL_TICKINT_Msk ;<br />
위와 같은 코드가 삽입되어 있었습니다.</p>
<p><span style="color: #ff6600"><strong>4.9 USART &#8211; Polling</strong></span></p>
<p>UART1를 PC와 115200bps Baudrate로 통신(RX, TX)을 하는 Echo server로 만들어 봅시다.<br />
RX, TX 통신을 폴링 방식으로 처리합니다. 터미널에서 ‘x’ 가 입력되면 폴링을 종료합니다.</p>
<p><span style="color: #99cc00"><strong>(1) Dragon 개발보드의 UART 회로</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-31.jpg" rel="lightbox[21271]"><img class="alignnone size-full wp-image-21179" alt="20feajk (31)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-31.jpg" width="568" height="329" /></a><br />
Dragon 개발보드에는 COM포트가 없는 노트북, 데스크탑에서 편리하게 사용하게 하기 위해서 USB to Serial 포트가 내장되어 있습니다.<br />
회로도를 보면 PA10이 RX, PA9가 TX 포트입니다. 이번 예제 테스트를 위해서 단순히 USB 미니케이블을 이용해서 Dragon Bottom 보드에 있는 UART 0번과 PCB의 USB 포트에 연결하면 됩니다. 이때 아직 USB to Serial USB 드라이버를 설치하지 않았다면 이전 강좌에서 설명한 &#8220;PL2303 USB to Serial 드라이버 설치&#8221; 부분을 참조하시기 바랍니다.</p>
<p><span style="color: #99cc00"><strong>(2) Peripheral Bus</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-32.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21180" alt="20feajk (32)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-32.png" width="398" height="210" /></a><br />
APB2 버스에 연결되어 있는 USART1과 GPA9, 10번 포트도 사용되고 있기 때문에 2개의 Peripheral Clock을 모두 Enable해 주어야 합니다.</p>
<p><span style="color: #99cc00"><strong>(3) UART1 사용을 위한 GPIO 포트 초기화</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-41.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21189" alt="20feajk (41)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-41-620x313.png" width="496" height="250" /></a></p>
<p><span style="color: #99cc00"><strong>(4) 프로젝트와 stm32f10x_conf.h 파일 수정</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-95.jpg" rel="lightbox[21271]"><img class="alignnone  wp-image-21242" alt="20feajk (95)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-95-620x330.jpg" width="496" height="264" /></a></p>
<p><span style="color: #99cc00"><strong>(5) USART Status register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-42.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21190" alt="20feajk (42)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-42-620x209.png" width="496" height="167" /></a></p>
<p>&nbsp;</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void usart1_test_polling(void)<br />
{<br />
GPIO_InitTypeDef GPIO_InitStructure;<br />
USART_InitTypeDef USART_InitStructure;</p>
<p>char receive_data;<br />
// APB2 Clock enable for USART(GPIOA9, A10)<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);<br />
/* USART1 clock enable */<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);</p>
<p>/* Configure the GPIO ports( USART1 Transmit and Receive Lines) */<br />
/* Configure the USART1_Tx as Alternate function Push-Pull */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;<br />
GPIO_Init(GPIOA, &amp;GPIO_InitStructure);</p>
<p>/* Configure the USART1_Rx as input floating */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;<br />
GPIO_Init(GPIOA, &amp;GPIO_InitStructure);</p>
<p>/* Configure the USART1 */<br />
USART_InitStructure.USART_BaudRate = 115200;<br />
USART_InitStructure.USART_WordLength = USART_WordLength_8b;<br />
USART_InitStructure.USART_StopBits = USART_StopBits_1;<br />
USART_InitStructure.USART_Parity = USART_Parity_No;<br />
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;<br />
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;<br />
USART_Init(USART1, &amp;USART_InitStructure);</p>
<p>/* Enable the USART1 */<br />
USART_Cmd(USART1, ENABLE);</p>
<p>while(1)<br />
{<br />
// Rx not empty 가 될때까지 Polling<br />
while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET );<br />
// Rx not empty가 되면 USART Data register 에서 data를 읽어옴<br />
receive_data = USART_ReceiveData(USART1) &amp; 0xFF;</p>
<p>// Tx data 전송<br />
USART_SendData(USART1, receive_data);<br />
// Tx empty가 상태가 될때까지 Polling<br />
// Tx 전송시 이 코드를 생략하면 빠른 Data 전송시 중간에 Tx Data 가 유실될수 있음<br />
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );</p>
<p>if( receive_data == &#8216;x&#8217; )<br />
break;<br />
}<br />
}</p>
</div>
<p>&nbsp;</p>
<p><strong><span style="color: #ff6600">4.10 USART &#8211; Interrupt</span></strong></p>
<p>UART1를 PC와 115200bps Baudrate로 통신(RX, TX)을 하는 Echo server로 만들어 봅시다. TX는 폴링 방식으로 처리하고 RX는 Interrupt 방식으로 처리합니다.</p>
<p><span style="color: #99cc00"><strong>(1) USART1 Control Register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-43.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21191" alt="20feajk (43)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-43-620x311.png" width="496" height="249" /></a></p>
<p>&nbsp;</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void USART1_IRQHandler(void)<br />
{<br />
char receive_data;</p>
<p>if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)<br />
{<br />
receive_data = USART_ReceiveData(USART1) &amp; 0xFF;</p>
<p>USART_SendData(USART1, receive_data);<br />
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );</p>
<p>USART_ClearITPendingBit(USART1, USART_IT_RXNE);<br />
}<br />
}<br />
void usart1_test_interrupt(void)<br />
{<br />
GPIO_InitTypeDef GPIO_InitStructure;<br />
USART_InitTypeDef USART_InitStructure;<br />
NVIC_InitTypeDef NVIC_InitStructure;</p>
<p>// APB2 Clock enable for USART(GPIOA9, A10)<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);</p>
<p>/* USART1 clock enable */<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);</p>
<p>/* Enable the USART1 Interrupt */<br />
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;<br />
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<br />
NVIC_Init(&amp;NVIC_InitStructure);</p>
<p>/* Configure the GPIO ports( USART1 Transmit and Receive Lines) */<br />
/* Configure the USART1_Tx as Alternate function Push-Pull */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;<br />
GPIO_Init(GPIOA, &amp;GPIO_InitStructure);</p>
<p>/* Configure the USART1_Rx as input floating */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;<br />
GPIO_Init(GPIOA, &amp;GPIO_InitStructure);</p>
<p>/* Configure the USART1 */<br />
USART_InitStructure.USART_BaudRate = 115200;<br />
USART_InitStructure.USART_WordLength = USART_WordLength_8b;<br />
USART_InitStructure.USART_StopBits = USART_StopBits_1;<br />
USART_InitStructure.USART_Parity = USART_Parity_No;<br />
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;<br />
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;<br />
USART_Init(USART1, &amp;USART_InitStructure);<br />
// Rx Not empty interrupt enable<br />
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);</p>
<p>/* Enable the USART1 */<br />
USART_Cmd(USART1, ENABLE);<br />
}</p>
</div>
<p><strong style="color: #ff6600">4.11 USART &#8211; Name Card</strong></p>
<p>PC의 터미널에 다음과 같이 명함을 출력해 보세요.</p>
<p>*************************************<br />
* Name : Kyung Yeon Kim *<br />
* Company : JK Electronics *<br />
* No : 010-XXXX-XXXX *<br />
*************************************</p>
<p>참고1. 터미널의 행 개행 문자는 “\r\n”<br />
참고2. 터미널 문자열 출력을 하는데 문자열 출력 함수를 만들어 사용하세요.<br />
void usart1_send_string(char *data);<br />
참고3. usart1 초기(폴링방식)화 함수를 작성하세요.<br />
void usart1_init(void);</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>예제 전체 코드</p>
<p>void usart1_init(void)<br />
{<br />
GPIO_InitTypeDef GPIO_InitStructure;<br />
USART_InitTypeDef USART_InitStructure;</p>
<p>// APB2 Clock enable for USART(GPIOA9, A10)<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);</p>
<p>/* USART1 clock enable */<br />
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);</p>
<p>/* Configure the GPIO ports( USART1 Transmit and Receive Lines) */<br />
/* Configure the USART1_Tx as Alternate function Push-Pull */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;<br />
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;<br />
GPIO_Init(GPIOA, &amp;GPIO_InitStructure);</p>
<p>/* Configure the USART1_Rx as input floating */<br />
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;<br />
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;<br />
GPIO_Init(GPIOA, &amp;GPIO_InitStructure);<br />
/* Configure the USART1 */<br />
USART_InitStructure.USART_BaudRate = 115200;<br />
USART_InitStructure.USART_WordLength = USART_WordLength_8b;<br />
USART_InitStructure.USART_StopBits = USART_StopBits_1;<br />
USART_InitStructure.USART_Parity = USART_Parity_No;<br />
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;<br />
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;<br />
USART_Init(USART1, &amp;USART_InitStructure);</p>
<p>/* Enable the USART1 */<br />
USART_Cmd(USART1, ENABLE);<br />
}<br />
void usart1_send_string(char* data)<br />
{<br />
while(*data != &#8221;)<br />
{<br />
USART_SendData(USART1, *(unsigned char *)data);<br />
while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET );<br />
data++;<br />
}<br />
}<br />
void usart1_test_namecard(void)<br />
{<br />
usart1_init();</p>
<p>usart1_send_string(&#8220;\r\n&#8221;);<br />
usart1_send_string(&#8220;****************************************\r\n&#8221;);<br />
usart1_send_string(&#8220;* Name : Kyung Yeon Kim *\r\n&#8221;);<br />
usart1_send_string(&#8220;* Company : JK Electronics *\r\n&#8221;);<br />
usart1_send_string(&#8220;* No : 010-XXXX-XXXX *\r\n&#8221;);<br />
usart1_send_string(&#8220;****************************************\r\n&#8221;);<br />
usart1_send_string(&#8220;\r\n&#8221;);<br />
}</p>
</div>
<p><span style="color: #ff6600"><strong>4.12 Interrupt Priority1</strong></span></p>
<p>BTN3를 누르면 LED3를 무한 반복을 하면서 On을 시키고 BTN4를 누르면 LED4를 무한 반복을 하면서 On을 시킨다.</p>
<p><span style="color: #99cc00"><strong>(1) Group, Sub Priority bit를 각각 2Bit씩 설정</strong></span></p>
<p><span style="color: #99cc00"><strong>(2) BTN3의 Group Priority를 2, Sub Priority를 0으로 설정</strong></span></p>
<p><span style="color: #99cc00"><strong>(3) BTN4의 Group Priority를 1, Sub Priority를 0으로 설정 후 테스트</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void EXTI2_IRQHandler(void)<br />
{<br />
if(EXTI_GetITStatus(EXTI_Line2) != RESET)<br />
{<br />
EXTI_ClearITPendingBit(EXTI_Line2);</p>
<p>while(1)<br />
{<br />
GPIO_SetBits(GPIOE, GPIO_Pin_3); // LED3 On<br />
}<br />
}<br />
}</p>
<p>void EXTI3_IRQHandler(void)<br />
{<br />
if(EXTI_GetITStatus(EXTI_Line3) != RESET)<br />
{<br />
EXTI_ClearITPendingBit(EXTI_Line3);</p>
<p>while(1)<br />
{<br />
GPIO_SetBits(GPIOE, GPIO_Pin_4); // LED4 On<br />
}<br />
}<br />
}<br />
void interrupt_priority1_test(void)<br />
{<br />
EXTI_InitTypeDef EXTI_InitStructure;<br />
NVIC_InitTypeDef NVIC_InitStructure;</p>
<p>gpio_init_led();<br />
gpio_init_key();</p>
<p>/* Connect EXTI */<br />
// External Interrupt configuration register1 (AFIO_EXTICR1)<br />
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);<br />
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);</p>
<p>/* Configure EXTI2 to generate an interrupt on falling edge */<br />
EXTI_InitStructure.EXTI_Line = EXTI_Line2;<br />
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;<br />
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;<br />
EXTI_InitStructure.EXTI_LineCmd = ENABLE;<br />
EXTI_Init(&amp;EXTI_InitStructure);</p>
<p>/* Configure EXTI3 to generate an interrupt on falling edge */<br />
EXTI_InitStructure.EXTI_Line = EXTI_Line3;<br />
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;<br />
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;<br />
EXTI_InitStructure.EXTI_LineCmd = ENABLE;<br />
EXTI_Init(&amp;EXTI_InitStructure);</p>
<p>// 2 bit for pre-emption priority, 2 bits for subpriority<br />
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);</p>
<p>NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;<br />
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;<br />
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;<br />
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<br />
NVIC_Init(&amp;NVIC_InitStructure);</p>
<p>NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;<br />
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;<br />
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<br />
NVIC_Init(&amp;NVIC_InitStructure);</p>
<p>/* Clear EXTI Line Pending Bit */<br />
// STM32F10x Pending Register : 0&#215;40010400 + 0&#215;14<br />
EXTI_ClearITPendingBit(EXTI_Line2);<br />
EXTI_ClearITPendingBit(EXTI_Line3);</p>
<p>/* Enable the Key EXTI line Interrupt */<br />
// Cortex-M3 Interrupt Clear-Pending Register : 0xE000E280-0xE000E29C<br />
NVIC_ClearPendingIRQ(EXTI2_IRQn);<br />
NVIC_ClearPendingIRQ(EXTI3_IRQn);<br />
}</p>
</div>
예제의 실행결과를 알 수 있겠죠. BTN3의 Group Priority를 2로 BTN4보다 높기 때문에 BTN3을 먼저 누르면 BTN4의 인터럽트가 실행되지 못합니다. 반대로 BTN4의 인터럽트 실행 중에 BTN3을 누르면 즉시 BTN3의 인터럽트 서비스 루틴이 실행됩니다.</p>
<p><strong><span style="color: #ff6600">4.13 Interrupt Priority2</span></strong></p>
<p>BTN3를 누르면 LED3를 무한 반복을 하면서 On을 시키고 BTN4를 누르면 LED4를 무한 반복을 하면서 On을 시킨다.</p>
<p><span style="color: #99cc00"><strong>(1) Group, Sub Priority bit를 각각 2Bit씩 설정</strong></span></p>
<p><span style="color: #99cc00"><strong>(2) BTN3의 Group Priority를 2, Sub Priority를 0으로 설정</strong></span></p>
<p><span style="color: #99cc00"><strong>(3) BTN4의 Group Priority를 2, Sub Priority를 1로 설정 후 테스트</strong></span></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>예제 전체 코드</p>
<p>void EXTI2_IRQHandler(void)<br />
{<br />
if(EXTI_GetITStatus(EXTI_Line2) != RESET)<br />
{<br />
EXTI_ClearITPendingBit(EXTI_Line2);</p>
<p>while(1)<br />
{<br />
GPIO_SetBits(GPIOE, GPIO_Pin_3); // LED3 On<br />
}<br />
}<br />
}</p>
<p>void EXTI3_IRQHandler(void)<br />
{<br />
if(EXTI_GetITStatus(EXTI_Line3) != RESET)<br />
{<br />
EXTI_ClearITPendingBit(EXTI_Line3);</p>
<p>while(1)<br />
{<br />
GPIO_SetBits(GPIOE, GPIO_Pin_4); // LED4 On<br />
}<br />
}<br />
}<br />
void interrupt_priority1_test(void)<br />
{<br />
EXTI_InitTypeDef EXTI_InitStructure;<br />
NVIC_InitTypeDef NVIC_InitStructure;</p>
<p>gpio_init_led();<br />
gpio_init_key();</p>
<p>/* Connect EXTI */<br />
// External Interrupt configuration register1 (AFIO_EXTICR1)<br />
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource2);<br />
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource3);</p>
<p>/* Configure EXTI2 to generate an interrupt on falling edge */<br />
EXTI_InitStructure.EXTI_Line = EXTI_Line2;<br />
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;<br />
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;<br />
EXTI_InitStructure.EXTI_LineCmd = ENABLE;<br />
EXTI_Init(&amp;EXTI_InitStructure);</p>
<p>/* Configure EXTI3 to generate an interrupt on falling edge */<br />
EXTI_InitStructure.EXTI_Line = EXTI_Line3;<br />
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;<br />
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;<br />
EXTI_InitStructure.EXTI_LineCmd = ENABLE;<br />
EXTI_Init(&amp;EXTI_InitStructure);</p>
<p>// 2 bit for pre-emption priority, 2 bits for subpriority<br />
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);</p>
<p>NVIC_InitStructure.NVIC_IRQChannel = EXTI2_IRQn;<br />
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;<br />
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;<br />
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<br />
NVIC_Init(&amp;NVIC_InitStructure);</p>
<p>NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;<br />
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;<br />
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;<br />
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;<br />
NVIC_Init(&amp;NVIC_InitStructure);</p>
<p>/* Clear EXTI Line Pending Bit */<br />
// STM32F10x Pending Register : 0&#215;40010400 + 0&#215;14<br />
EXTI_ClearITPendingBit(EXTI_Line2);<br />
EXTI_ClearITPendingBit(EXTI_Line3);</p>
<p>/* Enable the Key EXTI line Interrupt */<br />
// Cortex-M3 Interrupt Clear-Pending Register : 0xE000E280-0xE000E29C<br />
NVIC_ClearPendingIRQ(EXTI2_IRQn);<br />
NVIC_ClearPendingIRQ(EXTI3_IRQn);<br />
}</p>
</div>
<p>이번 예제에서는 BTN3과 4의 Group 우선순위가 같기 때문에 서로 인터럽트 수행 중에는 선점을 하지 못합니다.</p>
<p><strong><span style="color: #ff6600">4.14 Power Management &#8211; Sleep</span></strong></p>
<p>Cortex-M3에서 Power Management 기능은 NVIC에 포함되어 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-44.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21192" alt="20feajk (44)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-44-620x234.png" width="496" height="187" /></a></p>
<p><span style="color: #99cc00"><strong>(1) Sleep 모드 테스트</strong></span><br />
터미널 창에 아래와 같이 표시되도록 합니다.<br />
Entered Sleep mode.<br />
__WFI(); // Sleep mode 로 진입<br />
Exit Sleep mode.</p>
<p><span style="color: #99cc00"><strong>(2) BTN2를 인터럽트 모드로 입력 받아서 Sleep 모드를 빠져 나오도록 합니다. 추가로 BTN2를 누르면 LED2를 On 시키고 BTN2를 떼면 LED2를 Off 합니다.</strong></span></p>
<p><span style="color: #99cc00"><strong>(3) STM32F Low Power Mode</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-45.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21193" alt="20feajk (45)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-45-620x291.png" width="558" height="262" /></a><br />
STM32에서 Sleep 모드로 진입하기 위해서는 WFI(Wait for Interrupt) or WFE(Wait for Event) 어셈블리어에 의해서 진입할 수 있습니다. 이번 예제에서는 WFI를 이용해서 Sleep 모드로 진입하도록 하겠습니다. WFI에 의해서 진입한 Sleep 모드에서 깨어나기 위해서는 어떠한 인터럽트 발생에 의해서라도 깨어날 수 있습니다.</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void power_management_sleep_test(void)<br />
{<br />
key_input_test_interrupt();</p>
<p>usart1_send_string(&#8220;\r\nEnter Sleep mode.\r\n&#8221;);</p>
<p>__WFI();</p>
<p>usart1_send_string(&#8220;\r\nExit Sleep mode.\r\n&#8221;);</p>
<p>}</p>
</div>
Sleep모드의 장점은 Cortex-M3 Core의 Clock만 멈추어 있는 상태여서 인터럽트에 의해서 즉시 깨어날 수가 있어서 Sleep 모드에 진입해있는지 조차 알 수가 없다는 것이고 단점은 Stop, StandBy 모드에 비해서 소모전류가 많다는 것입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-46.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21194" alt="20feajk (46)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-46-620x315.png" width="496" height="252" /></a><br />
Sleep 모드별 Wakeup 방식과 Clock Management 방법입니다.</p>
<p><span style="color: #ff6600"><strong>4.15 Power Management &#8211; Stop</strong></span></p>
<p>Stop, StandBy 모드는 모두 Cortex-M3 Deep sleep 모드에 해당 합니다.</p>
<p><span style="color: #99cc00"><strong>(1) Stop 모드 실험</strong></span><br />
□ Timer2 인터럽트를 1초 간격으로 발생시켜 LED2, LED3를 Toggle<br />
□ PWR_EnterSTOPMode() 함수를 호출하여 Stop 모드로 진입 합니다.<br />
□ BTN2를 인터럽트 모드로 입력 받아서 Stop 모드를 빠져 나오도록 합니다. 추가로 BTN2를 누르면 LED2를 On 시키고 BTN2를 떼면 LED2를 Off 합니다.<br />
□ STOP 모드를 빠져나온 이후에 LED2, LED3이 1초 간격으로 Toggle<br />
□ PWR_EnterSTOPMode를 호출하면 진입</p>
<p style="padding-left: 60px">■ SRAM, Register 상태는 유지<br />
■ 1.8V Domain에 있는 모든 클럭이 Stop<br />
■ PLL, HIS RC, HSE crystal oscillator 모두 disable<br />
■ Voltage regulator는 normal or low power mode</p>
<p>□ Wakeup</p>
<p style="padding-left: 30px">■ EXTI line 중의 하나를 받아야 함<br />
■ 16개의 EXTI line or PVD output, RTC alarm, USB wakeup</p>
<p><span style="color: #99cc00"><strong>(2) Peripheral Bus &#8211; PWR</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-47.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21154" alt="20feajk (47)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-47-620x251.png" width="496" height="201" /></a><br />
STM32F의 Power 블럭은 APB1 버스에 연결되어 있습니다.</p>
<p><span style="color: #99cc00"><strong>(3) 프로젝트와 stm32f10x_conf.h 파일 수정</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-96.jpg" rel="lightbox[21271]"><img class="alignnone  wp-image-21243" alt="20feajk (96)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-96-620x289.jpg" width="496" height="231" /></a></p>
<p><span style="color: #99cc00"><strong>(4) STM32 PWR 블럭도</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/11/20feajk-51.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21280" alt="20feajk 51" src="http://www.ntrexgo.com/wp-content/uploads/2013/11/20feajk-51-620x416.png" width="496" height="333" /></a></p>
<p><span style="color: #99cc00"><strong>(5) Cortex-M3 System Control Registe</strong></span><span style="color: #99cc00"><strong>r</strong></span></p>
<p><span style="color: #99cc00"><strong><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-33.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21181" alt="20feajk (33)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-33-620x451.png" width="496" height="361" /></a></strong></span><br />
Stop 모드로 진입시키기 위해서는 2번 비트의 SLEEPDEEP을 Set해야 합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-34.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21182" alt="20feajk (34)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-34-620x534.png" width="496" height="427" /></a></p>
<p><span style="color: #99cc00"><strong>(6) STM32 Power Control Register</strong></span><br />
PDDS를 o으로, LPDS를 0으로 할 수도 있고, 1로 할 수도 있으나 이번 예제에서는 1로 설정하여 Vdd Domain에 있는 Voltage Regulator를 low-power 모드로 설정합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/11/20feajk-52.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21281" alt="20feajk 52" src="http://www.ntrexgo.com/wp-content/uploads/2013/11/20feajk-52-620x487.png" width="496" height="390" /></a></p>
<p>&nbsp;</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>// STOP 모드에 진입하면 HSE Clock 등이 Disale 되기 때문에 Wakeup시에 다시 설정을 해주어야 합니다.<br />
void system_clock_config_stop(void)<br />
{<br />
RCC_HSEConfig(RCC_HSE_ON); // Enable HSE</p>
<p>if( RCC_WaitForHSEStartUp() == SUCCESS)<br />
{<br />
RCC_PLLCmd(ENABLE); // Enable PLL</p>
<p>// Wait until PLL is ready<br />
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}</p>
<p>// Select PLL as system clock source<br />
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);</p>
<p>// wait until PLL is used as system clock source<br />
while(RCC_GetSYSCLKSource() != 0&#215;08) {}<br />
}<br />
}<br />
void power_management_stop_test(void)<br />
{<br />
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);</p>
<p>timer2_test();<br />
key_input_test_interrupt();</p>
<p>usart1_send_string(&#8220;\r\nEnter Stop mode.\r\n&#8221;);</p>
<p>// STOP 모드로 진입하고 외부 인터럽트에 의해서 깨어남<br />
PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);</p>
<p>system_clock_config_stop();</p>
<p>usart1_send_string(&#8220;\r\nExit Stop mode.\r\n&#8221;);<br />
}</p>
</div>
<p>&nbsp;</p>
<p><span style="color: #ff6600"><strong>4.16 Power Management &#8211; StandBy</strong></span></p>
<p><strong><span style="color: #99cc00">(1) PWR_WakeUpPinCmd(ENABLE)를 호출, PA0를 Wakeup 핀으로 설정</span></strong></p>
<p><span style="color: #99cc00"><strong>(2) BTN2를 인터럽트 모드로 입력 받아서 Stop 모드를 빠져나오도록 설정</strong></span></p>
<p><span style="color: #99cc00"><strong>(3) PWR_EnterSTANDBYMode()를 호출, StandBy 모드로 진입</strong></span><br />
StandBy모드로 진입하는 방법은 STOP모드로 진입하는 방법에서 STM32의 PWR_CR 레지스터의 PDDS를 1로 설정하는것을 제외하면 동일합니다. 단지 StandBy모드에서는 Wakeup 하는 방법에서 차이가 있으면 StandBy모드에서 Wakeup을 한다는 것은 CPU가 처음부터 다시 부팅하는 절차와 동일합니다. 하지만 StandBy모드에서 Wakeup이 되는 경우에는 PWR_CSR 레지스터의 Standby Flag가 H/W 적으로 Set이 되어 있습니다.</p>
<p><span style="color: #99cc00"><strong>(4) Power Control Register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-36.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21184" alt="20feajk (36)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-36-620x524.png" width="496" height="419" /></a></p>
<p><span style="color: #99cc00"><strong>(5) System Control Register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-37.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21185" alt="20feajk (37)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-37-620x428.png" width="496" height="342" /></a></p>
<p><span style="color: #99cc00"><strong>(6) Enable Wakeup PIN</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-38.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21186" alt="20feajk (38)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-38-620x484.png" width="496" height="387" /></a><br />
StandBy모드에서 깨어나기 위해서 Wakeup핀을 Enable 합니다. 반드시 PA0 핀이 이용됩니다.</p>
<p><span style="color: #99cc00"><strong>(7) Power control/status register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-39.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21187" alt="20feajk (39)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-39-620x418.png" width="496" height="334" /></a></p>
<p>※ StandbyMode에서 깨어났을 경우에 Hardware적으로 1로 설정됨</p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p>예제 전체 코드</p>
<p>void power_management_standby_test(void)<br />
{<br />
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);</p>
<p>// Enable Wakeup Pin(should be PA0)<br />
PWR_WakeUpPinCmd(ENABLE);</p>
<p>usart1_send_string(&#8220;\r\nWakeup pin enabled.\r\n&#8221;);</p>
<p>usart1_send_string(&#8220;Enter Standby mode.\r\n&#8221;);</p>
<p>// Standby Mode<br />
PWR_EnterSTANDBYMode();</p>
<p>// 이 코드는 실행될수 없음<br />
usart1_send_string(&#8220;\r\nExit Standby mode.\r\n&#8221;);<br />
}</p>
</div>
<p>&nbsp;</p>
<p><span style="color: #ff6600"><strong>4.17 Mode Privilege</strong></span></p>
<p><span style="color: #99cc00"><strong>(1) Reset 이후의 Mode(Privilege or Unprivilege)와 어떤 Stack(Main Stack, Process Stack)을 사용하는지를 PC의 터미널에 표시합니다.</strong></span></p>
<p><span style="color: #99cc00"><strong>(2) Mode를 Unprivilege 모드로 전환합니다.</strong></span></p>
<p><strong><span style="color: #99cc00">(3) 모든 전환 이후에 Mode(Privilege or Unprivilege)와 어떤 Stack(Main Stack, Process Stack)을 사용하는지를 PC의 터미널에 표시합니다.</span></strong></p>
<p><span style="color: #99cc00"><strong>(4) SVC 명령어 “__ASM(&#8220;svc #1&#8243;)” 를 사용해서 SVC_Handler Exception을 발생시키고 SVC_Handler 핸들러 진입 여부를 터미널에 표시합니다.</strong></span></p>
<p><span style="color: #99cc00"><strong>(5) SVC 핸들러내에서 Mode를 Privilege 모드로 전환합니다.</strong></span></p>
<p><span style="color: #99cc00"><strong>(6) 모든 전환 이후에 Mode(Privilege or Unprivilege)와 어떤 Stack(Main Stack, Process Stack)을 사용하는지를 PC의 터미널에 표시합니다.</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-40.png" rel="lightbox[21271]"><img class="alignnone  wp-image-21188" alt="20feajk (40)" src="http://www.ntrexgo.com/wp-content/uploads/2013/08/20feajk-40-620x250.png" width="496" height="200" /></a></p>
<div class="symple-box gray none" style="text-align:left; width:100%;"> 
<p><strong>예제 전체 코드</strong></p>
<p>void SVC_Handler(void)<br />
{<br />
usart1_send_string(&#8220;\r\nSVC_Handler\r\n&#8221;);<br />
usart1_send_string(&#8220;Mode change to privilege\r\n&#8221;);<br />
__set_CONTROL(0&#215;0);<br />
}</p>
<p>void mode_privilege_test(void)<br />
{<br />
usart1_send_string(&#8220;\r\n\r\n&#8212;- mode privilege test start &#8212;-\r\n\r\n&#8221;);</p>
<p>// Mode<br />
if( (__get_CONTROL() &amp; 0&#215;1) == 0&#215;1 )<br />
usart1_send_string(&#8220;Mode = Unprivilege\r\n&#8221;);<br />
else if( (__get_CONTROL() &amp; 0&#215;1) == 0&#215;0 )<br />
usart1_send_string(&#8220;Mode = Privilege Mode\r\n&#8221;);</p>
<p>// Stack<br />
if( (__get_CONTROL() &amp; 0&#215;2) == 0&#215;0 )<br />
usart1_send_string(&#8220;Stack = MSP Stack\r\n&#8221;);<br />
else if( (__get_CONTROL() &amp; 0&#215;2) == 0&#215;1 )<br />
usart1_send_string(&#8220;Stack = PSP Stack\r\n&#8221;);</p>
<p>// mode change to unprivilege<br />
usart1_send_string(&#8220;Mode change to unprivilege\r\n&#8221;);<br />
__set_CONTROL(0&#215;1);</p>
<p>// Mode<br />
if( (__get_CONTROL() &amp; 0&#215;1) == 0&#215;1 )<br />
usart1_send_string(&#8220;Mode = Unprivilege\r\n&#8221;);<br />
else if( (__get_CONTROL() &amp; 0&#215;1) == 0&#215;0 )<br />
usart1_send_string(&#8220;Mode = Privilege Mode\r\n&#8221;);</p>
<p>// Stack<br />
if( (__get_CONTROL() &amp; 0&#215;2) == 0&#215;0 )<br />
usart1_send_string(&#8220;Stack = MSP Stack\r\n&#8221;);<br />
else if( (__get_CONTROL() &amp; 0&#215;2) == 0&#215;1 )<br />
usart1_send_string(&#8220;Stack = PSP Stack\r\n&#8221;);</p>
<p>__ASM(&#8220;svc #1&#8243;);</p>
<p>// Mode<br />
if( (__get_CONTROL() &amp; 0&#215;1) == 0&#215;1 )<br />
usart1_send_string(&#8220;Mode = Unprivilege\r\n&#8221;);<br />
else if( (__get_CONTROL() &amp; 0&#215;1) == 0&#215;0 )<br />
usart1_send_string(&#8220;Mode = Privilege Mode\r\n&#8221;);</p>
<p>// Stack<br />
if( (__get_CONTROL() &amp; 0&#215;2) == 0&#215;0 )<br />
usart1_send_string(&#8220;Stack = MSP Stack\r\n&#8221;);<br />
else if( (__get_CONTROL() &amp; 0&#215;2) == 0&#215;1 )<br />
usart1_send_string(&#8220;Stack = PSP Stack\r\n&#8221;);</p>
<p>usart1_send_string(&#8220;&#8212;- mode privilege test end &#8212;-\r\n\r\n&#8221;);<br />
}</p>
</div>
<p>여기까지 전통적인 ARM 프로세서인 ARM9의 구조를 시작으로 ARM9 Application을 거쳐 Cortex-M3 Architecture, Cortex-M3 Application의 모든 과정이 마무리되었습니다. 머리 속에 있는 내용을 글로 옮긴다는 것이 쉽지는 않았던 것 같습니다. Cortex-M3 Application part에서 기본적인 예제만 다룬 것이 아쉬움이 남네요. 기회가 된다면 STM32 Dragon 개발보드에 있는 모든 디바이스들을 제어해보는 연재를 다시 시작해볼까 합니다. 그리고 개발 환경도 GCC와 이클립스 환경으로 바꾸어 좀 더 사이즈가 크고 전문적인 S/W개발 방법에 대해서 공부해보도록 하겠습니다. 특히 SD메모리와 LCD를 이용해서 예쁜 GUI를 구성하는 부분에 대해서 집중적으로 준비해보도록 하겠습니다.</p>
<p>수고하셨습니다.</p>
<p>&nbsp;</p>
<p><span style="background-color: #3366ff;color: #ffffff">JK전자와 함께하는 ARM 완전정복 시즌1이 모두 마무리 되었습니다.</span><br />
<span style="background-color: #3366ff;color: #ffffff"> 약 6개월 뒤쯤 새롭게 시작될 시즌 2도 기대해주시기 바랍니다. </span><br />
<span style="background-color: #3366ff;color: #ffffff">아울러 컨텐츠를 제공해주신 JK전자 관계자분들께 다시 한번 감사의 말씀을 드립니다.</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/21271/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[19호]JK전자와 함께하는 ARM 완전정복(5)</title>
		<link>http://www.ntrexgo.com/archives/15527</link>
		<comments>http://www.ntrexgo.com/archives/15527#comments</comments>
		<pubDate>Sun, 30 Jun 2013 00:55:19 +0000</pubDate>
		<dc:creator>디바이스마트 매거진</dc:creator>
				<category><![CDATA[디바이스마트 매거진]]></category>
		<category><![CDATA[특집]]></category>
		<category><![CDATA[19호]]></category>
		<category><![CDATA[ARM완전정복]]></category>
		<category><![CDATA[Feature]]></category>
		<category><![CDATA[jk전자]]></category>
		<category><![CDATA[매거진]]></category>

		<guid isPermaLink="false">http://www.ntrexgo.com/?p=15527</guid>
		<description><![CDATA[디바이스마트 매거진 19호 &#124; 이번 강좌에서는 Cortex-M3의 주요한 특징인 Bit Banding, System Timer, NVIC, Programmers's Model에 대해서 주로 다루도록 하겠습니다.]]></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[15527]"><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>&nbsp;</p>
<p>Ⅲ.Cortex-M3 Architecture</p>
<p>&nbsp;</p>
<p>글 | JK전자</td>
</tr>
</tbody>
</table>
<p>드디어 길고 지루했던 전통적인 ARM에 대해서 어느 정도 설명이 끝나고 원래 목표하고자 했던 Cortex-M3 파트까지 왔습니다. 이전 파트에서 아쉬움이 있다면 Cache, MMU 부분이 빠졌다는 것입니다. 기회가 된다면 Cortex-M3 강좌가 끝나면 Cache, MMU 부분만 별도로 강좌를 올릴 수 있도록 하겠습니다. 사실 Cortex-M3는 ARM7, ARM9 보다는 단순한 면이 있습니다. Core의 동작 모드가 Handler, Thread 2가지(전통적인 ARM은 7가지) 밖에 없고 Architecture 차원에서 Memory Map이 동일하기 때문입니다. 또한 어셈블리어를 잘 몰라도 Startup 코드를 작성할 수 있고 실제로 대부분의 인기있는 컴파일러는 컴파일러 차원에서 Startup 코드를 제공하고 있습니다. 이것이 가능한 것도 Architecture 차원에서 Memory Map이 동일하기 때문입니다. 이번 강좌에서는 Cortex-M3의 주요한 특징인 Bit Banding, System Timer, NVIC, Programmers&#8217;s Model에 대해서 주로 다루도록 하겠습니다.</p>
<p><span style="background-color: #ff6600;color: #ffffff"><strong>강의 전체 로드맵</strong></span></p>
<p>I. ARM Architecture | 임베디드 시스템 개론에 대한 설명과 ARM7, ARM9 의 구조에 대해서 설명합니다.<br />
II. ARM Applications | 삼성의 S3C2440(ARM9) 개발보드(S3C2440 Mini 개발보드)를 이용해서 어셈블리어와 UART, GPIO 등을 실습합니다.<br />
<span style="color: #0000ff">III. Cortex-M3 Architecture | Cortex-M3의 특징과 구조에 대해서 설명합니다.</span><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@deviceshop.net로 메일을 보내주시기 바랍니다. 가급적이면 여러 사람이 질문에 대한 답변을 공유할 수 있도록 네이버 카페 게시판을 이용해주셨으면 합니다. 감사합니다.</p>
<p><span style="background-color: #ff6600"><strong><span style="color: #ffffff">Ⅲ.  Cortex-M3 Architecture</span></strong></span></p>
<p>1. Cortex-M3 Processor 소개<br />
1.1 ARM Cortex-M3 프로세서란 무엇인가?<br />
2. Cortex-M3 Procesor 개요<br />
2.1 Cortex-M3 Procesor Overview<br />
2.2 Cortex-M3 Processor Block Diagram<br />
3. Cortex-M3 Processor Architectureㅅ<br />
3.1 Register<br />
3.2 Operation Mode<br />
3.3 Stack<br />
3.4 Cortex-M3 Memory Map<br />
3.5 Bit Banding<br />
3.6 System Timer(SysTick)<br />
4. Nested Vectored Interrupt Controller<br />
4.1 NVIC<br />
4.2 Interrupt Response</p>
<p><span style="background-color: #ff6600;color: #ffffff"><strong>1. Cortex-M3 Processor 소개</strong></span></p>
<p><span style="color: #ff9900"><strong>1.1 ARM Cortex-M3 프로세서란 무엇인가 ?</strong></span></p>
<p>Cortex-M3 Processor는 ARMv7-M profile 프로세서로 low gate count, low interrupt latency, and low-cost의 특징을 갖는 기존의 8Bit Microcontroller(AVR, PIC, 8051 등) 시장에 대응하는 Processor입니다. 또한 Cortex는 각각 다른 특징을 갖는 3가지의 Profile이 있습니다.</p>
<p><span style="background-color: #ffffff;color: #99cc00"><strong>(1) A profile (ARMv7-A) : Application Profile</strong></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: #99cc00"><strong>(2) R profile (ARMv7-R) : Real-time Profile</strong></span><br />
- For real-time system<br />
- ARM, Thumb, Thumb-2 instruction sets</p>
<p><span style="color: #99cc00"><strong>(3) M profile (ARMv7-M) : Microcontroller Profile</strong></span><br />
- For cost-sensitive and microcontroller applications<br />
- Thumb-2 instruction set only<br />
- Banked Stack Pointer (SP) only.<br />
- Hardware divide instructions, SDIV and UDIV (Thumb-2 32-bit instructions).<br />
- Handler and Thread modes.<br />
- Thumb and Debug states.<br />
- Interruptible-continued LDM/STM, PUSH/POP for low interrupt latency.<br />
- Automatic processor state saving and restoration for low latency Interrupt Service Routine (ISR) entry and exit.<br />
- Support for ARMv6 unaligned accesses.<br />
- Support Nested Vectored Interrupt Controller (NVIC)<br />
- STM32F, LPC111x Series</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm002.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15594" alt="19feaarm002" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm002.png" width="428" height="221" /></a></p>
<p>&nbsp;</p>
<p><span style="background-color: #ff6600;color: #ffffff"><strong>2. Cortex-M3 Procesor 개요</strong></span></p>
<p><span style="color: #ff9900"><strong>2.1 Cortex-M3 Procesor Overview</strong></span></p>
<p><span style="color: #99cc00"><strong>(1) Thumb-2 Instruction Set Architecture</strong></span><br />
- 16, 32 bit 명령을 조합해서 사용할 수 있습니다.<br />
- No more mode switching<br />
- 16-bit code density로 32-bit 명령 성능을 낼 수 있습니다.<br />
- 16-bit Thumb Instruction과 하위 호환성이 있습니다.</p>
<p><span style="color: #99cc00"><strong>(2) Harvard architecture</strong></span><br />
- Separate I&amp;D buses allow parallel instruction fetching &amp; data storage<br />
- 명령어와 Data를 동시에 Fetch할 수 있는 기능은 인터럽트 수행시 Latency를 줄일수 있는 중요한 feature입니다.</p>
<p><span style="color: #99cc00"><strong>(3) 3-Stage Pipeline with Branch Speculation- Fetch, Decode, Execute</strong></span><br />
- 분기 예측을 할 수 있다면 Pipeline에서 Branch 시 Pipeline Flush를 줄일 수 있어 시스템의 성능을 높일 수 있습니다.</p>
<p><span style="color: #99cc00"><strong>(4) Integrated Nested Vectored Interrupt Controller(NVIC) for low latency interrupt processing</strong></span></p>
<p><span style="color: #99cc00"><strong>(5) Vector Table is address, not instruction</strong></span></p>
<p><span style="color: #99cc00"><strong>(6) Designed to be fully programmed in &#8220;C&#8221;</strong></span></p>
<p><span style="color: #99cc00"><strong>(7) System Timer(SysTick) for Real Time OS &#8211; Not Peripheral timer</strong></span></p>
<p><span style="color: #99cc00"><strong>(8) Bit Band Aliasing</strong></span></p>
<p><span style="color: #99cc00"><strong>(9) Interruptible-continued LDM/STM, PUSH/POP</strong></span></p>
<p><span style="color: #99cc00"><strong>(10) Support Unaligned Data Access</strong></span><br />
- Unaligned access를 지원해서 메모리 사용의 효율성은 높였지만 여전히 속도를 위해서는 Aligned access를 하는 것이 효율적입니다.</p>
<p><span style="color: #ff9900"><strong>2.2 Cortex-M3 Processor Block Diagram</strong></span></p>
<p><span style="color: #99cc00"><strong>(1) Cortex-M3 블럭도</strong></span><br />
Cortex-M3 Core는 Bus Matrix( I-code, D-code, System Bus)를 통해서 Cortex-M3 코어를 Base로 하는 CPU들(STM32F, LPC111x 시리즈 등)과 연결이 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm003.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15595" alt="19feaarm003" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm003-620x360.png" width="620" height="360" /></a></p>
<p><span style="color: #99cc00"><strong>(2) Bus Matrix System</strong></span><br />
- ICode Bus : Instruction &amp; Vector fetches from CODE space<br />
(0&#215;0000.0000 ~ 0x1FFF.FFFF)<br />
- DCode Bus : Data &amp; Debugging access to CODE space<br />
(0&#215;0000.0000 ~ 0x1FFF.FFFF)<br />
- System Bus : Instruction &amp; Vector fetches from System Memory space<br />
Data &amp; Debug accesses to System Memory space<br />
System Memory( SRAM, External RAM )</p>
<p><span style="color: #99cc00"><strong>(3) STM32F 시리즈 블럭도</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm005.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15545" alt="19feaarm005" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm005-620x485.png" width="620" height="485" /></a></p>
<p>위의 블럭도에서 Cortex-M3부분만 ARM사에서 디자인한 것이고 나머지 부분은 ST Microelectronics에서 설계한 것입니다. Philips사의 LPC11x Cortex-M3 시리즈도 Cortex-M3 Core 부분은 STM32F 시리즈의 Core와 동일하고 주변 Peripheral, interface bus 등의 부분만 다른 것입니다.</p>
<p><span style="color: #99cc00"><strong>(4) Cortex-M3와 ARM7 비교</strong></span></p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td></td>
<td> <strong>ARM7TDMI</strong></td>
<td><strong> Cortex-M3</strong></td>
</tr>
<tr>
<td> Architecture</td>
<td> ARMv4T(von Neumann)</td>
<td> ARMv7M(Harvard)</td>
</tr>
<tr>
<td> ISA Support</td>
<td> ARM(32-Bit) &amp; Thumb(16-Bit)<br />
need Mode Change</td>
<td> Thumb-2 Only<br />
No more Mode Change</td>
</tr>
<tr>
<td> DMIPS/MHz</td>
<td> 0.74(Thumb)/0.93(ARM)</td>
<td> Thumb-2(1.25)</td>
</tr>
<tr>
<td> Pipeline</td>
<td> 3-Stage</td>
<td> 3-Stage+Branch Speculation</td>
</tr>
<tr>
<td> Interrupts</td>
<td> IRQ/FIQ</td>
<td> <span style="line-height: 19px">NMI,SysTick and up to 240</span>Interrupts. Integrated NVICInterrupt ControllerUp to 1-255 Priorities</td>
</tr>
<tr>
<td> Interrupt Latency</td>
<td> 24~42 Cycles</td>
<td> <span style="line-height: 19px">12 Cycles</span>(6 when Tail Chaining)</td>
</tr>
<tr>
<td> Memory Map</td>
<td> Undefined</td>
<td> Architecture defined</td>
</tr>
<tr>
<td> System Status</td>
<td> <span style="line-height: 19px">PSR, 6modes</span><br />
20 Banked regs</td>
<td><span style="line-height: 19px">xPSR, 2modes(Thread, Handler)</span><br />
Stacked regs(1 bank)</td>
</tr>
<tr>
<td> Sleep Modes</td>
<td> No</td>
<td> Three</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><span style="background-color: #ff6600;color: #ffffff"><strong>3. Cortex-M3 Processor Architecture</strong></span></p>
<p><span style="color: #ff9900"><strong>3.1 Register</strong></span></p>
<p><span style="color: #99cc00"><strong>(1) General Register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm007.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15547" alt="19feaarm007" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm007.png" width="281" height="410" /></a><br />
전통적인 ARM(ARM7,ARM9)에서는 7개의 동작 모드별로 Banked Register가 있었으나 Cortex-M3에 와서는 R13(SP)이 Main Stack Pointer와 Process Stack Pointer로 구분되어 Banked Register로 존재하고 나머지 레지스터는 Cortex-M3 동작 모드(Thread Mode, Handler Mode)에 상관없이 1개씩만 존재합니다. 16-bit Thumb 명령어에서는 R0 ~ R7 레지스터만 사용이 되고 32-bit Thumb2 명령어에서는 R0 ~ R15가 모두 사용이 됩니다. Stack Pointer (R13)는 항상 4-Byte정렬이 되어 운영되어야 하므로 Stack Pointer의 하위 2비트는 항상 &#8217;2b00&#8242;이 되어야 하겠지요. 그리고 Stack은 Full Descending 방식으로 운영이 됩니다. Linked Register(R14)는 전통적인 ARM과 마찬 가지로 BLX 명령어 사용시 복귀할 주소가 저장되어 있습니다. Program Counter(R15)는 당연히 현재 실행하고 있는 명령어의 주소(엄밀히 말하연 Pipeline 단계에서 Fetch 하고 있는 명령어의 주소)를 가지고 있습니다. 그러므로 실제 PC는 현재 실행하고 있는 명령어 다음 다음의 명령어의 주소가 저장되어 있습니다.</p>
<p><span style="color: #99cc00"><strong>(2) Special Register</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm008.png" rel="lightbox[15527]"><img class="alignnone size-full wp-image-15548" alt="19feaarm008" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm008.png" width="351" height="240" /></a><br />
전통적인 ARM에서는 CPSR(Current Processer Status Register) 이라는 특별한 상태 레지스터와 동작 모드별로 SPSR(Saved Processor Status Register)이 존재하였는데, Cortex-M3에서는 Special Register의 종류가 많이 늘어 났습니다. 하지만 기존의 CPSR 레지스터와 저장하고 있는 정보는 비슷합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/48.png" rel="lightbox[15527]"><img class="size-large wp-image-15598" alt="ARM7 에서의 CPSR 레지스터" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/48-620x368.png" width="620" height="368" /></a></p>
<p>xPSR은 APSR, IPSR, EPSR 3개의 Special Register로 나누어 볼수 있습니다.</p>
<p><strong>■ APSR(Application Program Status Register)</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm010.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15550" alt="19feaarm010" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm010-620x150.png" width="620" height="150" /></a><br />
현재 실행하고 있는 프로그램의 상태 정보를 담고 있습니다. 예를 들면 CMP 명령어와 같은 비교문이나 ALU 연산의 결과가 APSR 레지스터의 Flag 비트를 업데이트 합니다.</p>
<p style="padding-left: 60px">▷ 어셈블리어<br />
CMP R0, R1 ; R0 = 0, R1 = 1, R0 &#8211; R1 and update APSR Register<br />
ADDMI R0, R0, R1 ; R0 = R0 + R1<br />
SUBEQ R0, R0, R1 ; R0 = R0 &#8211; R1</p>
<p style="padding-left: 60px">▷ C언어<br />
if( R0 &#8211; R1 &lt; 0 )<br />
R0 = R0 + 1<br />
else<br />
R0 = R0 &#8211; R1</p>
<p>CMP 명령어는 결국은 R0 &#8211; R1을 한 결과를 가지고 APSR 레지스터를 업데이트 합니다. 결국 0에서 1을 빼면 -1이 되고 Negative &#8220;N&#8221; 이 APSR레지스터 31번 비트에 Set이 됩니다. &#8220;N&#8221; Flag가 Set이 되면 위의 명령어 중에서 ADDMI 명령어만 실행이 되고 SUBEQ 명령어는 NOP 명령어로 대체가 되어 실행이 되지 않습니다. ARM7에서는 CPSR 레지스터의 [31:27] 비트와 같은 역할을 합니다.</p>
<p><strong>■ IPSR(Interrupt Program Status Register)</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm011.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15551" alt="19feaarm011" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm011-620x150.png" width="620" height="150" /></a><br />
이전의 ARM Processor는 인터럽트 컨트롤러가 ARM Core에 존재하지는 않았습니다. 주로 CPU를 설계, 제조하는 반도체 Vendor에서 ARM Core의 외부에 CPU 설계시 추가하는 Peripheral들 중의 하나였습니다. 그래서 IRQ가 발생하면 어떤 인터럽트가 발생하였는지를 CPU에 존재하는 인터럽트 컨트롤러에서 INTOFFSET과 같은 ARM Core 외부의 SFT 레지스터에 저장이 되었습니다. 하지만 Cortex-M Profile에서는 인터럽트 컨트롤러가 ARM Core 내부(NVIC)에 존재합니다. IPSR은 현재 수행중인 Exception(Interrupt)의 번호를 저장하고 있는 레지스터입니다.</p>
<p><strong>■ EPSR(Execution Program Status Register)</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm012.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15552" alt="19feaarm012" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm012-620x150.png" width="620" height="150" /></a><br />
ICI(Interruptible-Continuable Instruction)/IT(If-Then) 2개의 중첩된 필드를 지니고 있는 레지스터입니다. 전통적인 ARM에서는 LDM, STM 명령어 수행 중에 인터럽트가 발생을 하더라도 멈출수가 없었습니다. 명령어 Boundary에서 인터럽트 처리가 되기 때문에 LDM(POP), STM(PUSH) 명령어 수행이 끝나고 나서야 인터럽트를 처리할 수가 있습니다. 하지만 Cortex-M3에서는 LDM(POP)/STM(PUSH) 명령 수행 중에도 인터럽트 처리가 가능합니다.</p>
<p style="padding-left: 60px">LDMFD SP!, {R0, R1, R4-R6}</p>
<p>위와 같이 Multiple Load 명령어 수행시 R1을 Load 하는 중에 인터럽트가 발생을 하게되면 Cortex-M3에서는 R1 레지스터까지만 처리한 다음 LDM 명령을 중단하고 현재 발생한 Exception(인터럽트) 처리를 끝냅니다. 그리고 중단되었던 나머지 R4-R6 Load 명령을 수행하게 되는데, 이때 인터럽트를 끝내고 나서 중단되었던 레지스터부터 다시 Load 명령어를 수행할 수 있도록 임시로 ICI 필드에 중단 지점의 레지스터 순서를 저장하게 되는데 그 저장소가 바로 EPSR 레지스터의 ICI 필드입니다. [15:12] 비트만 사용을 하고 나머지 비트 [11:10], [26:25] 필드는 사용하지 않습니다.</p>
<p>IT 필드는 Thumb-2 명령어인 If-Then 블럭의 Condition과 명령어의 순서 번호를 가지고 있습니다.</p>
<p style="padding-left: 60px">CMP R0, R1<br />
ITTEE EQ<br />
ADDEQ R2, R0, R1 ; R2 = R0 + R1<br />
ADDEQ R2, R0, R3 ; R2 = R0 + R3<br />
SUBNE R2, R0, R1 ; R2 = R0 &#8211; R1<br />
SUBNE R2, R0, R3 ; R2 = R0 &#8211; R3</p>
<p>위의 어셈블리어 명령어들을 해석해 보면 R0 &#8211; R1 한 결과가 &#8220;0&#8243; 이면 ADDEQ 명령어 2개를 실행하고 &#8220;0&#8243; 이 아니면 SUBNE 명령어 2개를 실행하라 입니다. C언어로 표현하면 아래와 같습니다.</p>
<p style="padding-left: 60px">if( R0 == R1 )<br />
{<br />
R2 = R0 + R1<br />
R2 = R0 + R3<br />
}<br />
else<br />
{<br />
R2 = R0 &#8211; R1<br />
R2 = R0 &#8211; R3<br />
}</p>
<p>If-Then 명령어 Block 수행중에 인터럽트가 발생하면 인터럽트 서비스 루틴으로 분기를 했다가 다시 If-Then 명령어 Block으로 복귀하여 인터럽트가 발생했던 지점의 다음 명령어부터 수행해야 하는데 인터럽트 서비스 루틴으로 분기하기 전에 IT 필드에 몇 번째 명령어까지 수행했었는지를 잠시 저장하는 레지스터입니다. 이때 IT[7:5] 비트는 Base Condition 정보 &#8220;CMP&#8221; 를 저장하고 있고 IT[1:0], IT[7:4] 비트는 If-Then 명령어 Block안의 ISR이 발생하기 전까지의 수행된 명령어 번호를 저장하고 있습니다. 또한 ICI/IT는 EPSR 레지스터 안에서 같은 비트의 필드를 공유하고 있기 때문에 If-Then Block에서 LDM/STM과 같은 Multiple Load/Store 명령어를 사용하면 LDM/SDM 명령어 수행 중에 인터럽트가 발생해서 인터럽트 서비스 루틴을 끝내고 복귀 했을때 수행했던 레지스터 번호부터 시작하지 못하고 처음부터 다시 LDM/STM 명령어가 수행되게 됩니다. EPSR 레지스터의 각 비트들을 표로 정리하였습니다.</p>
<table style="border-collapse: collapse;width: 620px" border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>EPSR[26:25]</strong></td>
<td><strong>EPSR[15:12]</strong></td>
<td><strong>EPSR[11:10]</strong></td>
</tr>
<tr>
<td>IT[1:0]</td>
<td>IT[7:4]
[7:5] &#8211;&gt; Base Condition 정보</td>
<td>IT[3:2]</td>
</tr>
<tr>
<td>ICI[7:6] (‘00’)</td>
<td>ICI[5:2] &#8211;&gt; reg_num</td>
<td>ICI[1:0] (‘00’)</td>
</tr>
</tbody>
</table>
<p>reg_num는 LDM, STM 명령어 수행 중에 인터럽트가 발생하여 잠시 중단되었던 레지스터의 번호입니다.</p>
<p><span style="color: #ff9900"><strong>3.2 Operation Mode</strong></span></p>
<p>전통적인 ARM에서는 동작모드가 7종류(User, System, Fiq, Irq, SVC, Abord, Undefined)가 있었습니다. Cortex-M3에서는 Thread, Handler Mode 두가지로 축소되었습니다. 그리고 Priviledge Level 에는 Privileged, Unprivileged 두가지의 경우가 있습니다. Cortex-M 이전의 ARM에서는 USER Mode를 제외한 나머지 6개의 동작 모드가 Privilegdge Mode입니다.</p>
<p><span style="color: #99cc00"><strong>(1) Thread Mode</strong></span><br />
Exception이 발생하지 않은 보통의 상태가 Thread Mode입니다.<br />
Reset Exception 발생시(CPU에 전원이 인가되어 초기 부팅시)에 Thread Mode + Privileged + Main_stack(Stack Pointer)로 시작하게 됩니다. 당연히 초기 부팅시에는 권한이 있는 모드로 실행이 되어야 하겠지요? 권한이 있는 모드로 부팅을 시작해야 H/W, S/W 설정을 끝내고 Unprivileged 모드로 전환을 해서 User Application을 실생 시킬수 있을테니까요. 그리고 한번 권한이 없는 모드로 전환이 되고 나면 일반적인 방법으로는 Privilege 모드로 전환할 수 없습니다. Exception이 발생하여 Handler Mode(Handler Mode에서는 항상 Privilege 모드)로 전환이 되거나 혹은 S/W적으로 &#8220;SVC(Super Visor Call)&#8221; 명령어를 써서 SVC_Handler Exception 을 발생시켜서 Handler Mode의 서비스 루틴에서 MSR 명령어를 사용하여 Priviledge Mode로 변경시켜야 합니다. Privilege 모드에서 Unprivileged로 전환하는 방법은 MSR 명령어를 사용하는 것입니다. 당연히 MSR 명령어는 Privilege 모드에서만 사용이 가능합니다. Privilege level 변경 방법은 CONTROL Register 설명 시에 예를 들어 보도록 하겠습니다.</p>
<p><span style="color: #99cc00"><strong>(2) Handler Mode</strong></span><br />
Thread Mode에서 IRQ, Fault 등의 Exception이 발생했을 경우 문맥 보존을 위해서 Stack에 {R0~R4, R12, LR, PC, xPSR} 레지스터가 Stack에 H/W적으로 PUSH(저장)가 되고 이와 병렬적으로 Thread Mode에서 자동으로 Handler Mode로 전환이 되면서 Cortex-M3 Architecture적으로 미리 정의 되어 있는 Vector Table에 있는 Exception Handler 주소가 Fetch 되어 PC의 주소가 바뀌게 됩니다. 이렇게 Stack 메모리와 Vector Table Fetch 작업이 동시에 이루어질 수 있는 이유는 Cortex-M3가 Havard Architecture 구조이기 때문에 가능합니다. Harvard Architecure는 구조적으로 Code, Data Bus가 별도로 존재하는 구조입니다. 반대로 Code와 Data Bus가 하나만 존재하는 구조를 Von-Neumann Bus 구조라고 합니다.</p>
<p><img class=" wp-image-15592 " alt="Von-Neumann bus 구조 - Wikipedia 참조" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm052.png" width="356" height="238" /></p>
<div id="attachment_15591" class="wp-caption alignnone" style="width: 370px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm051.png" rel="lightbox[15527]"><img class=" wp-image-15591  " alt="Harvard bus 구조 - Wikipedia 참조" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm051.png" width="360" height="229" /></a><p class="wp-caption-text">Harvard bus 구조 &#8211; Wikipedia 참조</p></div>
<p>당연히 Harvard Architecure 구조가 Von-Neumann Bus 구조보다 효율적이겠지요. Handler Mode에서는 권한 상태가 항상 Privilegde 모드입니다. Handler 서비스 루틴이 끝나면 Exception 이 발생한 명령어의 다음 명령어로 PC가 복귀가 되고 그와 동시에 Stack에서 POP이 발생하여 이전에 Stack에 잠시 보관되었던 {R0~R4, R12, LR, PC, xPSR} 레지스터들이 복구가 됩니다. {R0~R4, R12} 레지스터를 Cortex-M3에서 자동으로 Stack에 저장하는 이유는 {R0~R4, R12} 레지스터들이 Scratch 레지스터들 이기 때문입니다. 자세한 사항은 아래 AAPCS Register 부분을 참조하세요.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm017.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15557" alt="19feaarm017" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm017-620x407.png" width="558" height="366" /></a></p>
<p>&nbsp;</p>
<p><span style="color: #ff9900"><strong>3.3 Stack</strong></span></p>
<p>Cortex-M3에서 Stack은 Main_stack, Process_stack 2개가 Banked 되어 존재하고 항상 4Byte Aligned 되어있어야 합니다. 4Byte로 Aligned 되어야 한다는 것은 Stack Memory에 8Bit, 16Bit 데이터를 저장(PUSH) 하더라도 항상 32Bit 공간을 차지한다는 것입니다. 전통적인 ARM에서는 7가지 동작 모드별로 SP가 별도로 존재 하였습니다. Reset Exception 발생시(CPU 에 전원이 인가되어 초기 부팅시)에 Thread Mode + Privileged + Main_stack로 시작한다고 하였습니다. Reset Exception 발생 시에 위의 사항 말고도 하는 일이 한가지 더 있습니다. 그것은 0&#215;00 번지에 있는 주소를 Hardware 적으로 읽어와서 Main_stack Pointer를 Setup하고 나서 0&#215;4 번지 주소에 있는 Reset Handler Address( Progragm 시작 주소)를 읽어와서 PC에 저장하는 것입니다. 이러한 이유 때문에 Cortex-M3에서는 실제로 프로그램의 시작 주소가 0&#215;4 번지가 됩니다. 전통적인 ARM에서는 0&#215;0 주소에 프로그램의 시작 포인터인 Reset Handler가 존재하였고 0&#215;0 주소의 내용은 명령어(Branch)가 존재해야만 했으며 7가지 동작 모드별로 Boot 코드에서 S/W 적으로 MSR 명령어를 사용하여 SP를 Setup해야만 했습니다. 이에 비하면 Cortex-M3 의 Stack Pointer Setup은 H/W 적으로 이루어 지고 있어 개발자 입장에서는 많은 수고를 덜 수가 있습니다. 참고로 STM32F 시리즈에서는 0&#215;0 번지와 0&#215;8000000 번지가 Alias 되어 있어 0&#215;0 주소의 내용과 0&#215;8000000 주소의 내용이 동일합니다.</p>
<table border="0">
<tbody>
<tr>
<td><img class="alignnone size-medium wp-image-15553" alt="19feaarm013" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm013-300x128.png" width="300" height="128" /></td>
<td><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm014.png" rel="lightbox[15527]"><img class="alignnone size-medium wp-image-15554" alt="19feaarm014" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm014-300x127.png" width="300" height="127" /></a></td>
</tr>
<tr>
<td style="text-align: center">STM32F 에서의 0&#215;8000000 주소의 Memory 내용</td>
<td style="text-align: center">STM32F 에서의 0&#215;0000000 주소의 Memory 내용</td>
</tr>
</tbody>
</table>
<p>Main_stack pointer가 H/W적으로 Setup이 된다는 것은 0&#215;04 번지에서 Segment 초기화를 끝내고 바로 main 함수로 분기하여 &#8220;C&#8221; Program 루틴에서부터 부팅을 시작할 수 있다는 이야기입니다. 여기서 Segment 초기화라는 용어가 나오는데 잠시 짚고 넘어 가도록 하겠습니다. 이전에 ARM Architecture 강좌에서도 한번 언급을 했었습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm016.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15556" alt="19feaarm016" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm016-620x296.png" width="496" height="237" /></a></p>
<p>main.c 파일을 컴파일하고 어셈블하여 main.o 파일이 생성이 된다면 .o 파일의 구조는 위와 같이 ZI(Zero Initialized), RW(Read Write), RO(Read Only) 영역 등으로 나누어져 생성이 됩니다. 결국 hex(bin) 파일의 구조는 main.o 파일과 같은 여러 개의 *.o + *.a(라이브러리 파일) + Link Script(Scattor Loading) 파일이 조합이 되어 Linker에 의해 생성이 되는 것입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm018.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15558" alt="19feaarm018" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm018.png" width="473" height="170" /></a><br />
ZI, RO, RW 영역들을 Segment라고 하며 이 Segment들이 타겟 시스템의 RAM, ROM에 적당히 자리를 잡고 있도록 하는 작업을 Segment 초기화 작업이라고 합니다. Segment 초기화 작업은 H/W적으로 이루어지지는 않습니다. Hex 파일을 JTAG 등의 장비를 이용하여 ROM 영역에 퓨징(Write)을 한 상태에서 부팅을 하면 Startup(Bootloader) 코드에서 ROM 메모리에서 RW 영역을 읽어와서 RAM에 복사해주고 ZI 영역은 모두 0&#215;0 값으로 초기화 해주는 작업을 해주어야 합니다. 이러한 Segment 초기화 작업을 해주지 않으면 C언어에서 사용하는 전역변수 등에 올바른 초기값이 들어가 있지 않습니다. hex(bin) 파일과 시스템의 RAM, ROM과의 관계를 그림으로 표현해 보았습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm019.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15559" alt="19feaarm019" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm019-620x270.png" width="620" height="270" /></a><br />
참고로 Cortex-M3 IAR 컴파일러는 부트코드 라이브러리에서 이 작업을 개발자 대신 해주고 있습니다. IAR Startup 코드중에서 __iar_program_start 라는 서브루틴 코드에서 아래 그림과 같은 라이브러리 루틴들이 순차적으로 호출됩니다. __iar_data_init3가 Segment 초기화 작업 서브 루틴입니다.</p>
<div id="attachment_15560" class="wp-caption alignnone" style="width: 568px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm020.png" rel="lightbox[15527]"><img class=" wp-image-15560" alt="19feaarm020" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm020-620x153.png" width="558" height="138" /></a><p class="wp-caption-text">IAR 컴파일러 Cortex-M3 지원 코드</p></div>
<p><span style="color: #99cc00"><strong>(1) Main Stack setup</strong></span><br />
Main Stack 포인터는 부팅 시에 H/W적으로 0&#215;0 번지에서 32Bit(4Byte) 값(Main Stack 포인터의 주소)을 읽어와서 자동으로 Setup이 된다고 하였습니다. Cortex-M3에서 0&#215;0 번지에는 항상 Main Stack의 주소가 있어야 합니다. 자동으로 Setup이 되지만 부팅 이후에 Main Stack 포인터를 변경하는 경우에는 MSR 명령어를 사용하면 됩니다.</p>
<p style="padding-left: 60px">MOV R0 , #0&#215;20002000<br />
MSR MSP , R0</p>
<p><span style="color: #99cc00"><strong>(2) Processor Stack setup</strong></span><br />
보통의 경우에는 Main Stack만 사용해서 프로그램을 개발하면 됩니다. 하지만 RTOS등에서 커널은 Privilegde + Main Stack을 사용하게 하고 User Application에서는 Unpriviledge + Processor Stack을 사용하여 운영체제를 보호하고 싶다면 Processor_stack 포인터를 Setup해야 합니다.</p>
<p style="padding-left: 60px">MOV R0 , #0&#215;20001500<br />
MSR PSP , R0</p>
<p>레지스터 설명에서 CONTROL 레지스터에 대한 설명을 하지 않았었는데, 여기서 살펴보도록 하겠습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm021.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15561" alt="19feaarm021" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm021-620x46.png" width="558" height="41" /></a><br />
CONTROL 레지스터는 Cortex-M3 Core의 현재 권한 레벨(Privilege, Unprivileged)과 사용하고 있는 Stack을 저장하고 있는 Special Register입니다.</p>
<p style="padding-left: 60px">- Bit[0] : 0 : privileged, 1 : Unprivileged<br />
- Bit[1] : 0 : Use SP_main, 1 : Use SP_process<br />
- Bit[2] : 0 : FP extension not active, 1 : Active<br />
- Bit[31:3] : Reserved</p>
<p><span style="color: #99cc00"><strong>(3) Stack Setup 예제</strong></span><br />
ARM에서 Stack은 Full-Descending 방식으로 운영되기 때문에 보통 RAM의 가장 높은 주소 영역에 Stack Pointer를 설정하게 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm022.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15562" alt="19feaarm022" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm022-620x396.png" width="502" height="320" /></a><br />
위의 예제에 있는 어셈블리어는 Processor Stack 포인터를 0&#215;20001800으로 설정(MSR PSP, R0)하고 MSR 명령어를 사용해서 CONTROL 레지스터의 하위 [1:0] 비트를 &#8220;2b11&#8243; 로 설정하여 Cortex-M3의 권한 레벨을 Unprivileged로 Stack 포인터는 Processor Stack을 사용하도록 하는 코드입니다.</p>
<p><strong>■ Full-Descending 방식이란?</strong><br />
Stack 메모리에 데이터가 저장이 될 때 Full-Descending에서 Full 이라는 것은 Stack 동작이 끝나고 났을 때 항상 SP는 유효한 데이터를 가르키고 있다는 것이고 Descending 이라는 것은 높은 주소에서 낮은 주소로 주소가 감소하면서 데이터가 저장이 되는 방식입니다. Stack PUSH 동작이 끝났을 때 SP가 유효한 데이터를 가르키고 있으려면 데이터를 PUSH하기 전에 먼저 SP의 주소를 4Byte 감소시키고 나서 데이터를 저장해야 합니다. 반대로 POP 동작에서는 데이터를 먼저 꺼내고 나서 SP의 주소를 4Byte 증가시켜야 합니다. PUSH, POP 동작을 그림으로 예를 들어 보겠습니다.</p>
<p><strong>■ PUSH Operation</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm025.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15565" alt="19feaarm025" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm025-620x305.png" width="496" height="244" /></a></p>
<p><strong>■ POP Operation</strong></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm026.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15566" alt="19feaarm026" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm026-620x305.png" width="496" height="244" /></a></p>
<p>위의 그림에서 POP 동작이 끝난 이후에도 RAM STACK 영역에는 데이터가 그대로 남아 있습니다. POP을 했다고 해서 메모리에서 데이터가 사라지는 것은 아니고 단지 SP만이 변경된다는 사실을 알수 있습니다.</p>
<p><span style="color: #ff9900"><strong>3.4 Cortex-M3 Memory Map</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm023.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15563" alt="19feaarm023" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm023-620x417.png" width="620" height="417" /></a><br />
Cortex-M3에서는 CODE 영역(ROM)과 RAM(SRAM)의 주소가 Architecture 차원에서 정의가 되어있기 때문에 Cortex-M3 Core를 기반으로한 CPU(ST, Luminsary, TI, Samsung사의 Cortex-M3 CPU)들 사이에는 포팅 작업이 많이 쉬워 졌습니다. 이전의 전통적인 ARM에서는 CPU의 메모리 뱅크에 따라서 RAM의 시작 주소가 같지 않을 수 있고, Peripheral들의 시작 주소 또한 CPU마다 다를 수 있습니다. 위의 Memory Map을 보면 32bit Core이기 때문에 4GB 메모리까지 접근이 가능하고 SRAM, Peripheral 영역의 주소에 특이하게도 Bit band alias 영역이라는 것이 존재합니다. 이 부분은 Bit Banding 장에서 자세히 설명하도록 하겠습니다.</p>
<p><span style="color: #99cc00"><strong>(1) STM32F103VC(High desnsity)의 Memory Model</strong></span><br />
0&#215;0800.0000 ~ 0&#215;0801.FFFF (FLASH)<br />
0&#215;2000.0000 ~ 0&#215;2000.BFFF (SRAM)<br />
0&#215;4000.0000 ~ 0&#215;4002.3FFF (Peripheral Memory Map)<br />
0xE000.0000 ~ 0xE00F.FFFF (Cortex-M3 Internal Peri.)</p>
<p><span style="color: #ff9900"><strong>3.4 Thumb-2 Instruction Set</strong></span></p>
<p>Cortex-M3는 Thumb-2 명령어만 지원합니다. 전통적인 ARM에서는 16Bit Thumb 명령어와 32Bit ARM 명령어를 사용할 수가 있었는데, Thumb 모드에서는 16Bit 명령어만 사용할 수 있고 32Bit 명령어를 사용하기 위해서는 Mode Change(Thumb Mode &#8211;&gt; ARM Mode)를 해야만 했습니다. Mode Change를 위해서는 BX라는 분기 명령어를 사용해야 했습니다. Thumb-2 명령어의 가장 큰 특징은 Thumb모드와 ARM모드 사이에 모드 전환 없이 16bit Thumb 명령어와 32Bit 명령어를 섞어서(Blend) 사용할 수 있는 것입니다. 이러한 특징으로 Thumb 명령어만 사용했을 때 보다 성능은 좋아지고 코드의 집적는 ARM 32Bit 명령어에 비해서 좋아졌습니다. Thumb-2 명령어는 기존의 Thumb 명령어와 하위 호환성을 유지합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm024.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15564" alt="19feaarm024" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm024-620x237.png" width="620" height="237" /></a></p>
<p>위의 그림은 명령어들 사이의 Performance와 Code size를 표로 나타낸 것입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm027.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15567" alt="19feaarm027" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm027-620x200.png" width="620" height="200" /></a><br />
ARM 명령어를 사용했을 때와 Thumb-2 명령어를 사용했을 때의 코드 사이즈를 비교해 보았습니다. 위의 어셈블리 명령어는 두수(R0, R1) 사이의 절대 값을 구하는 명령어 입니다. &#8220;C&#8221; 언어를 참조하세요. 16Bit Thumb 명령어에서는 Conditional Execution을 사용할 수 없습니다. 단, Thumb 명령어에서도 BX 명령어의 경우에는 Conditional Execution을 사용할 수 있습니다.</p>
<p><span style="color: #ff9900"><strong>3.5 Bit Banding</strong></span></p>
<p>Cortex-M3 Memory Map을 설명할 때 Bit band alias 영역이 있다고 하였습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm028.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15568" alt="19feaarm028" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm028-620x258.png" width="620" height="258" /></a><br />
SRAM, Peripheral 영역에 존재하며 SRAM영역의 경우 0&#215;22000000 주소에 &#8217;0&#8242; or &#8217;1&#8242;을 Write하면 0&#215;20000000 주소의 실제 SRAM의 [0]번 비트에 &#8217;0&#8242; or &#8217;1&#8242;이 Write 되어지는 것입니다. Write 뿐만이 아니라 0&#215;22000000 주소의 Data을 읽으면 0&#215;20000000 주소의 SRM의 [0] 번 비트가 읽어집니다. 즉 SRAM 1MB bit-band region 1비트는 32MB의 alias region 영역의 32bit(1 WORD) 와 Alias(동일하게 Mapping) 되어있는 것입니다. 이러한 특징은 Peripheral 영역도 마찬가지로 적용이 됩니다. 그림으로 다시 보면 아래와 같습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm029.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15569" alt="19feaarm029" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm029-620x389.png" width="620" height="389" /></a><br />
그러면 Cortex-M3 의 이런 특징이 있는 이유는 무엇일까요? 예를 들면 0x4001180C 주소에 32bit GPIOE 그룹의 데이터 레지스터가 존재하고 있고 GPIOE2, 3, 4 포트에 각각 LED 가 연결되어 있다고 가정해 봅시다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm030.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15570" alt="19feaarm030" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm030-620x318.png" width="496" height="254" /></a><br />
회로상으로는 위의 그림과 같습니다. 여기서 PE2, PE4의 상태는 건드리지 않고 PE3에 연결되어 있는 LED3만 ON(PE3 포트를 High)시키려고 한다면 Bit Banding이 지원되지 않는 시스템에서는 다음과 같이 코드를 작성해야 합니다.</p>
<p style="padding-left: 60px">(*(volatile unsigned *)0x4001180C) |= (0&#215;1 &lt;&lt; 2);</p>
<p>ARM의 Load, Store 구조에서 이것을 어셈블리어로 다시 작성해 보도록 하겠습니다.</p>
<p style="padding-left: 60px">LDR R0, = 0x4001180C ; R0 = 0x4001180C<br />
MOV R2, #0&#215;4 ; R2 = 0&#215;4<br />
LDR R1, [R0] ; R0가 가르키는 주소에서 32Bit 데이터를 읽어와서 R1 레지스터에 저장<br />
ORR R1, R2 ; R1 | R2<br />
STR R1, [R0] ; R1레지스터의 값을 R0가 가르키는 주소에 저장</p>
<p>이와 같이 Bit Banding을 지원하지 않는 시스템에서는 Register에 메모리의 내용을 Load 해놓고 Bit wise 연산을 한 이후에 다시 STR 명령어를 사용해서 Register의 내용의 메모리에 저장하는 방식으로 해야만 합니다. ARM에서 연산 명령어들은 레지스터와 메모리의 내용으로 직접 연산을 할 수가 없고 항상 메모리의 내용을 레지스터에 읽어와서 연산을 마친 이 후에 메모리에 다시 저장하는 방식으로 사용해야 합니다. ARM은 Load/Store 방식이기 때문입니다.</p>
<p>이번에는 Bit Banding을 이용해서 같은 작업을 수행해보도록 하겠습니다. 우선 C 코드로 작성해보도록 하겠습니다.</p>
<p style="padding-left: 60px">(*(volatile unsigned *)(0&#215;42000000 + (0x4001180C-0&#215;40000000)*32 + 3*4)) = 0&#215;0;</p>
<p>어셈블리어로 바꾸어 보면</p>
<p style="padding-left: 60px">; 상수들의 연산은 이해를 돕기 위한 의사 코드임<br />
; 실제로는 덧셈과 곱셈이 완료된 최종 상수값이 와야 합니다.<br />
LDR R0, = (0&#215;42000000 + (0x4001180C-0&#215;40000000)*32 + 3*4))<br />
MOV R2, #1<br />
STR R2, [R0]
<p>Bit Banding이 지원되지 않는 시스템에서의 &#8220;LDR, ORR, STR&#8221; 3개의 명령어를 사용해서 구현되었던 내용이 &#8220;STR&#8221; 명령어 1개를 이용해서 같은 작업을 하는 코드로 바꿀 수가 있습니다. 이러한 특징은 수행 속도와 코드 집적도에서도 유리하며 이러한 기능이 주는 가장 중요한 특징은 바로 Atomic Operation이 가능하다는 것입니다. Atomic Operation이라는 것은 더 이상 쪼개지지 않는 즉, 1개의 명령으로 기능이 수행되어 명령어 수행 도중에 인터럽트가 발생하지 않는 것을 이야기합니다. 여러가지 복잡한 인터럽트가 많은 시스템에서 Atomic Operation이 된다는 것은 전역 데이터 혹은 Peripheral의 SFR(Special Function Register)등에 접근할 때 인터럽트에 의해서 데이터 처리 명령이 침해 당하지 않는 것을 보장합니다.<br />
Atomic Operation이 아닌 명령어로 2개 이상의 인터럽트 서비스 루틴에서 공유로 사용하는 전역 데이터등을 처리하기 위해서는 일반적으로 데이터 처리 전에 인터럽트를 Disable시키고 데이터 처리가 끝나면 다시 인터럽트를 Enable 시키는 방식으로 처리합니다. 참고로 ARM에서 인터럽트는 명령어 바운더리(Boundary)에서 발생합니다. 명령어 Boundary라는 것은 명령어와 명령어 사이를 이야기합니다. Cortex-M3에서 LDM, STM(PUSH, POP)등 Multiple 데이터처리 명령을 제외하면 단일 명령어 수행 중에 인터럽트가 발생을 하더라도 명령어 수행이 끝나면 인터럽트가 시작됩니다.</p>
<p>Bit band region과 Bit band alias 영역과의 Alias 관계를 정규화된 수식으로 표현하면 아래와 같습니다.</p>
<p style="padding-left: 60px">bit_word_offset = (byte_offset x 32) + (bit_number × 4)<br />
bit_word_addr = bit_band_base + bit_word_offset</p>
<p>0&#215;40000000의 1번 비트에 해당하는 Bit Banding 주소는 0&#215;42000000 + 32*0 + 4*1의 수식이 적용됩니다.</p>
<p>약간 복잡한 듯 보이지만 잘 생각해보면 계산식을 이해할 수 있습니다.</p>
<p><span style="color: #ff9900"><strong>3.6 System Timer(SysTick)</strong></span></p>
<p>Cortex-M3 Core 내부에 위치한 시스템 타이머입니다. 24bit self-reloading down counter이며 count가 0이 되면 SysTick Interrupt를 발생시킬 수 있습니다. 모든 CPU에는 보통 타이머를 1개 이상은 가지고 있습니다. 하지만 SysTick이 일반 타이머와 다른점이라면 Core(정확히는 NVIC에 존재함)에 내장된 타이머라는 것입니다. 이러한 특징은 Cortex-M3 Core를 사용한 모든 CPU는 모두 동일한 System Timer를 가지고 있다는 것입니다. 예를 들어 RTOS를 포팅한다고 했을 때 필수적으로 주기적인 타이머 인터럽트가 필요한데 Cortex-M3 이전의 프로세서에서 RTOS를 포팅을 하는 경우에는 Core자체에 Timer가 없기 때문에 Vendor Specific한 Timer를 사용하게 됩니다. 어떤 개발자는 Timer0를 사용할 수도 있고 다른 개발자는 Timer1을 사용해서 포팅을 할 수 있습니다. 이렇게 되면 같은 ARM Core를 사용했다고 하더라도 Processor들 간의 SW 포팅이 달라져야 합니다. 하지만 Cortex-M3 Core를 사용해서 RTOS 포팅을 한다면 당연히 Core에 내장된 공통적인 Timer인 System Timer를 사용해야 겠지요. System Timer에 대한 좀 더 상세한 내용과 사용법은 Cortex-M3 Applicaiton 강좌에서 하도록 하겠습니다.</p>
<p>&nbsp;</p>
<p><span style="background-color: #ff6600;color: #ffffff"><strong>4. Nested Vectored Interrupt Controller</strong></span></p>
<p><span style="color: #ff9900"><strong>4.1 NVIC</strong></span></p>
<p>Cortex-M3의 가장 중요한 특징 중의 하나입니다. Cortex-M3 이전의 전통적인 ARM에서는 인터럽트 컨트롤러가 ARM Core의 외부에 위치해 있었습니다. 우측 상단 그림은 ARM9 S3C2440 CPU의 블럭도입니다. 자세히 보면 Interrupt Controller가 CPU의 Peripheral로 구현이 되어 있습니다.</p>
<p><img class="alignnone size-large wp-image-15572" alt="19feaarm032" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm032-620x515.png" width="620" height="515" /></p>
<p>하지만 Cortex-M3에서는 Interrupt Controller가 ARM Core의 내부 자원으로 들어와 있습니다. 그것도 Nested Vectored Interrupt Controller라는 새로운 이름을 달고 말입니다. 우측 하단 그림에 있는 점선 박스 부분이 CM3Core(Cortex-M3 Core)에 내장된 NVIC(Nested Vectored Interrupt Controller)입니다. 참고로 아래 블럭도는 STM32F103x 시리즈 CPU의 블럭도입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm033.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15573" alt="19feaarm033" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm033-620x389.png" width="620" height="389" /></a></p>
<p>CM3Core 부분은 Vendor Defined Specific 부분이 아니라 Cortex-M3 CPU들의 공통 사양입니다. NVIC는 CM3Core 내부에 위치해있습니다. 위에서 설명했던 Register(R0 ~ R15), Special Register(xPSR, CONTROL)등은 모두 CM3Core 내부에 위치해 있는 것입니다. Nested Vectored Interrupt Controller라고 하였는데 우선 Vectored라는 용어부터 설명을 하도록 하겠습니다. 전통적인 ARM의 인터럽트 블럭도를 간략하게 표현해 보았습니다.</p>
<div id="attachment_15574" class="wp-caption alignnone" style="width: 621px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm034.png" rel="lightbox[15527]"><img class="size-full wp-image-15574" alt="전통적인 ARM CPU의 간략한 인터럽트 구성도" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm034.png" width="611" height="134" /></a><p class="wp-caption-text">전통적인 ARM CPU의 간략한 인터럽트 구성도</p></div>
<p>전통적인 ARM에서는 인터럽트 컨트롤러가 ARM Core의 외부에 위치해 있으며 CPU의 여러 개의 Peripheral들이 1개의 IRQ, FIQ에 연결이 되어 있습니다. 이러한 이유로 만약에 EINT0 인터럽트가 발생을 하였다면 CPU 외부에 있는 인터럽트 컨트롤러를 통해서 ARM Core에 Interrupt Request가 전달되게 되는데 ARM Core 입장에서 보면 EINT0이 발생하였는지 EINT1이 발생한 것인지 알 수 있는 방법이 없습니다.<br />
ARM Core에서 알 수 있는 방법은 S/W적으로 ARM Core 외부에 있는 Interrupt Controller의 SFR 레지스터에 접근하여 INTOFFSET(현재 발생한 인터럽트 번호가 저장되어 있는 레지스터)을 읽어와서 인터럽트 번호를 확인하고 적당한 인터럽트 서비스 루틴으로 분기를 하는 것입니다. 하지만 Cortex-M3에서는 이것보다 훨씬 효율적인 방법으로 인터럽트 서비스 루틴으로 분기를 합니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm035.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15575" alt="19feaarm035" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm035.png" width="460" height="210" /></a><br />
Cortex-M3에서는 EINT0 인터럽트가 발생하면 이미 정해진 Interrupt Vector Table에 있는 주소로 바로 분기하며 이때 Special Register 중 IPSR에 발생한 인터럽트 번호가 저장이 됩니다. 물론 인터럽트 서비스 루틴으로 분기하기 전에 문맥 보존을 위해서 H/W적으로 {R0-R3,R12,LR,PC,xPSR} 레지스터들이 Stack에 저장이 되었다가 ISR 서비스 루틴이 끝나면 다시 H/W적으로 Stack에서 레지스터로 복원이 됩니다. 전통적인 ARM에서 문맥 보존은 S/W적으로 개발자의 몫이었습니다. R0-R3, R12를 Stack에 저장하는 이유는 앞에서 설명했듯이 Scratch Register들이기 때문입니다. Cortex-M3에서 Exception의 종류는 최대 256개까지 존재 할 수 있고 0 ~ 15까지는 Cortex-M3 Internal Exception이고 16번 부터 나머지 240개는 Core 외부 Exception 입니다.<br />
Exception Vector 0 ~ 15번 까지는 Cortex-M3 Core를 사용하는 모든 CPU는 동일하며 16 ~ 254 까지는 Vendor Specific 사양 입니다. 즉 CPU 마다 다를 수 있다는 이야기입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm036.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15576" alt="19feaarm036" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm036-620x398.png" width="620" height="398" /></a><br />
Vectored 라는 말은 0 ~ 255 까지의 Exception Vector의 주소가 이미 정해져 있다는 말입니다. 그러므로 Exception이 발생했을때 어떤 Exception이 발생했는지 여부에 상관없이 정해진 Vector Table의 주소에 있는 내용의 Address로 바로 Exception 분기를 할 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm038.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15578" alt="19feaarm038" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm038-620x481.png" width="620" height="481" /></a></p>
<p>위의 그림은 STM32F10x 시리즈의 Exception Vector Table입니다. Cortex-M3 외부 인터럽트 벡터의 주소가 0x0000_0040부터 시작하고 있네요. Reset시에 Vector Table의 Offset 주소는 0&#215;0이지만 Exception Vector Table의 시작 주소는 Vector Table Offset Register를 수정하면 옮길 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm039.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15579" alt="19feaarm039" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm039-620x288.png" width="620" height="288" /></a><br />
TBLBASE 의 값을 &#8220;1&#8243; 로 수정을 하면 Vector Table을 RAM에 위치 시킬 수도 있습니다. 그리고 TBLOFF 에 따라서 Vector Table의 주소를 정해줄 수 있습니다.<br />
다음으로 Nested 라는 용어를 살펴 보지요. Nested 라는 것은 사전적인 용어로는 &#8220;중첩되어 있는&#8221; 뭐 이러한 의미입니다. Cortex-M3에서는 인터럽트 수행 중에 우선 순위가 높은 인터럽트가 발생을 하면 현재 수행 중인 인터럽트를 잠시 중단하고 나중에 발생한 우선 순위가 높은 인터럽트를 먼저 수행한 이후에 잠시 중단 되었던 인터럽트 루틴으로 복귀하여 수행을 마치고 Normal 루틴으로 복귀를 합니다. 이러한 경우를 인터럽트가 중첩되었다고 합니다. 전통적인 ARM에서 IRQ끼리는 중첩되는 경우가 없습니다. 모든 IRQ는 우선순위가 같기 때문에 중첩이 되지 않고 IRQ 수행중에 다시 IRQ가 발생을 하면 나중에 발생한 인터럽트는 잠시 Pending상태에 들어 갔다가 현재 수행중인 인터럽트 서비스 루틴이 종료되면(엄밀히 말하면 인터럽트 서비스 루틴안에서 Pending Clear를 하는 시점에서) 잠시 Pending 되었던 인터럽트가 시작됩니다. 인터럽트가 중첩되는 경우는 IRQ 수행 도중에 FIQ(Fast IRQ)가 발생하는 경우에만 중첩이 됩니다. 인터럽트가 중첩이 되려면 인터럽트마다 우선 순위가 달라야 하는데 Cortex-M3에서는 최대 255 단계의 우선 순위 레벨을 정해줄 수가 있습니다. 인터럽트 우선순위 단계는 AIRCR(Application Interrupt and Reset Control Register)에 의해서 정해줄 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm041.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15581" alt="19feaarm041" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm041-620x375.png" width="620" height="375" /></a><br />
PRIGROUP 부분에 0 ~ 7 사이의 값을 Write 할 수 있습니다. PRIGROUP에 의해서 Goup Priority(Pre-emption)과 Sub Priority의 경계를 나누어 줄 수 있습니다.</p>
<div id="attachment_15580" class="wp-caption alignnone" style="width: 257px"><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm040.png" rel="lightbox[15527]"><img class=" wp-image-15580  " alt="Cortex-M3 에서의 우선순위 그룹" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm040.png" width="247" height="91" /></a><p class="wp-caption-text">Cortex-M3 에서의 우선순위 그룹</p></div>
<p>STM32F10x 시리즈에서는 0 ~ 7 비트중에서 4비트(상위 4 ~ 7 비트)만 사용하여 Priority가 구현되어 있습니다. 하위 4비트는 H/W적으로 &#8220;0&#8243; 으로 Mapping 되어있습니다. STM32F10x 시리즈에서 PRIGROUP의 값에 의해서 정해지는 Priority 단계를 표로 나타내 보았습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm042.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15582" alt="19feaarm042" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm042-620x218.png" width="496" height="174" /></a><br />
위의 표에서 PRIGROUP의 값이 0b100(4)가 되면 Group Priorities로 8단계, Sub Priorities로 2단계까지 레벨을 정할 수 있습니다. PRIGROUP값에 의해서 Group Priorities와 Sub Priorities의 레벨을 동적으로 조정할 수 있는 것입니다. Group Priorities와 Sub Priorities에는 차이점이 있습니다. 예를 들어 PRIGROUP의 값이 0b100(4)로 하고 EINT0, EINT1에 대해서 아래 그림과 같이 우선순위 레벨을 정의해주었다고 가정해봅시다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm044.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15584" alt="19feaarm044" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm044.png" width="414" height="190" /></a><br />
STM32F10x 시리즈에서는 상위 4bit만 이용하여 인터럽트 Priority를 구현하였다고 하였습니다. PRIGROUP이 0b100(0&#215;4)일 경우에 아래 그림과 같이 Group Priority로 3bit, Sub Priority로 1bit를 이용할 수 있습니다. 그러므로 Group Priority 값에는 0&#215;0 ~ 0&#215;7 사이의 값, Sub Priority에서는 0&#215;0 ~ 0&#215;1의 값이 올 수 있습니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm043.png" rel="lightbox[15527]"><img class="alignnone  wp-image-15583" alt="19feaarm043" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm043.png" width="302" height="90" /></a><br />
EINT0의 인터럽트가 먼저 발생하여 인터럽트 서비스 루틴이 실행중에 있을때 EINT1이 발생하면 EINT0의 Group Priority가 높기 때문에 EINT0가 끝날 때까지 EINT1은 Pending 상태에 있다가 EINT0이 끝나면 EINT1이 수행이 됩니다. 그러면 반대로 EINT1이 먼저 발생하여 인터럽트 서비스 루틴 실행 중에 EINT0가 나중에 발생하면 어떻게 될까요? 이 경우에는 EINT0의 Group Priority가 높기 때문에 EINT1 수행을 잠시 중단하고 EINT0를 수행한 이후에 중단되었던 EINT1이 수행이 됩니다. 여기서 알 수 있는 것은 Sub Priority와는 상관없이 Group Priority에 의해서 인터럽트의 선점 우선순위가 달라 집니다. 그렇다면 Sub Priority는 어떤 용도로 사용이 될까요? EINT0, EINT1의 Group Priority의 값이 같은 경우 동시에 인터럽트가 발생하면 Sub Priority가 높은 EINT1이 먼저 수행이 완료되고 나면 EINT0가 나중에 수행이 됩니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm045.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15585" alt="19feaarm045" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm045-620x320.png" width="620" height="320" /></a></p>
<p>Exception이 발생하여 Exception Handler 루틴이 호출되고 다시 원래의 루틴으로 복귀할 때까지의 흐름을 그림으로 표현해 보았습니다.<br />
다음 Chapter에서는 전통적인 ARM의 Interrupt Response에 비해서 Cortex-M3에서 얼마나 좋아졌는지 살펴 보겠습니다.</p>
<p><span style="color: #ff9900"><strong>4.2 Interrupt Response</strong></span></p>
<p><span style="color: #99cc00"><strong>(1) Tail Chaining</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm046.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15586" alt="19feaarm046" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm046-620x263.png" width="620" height="263" /></a><br />
위의 그림을 보면 전통적인 ARM에서는 IRQ1이 IRQ2보다 우선순위가 높고 동시에 발생했을 경우에 IRQ1이 먼저 수행이 끝나고 IRQ2가 수행이 됩니다. 이 과정에서 당연히 문맥 보존을 위해서 ISR1루틴으로 분기하기 전에 {R0-R3, R12, LR, PC} 레지스터 등을 S/W적으로 PUSH하고 ISR1 서비스 루틴이 끝날 때 POP을 합니다. 그리고 다시 ISR2 루틴으로 분기하기 전에 PUSH를 하고 ISR2 루틴이 끝날 때 POP을 하게 됩니다. 여기서 사실 ISR1에서 ISR2 루틴으로 연결될 때 중간에 있는 POP, PUSH는 하지 않아도 되는 불필요한 동작입니다. 왜냐하면 이 과정에서 ISR2 루틴이 끝나고 수행되는 POP과, PUSH 하는 레지스터들은 ISR1 시작 전에 PUSH 되는 레지스터들과 동일하기 때문입니다. Cortex-M3 에서는 중복되는 중간 부분의 POP, PUSH를 생략하고 ISR1 루틴이 끝나면 6Cycle에 해당하는 Tail-Chaining이 수행된 이후에 바로 ISR2 루틴으로 분기를 합니다. 참 효율적이죠. Tail-Chaining부분에서 6Cycle 동안에 실제적으로는 하는 일은 Vector Table에서 ISR2의 시작 주소를 Fetech해오는 작업을 합니다.</p>
<p><span style="color: #99cc00"><strong>(2) Preemption</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm047.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15587" alt="19feaarm047" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm047-620x311.png" width="620" height="311" /></a><br />
위의 경우는 ISR1 서비스 루틴 수행을 끝내고 문맥 보존을 위해서 POP을 수행하고 있는 도중에 IRQ2가 발생하는 경우입니다. 전통적인 ARM에서는 Multiple Load 명령어 수행 중에 인터럽트가 발생할수 없으므로 POP을 모두 수행하고 다시 ISR2를 위한 PUSH루틴으로 진입합니다. 하지만 Cortex-M3에서는 POP(LDMFD) 수행 중에도 인터럽트가 가능하기 때문에 ISR1과 ISR2 사이에 Tail-Chaining 이 발생하면 6Cycle 이후에 ISR2 루틴이 수행될 수 있습니다.</p>
<p><span style="color: #99cc00"><strong>(3) Late Arriving</strong></span></p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm048.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15588" alt="19feaarm048" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm048-620x255.png" width="620" height="255" /></a><br />
전통적인 ARM에서 IRQ2(IRQ) 수행을 위해서 PUSH 도중에 IRQ1 보다 우선순위가 높은 인터럽트(FIQ)가 발생하면 ISR2을 위한 PUSH작업이 끝나자 마자 ISR1을 위한 PUSH 작업이 진행됩니다. Cortex-M3에서는 ISR2를 위한 PUSH 작업중에 IRQ2보다 우선순위가 높은 IRQ1이 발생하게 되면 IRQ1를 위한 PUSH 작업은 진행되지 않고 바로 우선 순위가 높은 ISR1이 수행되고 Tail-Chaining이후에 ISR2를 수행하게 됩니다.</p>
<p>여기까지 Cortex-M3에 대한 구조는 어느 정도 정리가 된 것 같습니다. 놓친 부분이 있다면 이후에 진행된 Cortex-M3 Application에서 예제를 통해서 다시 언급하도록 하겠습니다. Cortex-M3 Application에서는 STM32F103VC Dragon 개발보드를 가지고 Cortex-M3 Architecture에서 이론으로 다루었던 내용들을 실습을 통해서 하나씩 공부해보도록 하겠습니다. 실제 예제에서 컴파일러는 IAR 5.4 Evaluation 버전을 사용할 것이고 Emulator로는 ARM-JTAG Light Edition을 이용할 것입니다. 참고로 아래 그림은 우리가 Cortex-M3 Application에서 사용하게 될 개발보드의 사양입니다.</p>
<p><a href="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm049.png" rel="lightbox[15527]"><img class="alignnone size-large wp-image-15589" alt="19feaarm049" src="http://www.ntrexgo.com/wp-content/uploads/2013/07/19feaarm049-620x390.png" width="620" height="390" /></a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.ntrexgo.com/archives/15527/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>[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>
