Your SlideShare is downloading. ×
Ubee430 menual[r1.8]
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

Ubee430 menual[r1.8]

3,746
views

Published on

Published in: Education

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,746
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. UBee430TM Programming GuideDocument Version : 1.8 Last Update : 2011.1.18 TinyOS2.x 기반 유비쿼터스 센서 네트워크 설계 및 응용 Copyright 2011, Huins Co.Ltd● 본 교재에서는 UBee430, UBee-Dust, UBee430-BN Platform 및 UBee430-AP-KIT에 대하여 TinyOS 2.0.2 설치 및 예제 코드를 제공 합니다.● 본 교재는 휴인스의 동의나 허락 없이 어떠한 형태의 출판이나 무단 배포를 할 수 없습니다.Document History Revision Date Description Rev 1.0 2008-1-4 First Edition Rev 1.6 2009-4-23 패킷 데이터 수정 Rev 1.7 2010-4-22 환경설치 매뉴얼 수정 Rev 1.8 2011-1-18 RFID 모듈 수정SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 1
  • 2. UBee430TM Programming Guide - 목차 -I. UBee430에 대해서 ··························································································· 111. UBee430 하드웨어 설명 ························································································ 11 1.1. UBee430 ······················································································································ 11 1.2. 블록도 ··························································································································· 11 1.3. 특징 ······························································································································· 12 1.4. 구성도 ··························································································································· 13 1.5. 설정 및 전원 ··············································································································· 14 1.5.1. 전원 스위치 설정 ··································································································· 14 1.5.2. USB 모듈 결합 ······································································································· 14 1.6. Memory Map ( DS28DG02 ) ················································································ 15 1.7. 기구도 ··························································································································· 162. UBee-Dust 하드웨어 설명 ··················································································· 17 2.1. UBee-Dust ·················································································································· 17 2.2. 블록도 ··························································································································· 17 2.3. 특징 ······························································································································· 18 2.4. 구성도 ··························································································································· 18 2.5. 설정 및 전원 ··············································································································· 19 2.5.1. 전원 스위치 설정 ··································································································· 19 2.5.2. USB 모듈 결합 ······································································································· 19 2.6. Pin Map ······················································································································· 20 2.7. 기구도 ··························································································································· 203. UBee430-BN 하드웨어 설명 ·············································································· 21 3.1. UBee430-BN ·············································································································· 21 3.2. 블록도 ··························································································································· 21 3.3. 특징 ······························································································································· 22 3.4. 구성도 ··························································································································· 22 3.5. 설정 및 전원 ··············································································································· 23 3.6. 기구도 ··························································································································· 23SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 2
  • 3. UBee430TM Programming GuideII. UBee430 개발환경 구축 ··········································································· 241. TinyOS 2.x 개발환경 구축 ··················································································· 24 1.1. Install Java 1.5 JDK (JDK 5.0 Update 12) ····················································· 26 1.2. Install Cygwin ············································································································ 28 1.3. Installing Graphviz ···································································································· 32 1.4. Huins UBee430 mote 설치 ···················································································· 34 1.4.1. Huins_UBee430 - USB to serial Converter 드라이버 설치 ····················· 34 1.4.2. Huins_UBee430 - USB Serial Port ································································· 36 1.5. Install native compilers ··························································································· 38 1.5.1. Atmel AVR toolchain 설치 ·················································································· 38 1.5.2. MSP430 toolchain 설치 ······················································································· 38 1.6. Install TinyOS 2.x toolchain ·················································································· 39 1.6.1. nesC toolchain 설치 ···························································································· 39 1.6.2. TinyOS tools 설치 ································································································· 39 1.7. Install the TinyOS 2.x Source tree ····································································· 40 1.7.1. TinyOS 2.x 소스트리 설치 ·················································································· 40 1.7.2. 환경변수 등록 ········································································································· 40 1.8. 자동 설치 ··················································································································· 42 1.9. 테스트 ························································································································· 43 1.9.1. mote 연결 테스트 ································································································ 43 1.9.2. TinyOS 개발 환경 테스트 ···················································································· 43 1.9.3. 컴파일 및 설치 테스트 ····················································································· 44 1.9.4. 자바 프로그램 실행 테스트 ················································································· 44 1.9.5. C언어 SDK 컴파일 및 테스트 ·········································································· 44III. 컴파일 ·························································································································· 461. 컴파일 및 인스톨 방법 ··························································································· 46IV. Tutorial ····················································································································· 481. Lesson1[Getting Started with TinyOS and nesC] ······························ 482. Lesson2[Modules and the TinyOS Execution Model] ······················ 653. Lesson3[Mote-mote radio communication] ··········································· 814. Lesson4[Mote-PC serial communication and SerialForwarder]1015. Lesson5[Sensing] ·································································································· 125SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 3
  • 4. UBee430TM Programming Guide6. Lesson6[TinyOS Boot and System Initialization] ······························ 1357. Lesson7[Permanent Data Storage] ···························································· 1418. Lesson8[Resource Arbitration and Power Management] ·········· 153V. TinyOS Programming Guide ······························································ 1671. TinyOS 2.0 OverView ··························································································· 1672. TinyOS 2.x Boot Sequence ············································································· 1743. TinyOS_Programming ··························································································· 184VI. 기본 예제를 통한 UBee430 마스터 ········································· 2571. Null ·································································································································· 257 1.1. 목적 ···························································································································· 257 1.2. 소스 파일들의 역할 ································································································ 257 1.2.1. Makefile ··············································································································· 257 1.2.2. NullAppC.nc ········································································································ 257 1.2.3. NullC.nc ················································································································· 258 1.3. TinyOS 시뮬레이터 - TOSSIM ············································································ 259 1.3.1. TOSSIM 설정 ········································································································ 259 1.3.2. 시뮬레이션 수행 ··································································································· 2602. Blink ································································································································ 263 2.1. 목적 ···························································································································· 263 2.2. 실행방법 ···················································································································· 263 2.3. 결과 ···························································································································· 263 2.4. 코드설명 ···················································································································· 263 2.4.1. BlinkAppC.nc ········································································································ 263 2.4.2. BlinkC ····················································································································· 265 2.5. Blink 시뮬레이션 ··································································································· 2663. BlinkToRadio ·············································································································· 270 3.1. 목적 ···························································································································· 270 3.2. 실행방법 ···················································································································· 270 3.3. 실행결과 ·················································································································· 270 3.4. 코드설명 ···················································································································· 270 3.4.1. BlinkToRadio.h ····································································································· 270 3.4.2. BlinkToRadioAppC.nc ························································································ 272 3.4.3. BlinkToRadioC.nc ······························································································· 273SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 4
  • 5. UBee430TM Programming Guide 3.5. BlinkToRadio 시뮬레이션 ······················································································ 2764. BlinkToSerial ·············································································································· 278 4.1. 목적 ···························································································································· 278 4.2. 실행방법 ···················································································································· 278 4.3. 수행결과 ···················································································································· 2795. BaseStation ················································································································ 281 5.1. 목적 ···························································································································· 281 5.2. 실행방법 및 결과 ···································································································· 281 5.3. 코드설명 ···················································································································· 283 5.3.1. Makefile ················································································································· 283 5.3.2. BaseStationC.nc ·································································································· 283 5.3.3. BaseStationP.nc ·································································································· 2846. Sense ····························································································································· 291 6.1. 목적 ···························································································································· 291 6.2. 실행방법 ···················································································································· 291 6.3. 수행결과 ···················································································································· 291 6.4. 코드설명 ···················································································································· 291 6.4.1. SenseAppC ··········································································································· 291 6.4.2. SenseC ·················································································································· 292 6.4.3. DemoSensorC ······································································································ 293 6.5. Sense 시뮬레이션 ··································································································· 2947. Oscilloscope ·············································································································· 296 7.1. 목적 ···························································································································· 296 7.2. 실행방법 및 결과 ···································································································· 296 7.3. 코드설명 ···················································································································· 298 7.3.1. Oscilloscope.h ····································································································· 298 7.3.2. OscilloscopeAppC.nc ························································································ 299 7.3.3. OscilloscopeC.nc ································································································ 2998. BlinkConfig ················································································································· 304 8.1. 목적 ···························································································································· 304 8.2. 실행방법 ···················································································································· 304 8.3. 코드설명 ···················································································································· 305 8.3.1. 주요 실행 흐름 ····································································································· 305 8.3.2. BlinkConfigAppC.nc ··························································································· 306 8.3.3. BlinkConfigC.nc ··································································································· 306 8.4. BlinkConfig 시뮬레이션 ························································································· 311SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 5
  • 6. UBee430TM Programming Guide9. BLOCK ··························································································································· 312 9.1. 목적 ···························································································································· 312 9.2. 실행방법 ···················································································································· 312 9.3. 결과 ···························································································································· 313 9.4. 코드설명 ···················································································································· 313 9.4.1. RandRWAppC.nc ······························································································· 313 9.4.2. RandRWC.nc ········································································································ 31510. CircularLog ··············································································································· 322 10.1. 목적 ·························································································································· 322 10.2. 실행방법 ·················································································································· 322 10.3. 결과 ·························································································································· 322 10.4. 코드설명 ·················································································································· 322 10.4.1. RandRWAppC.nc ···························································································· 322 10.4.2. RandRWC.nc ······································································································ 32511. SyncLog ····················································································································· 332 11.1. 목적 ·························································································································· 332 11.2. 실행방법 ·················································································································· 332 11.3. 결과 ·························································································································· 333 11.4. 코드설명 ·················································································································· 333 11.4.1. SyncLogAppC.nc ···························································································· 333 11.4.2. SyncLogC.nc ····································································································· 33512. arbiters ······················································································································· 341 12.1. TestFcfsArbiter 예제 ···························································································· 341 12.1.1. TestFcfsArbiterC 설명 ····················································································· 341 12.1.2. TestFcfsArbiterC에서 사용하는 주요 컴포넌트 ········································· 342 12.1.3. 어플리케이션의 동작 ························································································ 343 12.1.4. 실행방법 ·············································································································· 344 12.1.5. 결과 ······················································································································ 34513. RoundRobinArbiter ······························································································ 346 13.1. RoundRobinArbiter 목적 ····················································································· 346 13.1.1. 예제 설명 ············································································································ 346 13.1.2. 주요 컴포넌트 설명 ·························································································· 347 13.1.3. 어플리케이션의 동작 ························································································ 348 13.1.4. 결과 ······················································································································ 349SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 6
  • 7. UBee430TM Programming GuideVII. 실전 예제 ············································································································ 3511. InternalSense ············································································································· 351 1.1. 목적 ···························································································································· 351 1.2. 실행방법 및 결과 ···································································································· 351 1.3. 코드 설명 ·················································································································· 352 1.3.1. InternalSense.h ···································································································· 353 1.3.2. InternalSenseAppC.nc ······················································································· 355 1.3.3. InternalSenseC.nc ······························································································· 356 1.3.4. Makefile ················································································································· 3592. Sht11Sensing ············································································································ 361 2.1. 목적 ···························································································································· 361 2.2. 실행방법 및 결과 ···································································································· 361 2.3. 코드 설명 ·················································································································· 363 2.3.1. Sht11SensingAppC ····························································································· 364 2.3.2. Sht11SensingC.nc ······························································································ 3643. DS28DG02 ················································································································ 368 3.1. 목적 ···························································································································· 368 3.2. 실행방법 ···················································································································· 369 3.2.1. ID ····························································································································· 369 3.2.2. RTC / Calendar ··································································································· 372 3.2.3. GPIO ······················································································································· 375 3.2.4. EEPROM ················································································································ 3784. UserSwitch ·················································································································· 383 4.1. 목적 ···························································································································· 383 4.2. 실행방법 ···················································································································· 383 4.3. 결과 ···························································································································· 383 4.4. 코드설명 ···················································································································· 383 4.4.1. TestUserSwitchAppC.nc ·················································································· 383 4.4.2. TestUserSwitchC.nc ··························································································· 3855. LightToVoltageSensor ·························································································· 387 5.1. 목적 ···························································································································· 387 5.2. 실행방법 ···················································································································· 388 5.3. 코드설명 ···················································································································· 3886. ADCZeroSensor ······································································································· 390 6.1. 목적 ···························································································································· 390 6.2. 센서특징 ···················································································································· 390SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 7
  • 8. UBee430TM Programming Guide 6.2.1 지자기센서 ·············································································································· 390 6.2.2 소리센서 ·················································································································· 391 6.2.3 진동센서 ·················································································································· 392 6.2.4 가속도센서 ·············································································································· 392 6.2.5 인체감지센서 ·········································································································· 392 6.3 실행방법 ······················································································································ 393 6.4 코드설명 ······················································································································ 393VIII. UBee430-AP-KIT 응용 ········································································· 3961. UBee430-AP-KIT 개요 ························································································ 396 1.1. 개요 ···························································································································· 396 1.2. 블록도 ························································································································ 396 1.3. POWER FLOW ········································································································· 397 1.4. 시스템 구성 ·············································································································· 398 1.5. 전원 ···························································································································· 400 1.5.1. 전원 케이블 연결 방법 ······················································································· 400 1.5.2. 전원 스위치 ON ··································································································· 401 1.6. xStation <-> 베이스 노드 연결 ·········································································· 4022. UBee430-AP-KIT 주변 장치 ············································································ 403 2.1. RFID ··························································································································· 403 2.1. 가스밸브 ···················································································································· 406 2.1. 난방밸브 ···················································································································· 407 2.1. AC램프 ······················································································································· 409 2.1. 디지털도어락 ············································································································ 410 2.1. 혈압계 ························································································································ 4113. TinyOS 응용 프로그램 설치 ·············································································· 414 3.1. 응용 프로그램 목록 ································································································ 414 3.2. Protocol ····················································································································· 414 3.2.1. 전체 패킷 구조 ····································································································· 414 3.2.2. UBee430 -> 호스트[ Payload ] ···································································· 415 3.2.3. UBee430 -> 호스트[ Payload ] ···································································· 415 3.2.4. 호스트 -> UBee430[Payload] ········································································ 415 3.3. RFID ··························································································································· 416 3.3.1. 목적 ························································································································· 416 3.3.2. 컴파일 및 다운로드 방법 ··················································································· 416 3.3.3. 결과 ························································································································· 417SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 8
  • 9. UBee430TM Programming Guide 3.4.1. 가스밸브 ················································································································· 418 3.4.2. 목적 ························································································································· 418 3.4.3. 컴파일 및 다운로드 방법 ··················································································· 418 3.4.4. 결과 ························································································································· 419 3.5. AC램프 ······················································································································· 420 3.5.1. 목적 ························································································································· 420 3.5.2. 컴파일 및 다운로드 방법 ··················································································· 420 3.5.3. 결과 ························································································································· 420 3.6. 난방밸브 ···················································································································· 420 3.6.1. 목적 ························································································································· 420 3.6.2. 컴파일 및 다운로드 방법 ··················································································· 420 3.6.3. 결과 ························································································································· 421 3.7. 디지탈도어락 ············································································································ 421 3.7.1. 목적 ························································································································· 421 3.7.2. 컴파일 및 다운로드 방법 ··················································································· 421 3.7.3. 결과 ························································································································· 421 3.8. 혈압계 ························································································································ 421 3.8.1. 목적 ························································································································· 422 3.8.2. 컴파일 및 다운로드 방법 ··················································································· 422 3.8.3. 결과 ························································································································· 423 3.9. 센서노드 ···················································································································· 424 3.9.1. Magnetic Sensor Module ················································································· 424 3.9.2. Sound Sensor Module ······················································································ 424 3.9.3. Ultra-sonic Sensor Module ············································································· 424 3.9.4. Vibration Sensor Module ·················································································· 424 3.9.5. Acceleration Sensor Module ··········································································· 425 3.9.6. Motion-Detector Sensor Module ··································································· 425 3.10. BaseStation ············································································································ 425 3.10.1. 목적 ······················································································································ 425 3.10.2. 컴파일 및 다운로드 방법 ················································································ 425 3.10.3. 결과 ······················································································································ 425IX. 자바 응용 ··········································································································· 4261. USN PC 응용프로그램 개발 준비 ·································································· 4262. PC 환경 구축 ············································································································· 428 2.1. 자바 설치 ·················································································································· 428SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 9
  • 10. UBee430TM Programming Guide 2.2. PC에 웹캠 설치하기 ······························································································· 433 2.3. Java Media FrameWork 2.1버젼 설치 ····························································· 436 2.4. USB to Serial 드라이버 설치 ·············································································· 4403. 제공 어플리케이션 실행 ······················································································· 4334. PC 어플리케이션 개발 환경_Eclipse 환경구축 ······································ 4485. Eclipse에 실행소스와 리소스 Import 작업 ··············································· 452 5.1. SerialForwarder 실행소스 Import ······································································· 452 5.2. UBee430_PC 어플리케이션 Import ···································································· 4606. Eclipse에서 실행 및 유의 사항 ······································································· 4667. TinyOS 2.x 가 지원하는 Java SDK를 이용한 어플리케이션 ········· 467 7.1. SerialForwarder ······································································································· 467 7.2. UBee430_PC ············································································································ 477X. Appendix ················································································································· 4891. 운용환경 설정 팁 ····································································································· 489 1.1. gvim 설치 ·················································································································· 489 1.1.1. 다운로드 ················································································································· 489 1.1.2. 설치 ························································································································· 489 1.2. 시그윈 쉘 환경 꾸미기 ·························································································· 493 1.2.1. Bash에 대해서 ····································································································· 493 1.2.2. 한글 입출력 문제 해결 및 alias 설정 ···························································· 494 1.2.3. 프롬프트 변경 ······································································································· 4962. 초저전력 임베디드 설계에서 위험 요소를 피하는 방법 ···················· 4983. UBee430 RF 설정 방법 ······················································································· 502 3.1 CC2420_DEF_CHANNEL 설정 ·············································································· 502 3.2 CC2420_DEF_RFPOWER 설정 ·············································································· 5034. UBee430 UART 설정 방법 ················································································ 504 4.1 UBee430 UART0 설정 ···························································································· 504 4.2 UBee430 UART1 설정 ···························································································· 5055. UBee430 SHT11(온/습도)센서 Calibration ·············································· 506SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 10
  • 11. UBee430TM Programming GuideI. UBee430에 대해서1. UBee430 하드웨어 설명1.1. UBee430 UBee430은 MSP430와 CC2420을 기반으로 설계 된 USN RF 모듈입니다. IEEE 802.15.4를 지원하 며, TinyOS2.0.2가 탑재되어 있습니다. UBee430 은 보드 내에 온도/습도 및 조도센서가 기본적으 로 내장되어 있습니다. 또한 사용자가 실제 어플 리케이션 구현 시 유용할 수 있는 주변장치를 제 공하고 있습니다. 주변 장치로는 External Flash(1MBytes), EEPROM(2KBytes) , RTC, Unique ID, User Switch 등이 있으며, 강력한 배터리 모니터링 기능을 지원 합니다. 또한 GPIO (General Purpose Input Output) 확장을 위하여 MSP430 GPIO 외에 포트 확장 IC 를 이용하여 추가적인 12개의 GPIO를 제공 합니다. 확장된 GPIO는 입력 또는 출 력 , 오프 드레인 또는 푸시풀로 동작이 가능 합니다.1.2. 블록도SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 11
  • 12. UBee430TM Programming Guide1.3. 특징 ● 250Kbps 2.4Ghz IEEE 802.15.4 Chipcon Wireless Transceiver - CC2420 ● Texas Instruments MSP430 Micro controller - 16bit RISC - Memory : Internal Flash - 48Kbyte , internal RAM - 10Kbyte - Ultra low current consumption ● USB Interface - USB를 이용한 노드 프로그래밍 - USB To Serial Interface 제공 ● ANTENNA - PCB ANTENNA / EXTERNAL ANTENNA ( 최대 150M , Open Area ) ● Peripheral Device - External FLASH1 ( 1Mbyte ) - External EEPROM ( 2Kbyte ) : SPI Interface - RTC ( Real Time Clock ) : SPI Inerface , RTC/Calender/Alarm - Battery Monitor : 다양한 전압 모니터링 기능을 제공 한다. ① MSP430 Internal voltage sensor ② ADC를 이용한 Voltage Sensing ③ 외부 Batter Monitor 장치를 이용한 전압 감시 기능 : 2.5V / 2.25V / 2.0V / 1.75V 설정된 전압 이하로 Drop시 알람 기능 - Unique ID : UBee430은 각각의 노드가 64-BIT의 개별적인 ID를 제공 - GPIO 확장 : SPI Interface , MSP430 GPIO 외에 추가적인 12개의 GPIO를 확장 INPUT / OUTPUT , Open-Drain / Push-Pull - LED : 3EA - USER SWITCH : 2 개 , - RESET Switch - Power Switch ● Sensor - Temperature Sensor - Humidity Sensor - Light Sensor ( Light to Voltage ) ● USER I/O - ADC 6채널 - I2C / SPI - UART RX/TX 2채널SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 12
  • 13. UBee430TM Programming Guide - GPIO 19EA ( MSPGPIO 7EA , 확장 GPIO 12EA ) - JTAG ● 확장 모듈 - AC Control B/D , DC Control B/D - Gas Gear Control B/D - RFID Interface B/D - 혈압계 Interface B/D ● 확장 센서 - 초음파 , 지자기 , 진동 , 가속도 , 인체감지 , 사운드 센서 모듈 - RS232모듈 , USB 모듈 , GPIO 테스트 모듈 - User Interface 모듈 ( 만능 기판형 ) ● TinyOS Support - TinyOS 2.0.21.4. 구성도 < Top View >SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 13
  • 14. UBee430TM Programming Guide <Bottom View >1.5. 설정 및 전원1.5.1. 전원 스위치 설정 UBee430의 전원 스위치는 USB 전원 및 배터리 전원을 선택 하도록 설계 되었다. 그러므로 USB 연결 시에는 반드시 전원 스위치를 USB 방향으로 전환 시키고, 독 립적인 배터리 사용 시에는 BAT 방향으로 전환 시켜야 한다. 배터리 전원 사용 USB 전원 사용 프로그램 다운로드1.5.2. USB 모듈 결합 USB를 이용하여 프로그램 다운로드 시에는 UBee430 USB 모듈을 결합하여야 하 며, USB 모듈을 연결하기 전에 반드시 전원을 OFF/USB 상태로 먼저 설정 한 뒤 USB 모듈을 결합해야 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 14
  • 15. UBee430TM Programming Guide <UBee430 USB 모듈 > <UBee430 + USB 모듈 >1.6. Memory Map ( DS28DG02 ) UBee430은 EEPROM , RTC, Unique ID, 확장 GPIO ,배터리 모니터링 등의 추가 적인 기능을 지원하기 위하여 DS28DG02라는 One-Chip을 사용하고 있다. DS28DG02는 MSP430의 GPIO와 연결되어 있다. UBee430에서 제공하는 DS28DG02 컴포넌트는 다음 메모리맵을 기준으로 만들어 졌다. ADDRESS TYPE ACCESS DESCRIPTION 000h to 03Fh EEPROM R/W User memory block 0. 040h to 07Fh EEPROM R/W User memory block 1. 080h to 0BFh EEPROM R/W User memory block 2. 0C0h to 0FFh EEPROM R/W User memory block 3. 100h to 109h — — Reserved, contents undefined. 10Ah EEPROM R/W Power-on default for PIO output state (PIO0 to PIO7). 10Bh EEPROM R/W Power-on default for PIO output state (PIO8 to PIO11). 10Ch EEPROM R/W Power-on default for PIO direction (PIO0 to PIO7). 10Dh EEPROM R/W Power-on default for PIO direction (PIO8 to PIO11). 10Eh EEPROM R/W Power-on default for PIO read-inversion (PIO0 to PIO7). Power-on default for PIO read-inversion (PIO8 to PIO11), 10Fh EEPROM R/W PIO output type (PIO0 to PIO11 in groups of 4 PIOs), PIO output mode (same mode for all PIOs). 110h to 117h — — Reserved, contents is undefined. 118h to 11Fh ROM R 64-bit unique registration number. 120h SRAM R/W PIO output state (PIO0 to PIO7). 121h SRAM R/W PIO output state (PIO8 to PIO11). 122h SRAM R/W PIO direction (PIO0 to PIO7). 123h SRAM R/W PIO direction (PIO8 to PIO11). 124h SRAM R/W PIO read-inversion (PIO0 to PIO7). PIO read-inversion (PIO8 to PIO11), PIO output type 125h SRAM R/W (PIO0 to PIO11 in groups of 4 PIOs), PIO output mode (same mode for all PIOs).SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 15
  • 16. UBee430TM Programming Guide R 126h — PIO read access (PIO0 to PIO7). R 127h — PIO read access (PIO8 to PIO11). 128h — — Reserved, contents undefined. 129h to 12Fh NV SRAM R/W RTC and calendar. 130h to 133h NV SRAM R/W RTC alarm. 134h NV SRAM R/W Multifunction control/setup register. 135h NV SRAM R/Clear Alarm and status register. 136h and — — Reserved, contents undefined. above 추가적인 내용을 확인하려면 DS28DG02 데이터시트를 참고 하시길 바랍니다. 제품 출고시 동봉된 CD에 Datasheet 첨부됨.1.7. 기구도SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 16
  • 17. UBee430TM Programming Guide2. UBee-Dust 하드웨어 설명2.1. UBee-DustUBee-Dust는 MSP430와 CC2420을 기반으로 설계된 USN RF 모듈입니다. IEEE 802.15.4를 지원하며, TinyOS2.0.2가 탑재되어 있습니다.UBee-Dust는 초소형, 저전력, Low-Cost를 목적으로 설계된 모듈입니다.UBee-Dust는 UBee430과 같은 플랫폼 구조를 가지고 있습니다. 컴파일 및 다운로드시 UBee430과 똑같이 사용 됩니다. 하지만 UBee-Dust는 초소형 및 저전력을 구현하기 위하여 UBee430에 구현된 일부 Peripheral Device는 제외 되었습니다.2.2. 블록도SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 17
  • 18. UBee430TM Programming Guide2.3. 특징● 250Kbps 2.4Ghz IEEE 802.15.4 Chipcon Wireless Transceiver - CC2420● Texas Instruments MSP430 Micro controller - 16bit RISC - Memory : Internal Flash - 48Kbyte , internal RAM - 10Kbyte - Ultra low current consumption● USB Interface - USB를 이용한 노드 프로그래밍 - USB To Serial Interface 제공● ANTENNA - 칩 안테나● Peripheral Device - LED : 3EA - USER SWITCH , Power-Path Switch● Sensor - Internal Voltage , Internal Temperature , Light● User IO - JTAG , REST , 3V , GPIO 3EA , ADC CH-3● Power - 3V Coin Battery ( CR2032 )2.4. 구성도 칩 안테나 유저 스위치 전원 스위치 조도센서 CC2420 User I/O User I/O (RESET, UART , JTAG) (GPIO 3EA, ADC 3EA , POWER ) < TOP VIEW >SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 18
  • 19. UBee430TM Programming Guide 배터리 MSP430 (배터리 홀더 하단 ) < BOTTOM VIEW >2.5. 설정 및 전원2.5.1. 전원 스위치 설정 UBee-Dust의 전원 스위치는 USB 전원 및 배터리 전원을 선택 하도록 설계 되었 다. 그러므로 USB 연결 시에는 반드시 전원 스위치를 USB 방향으로 전환 시키고, 독립적인 배터리 사용 시에는 ON 방향으로 전환 시켜야 한다. 배터리 전원 사용 시 USB 전원 사용 시2.5.2. USB 모듈 결합 USB를 이용하여 프로그램 다운로드 시에는 UBee430 USB 모듈을 결합하여야 하 며, USB 모듈을 연결하기 전에 반드시 전원을 OFF/USB 상태로 먼저 설정 한 뒤 USB 모듈을 결합해야 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 19
  • 20. UBee430TM Programming Guide <UBee-Dust + USB 모듈 >2.6. Pin Map J4 J5 PIN SIGNAL NAME PIN SIGNAL NAME 1 VCC3.3V ( USB ) 1 VCC3V ( BATTERY ) 2 MSP430_TCK 2 ADC0 3 RESET 3 GPIO 1.2 4 MSP430_TMS 4 ADC1 5 UART1RX 5 GPIO 2.5 6 MSP430_TDI 6 ADC2 7 UART1TX 7 GPIO 4.0 8 MSP430_TDO 8 GND2.7. 기구도SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 20
  • 21. UBee430TM Programming Guide3. UBee430-BN 하드웨어 설명3.1. UBee430-BNUBee430-BN은 호스트 시스템과 각각의 RF모듈을 인터페이스 시키는 USB 동글 형태의 보드입니다. UBee430-BN는 USB 관련 부품과 MSP430,CC2420등의 핵심적인 부품만을 적용하여 구성된모듈이며, TinyOS2.0.2가 탑재되어 있습니다.UBee430-BN은 각각의 센서 노드와 무선으로 인터페이스 되며 각 노드에서 전달한센서 및 기타 무선 데이터를 Host PC 또는 xStation과 같은 임베디드 시스템에 전달합니다.3.2. 블록도SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 21
  • 22. UBee430TM Programming Guide3.3. 특징● 250Kbps 2.4Ghz IEEE 802.15.4 Chipcon Wireless Transceiver - CC2420● Texas Instruments MSP430 Micro controller - 16bit RISC - Memory : Internal Flash - 48Kbyte , internal RAM - 10Kbyte - Ultra low current consumption● USB Interface - USB를 이용한 노드 프로그래밍 - USB To Serial Interface 제공● ANTENNA - EXTERNAL ANTENNA ( 최대 150M , Open Area )● Peripheral Device - LED : 3EA - RESET Switch3.4. 구성도 RX LED TX LED MSP430 LED RESET SWITCH CC2420 EXTERNAL ANTENNA < TOP VIEW >SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 22
  • 23. UBee430TM Programming Guide MSP430 FT232BM < BOTTOM VIEW >3.5. 설정 및 전원 UBee430-BN은 독립적인 배터리를 사용하지 않고 USB 포트로부터 전원을 공급 받아 동작을 한다.3.6. 기구도SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 23
  • 24. UBee430TM Programming GuideII. UBee430 개발환경 구축 휴인스에서는 쉬운 개발환경 설치를 위하여 Vmware 기반의 Virtual Image를 제공 한다. 이 이미지는 TinyOS 사용을 위한 rpm 및 기타 유틸리트가 모두 설치 되었으며, UBee430 사용을 위한 모든 포팅 과정 및 설정이 완료된 이미지 이다.1. 설치에 필요한 프로그램 UBee430 배포용 CD는 다음 프로그램을 제공 한다. ( UBee430[Rev 1.3 이상]_CD2 ) 1. VMware-player-2.0.2-59824.exe : VMware Player 2. Xubuntos 2.0-UBee430-080117.exe : 압축된 Virtual Image2. VMware Player 설치1.1. VMware-player-2.0.2-59824.exe 를 더블 클릭하여 설치를 시작SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 24
  • 25. UBee430TM Programming GuideSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 25
  • 26. UBee430TM Programming Guide1.2. VMware Player에서 loading할 폴더를 만든다. 윈도우 탐색기를 이용하여 내 문서에 My Virtual Machines 폴더를 만든다. My Virtual Machines 폴더에 Xubuntos 2.0-UBee430-080117 이미지를 복사한 다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 26
  • 27. UBee430TM Programming Guide3. Virtual Image 복사 및 압축해제1.3. 휴인스에서 제공하는 Xubuntos 2.0-UBee430-080117 이미지를 My Virtual Machines 폴더에 복사하여 붙여넣기 한다. Xubuntos 2.0-UBee430-080117 이미지는 배포용 CD에 압축된 상태로 제공된 다.1.4. Xubuntos 2.0-UBee430-080117.exe 파일을 내 문서 My Virtual Machines 폴더에 복사 한다.1.5. Xubuntos 2.0-UBee430-080117.exe 파일을 더블클릭하여 압축을 해제 한다. Xubuntos 2.0-UBee430-080117.exe 파일을 더블 클릭 ( 자동 압축 풀림 )SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 27
  • 28. UBee430TM Programming Guide1.6. VMware Player 실행 바탕화면의 바로가기 아이콘을 더블 클릭 한다 VMware Player가 실행되면 Image를 loading 한다. Open 클릭 C: ₩Documents and Settings ₩<유저계정> ₩My Documents ₩My Virtual Machines ₩Xubuntos2.0-UBee430- 080117 폴더의 Xubuntos 2.0.vmx 파일 을 선택한 후 열기를 누른다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 28
  • 29. UBee430TM Programming Guide xubuntu 가 실행이 된다. Username를 입력 한다 마우스 커서를 입력란에 클릭한 후 Username은 "xubuntos"를 입력 한다. 그리고 엔터를 입력 한다 Password를 입력 한다. "tinyos"를 입력 한다. 그리고 엔터를 입력 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 29
  • 30. UBee430TM Programming Guide loading이 완료되었다면 다음 화면을 볼수 있을 것이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 30
  • 31. UBee430TM Programming Guide4. 테스트1.7. UBee430 연결 테스트 UBee430을 현재 개발환경이 설치된 PC의 USB 포트에 장착 한다. 터미널을 실행 시킨다. motelist를 입력하여 UBee430이 연결되었는지 확인 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 31
  • 32. UBee430TM Programming Guide 만약 UBee430이 검색이 안되면 xubuntos에 Future Devies USB Device 아이콘 을 클릭하여 재인식 시킨다. 이때 VMware Player에서 윈도우로 탈출하려면 키보드의 ctrl + Alt를 동시에 눌러 야 한다.5. 컴파일 및 설치 테스트 터미널을 실행 시킨다. ( 현재 터미널이 실행되어 있으면, 현재의 터미널에서 수행 한다.) TinyOS 어플리케이션을 컴파일하고 UBee430에 다운로드 한다. $ cd /opt/opt/tinyos-2.x/apps/tests/TestSerial $ make UBee430 installSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 32
  • 33. UBee430TM Programming Guide 자바 프로그램 실행 테스트 $ java net.tinyos.tools.Listen -comm serial@/dev/ttyUSB0:UBee430SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 33
  • 34. UBee430TM Programming GuideIII. 컴파일 어플리케이션을 작성하여, 사용하기 위해서 컴파일을 해주어야 한다. 이번 챕터에서 는 작성한 어플리케이션을 컴파일하고, 모트에 설치하는 방법을 다루고자 한다.1. 컴파일 및 인스톨 방법 TinyOS에서는 make를 명령을 사용하여 컴파일과 mote에 설치하는 작업을 수행한 다. 아래에 자주 사용되는 make 명령을 예로 들었다. make [ 플랫폼 이름 ] [ 옵션 ] make UBee430 컴파일 make UBee430 install 컴파일 후 설치 make UBee430 reinstall 컴파일 없이 재설치 make clean 컴파일 결과들을 삭제 make UBee430 reinstall,1 mote의 ID를 1로 하여 재설치 make UBee430 bsl,6 reinstall COM7에 연결된 mote에 재설치 make UBee430 docs NesC 문서를 생성 ( html 파일 ) Null 어플리케이션을 컴파일하고 설치해보자. 우선 Null 어플리케이션 디렉터리로 이 동한다. 그리고 어플리케이션을 컴파일 하기 위해 필요한 3가지 파일이 있는지 확 인한다. make 명령을 사용하여 컴파일을 후, 모트로 프로그램을 다운로드한다. $ cd /opt/tinyos-2.x/apps/Null $ ls ..................................................... ① 파일확 인 Makefile NullAppC.nc NullC.nc $ make UBee430 install .................... ② 컴파 일 후 인 스톨 mkdir -p build/UBee430 compiling NullAppC to a UBee430 binary ncc -o build/UBee430/main.exe -Os -O -mdisable-hwmul -Wall -Wshadow -DDEF_TOS_AM_GROUP=0x7d -Wnesc-all -target=UBee430 -fnesc-cfile=build/UBee430/app.c -board= -DIDENT_PROGRAM_NAME=₩"NullAppC₩" -DIDENT_USER_ID=₩"이정주₩" -DIDENT_HOSTNAME=₩"nautes₩" -DIDENT_USER_HASH=0xbcec09c4L -DIDENT_UNIX_TIME=0x46d4c282L -DIDENT_UID _HASH=0xf759d9b3L NullAppC.nc -lm compiled NullAppC to build/UBee430/main.exe 1418 bytes in ROMSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 34
  • 35. UBee430TM Programming Guide 4 bytes in RAM msp430-objcopy --output-target=ihex build/UBee430/main.exe build/UBee430/main.ih ex writing TOS image cp build/UBee430/main.ihex build/UBee430/main.ihex.out found mote on COM7 (using bsl,auto) installing UBee430 binary using bsl tos-bsl --telosb -c 6 -r -e -I -p build/UBee430/main.ihex.out MSP430 Bootstrap Loader Version: 1.39-telos-8 Mass Erase... Transmit default password ... Invoking BSL... Transmit default password ... Current bootstrap loader version: 1.61 (Device ID: f16c) Changing baudrate to 38400 ... Program ... 1450 bytes programmed. Reset device ... rm -f build/UBee430/main.exe.out build/UBee430/main.ihex.out 정상적으로 컴파일이 되고, 장치 설정이 정상적으로 되어있다면, 위와 같은 메시지 를 볼 수 있을 것이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 35
  • 36. UBee430TM Programming GuideIV. Tutorial 번역 과정에서 오역이 있을 수 있으니 원문 Tutorial을 참고 하시길 바랍니다. 본 tutorial은 원문 tutorial을 UBee430에 맞추어 재구성 한 번역본입니다. 번역 과정에서 삭제 및 추가한 부분이 있습니다. 이점 참고 바랍니다.1. Lesson 1: Getting Started with TinyOS and nesC소개이번 lesson에서는 TinyOS 프로그램을 컴파일하고 mote에 설치하는 방법에 대해 설명 한다. 그리고 TinyOS 컴포넌트 모델의 기본적인 개념과 구문(syntax)에 대해 소개한다. 또한 TinyOS의 소스 코드 문서를 생성하고 찾는(navigate) 방법에 대해 설명 한다.컴파일과 설치첫 번째 연습으로써 매우 간단한 TinyOS 어플리케이션인 Blink를 컴파일하고 설치해볼 것이다. mote 하드웨어가 없다면, TinyOS 시뮬레이터인 TOSSIM을 위해 컴파일을하면 된다.TinyOS 어플리케이션은 make 프로그램을 사용하여 컴파일 한다. TinyOS는 강력하고확장성 있는 make system을 사용함으로써 새로운 플랫폼이나 컴파일 옵션을 쉽게 추가 할 수 있다. make system 정의는 /opt/tinyos-2.x/support/make에 위치해 있다.첫 번째 단계로 TinyOS 환경이 올바르게 셋업이 되었는지 체크해야 한다.tos-check-env 명령을 실행 시킨다. $ tos-check-env이 스크립트는 TinyOS 환경에서 필요로 하는 모든 것을 체크한다. 정상적으로 설치되었다면, tos-check-env 실행 후, 아래 문구를 볼 수 있다. tos-check-env completed without error.UNIX 환경에 익숙하다면 대부분의 경고들은 여기서 따로 설명할 필요가 없을 것이다.경고들로 문제를 겪는다면 이메일 리스트에 가입해서 질문하기를 권장한다. 문제를 겪SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 36
  • 37. UBee430TM Programming Guide고 있는 문제를 찾기 위해서는 help archives( http://mail.millennium.berkeley.edu/pipermail/tinyos/ )가 유용할 것이다.만약 시스템에서 일부 명령어들이 사용불가라고 한다면, TinyOS tools RPM을 설치가필요하다. 설치 문서를 참고하기 바란다. rpm으로 설치를 했다면 tos-check-env명령을 /usr/bin에서 찾을 수 있을 것이다. $ which tos-check-env /usr/bin/tos-check-env두 번째로 체크해야 하는 것은 TinyOS 빌드 시스템이 사용가능 한지이다. 이것은makerule 환경변수와 관련이 있다. 쉘에서 다음 명령을 입력하자. $ printenv MAKERULES /opt/tinyos-2.x/support/make/Makerules만약 TinyOS 트리가 기본 설치 위치가 아닌 다른 곳에 설치가 되었다면, /opt대신 다른 초기 패스로 되어 있을 것이다.printenv가 아무것도 출력하지 않았다면 MAKERULES가 설정되어 있지 않은 것이다.사용하는 쉘에 따라 export 또는 setenv를 사용해서 환경변수를 설정해야 한다. 쉘 환경변수에 대해 알 지 못한다면 http://www.ee.surrey.ac.uk/Teaching/Unix/unix8.html이 도움이 될 것이다.TinyOS 어플리케이션을 컴파일하기 위해 어플리케이션 디렉터리에서 실행되어야 할make 명령은 make [platform]이다. Blink 예제를 컴파일하기 위해서는 apps/Blink 디렉터리로 이동한 후, 가지고 있는 하드웨어에 따라 make micaz, make mica2, maketelosb를 입력하거나 시뮬레이션을 위해 make micaz sim을 입력하면 된다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 37
  • 38. UBee430TM Programming GuideTOSSIM을 위해 컴파일을 한다면, 보다 긴 메시지를 볼 수 있을 것이다. TOSSIM을빌드하는 것은 공유라이브러리 빌드나 스크립팅 지원 같은 여러 단계를 필요로 하기때문이다.Cygwin을 실행 하고나서 에러 메세지를 발견한다면 다른 Cygwin nesC RPM을설치해야 한다. ( 설치문서의 4단계나 업그레이드 문서의 2단계 )적당한 버전의 nesC 컴파일러를 호출하고 있다는 것을 확신아래와 같은 에러가 발생 했다면BlinkAppC.nc:46: syntax error before `newmake: *** [exe0] Error 1오래된 nesc 컴파일러를 호출했기 때문이다. ncc --version을 입력하여 체크하자.아래와 같은 것을 볼 수 있을 것이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 38
  • 39. UBee430TM Programming Guide사용 중인 C 컴파일러의 버전에 대한 정보도 뒤에 따라 보일 것이다. 위에 나온 버전과 다르다면 make가 잘못된 버전을 호출해서 컴파일 문제가 발생했을 것이다.TinyOS 1.x에서 업그레이드를 했을 때 발생하기 쉬운 문제이다. 시스템에 적절한 컴파일러가 설치되어 있다면, tos-check-env 명령을 패스할 것이다. 그렇지 않으면 컴파일시 문제를 일으킬 것이다.ncc는 NesC 컴파일러를 호출하는 스크립트이다.tinyos-2.x/tools/tinyos/ncc에 설치되어 있을 것이다. RPM으로 설치를 했다면 새로운 버전의 ncc는 /usr/bin에 설치된다.make가 호출하는 ncc의 위치를 다음 명령으로 알아볼 수 있다.이 경우, ncc의 버전이 너무 오래 되서 --version 플래그에 응답을 하지 않는다.반면에SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 39
  • 40. UBee430TM Programming Guide이 문제에 대한 최적의 방법은 오래된 ncc의 이름을 변경하는 것이다.[ UBee430은 컴파일러 오류가 없으니 다음 부분은 굳이 실행 하지 않아도 된다.]$ mv /usr/local/bin/ncc /usr/local/bin/ncc.old$ which ncc/usr/bin/ncc같은 처리를 nescc에도 적용 할 수 있다.$ nescc --versionncc: 1.1.2$ which nescc/usr/local/bin/nescc$ /usr/bin/nescc --versionnescc: 1.2.5$ mv /usr/local/bin/nescc /usr/local/bin/nescc.old$ which nescc/usr/bin/nescc이제 어플리케이션을 컴파일 했다. mote에 설치하고 실행을 해볼 차례이다. 다음 단계는 프로그래밍 하고 있는 mote family에 따라 다르다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 40
  • 41. UBee430TM Programming GuideInstalling on telos-family mote (telosa, telosb)telos mote는 USB디바이스이다. USB 포트에 연결하여 사용할 수 있다. telos mote telos mote plugged into a USB port UBee430 UBee430 USBTelos mote는 USB 장치이기 때문에 USB 포트에 연결하면 OS에 등록이 된다. 현재연결된 mote가 어느 포트에 연결되었는지 motelist명령으로 확인할 수 있다.[ 사전에 USB 드라이버가 설치되어 있어야 한다. ]$ motelistReference CommPort Description-----------------------------------------------------------UCC89MXV COM4 Telos (Rev B 2004-09-27)[ UBee430 motelist시에는 다음과 같다. ]SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 41
  • 42. UBee430TM Programming GuideWindows에서는 mote가 연결된 COM port 번호가 출력되며, 리눅스에서는 USB 시리얼 port번호가 출력된다.애플리케이션을 설치하려면 다음 명령어를 사용하면 된다. 윈도우즈 버전에서는[COM포트 번호 - 1]을 인자로 준다는 점에 주의해야 한다. $ make telos install.2 bsl.3mote의 ID를 2로 설정하여 telos 플랫폼에 맞게 이미지가 컴파일 한 후, COM4 포트에 연결된 mote에 인스톨이 된다. 하나의 mote에 설치를 한다면, bsl과 디바이스 번호를 생략해도 된다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 42
  • 43. UBee430TM Programming GuideInstallation optionsmote를 프로그래밍 보드에서 분리한 후, 스위치를 켜면 다운로드 된 프로그램이 실행된다.세 개의 LED가 증가 카운터를 출력하면 정상적인 것이다.[ 새로 컴파일을 하여 인스톨한다.]make telos install[ 새로 컴파일을 하지 않고 현재 컴파일 되어 있는 바이너리 이미지를 mote에 설치한다. ]make telos reinstall[ 컴파일 된 모든 바이너리 이미지 파일을 제거한다. ]make clean네트워크상에서 mote는 고유의 식별자를 가지고 있어야 한다. TinyOS 애플리케이션을 컴파일 할 때, 옵션으로 주지 않으면 디폴트로 식별자는 1이 된다. 다른 식별자를노드에 부여하기 위해서는 설치 시 옵션으로 지정해야 한다. 예를 들어 make telosbinstall.5 또는 make telosb reinstall.5 명령을 내리면, 식별자로써 5를 가지게 된다.자세한 빌드 시스템에 대한 정보는 13장에 있다.Components and InterfacesBlink을 mote에 설치했다. 이제 어떻게 동작하는지 알아보자.TinyOS 코드처럼 Blink도 nesC로 작성되었다.nesC는 C언어에 컴포넌트와 concurrency를 위한 추가적인 언어 특징을 추가한 것이다. nesC 어플리케이션은 하나 이상의 컴포넌트들이 연결되어 구성 된다.컴포넌트는 두개의 스코프를 정의된다. 첫 번째 스코프는 인터페이스의 이름을 포함하고 있고, 구현을 위한 두 번째 스코프가 있다.컴포넌트는 provided인터페이스와 used인터페이스가 있다. provided인터페이스는 컴포넌트가 specification내에서 사용자에게 제공하는 기능을 나타내며, used 인터페이스는 컴포넌트가 작업을 수행하는데 필요한 기능을 나타낸다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 43
  • 44. UBee430TM Programming Guide인터페이스는 양방향성(bidirectional)을 가지고 있다. 인터페이스의 공급자에 의해 제공되는 함수인 commands 집합을 명시한다. 그리고 인터페이스의 사용자에 의해 제공되는 함수인 events집합을 명시한다.Interfaces are bidirectional: they specify a set of commands, which are functionsto be implemented by the interfaces provider, and a set of events, which arefunctions to be implemented by the interfaces user.인터페이스에서 명령을 호출하는 컴포넌트에 대해서 반드시 해당 인터페이스의 이벤트를 구현해야 한다. 하나의 컴포넌트는 다수의 인터페이스와 같은 인터페이스내의 다수의 인스턴스를 사용하거나 공급한다.The set of interfaces which a component provides together with the set ofinterfaces that a component uses is considered that components signatureConfigurations and ModulesnesC에는 두 가지 타입의 컴포넌트가 있다. modules and configurations.Modules는 하나 이상의 인터페이스에 대한 구현을 제공한다. Configurations는 다른컴포넌트들을 조립(assemble)하는데 사용된다. 컴포넌트에서 사용되는 인터페이스를다른 컴포넌트가 제공하는 인터페이스와 연결한다. 모든 nesC 어플리케이션은 컴포넌트 내부적으로 어떻게 서로 연결되어 있는지 top-level configuration으로 기술된다.Blink: An Example Application구체적인 예제로 TinyOS 트리에 있는 Blink를 살펴보자. 이 예제는 세 개의 LED들로카운터를 디스플레이 한다. .25Hz에 LED0이 점멸되며, .5Hz에 LED1이 점멸되며,1Hz에 LED2가 점멸된다. 2초마다 세 개의 LED들이 1에서 7까지 바이너리 카운터를출력 한다Blink는 두개의 컴포넌트로 구성된다. BlinkC.nc파일이 module이고 BlinkAppC.nc 파일이 configuration이다. 모든 어플리케이션은 top-level 설정 파일이 요구된다. 설정파일의 이름은 어플리케이션 이름 뒤에 suffix가 붙는다.BlinkAppC.nc의 경우 Blnik 어플리케이션을 위한 설정파일이다. BlinkC.nc 는 nesC컴파일러가 실행 파일을 생성 할 때 사용하는 소스파일이다. 다른 면에서 보면 실제로Blink예제의 구현을 제공하는 부분이다. BlinkAppC.nc는 BlinkC.nc 모듈과 blink 어플리케이션에서 요구하는 다른 컴포넌트를 연결하기 위해 사용되어 진다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 44
  • 45. UBee430TM Programming Guidemodules와 configurations로 구별을 해놓는 이유는 시스템 디자이너가 이미 만들어놓은 구현으로 어플리케이션을 빌드 할 수 있게 해준다. 예를 들어, 디자이너는 실제로디자인을 하지도 않은 채 하나이상의 모듈들을 서로 연결한 configuration을 제공해줄 수 있다. 마찬가지로 개발자는 어플리케이션 범위 내에서 사용가능한 새로운 라이브러리 모듈 집합을 제공해 줄 수 있다.BlinkAppC와 BlinkC처럼 configuration과 module이 같이 제공되는 경우도 있다.Sometimes (as is the case with BlinkAppC and BlinkC) you will have aconfiguration and a module that go together. When this is the case, theconvention used in the TinyOS source tree is: File File Type Name Foo.nc Interface Foo.h Header File Public FooC.nc Module Private FooP.nc ModuleThe BlinkAppC.nc ConfigurationnesC 컴파일러는 top-level 설정파일이 주어질 때 nesC 어플리케이션을 컴파일 한다.일반적인 TinyOS 어플리케이션들은 플랫폼 선택해주고 ncc를 호출 할 때 적절한 옵션들을 어플리케이션의 설정파일에 적어주면 표준 Makefile을 사용하여 컴파일 하는것이 가능하다.어플리케이션을 위한configuration인BlinkAppC.nc를 먼저 살펴보자.apps/Blink/BlinkAppC.nc:configuration BlinkAppC {}implementation {components MainC, BlinkC, LedsC;components new TimerMilliC() as Timer0;components new TimerMilliC() as Timer1;SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 45
  • 46. UBee430TM Programming Guidecomponents new TimerMilliC() as Timer2;BlinkC -> MainC.Boot;BlinkC.Timer0 -> Timer0;BlinkC.Timer1 -> Timer1;BlinkC.Timer2 -> Timer2;BlinkC.Leds -> LedsC;}실제 설정은 implementation 키워드 뒤에 따라오는 {}내에 구현된다. components 라인은 설정을 참조하는 컴포넌트 집합을 지정한다. 지금의 경우에는 Main, BlinkC,LedsC, 그리고 세 개의 타이머 컴포넌트의 인스턴스(Timer0, Timer1, Timer2라는 이름으로 참조되는 TimerMilliC)이다. (1) as 키워드에 의해 별칭을 부여해서 이루어진다. (2)BlinkAppC 컴포넌트가 BlinkC 컴포넌트와 동일하지 않다는 것을 기억해야 한다.BlinkAppC 컴포넌트는 MainC, LedsC, 그리고 세 개의 타이머와 함께 BlinkC 컴포넌트로 구성되어 있다.BlinkAppC 설정의 나머지 부분들은 다른 컴포넌트가 제공하는 인터페이스와 컴포넌트에서 사용되는 인터페이스를 연결하는 부분들로 구성된다.MainC.Boot와 MainC.SoftwareInit인터페이스는 TinyOS boot sequence의 일부분이다. 자세한 내용은 3장에서 다룰 것이다. 이런 연결들이 LED들이나 타이머가 사용가능하도록 초기화시켜준다.마지막 네 줄은 인터페이스를 연결한다. BlinkC 컴포넌트는TimerMilliC and LedsCcomponents 가 제공하는 인터페이스를 사용한다.BlinkC 모듈의 정의와 구현을 살펴보는 것이 이런 연결의(wiring)의미를 이해하는데 도움이 된다.The BlinkC.nc Moduleapps/Blink/BlinkC.nc:module BlinkC {uses interface Timer<TMilli> as Timer0;uses interface Timer<TMilli> as Timer1;uses interface Timer<TMilli> as Timer2;uses interface Leds; users interface Boot;SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 46
  • 47. UBee430TM Programming Guide}implementation{// implementation code omitted}모듈 코드의 첫 부분에 BlinkC라 불리는 모듈이라는 것을 명시하고 있다. 그리고 제공하거나 사용될 인터페이스들을 선언하였다.BlinkC 모듈은 세 개의 Timer<TMilli> 인터페이스의 인스턴스를 Timer0, Timer1, Timer2라는 이름으로 사용한다(the <TMilli>syntax simply supplies the generic Timer interface with the required timerprecision). 마지막으로 BlinkC 모듈은 Leds와 Boot 인터페이스를 사용한다. 이것은의미한다. BlinkC가 호출하게 될 명령들은 이들이 사용될 인터페이스 내에 선언이 되어 있어야 한다. 그리고 이들 인터페이스에 이벤트들을 구현해야 한다.BlinkC 컴포넌트에 의해 사용되는 인터페이스를 다시 본 후에, BlinkAppC.nc에 있는마지막 네 줄의 의미가 이해하기 쉬워질 것이다. BlinkC.Timer0 -> Timer0라인은BlinkC컴포넌트의 Timer0,Timer1,Timer2인터페이스를 TimerMilliC 컴포넌트에 의해 제공되는 세개의 Timer<TMilli> 인터페이스에 연결한다. The BlinkC.Leds -> LedsC 라인은 BlinkC컴포넌트의 Leds인터페이스를 LedsC 컴포넌트에 의해 제공 되어지는Leds 인터페이스에 연결한다.nesC에서는 인터페이스 간에 묶기 위해서 화살표를 사용한다. 오른쪽 화살표(A->B)는 A를 B에 연결한다(묶는다). 화살표 왼쪽에 있는 A는 인터페이스의 사용자이고, 화살표 오른쪽에 있는 B는 공급자이다. 완전한 묶음(연결)은 A. a -> B. b이다. A컴포넌트의 a 인터페이스를 B컴포넌트의 b인터페이스에 연결한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 47
  • 48. UBee430TM Programming Guide인터페이스에 이름을 붙이는 것은 같은 인터페이스의 다수의 인스턴스를 컴포넌트가사용하거나 제공 할 때 중요하다.예를 들어 BlinkC는 Timer의 세 개의 인스턴스를 사용한다.: Timer0, Timer1, Timer2컴포넌트가 인터페이스의 하나의 인스턴스만을 가지면, 인터페이스의 이름을 생략할수 있다. 예를 들어 BlinkAppC를 다시 보자.apps/Blink/BlinkAppC.nc:configuration BlinkAppC {}implementation {components MainC, BlinkC, LedsC;components new TimerMilliC() as Timer0;components new TimerMilliC() as Timer1;components new TimerMilliC() as Timer2;BlinkC -> MainC.Boot;BlinkC.Timer0 -> Timer0;BlinkC.Timer1 -> Timer1;BlinkC.Timer2 -> Timer2;BlinkC.Leds -> LedsC;}인터페이스이름인 Leds는 컴포넌트 LedsC에 포함이 되어 있지 않다.The interface name Leds does not have to be included in LedsC:BlinkC.Leds -> LedsC; // Same as BlinkC.Leds -> LedsC.Leds왜냐하면 BlinkC는 Leds 인터페이스에서 하나의 인스턴스만을 사용하기 때문에가능하다.BlinkC -> LedsC.Leds; // Same as BlinkC.Leds -> LedsC.LedsTimerMilliC 컴포넌트들은 각각 하나의 Timer 인스턴스를 제공한다. TimerMilliC 컴포넌트의 이름은 연결하는데 포함이 되어 있지 않다.BlinkC.Timer0 -> Timer0;BlinkC.Timer1 -> Timer1;BlinkC.Timer2 -> Timer2;그러나 BlinkC는 Timer의 세 개의 인스턴스를 가지고 있다. 사용자 쪽의 이름을 제거SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 48
  • 49. UBee430TM Programming Guide하면 컴파일 에러가 난다. 컴파일러는 어느 타이머 인스턴스와 연결되는지 모르기 때문이다.BlinkC.Timer0 -> Timer0;를 BlinkC -> Timer0;로 바꾸면 컴파일 에러가 난다.연결 화살표의 방향은 사용자로부터 공급자로 향한다. 만약 공급자가 왼편에 있다면왼쪽으로 향하는 화살표를 사용해야 한다. 하지만 읽기에는 왼쪽에서 오른쪽으로 연결되는 것이 편하다.Timer0 <- BlinkC.Timer0; // Same as BlinkC.Timer0 -> Timer0;Visualizing a Component Graph모듈내부를 분석하거나 레이어(layer)들을 검색하는 것을(navigate) 텍스트 에디터로하는 것은 힘들다. 이런 처리를 위하여, TinyOS와 nesC는 nesdoc라는 문서화 기능을가지고 있다. 소스코드로부터 문서를 자동적으로 생성한다.nesdoc는 configuration의구조와 합성(composition)을 출력한다.어플리케이션을 위한문서를 생성하기 위해서는 다음과 같이 입력 하면 된다. $ make platform docs인터페이스와 컴포넌트에 대한 긴 리스트들을 보게 될 것이다 . 만약 아래와 같은 에러가 난다면 컴포넌트 그래프를 그려주는 프로그램인 graphviz 설치를 해야 한다.[UBee430의 경우 다음과 실행 ]문서가 생성되면 tinyos-2.x/doc/nesdoc로 이동하자[UBee430의 경우 다음 경로로 이동 ]₩tinyos₩cygwin₩opt₩tinyos-2.x₩doc₩nesdocSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 49
  • 50. UBee430TM Programming Guidemake시 옵션으로 준 플랫폼을 볼 수 있을 것이다. index.html을 웹브라우저로 열게되면 생성된 문서의 컴포넌트와 인터페이스의 리스트를 볼 수 있다.예를 들어 telosb플랫폼으로 Blink에 대한 문서를 생성하면, 문서에서Boot, Leds,Timer같은 인터페이스에 대한 문서와 하드웨어 구현에 대한 Msp430TimerEvent andHplMsp430GeneralIO를 볼수 있다.왼쪽에 있는 네비게이션 패널을 보면, 컴포넌트들이 인터페이스들 아래에 있다.BlinkAppC를 클릭하면 아래와 같은 그림을 보게 된다.[UBee430의 경우 다음 경로로 이동 ]₩tinyos₩cygwin₩opt₩tinyos-2.x₩doc₩nesdoc₩UBee430폴더로 이동한 후 index.html 파일을 더블 클릭 한다.nesdoc 다이어그램에서, 단일선 상자는 Module이고 이중선 박스는 Configuration을의미한다. 점선으로 외곽선이 그려진 상자들은 generic 컴포넌트를 의미 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 50
  • 51. UBee430TM Programming Guide Singleton Generic Module Configuratio n선은 연결을 나타낸다. 음영된 타원은 사용되거나 제공된 컴포넌트의 인터페이스를 나타낸다. 그래프에 있는 컴포넌트를 클릭하면 해당 컴포넌트 내부에 대한 자세한 설명을 볼 수 있다. MainC를 클릭하면, 부트 시컨스에 대한 연결에 대해 보여준다.음영된 타원은 연결 가능한 인터페이스를 나타내며 두개의 음영된 타원이 존재 한다.왜냐 하면 MainC는 Boot 인터페이스를 제공하고 init 인터페이스(asSoftwareInit)를사용한다.화살표의 방향에 주의해야 한다. SoftwareInit를 사용하기 때문에 RealMainP로 부터SoftwareInit로 연결이 되어 있다. Boot를 제공하기 때문에 Boot로 부터 RealmainP로연결이 되어 있다.MainC에 대해 자세히 다루는 것은 여기서 중요하지 않다. 3장에서 보다 깊이 살펴 볼것이다. 또한 TEP 107도 읽어보기 바란다.컴포넌트를 살펴봄으로써 컴포넌트가 무엇인지 알 수 있다. : 스케줄러를 제어하고,하드웨어 플랫폼을 초기화 하며, 소프트웨어 컴포넌트를 초기화한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 51
  • 52. UBee430TM Programming Guide결론이 lesson에서는 TinyOS 컴포넌트 모델에 대한 개념을 소개했다.configurations, modules, interfaces and wiring.컴포넌트들이 어떻게 연결되어 어플리케이션이 만들어 지는지 살펴보았다. 다음 장에서도 Blink을 좀 더 자세히 계속 볼 것이다. (TinyOS 병행 모델과 실행 가능한 코드)Related Documentationmica mote Getting Started Guide at Crossbowtelos mote Getting Started Guide for Moteivnesc at sourceforgenesC reference manualTinyOS Programming GuideTEP 3: TinyOS Coding ConventionsTEP 102: TimersTEP 106: Schedulers and TasksTEP 106: TinyOS 2.x Boot Sequence(1) TimerMilliC 컴포넌트는 일반적인 컴포넌트로, 한번이상 인스턴스를 생성 할 수 있다.일반적인 컴포넌트는 인자로 타입과 상수를 가질 수 있다. TimerMilliC의 경우는 아무 인자도 없다. 일반적인 인터페이스 중 인자를 하나 가진 경우도 있다. 타이머 인터페이스는 TimerMilliC라는 일반적인 인터페이스에 의해 제공 되어 진다. 타입 인자는타이머가 필요로 하는 정밀도(precision)로 정의되어 있다.(this prevents programmer from wiring, e.g., microsecond timer users tomillisecond timer providers).일반적인 컴포넌트에 대한 설명은 이 문서의 범위를 넘어서는 것이다. nesc 일반적컴포넌트 문서를 읽어보길 바란다.(2) Programming Hint 10: as 키워드를 아낌없이 사용하라. From TinyOSProgrammingSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 52
  • 53. UBee430TM Programming Guide2. Lesson 2: Modules and the TinyOS Execution ModelLast updated June 27 2006nesC 모듈, 명령어, 이벤트 ,태스크에 대한 소개이다. TinyOS 실행 모델에 대한 설명을 하고 있다.Modules and StateTinyOS 애플리케이션을 컴파일하면 단일 바이너리 이미지(펌웨어)가 만들어 진다. 바이너리 이미지 안에는 하드웨어를 제어할 수 있는 모든 것이 포함된 상태이다. 따라서mote는 동시에 TinyOS 이미지를 하나만 실행시킬 수 있다.이미지는 애플리케이션에서 필요로 하는 컴포넌트들로 구성된다.대부분의 platform에는 하드웨어기반의 메모리 보호가 없다. 따라서 사용자 주소공간과 시스템 주소공간의 구분이 없다. 모든 컴포넌트들이 공유하는 하나의 주소공간이있을 뿐이다. 이런 이유로 대다수의 TinyOS 컴포넌트들은 private 상태를 유지하고 포인터 전달을 피한다. 하드웨어 보호가 없을 때, 메모리 손상이 일어나지 않는 가장 좋은 방법은 가능한 공유를 적게 하는 것이기 때문이다.Recall from lesson 1 that the set of interfaces a component uses and providesdefine its signature.설정 컴포넌트와 모듈 컴포넌트는 인터페이스를 제공하거나 사용한다. 이 둘 간의차이점은 구현에 있다. 설정은 다른 컴포넌트들이 어떻게 서로 연결되는지에 대한구현이다. 모듈은 실행 가능한 코드이다.After unwrapping all of the layers of abstraction that configurations introduce,modules always lie within.모듈 구현은 nesC 추상화의 설계를 제외하고 대부분은 C로 작성되었다.모듈은 상태 변수를 선언할 수 있다. ( state variable ). 어떤 상태의 컴포넌트이든private으로 선언된다. : 어떤 컴포넌트도 직접 접근을 할 수 없다. 두 컴포넌트 간에상호작용할 수 있는 유일한 방법은 인터페이스를 통하는 것이다.Blink 어플리케이션을 다시보자. Blink 모듈인 BlinkC의구현의 완전한 형태는 다음과같다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 53
  • 54. UBee430TM Programming Guideapps/Blink/BlinkC.nc:module BlinkC { uses interface Timer<TMilli> as Timer0; uses interface Timer<TMilli> as Timer1; uses interface Timer<TMilli> as Timer2; uses interface Leds; uses interface Boot;}implementation{ event void Boot.booted() { call Timer0.startPeriodic( 250 ); call Timer1.startPeriodic( 500 ); call Timer2.startPeriodic( 1000 ); } event void Timer0.fired() { call Leds.led0Toggle(); } event void Timer1.fired() { call Leds.led1Toggle(); } event void Timer2.fired() { call Leds.led2Toggle(); }}BlinkC 예제에서는 현재 상태 값을 얻을 수 없다. 로직을 약간 바꾸어보자.세 개의 LED가 서로 다른 타이머를 가지고 점멸하는 대신에 하나의 타이머를 사용하여 점멸하도록 바꿀 것이다. 그리고 점멸되는 상태를 확인 할 수 있도록 해보자.Blink 어플리케이션을 BlinkSingle로 복사한다. 그리고 해당 디렉터리로 이동하자.$ cd /opt/tinyos-2.x/apps$ cp -R Blink BlinkSingle$ cd BlinkSingle/BlinkC 모듈파일(BlinkC.nc)을 에디터로 열자. Timer1과 Timer2에서 LED 토글을주석처리 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 54
  • 55. UBee430TM Programming Guideevent void Timer1.fired() { dbg("BlinkC", "Timer 1 fired @ %s ₩n", sim_time_string()); //call Leds.led1Toggle(); }event void Timer2.fired() { dbg("BlinkC", "Timer 2fired @ %s.₩n", sim_time_string()); //call Leds.led2Toggle();}다음 단계로 BlinkC에 상태를 나타내기 위한 한 바이트 변수를 추가한다. C언어처럼,변수와 함수는 반드시 사용되기 전에 선언되어야 한다. 그래서 implementation의 처음에서 선언을 했다.implementation{ uint8_t counter = 0; event void Boot.booted() { call Timer0.startPeriodic( 250 ); call Timer1.startPeriodic( 500 ); call Timer2.startPeriodic( 1000 ); }int, long, char같은 표준 C 이름을 사용하는 대신, TinyOS 코드에서는 보다 명시적인타입을 사용한다.해당 변수의 사이즈로 선언하였다. 실제로 이들은 기본 C타입에 있는 것들로 매핑 되어 있다. 다른 플랫폼에서는 다르게 매핑 될 것이다. TinyOS code를 작성 시 int 타입을 사용하는 것을 피해야 한다. mica나 telos계열의 mote는 int가 16비트인데 반해,intelmote2는 int가 32비트이기 때문이다.TinyOS 코드에서는 부호가 없는 값들을 많이사용한다. 음수에 수를 더함으로써 의도하지 않은 결과가 나올 수 있다.타입의 최대범위를 넘어가서 오버플로우가 일어나게 되는 것이다. 일반적인 타입은 다음과 같다. 8 bits 16 bits 32 bits 64 bits signed int8_t int16_t int32_t int64_t unsigned uint8_t uint16_t uint32_t uint64_t또한 bool 타입이 있다.표준 C언어의 타입을 그대로 쓴다면, 크로스 플래폼 문제가 발생할 것이다. 또한uint32_t는 unsigned long보다 작성하기 쉽다. 하드웨어보다는 소프트웨어로 계산이SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 55
  • 56. UBee430TM Programming Guide이루어짐에도 불구하고 대부분의 플랫폼에서는 실수( 부동점 소수점 : floating pointnumbers )를 지원한다.(float almost always, double sometimes)개조한 BlinkC를 다시보자. 부호 없는 한 바이트를 counter변수로 할당했다. mote가부트 될 때마다 , 카운터는 0으로 초기화 될 것이다.다음 단계는 Timer0이 시작되면, counter를 증가시키고 그 결과를 LED들로출력하도록 만드는 것이다.event void Timer0.fired() { counter++; if (counter & 0x1) { call Leds.led0On(); } else { call Leds.led0Off(); } if (counter & 0x2) { call Leds.led2On(); } else { call Leds.led2Off(); } if (counter & 0x4) { call Leds.led2On(); } else { call Leds.led2Off(); }}또 다른, 보다 간결한 방법은 set커맨드를 사용하는 것이다.event void Timer0.fired() { counter++; call Leds.set(counter);}컴파일 하고 mote에 설치한다. 이전과 똑같이 동작하는 것을 볼 수 있을 것이다. 단지 세 개의 타이머를 사용하던 것을 하나의 타이머로 바꾸었을 뿐이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 56
  • 57. UBee430TM Programming Guide하나의 타이머만 사용됨으로써 , Timer1과 Timer2가 필요 없게 되어 CPU 자원과 메모리 낭비를 줄이게 되었다. BlinkC를 다시 열어서signature and implementation로부터 Timer1과 Timer2를 제거한다.수정 후, 아래와 같이 될 것이다.module BlinkC { uses interface Timer<TMilli> as Timer0; uses interface Leds; users interface Boot;}implementation{ uint8_t counter = 0; event void Boot.booted() { call Timer0.startPeriodic( 250 ); } event void Timer0.fired() { counter++; call Leds.set(counter); }}어플리케이션을 다시 컴파일 해보자.nesC에서 에러가 발생했다고 할 것이다. 왜냐하면 BlinkAppC의 configuration이 지금사용하지 않는 BlinkC의 인터페이스(Timer1, Timer2)로 작성되었기 때문이다.BlinkAppC를 다시 열어서, 두개의 타이머와 그들의 연결부분들을 지운 후 , 다시어플리케이션을 컴파일 하자.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 57
  • 58. UBee430TM Programming Guide[ Blink 어플리케이션을 Timer 3개를 이용하여 컴파일 시]ROM와 RAM의 크기를 수정 전 Blink 어플리케이션과 비교해보면 좀 더 작아 진 것을볼 수 있을 것이다. TinyOS는 하나의 타이머만 사용하며, 하나의 타이머를 위한 상태를 나타 내기위해 한 바이트 변수만을 할당하였다.Interfaces, Commands, and Events다시 tinyos-2.x/apps/Blink를 보자. lesson 1에서 배웠었다.컴포넌트가 인터페이스를 사용하면, 인터페이스의 명령을 호출하게 된다. 그리고 이벤트에 대해 핸들러가 실행되어야 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 58
  • 59. UBee430TM Programming GuideTimer와 Leds 그리고 Boot 인터페이스를 사용한 컴포넌트들을 또한 보았다 . 이들 인터페이스에 대해 살펴보자.tos/interfaces/Boot.nc:interface Boot { event void booted();}tos/interfaces/Leds.nc:interface Leds {/** * Turn LED n on, off, or toggle its present state.*/ async command void led0On(); async command void led0Off(); async command void led0Toggle(); async command void led1On(); async command void led1Off(); async command void led1Toggle(); async command void led2On(); async command void led2Off(); async command void led2Toggle();/*** Get/Set the current LED settings as a bitmask. Each bit corresponds to* whether an LED is on; bit 0 is LED 0, bit 1 is LED 1, etc.*/ async command uint8_t get(); async command void set(uint8_t val);}tos/interfaces/Timer.nc:interface Timer{ // basic interface command void startPeriodic( uint32_t dt ); command void startOneShot( uint32_t dt ); command void stop(); event void fired(); // extended interface omitted (all commands)SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 59
  • 60. UBee430TM Programming Guide}Boot, Leds, Timer를 살펴보면서 우리는 BlinkC에서 이들 인터페이스를 사용하기 위해서는Boot.booted()이벤트와 Timer.fired()이벤트에 대한 핸들러를 BlinkC에서 제공해야 한다는 것을 알게 되었다.Leds interface signature는 어떤 이벤트도 포함하고 있지 않다.BlinkC의 Boot.booted()에대한 구현을 살펴보자.apps/Blink/BlinkC.nc:event void Boot.booted() { call Timer0.startPeriodic( 250 ); call Timer1.startPeriodic( 500 ); call Timer2.startPeriodic( 1000 );}BlinkC는 TimerMilliC 컴포넌트의 인스턴스 3개를 사용하기 위해 인터페이스 Timer0,Timer1, Timer2와 각각 연결하고 있다.Boot.booted() 이벤트 핸들러는 각 인스턴스에서 시작한다. startPeriodic()에 대한 매개변수는 타이머가 시작된 이후로 밀리세컨드의 주기(period)동안으로 명시한다.( 인터페이스에서 <TMilli>가 millseconds이기 때문이다. )startPeriodic()명령을 사용하여 타이머가 시작되기 때문에, 타이머가 시작된 이후 매n 밀리세컨드마다 fired() 이벤트가 일어나면, 타이머는 리셋 될 것이다.인터페이스 명령을 호출하기 위해서 call 키워드를 사용한다. 인터페이스 이벤트를 호출하기 위해서 signal키워드를 사용한다. BlinkC는 어떤 인터페이스도 제공하지 않는다. 그래서 이 코드는 어떤 시그널 statement도 없다. 이후 lesson에서 Boot.booted()이벤트 신호를 보낼 boot sequence를 살펴 볼 것이다.Timer.fired()의 구현을 살펴보자.apps/Blink/BlinkC.nc:event void Timer0.fired() { call Leds.led0Toggle();}event void Timer1.fired() { call Leds.led1Toggle();SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 60
  • 61. UBee430TM Programming Guide}event void Timer2.fired() { call Leds.led2Toggle();}타이머 인터페이스의 세 개 인스턴스를 사용했기 때문에, BlinkC는 Timer.fired()event의 3개 인스턴스를 제공해야 한다. 인스턴스 함수를 실행하거나 호출할 때,함수의 이름은 항상 interface.function 이다. Timer0, Timer1, Timer2로 이름이붙여진 BlinkC의 세 개의 타이머 인스턴스는 세 개의 함수Timer0.fired, Timer1.fired,and Timer2.fired를 실행한다.TinyOS 실행 모델 : Tasks살펴보았던 모든 코드는 동기적(synchronous)이다. 단일 실행 context 내에서 실행이되었다. 그리고 선점은 없다. 동기적 코드가 실행되기 시작하면, 다른 동기적 코드가끝날 때 까지 CPU를 양도하지 않는다.간단한 메커니즘을 사용하여, TinyOS 스케줄러가 램의 소비를 최소화하고 동기적 코드를 매우 간단하게 유지하도록 한다. 그러나 이로 인해, 오랜 시간동안 하나의 동기코드가 실행된다면, 다른 동기 코드들을 실행되지 못하게 된다. 따라서 시스템 응답성에 악영항을 끼친다. 예를 들어, 오랜 시간 동안 실행되는 코드로 인해 mote가 패킷에 응답하는데 걸리는 시간을 증가 시킨다지금까지 모든 예제들에서 직접 함수 호출을 하는 것을 보았었다. 부트 sequence나타이머처럼, 시스템 컴포넌트가 이벤트 신호를 컴포넌트에게 보내면, 특정 동작을 한후(아마도 명령을 호출), 리턴하게 된다.대부분의 경우, 이런 프로그래밍 접근은 잘 동작한다. 왜냐하면 동기적 코드가 비선점이기 때문이다. 그러나 이런 접근은 커다란 computations에서는 동작하지 않는다. 컴포넌트는 커다란 computations을 한 번에 하나 실행되는 작은 부분으로 나눌 필요가있다. 또한 컴포넌트가 어떤 것을 하는 것을 필요로 하는 시점보다, 조금 늦게 실행되더라도 괜찮다.TinyOS는 먼저 기다리고 있던 모든 다른 것들을 처리할 때 까지 computation을 미룰수 있다. Giving TinyOS the ability to defer the computation until later can let itdeal with everything else thats waiting first.Tasks는 어플리케이션에서 컴포넌트가 범용의 백그라운드 처리를 수행하는 것을 가능하도록 한다. 태스크는 컴포넌트가 TinyOS에게 나중에 실행하기 위해 알려주는 함수SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 61
  • 62. UBee430TM Programming Guide이다. 고전 운영체제에서 가장 유사한 것이 interrupt bottom halves and deferredprocedure calls이다.Blink 어플리케이션의 복사본을 만들어 BlinkTask라고 이름을 변경하자.$ cd tinyos-2.x/apps$ cp -R Blink BlinkTask$ cd BlinkTaskBlinkC.nc을 열어보면 현재 Timer0.fired()에 대한 이벤트 핸들러는 다음과 같다.event void Timer0.fired() { dbg("BlinkC", "Timer 0 fired @ %s₩n", sim_time_string()); call Leds.led0Toggle();}얼마나 오래 실행되는지 충분히 알 수 있을 정도로 약간 수정을 해보자 mote관점에서보면, 24 Hz 또는 40 ms가 매우 느린 시간이라는 것을 알 수 있다.micaZ와 Telos는 그 시간에 약 20 패킷을 전송 할 수 있다. 그래서 이번 예제는 정말로 과장된 것이라는 것을 알 수 있다. 육안으로 이것을 관찰하기에는 충분하다. 이벤트 핸들러를 다음처럼 수정하자.event void Timer0.fired() { uint32_t i; dbg("BlinkC", "Timer 0 fired @ %s₩n", sim_time_string()); for (i = 0; i < 400001; i++) { call Leds.led0Toggle(); }}이 코드는 타이머가 한번이 아닌 400,001번 토글을 일으키게 할 것이다.This will cause the timer to toggle 400,001 times, ratherthan once. Because the number is odd, it will have the endresult of a single toggle, with a bit of flickering in-between.컴파일하고 프로그램을 인스톨하자. Led1과 Led2의 토글보다 Led1에서 많은 대기 시간이 있다는 것을 알 수 있을 것이다. 그래서 하나만 켜져 있는 상황을 보기 힘들 것이다. TelosB mote 에서는, 오랫동안 실행중인 태스크가 Tmer stack에서 이벤트를수행하지 않고 넘어가도록 할 수 있다. (try setting the count to 200,001 or100,001).SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 62
  • 63. UBee430TM Programming Guidecomputation이 타이머의 동작을 방해하는 것이 문제이다. TinyOS에게 computation을나중에 실행하라고 말하고 싶을 것이다. task를 사용하면 이렇게 할 수 있다.다음 syntax를 사용하여 task는 implementation 모듈에 선언된다.task void taskname() { ... }taskname ()는 task로 지정하려는 심볼릭 이름을 사용하면 된다. Task는 void를 리턴하고 어떤 인자도 가질 수 없다. (나중에) 실행하기 위해서 태스크를 dispatch하기 위해서 다음 syntax를 사용하면 된다.post taskname();command, event, task에서 컴포넌트는 task를 post할 수 있다. call graph의 루트에있기 때문에, 태스크는 안정하게 command를 호출하거나 이벤트 신호를 보낼 수 있다. 나중에 보겠지만 관습적으로 commands는 컴포넌트 관계를 가로지르는 순환 루프 만드는 것을 피하기 위해 이벤트 신호를 보내지 않는다. ( 예를 들어 컴포넌트 1에있는 command X가 컴포넌트 2에 있는 이벤트 Y에게 신호를 보냈다. 그런데 이벤트Y는 다시 컴포넌트 1에 있는 command X를 호출한다. )어플리케이션이 연결되는 방법에 따라 달라지기 때문에, 이런 루프는 프로그래머가 발견하기 힘들고 많은 스택을 사용하게 된다.태스크에서 loop를 수행하도록 BlinkC를 수정하자.task void computeTask() { uint32_t i; for (i = 0; i < 400001; i++) {}}event void Timer0.fired() { call Leds.led0Toggle(); post computeTask();}Telos 플랫폼에서는 아직 많은 노력이 필요하지만(struggle), mica 플랫폼에서는 동작이 잘될 것이다.post 연산은 태스크를 내부 태스크 큐에 넣는다. 태스크 큐는 작업을 FIFO 방식으로처리한다.태스크가 실행되면, 다음 태스크가 실행되기 전에 완료되어야 한다. 그러므로 위 예제에서처럼, 태스크가 오랜 시간동안 실행되어서는 안 된다. 태스크는 서로 선점을 할SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 63
  • 64. UBee430TM Programming Guide수 없다. 단, 하드웨어 인터럽트에 의해 선점이 될 수는 있다. (which we haventseen yet).길게 이어진 연산들을 실행시키기 원한다면 하나의 큰 태스크를 사용하기보다는 각 연산을 위한 태스크를 개별적으로 dispatch해야 한다. post연산은SUCCESS 또는 FAIL 값을 가지는 error_t를 반환한다. 태스크가 이미 실행되기 위해대기 중일 경우에만 post가 실패하게 된다. ( post가 성공적으로 되었으나 아직 호출되지 않고 대기 중인 상태이다. ) (1)예를 들어 아래를 보면uint32_t i;task void computeTask() { uint32_t start = i; for (;i < start + 10000 && i < 400001; i++) {} if (i >= 400000) { i = 0 } else { post computeTask(); }}위 코드는 계산하는 태스크를 여러 개의 작은 태스크로 나누었다. 각 계산 태스크의호출은 루프가 10,000번 반복되면서 실행된다. 400,001번 반복을 끝내지 못했다면,자기 자신을 다시 호출을 한다. 이 코드를 컴파일하고 mote에 설치해보자. Telos나mica family mote 모두 문제없이 동작 할 것이다.이런 방법으로 태스크를 사용 하면,또 컴포넌트에서 또 다른 변수 i를 필요로 한다. 왜냐하면 computeTask()는 10,000번 반복 후 리턴을 하는데, 다음 호출을 위해 이 값을 저장할 변수가 필요하기 때문이다. 이 경우, i는 C언어에서처럼 static 변수로 역할을 한다. 그러나 nesC 컴포넌트 상태는 완전히 private이기 때문에, static 키워드를사용하는 것은 naming scope를 제한하는데 도움이 되지 못한다.This code, for example, is equivalent:task void computeTask() { static uint32_t i; uint32_t start = i; for (;i < start + 10000 && i < 400001; i++) {} if (i >= 400000) { i = 0 } else { post computeTask(); }}SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 64
  • 65. UBee430TM Programming GuideInternal FunctionsCommands와 events는 컴포넌트에 있는 함수가 다른 컴포넌트에 의해 호출되어 질수 있는 유일한 방법이다. 컴포넌트 내부에서만 사용할 수 있는 private함수를 원하는경우가 있다. 컴포넌트는 표준 C함수로 정의할 수 있다. 다른 컴포넌트는 이름을 알수 없기 때문에 직접 호출을 할 수 없다.이런 내부 함수들은 command나 event 수정자를 가질 수 없기 때문에, 자유롭게command를 호출하거나 이벤트 신호를 보낼 수 있다.아래는 내부 함수에 대한 아주 적절한 nesC 코드이다.module BlinkC { uses interface Timer<TMilli> as Timer0; uses interface Timer<TMilli> as Timer1; uses interface Timer<TMilli> as Timer2; uses interface Leds; uses interface Boot;}implementation{ void startTimers() { call Timer0.startPeriodic( 250 ); call Timer1.startPeriodic( 500 ); call Timer2.startPeriodic( 1000 ); } event void Boot.booted() { startTimers(); } event void Timer0.fired() { call Leds.led0Toggle(); } event void Timer1.fired() { call Leds.led1Toggle(); } event void Timer2.fired() { call Leds.led2Toggle(); }}C언어처럼 내부 함수가 동작한다. call이나 signal키워드가 필요치 않다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 65
  • 66. UBee430TM Programming GuideSplit-Phase Operations컴파일 시간에 nesC 인터페이스가 연결되지 않기 때문에, TinyOS에서 callbacks(events)는 매우 효율적이다. 대부분의 C 유사 언어처럼, callbacks는 실행시간에 함수포인터로 등록된다.이것은 컴파일러가 코드를 최적화하는 것을 못하게 한다.This can prevent the compiler from being able to optimize code across callbackcall paths.nesC 에서는 정적으로 연결되기 때문에, 컴파일러는 어디서 호출되는 함수인지와 최적화 될 수 있는지를 정확히 알고 있다. 컴포넌트 경계를 넘어서 최적화 되는 것은TinyOS에서 매우 중요하다. 왜냐하면 블로킹 연산이 존재하지 않기 때문이다. 대신에모든 오래 실행되는 연산은 split-phase 방식을 사용한다.블로킹 시스템에서, 프로그램이 오래 실행되는 연산을 호출하게 되면, 연산이 완료될때까지 리턴 되지 않는다. 즉, 프로그램이 블록 된다.split-phase system에서는 프로그램이 오래 실행되는 연산을 호출하면, 즉시 리턴 된다.and the called abstraction issues a callback when it completes.이런 접근을 split-phase라고 부른다. 왜냐하면 실행의 개별적인 2단계를 호출과 완료로 나누었기 때문이다.블로킹과 split-phase의 차이를 알 수 있는 예를 보도록 하자 .if (send() == SUCCESS) {sendCount++;} Blocking// start phasesend();//completion phasevoid sendDone(error_t err) { if (err == SUCCESS) { sendCount++; } Split-Phase}SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 66
  • 67. UBee430TM Programming GuideSplit-phase 코드는 순차코드보다 장황하고 복잡하다. 그러나 여러 장점들이 있다.첫째로, split-phase호출은 실행되는 동안, 스택메모리를 많이 사용하지 않는다.(tieup)둘째로, 시스템 응답성을 유지 시킨다. 어플리케이션이 실행하는 것이 필요할 때, 블록 된 호출로 인해 쓰레드들의 모두가 묶여있는 상황이 생기지 않는다.셋째로, 스택에 커다란 변수가 생성하는 것이 거의 필요 없게 함으로써 스택의 이용을줄여주는 경향이 있다.Split-phase 인터페이스는 TinyOS 컴포넌트가 쉽게 여러 연산들을 동시에 시작 할 수있도록 해준다. 그리고 그들이 병렬적으로 실행될 수 있게 해준다. 또한 split-phase연산은 메모리를 절약시켜준다.왜냐하면 프로그램이 블로킹 연산을 호출할 때, 모든 상태들이call stack에 저장되기때문이다. 예를 들어 함수에서 선언된 지역변수 같은 것.스택의 정확한 크기를 결정하는 것은 힘들다. 운영체제는 매우 신중하게(conservative)선택을 하기 때문에 사이즈가 크다.물론 호출을 넘어 여전히 유지되는 데이터가 있다. split phase연산에서도 필요하기때문이다.Of course, if there is data that has to be kept across the call, split-phaseoperations still need to save it.Timer.startOneShot command는 split-phase 호출의 한 예이다. 타이머 인터페이스의사용자는 command를 호출한다. 그리고 즉시 리턴 된다(인자로 주어진 값만큼 대기하다가 ) 얼마 후, 타이머를 제공했던 컴포넌트는 Timer.fired에게 신호를 보낸다.블로킹 호출이 있는 시스템에서는 프로그램은 sleep()함수를 사용할 것이다.The user of the Timer interface calls the command, which returns immediately.Some time later (specified by the argument), the component providing Timersignals Timer.fired.state = WAITING;op1();sleep(500);op2(); Blockingstate = RUNNINGSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 67
  • 68. UBee430TM Programming Guidestate = WAITING;op1();call Timer.startOneShot(500);event void Timer.fired() { op2(); state = RUNNING;} Split-phase다음 레슨에서는, 가장 기본적인 split-phase연산 중 하나(sending packets)를 살펴볼 것이다.Related Documentation ● TEP 102: Timers ● TEP 106: Schedulers and Tasks(1) 태스크의 의미가 tinyos-2.x로 넘어가면서 변했다. tinyos 1.x에서는 태스크는 하나 이상으로 부터 포스트 될 수 있고, 태스크 큐가 꽉 차게 되면 post는 실패하게 된다. tinyos2.x에서는 태스크가 실행하기 위해 태스크 큐에서 대기 중일 때 에만 실패하게 된다. So a task can always run, but can only have one outstanding post atany time. If a component needs to post task several times, then the end of thetask logic can repost itself as need be.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 68
  • 69. UBee430TM Programming Guide3. Lesson 3: Mote-mote radio communicationLast Modified: June 27 2006TinyOS상에서 무선 통신을 지원해주는 인터페이스와 컴포넌트 대해 소개한다.Introduction무선상으로 메세지를 주고받는 방법에 대해 설명한다.TinyOS 2.x에서는 메세지 버퍼로 nesC로 구현된 message_t 구조체를 사용한다. 모든 인터페이스와 컴포넌트는 공통 메세지 버퍼 추상화로 message_t 구조체를 사용한다.TinyOS 1.x에서 사용되었던 TOS_Msg를 대체하며, 기존과 달리 message_t의 멤버가비공개로 되어 직접 접근을 할 수 없다. 다른 함수를 사용해야 message_t 구조체의멤버에 접근하여 읽고 쓰는 것이 가능하다.Basic Communications InterfacesTinyOS는 밑에 있는 통신 서비스를 추상화하여 다수의 인터페이스와 인터페이스를 제공하기 위한 다수의 컴포넌트를 제공한다. 이런 인터페이스와 컴포넌트는 message_t구조체를 사용한다.관련 인터페이스들은 tos/interfaces 디렉터리에 있다. 그 중 몇 가지 인터페이스를 살펴보도록 하자 .Packet - message_t 구조체에 접근할 수 있는 접근자를 제공한다. 메세지의 내용을지울 수 있고 페이로드 길이를 얻거나 페이로드 지역으로의 포인터를 가져올 수 있는명령어를 제공한다.Send - 주소가 자유로운(address-free) 메 세지를 전송하는 인터페이스를 제공한다.이 인터페이스는 메세지를 전송하거나 전송을 위해 대기 중인 메세지를 최소화하는명령을 제공한다. 메세지의 전송 성공여부를 확인 할 수 있는 인터페이스도 제공하고있다. 메세지의 최대 페이로드를 얻어 오는 함수와 메세지의 페이로드 영역으로의 포인터를 얻어오는 함수를 제공한다.Receive - 기본적인 메세지 수신 인터페이스를 제공한다. 이 인터페이스는 메시지를수신했을 경우의 이벤트를 제공한다. 메세지의 페이로드 길이를 얼어오거나 메세지의페이로드 영역을 가리키는 포인터를 얻어오는 명령을 제공한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 69
  • 70. UBee430TM Programming GuidePacketAcknowledgementes - 패킷기반으로 요청을 승인하는 메커니즘을 제공한다. (Provides a mechanism for requesting acknowledgements on a per-packet basis.)RadioTimeStamping - 무선 송수신을 위한 time stamping 정보를 제공한다.Active Message Interfaces같은 무선대역을 통해 통신을 할 때 다양한 서비스를 제공하기 위해서, TinyOS는 무선을 통해 다수의 접근이 가능하도록 Active Message( AM ) 레이어(layer)를 제공하고 있다.AM type이라는 용어는 멀티플레싱을 위해 사용되는 필드를 의미한다.AMtype은 통신 서비스를 위해 다중 접근이 가능하도록 사용되어 지는 Ethernet frametype field, IP protocol field, and the UDP port와 비슷한 기능을 한다. AM 패킷은또한 특정 mote에게 패킷을 보내기 위한 AM주소를 저장하는 수신 필드를 포함하고있다. 추가적인 인터페이스들은 AM서비스를 지원하기 위한 것이다.AMPacket - Packet 인터페이스와 유사하다.message_t 추상 데이터 타입을 위한 AM접근자를 제공한다. 이 인터페이스는 노드의 AM 주소를 얻어오거나 AM 패킷의 수신주소, AM 패킷의 타입들을 얻을 수 있는 명령을 제공한다. AM 패킷의 수신 주소와타입을 세팅하거나 수신지가 노컬 노드인지 체크를 할 수 있는 명령도 제공한다.AMSend - Send 인터페이스와 유사하다. Active Message를 전송하기 위한 인터페이스를 제공한다. AMSend는 Send의 차이점은 수신지의 주소를 가지고 있는지 여부이다.노드의 AM 주소는 인스톨을 할 때 다음 명령에 의해 설정된다. make install.n 또는reinstall.n실행중에는 ActiveMessageAddressC 컴포넌트를 사용하면 변경할 수 있다.Componentsactive message 인터페이스와 기본적인 통신을 위해 다수의 컴포넌트들이 구현되었다.관련 인터페이스는 /tos/system 디렉터리에 위치하고 있다.You should be familiar with these components because your code needs tospecify both the interfaces your application uses as well as the componentswhich provide (implement) those interfaces:SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 70
  • 71. UBee430TM Programming GuideAMReceiverC - 다음 인터페이스를 제공한다. :Receive, Packet, and AMPacket.AMSenderC -Provides AMSend, Packet, AMPacket, and PacketAcknowledgementsas Acks.AMSnooperC - Provides Receive, Packet, and AMPacket.AMSnoopingReceiverC - Provides Receive, Packet, and AMPacket.ActiveMessageAddressC - 노드의 액티브 메세지 주소를 설정하거나 얻기 위한 명령을 제공한다. 이 모듈을 사용하여 노드의 액티브 메세지 주소를 바꾸면 네트워크 스택이 깨질 수 있으므로 함부로 사용하지 않는 것이 좋다.Naming WrappersTinyOS는 다수의 플랫폼을 지원한다. 각각의 플랫폼은 해당 플랫폼에 맞게 구현된 무선 드라이버를 가지고 있다.ActiveMessageC라고 불리는 naming wrapper는 플래폼에맞게 구현된 인터페이스와 연결하기 위해 사용되어 진다.ActiveMessageC는 위에서 언급한 대부분의 통신 인터페이스를 제공한다.ActiveMessageC의 플폼에 의존적인 버전도 밑에 구현된 것들처럼 여러 플랫폼에서공유한다. ● ActiveMessageC for the eyesIFX platform is implemented by Tda5250ActiveMessageC. ● intelmote2, micaz, telosa, and telosb 플랫폼을 위한 ActiveMessageC는 CC2420ActiveMessageC에 구현되어 있다. ● ActiveMessageC for the mica2 platform is implemented by CC1000ActiveMessageC.The TinyOS 2.0 Message BufferTinyOS 1.x에서 사용되었던 TOS_Msg 구조체는 새로운 message_t 구조체로 대체되었으며 tos/types/message.h에 정의 되어 있다.typedef nx_struct message_t { nx_uint8_t header[sizeof(message_header_t)]; nx_uint8_t data[TOSH_DATA_LENGTH]; nx_uint8_t footer[sizeof(message_header_t)]; nx_uint8_t metadata[sizeof(message_metadata_t)];} message_t;Note: header, footer, and metadata 필드는 비공개되어서 직접 접근이 불가능하다.Packet, AMPacket 같은 몇몇 인터페이스를 통해서만 message_t 구조체에 접근이 가SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 71
  • 72. UBee430TM Programming Guide능하다. 이런 접근을 하게 된 이유는 2개의 링크 레이어간에 메세지를 전달하는 것을피하기 위해 고정된 오프셋을 유지하는 데이터(페이로드)를 허용하기 위해서이다.See Section 3 in TEP 111 for more details.Sending a Message over the Radio카운터를 증가시키고 세 개의 LED를 사용하여 카운터의 three least significant bits를 출력하는 간단한 애플리케이션을 만들 것이다. 그리고 카운터 값을 가진 메세지는무선을 통해 전송된다. lesson2에 있는 BlinkSingle 예제처럼 하나의 타이머와 카운터를 사용하여 구현 해볼 것이다.Reimplementing Blink먼저 Blink예제를 하나의 타이머와 카운터를 사용하도록 다시 구현을 한다.BlinkToRadio라는 이름으로 app디렉터리에 새로운 디렉터리를 만들자.$ cd tinyos-2.x/apps$ mkdir BlinkToRadio새로 만든 디렉터리로 이동하여, BlinkToRadioC.nc파일을 아래처럼 작성한다.#include <Timer.h>#include "BlinkToRadio.h"module BlinkToRadioC { uses interface Boot; uses interface Leds; uses interface Timer<TMilli> as Timer0;}implementation { uint16_t counter = 0; event void Boot.booted() { call Timer0.startPeriodic(TIMER_PERIOD_MILLI); } event void Timer0.fired() { counter++; call Leds.set(counter); }}프로그램에서 몇몇 중요한 라인을 살펴보자.첫 줄에 C 프리프로세서 include 지시자는 현재 위치가 Timer.h의 내용으로 교체된다는 것을 컴파일러에게 알려준다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 72
  • 73. UBee430TM Programming Guide컴파일러는 TinyOS 시스템 디렉터리인 tos와 그 서브 디렉터리에서 Timer.h 파일을찾는다.다른 곳에서 컴파일러가 헤더파일을 찾기를 원한다면 MakeFile에서 -I플래그 뒤에 디렉터리를 지정해서 추가 해주면 된다.두 번째 줄에 있는 include 지시자에서 헤더파일 주위에 angle brackets대신 quotes를 사용 한 것을 볼 수 있다. quotes는 프리프로세서에게 시스템에 설정되어 있는include 디렉터리를 찾기 전에 먼저 현재 디렉터리에서 헤더파일을 찾으라고 알려준다. 프로그램에서 사용하는 몇몇 상수를 정의하고 있는 BlinkToRadio.h 파일은 같은디렉터리에 존재한다.Leds.set함수를 호출하여 카운터 변수의 세 개의 하위비트로 세 개의 LED를 직접 설정하고 있다.Boot.booted 함수에서 Timer0.startPeriodic(TIMER_PERIOD_MILLI)를 호출하는 줄에서 TIMER_PERIOD_MILLI의 값은 BlinkToRadio.h 헤더파일에 아래처럼 정의 되어 있다.#ifndef BLINKTORADIO_H#define BLINKTORADIO_Henum { TIMER_PERIOD_MILLI = 250};#endififndef, define, endif 지시문은 각 헤더파일이 여러 번 포함되지 않도록 하기 위해서사용된다. 컴파일러가 여러 번 정의된 오브젝트로 인해 혼란스러워 하지 않게 하기 위해서이다. 관습적으로 지시문에선 마침표를 언더바로 변환한 대문자 파일이름을 사용한다.TIMER_PERIOD_MILLI 상수를 정의하기 위해서 enum을 사용한다. 상수 정의를 위해define보다는 enum을 정의하는 것이 좋다. enum은 정의된 literal이 나올 때 마다 바꾸지 않기 때문이다?스코프에 차이가 있다.#define 문은 전처리기에 의해서 컴파일러에게 소스가 넘겨지기 전에 전부 "치환" 되므로 #define은 언어하고는 별개입니다. 즉 스코프는 전처리기의 스코프에 의존하게 되어#undef 하기 전까지 유효합니다.그리고 가능하면 enum을 사용하시라고 권장하고 싶은데.. 이유는 enum은 언어적으로지원하는 키워드입니다. 따라서 디버깅 심볼이 생성이 되며 이를 디버깅에 이용할 수SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 73
  • 74. UBee430TM Programming Guide있습니다. 그런데 #define은 단순한 "치환"이므로 디버깅 심볼이 생성되지 않아 디버거로 원래의 심볼명을 복원할 수 없습니다.BlinkToRadioC.nc파일은 프로그램의 구현 로직을 정의한다.BlinkToRadio.h 파일은 상수와 데이터 구조를 정의한다.BlinkToRadioAppC.nc파일은 인터페이스들을 서로 연결한다.A third file is needed to wire the interfaces that the implementation uses to theactual components which provide these interfaces. The BlinkToRadioAppC.ncprovides the needed wiring:#include <Timer.h>#include "BlinkToRadio.h"configuration BlinkToRadioAppC {}implementation { components MainC; components LedsC; components BlinkToRadioC as App; components new TimerMilliC() as Timer0; App.Boot -> MainC; App.Leds -> LedsC; App.Timer0 -> Timer0;}세 개의 파일이 어플리케이션 코드를 구성한다.추가로 빌드 및 컴파일을 위한 Makefile이 필요하다. 간단한 하게 작성된다.COMPONENT=BlinkToRadioAppCinclude $(MAKERULES)첫 라인은 TinyOS make system에게 top-level 어플리케이션 컴포넌트가BlinkToRadioAppC라는 것을 알려준다. 두 번째 라인에서는 TinyOS 빌드 시스템으로모든 플래폼에 관한 빌드와 설치와 관련된 룰이 저장되어 있는 파일을 로드 한다.Defining a Message Structure이제 Blink는 하나의 타이머와 카운터를 사용하도록 다시 구현되었다. 이제 무선으로데이터를 전송하기 위해 사용되어지는 메세지 버퍼 포맷을 정의하는 것을 살펴보자.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 74
  • 75. UBee430TM Programming Guide메세지는 node id와 카운터 값을 무선으로 보낼 것이다.node id와 카운터 값을 포함하는 구조체를 만든 후, message payload area로 데이터를 복사하기 위해 structureassignment를 이용한다.메세지가 다양한 필드 또는 다중바이트 필드(=uint16_t, uint32_t)로 구성되어 있다면,구조체를 사용함으로써 메세지 페이로드를 기록하거나 읽어오는 것이 보다 편리해진다.왜냐하면 indices and then shifting and adding사용하여 페이로드로 부터 읽거나 페이로드로 쓰는 것을 피할 수 있기 때문이다. (e.g. uint16_t x = data[0] << 8 +data[1])메시지가 하나의 필드만 가지더라도, 구조체를 사용해서 가져올 것이다. 왜냐하면 바이트 단위로 페이로드를 읽거나 기록하게 되면 메세지에 필드를 추가 하거나 필드의일부를 이동시킬 때 페이로드의 위치 인덱스를 수동으로 일일이 고쳐야 하기 때문이다. 구조체를 사용하는 것이 더 수월하다.페이로드 상에서 uint16_t 노드 id와 uint16_t 카운터를 가지고 메세지 구조체를 정의하기 위해, BlinkToRadio.h 파일의 endif 지시문 앞에 다음 라인들을 추가한다.typedef nx_struct BlinkToRadioMsg { nx_uint16_t nodeid; nx_uint16_t counter;} BlinkToRadioMsg;C언어 구조체와 동일한 구조를 가지고 있다. nx_ prefix는 nesC 언어라는 것을 한정지어 주고, struct와 uint16_t이 external types라는 것을 의미한다. (3)(4).external types는 모든 플랫폼에 동일한 표현(representation)을 가지고 있다. nesC 컴파일러는 코드를 생성한다.External types have the same representation on all platforms. The nesC compilergenerates code that transparently reorders access to nx_ data types andeliminates the need to manually address endianness and alignment (extrapadding in structs present on some platforms) issues. So what is endianness?Read on...서로 다른 프로세서는 숫자를 표현할 때 다른 방법으로 나타낸다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 75
  • 76. UBee430TM Programming Guide일부 프로세서들은 16 또는 32비트에 저장된 숫자 표현 시 most significant bytes가낮은 메모리 주소에 위치하는 "빅 엔디안"표현을 사용한다. 반면 "리틀 엔디안"으로 반대 순서로 데이터를 저장 한다 .네트워크상으로 데이터를 연속적으로 전송할 때 문제가 발생한다. 왜냐하면 다른 프로세서는 자신이 가진 endianness에 따라 동일한 바이트집합을 다른 방법으로 디코드하기 때문이다.endianness 주요문제는 네트워크 프로토콜 규격이나 프로세서 아키텍처에 맞도록 바이트 순서를 재배치 하는 동작이 필요하다는 것이다. -- an annoying and error-prone process.소켓 API의 htons, htonl, ntohs, ntohl 함수들이 플랫폼 종속적인 함수의 한 예이다.네트워크 바이트 순서와 호스트 바이트 순서간의 변환에 사용된다.The htons, htonl, ntohs, and ntohlcalls used with the sockets API are anexample of platform-specific calls that convert between network and host byteorders, but you have to remember to use them.nesC 프로그래밍 언어에서는 이 문제에 대해 다르게 접근을 한다. 프로그래머가 바이트 재열을 다루는 것을 피하기 위해 external types를 정의하였다. 특별히, nx prefix가 데이터 타입에 붙어있다면, 필드가 빅엔디안 포맷으로 시리얼라이즈되어 있다는 것이다. 반면에 nxle_ prefix가 붙으면 필드가 리틀 엔디안 포맷으로 시리얼 라이즈 되어있다는 것이다.Sending a MessageBlinkToRadioMsg 어플리케이션을 위하여 메세지 타입을 정의하고 무선으로 어떻게메세지를 전송하는지 살펴보자.시작하기 전에, 어플리케이션의 목적을 다시보자.(1) 카운터의 증가,(2) LED로 카운터의 하위 3비트를 출력,(3) 노드의 id와 카운터 값을 무선 상으로 전송.이러한 결과로 타이머의 firing하는 시간에 종속적인(timer-driven) 시스템을 원한다.이 프로그램을 제공하기 위해서, 우리는 다음절에서 기술하고 있는 간단한 여러 단계를 거쳐야 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 76
  • 77. UBee430TM Programming Guide첫째로, 무선으로 접근을 제공하고, message_t 타입을 다루는 것이 허용되어 있는지인터페이스를 확인하는 것이 필요하다.둘째로 우리가 필요한 인터페이스를 위해 uses문장을 추가함으로써BlinkToRadioC.nc 파일에 있는 모듈 블럭을 업데이트해야 한다.셋째로, 새로운 변수를 선언하는 것이 필요하다 . 또한 인터페이스나 컴포넌트가 필요로 하는 initialization and start/stop code를 추가해주어야 한다.넷째로, 어플리케이션에서 필요로 하는 컴포넌트 인터페이스를 호출하는 부분을 추가해야한다 .다섯째로, 사용하기로 계획한 인터페이스에서 이벤트를 구현하는 것이 필요하다.여섯 번째로, 어플리케이션 설정 파일(BlinkToRadioApp.c)의 implementation 블록을사용하기 원하는 각 컴포넌트에 대하여 components 문장을 추가함으로써 업데이트한다.마지막으로, 어플리케이션에서 사용되는 인터페이스를 제공되는 인터페이스의 컴포넌트로 연결하는 것이 필요하다.단계별로 따라 가보자1. 무선으로 접근을 제공하고, message_t 타입을 다루는 것이 허용되어 있는지 인터페이스(와 컴포넌트)를 확인하는 것이 필요하다.message_t 데이터 타입에 접근하기 위해 Packet와 AMPacket 인터페이스를 사용하는것처럼, 패킷을 전송하기 위해서 AMSend 인터페이스를 사용한다. ActiveMessageC컴포넌트에 직접 연결하는 것이 가능하지만, 대신에 AMSenderC 컴포넌트를 사용할것이다. 그러나 ActiveMessageC.SplitControl 인터페이스를 사용하여 무선을 시작하는것이 필요하다. AMSenderC를 사용하는 이유는 virtualized abstraction를 제공하기 때문이다.TinyOS의 초기 버전에서는 무선으로의 가상화 접근이 가능하지 않았다. 그래서 두개의 컴포넌트가 서로의 것을 건드리기 위해 무선을 공유하는 것이 가능했다. 하나의 컴포넌트가 무선이 busy하다는 것을 아는 것이 흔치 않은 일이 아니다. 왜냐하면 첫 번째 컴포넌트가 알지 못하는 또 다른 컴포넌트가 active message layer를 접근하고 있기 때문이다.무선 가상화(virtualization)는 이 인터페이스를 address하기 위해서 TinyOS 2.0에서소개되었다. AMSenderC는 이 virtualization을 제공하기 위해서 작성되었다.AMSenderC의 사용자마다 1-deep queue를 제공한다. 그리고 모든 사용자의 큐는fair manner로 서비스 된다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 77
  • 78. UBee430TM Programming Guide2. 필요한 인터페이스를 위해 uses 문장을 추가하여 BlinkToRadioC.nc 내의 모듈 블럭을 업데이트 한다.module BlinkToRadioC {...uses interface Packet;uses interface AMPacket;uses interface AMSend;uses interface SplitControl as AMControl;}SplitControl 은 키워드로 사용되어지는 AMControl로 이름이 변경되었다. nesC는 여러 가지 이유로 이름이 변경된 인터페이스를 허용한다. 첫째로, 같은 모듈에서 필요로하는 두개 이상의 컴포넌트를 같은 인터페이스에 제공하기 위해서이다?nesC allows interfaces to be renamed in this way for several reasons. First, itoften happens that two or more components that are needed in the samemodule provide the same interface.as 키워드는 개별적으로 서로 다른 기억장소에 넣어 관리할 수 있도록 별개의 이름으로 변경함으로써 하나 이상의 이름을 허용한다.두 번째 이유는 인터페이스를 좀 더 의미 있는 이름으로 바꾸기 위해서이다. 여기에서는 SplitControl은 시작과 종료 컴포넌트를 위해 사용되어지는 일반적인 인터페이스이다. 그러나 AMControl이라는 이름은 SplitControl이 ActiveMessageC 컴포넌트를 제어하기 위해 사용되어지는 특별한 경우라는 것을 기억하기 쉽게 한다.3. 새로운 변수들을 선언하고 초기코드에서 필요로 한것들을 추가한다.message_t 구조체에 전송하기 원하는 데이터를 넣어두는 것이 필요하다. 또한 무선이전송하기에는 busy한 경우를 파악하기 위해 플래그가 필요하다. 이런 선언들은BlinkToRadioC.nc파일의 implementation 블럭에 추가되어야 한다.implementation { bool busy = FALSE; message_t pkt;...}다음으로, 무선을 초기화하는 것이 필요하다. 시스템이 부팅 되고나서 무선이 시작되기 위해서는 Boot.booted함수에서 AMControl.start를 호출해야 한다. 현재 구현에서골치 아픈 것은, 우리가 타이머를 Boot.booted 함수 내에서 시작을 하였고, 무선상으로 메세지를 전송하기위해 타이머를 사용하기로 했지만, 무선은 starting up이 완료SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 78
  • 79. UBee430TM Programming Guide될 때 까지 사용할 수가 없다는 것이다. 완료된 무선신호는 AMControl.startDone 이벤트를 발생시킨다.준비가 완료되기 전에 무선을 사용하기위해 시작을 한 적이 없다는 것을 확신하기 위해서는 무선이 완전히 시작한 이후로 타이머의 시작을 미루어야 한다. Boot.booted함수 내부에 있는 타이머의 시작을 위한 호출을 AMControl.startDone함수로 이동함으로써 성취할 수 있다.event void Boot.booted() { call AMControl.start();}또한, AMControl.startDone과 AMControl.stopDone 이벤트 핸들러를 구현하는 것이 필요하다.event void AMControl.startDone(error_t err) { if (err == SUCCESS) { call Timer0.startPeriodic(TIMER_PERIOD_MILLI); } else { call AMControl.start(); }}event void AMControl.stopDone(error_t err) { }무선이 성공적으로 시작되었다면, AMControl.startDone함수는 error_t 매개변수를SUCCESS의 값으로 설정하여 호출되어 질 것이다. 무선이 성공적으로 시작하면, 타이머를 시작하기에 적당하다. 그러나 무선이 시작하지 못했다면, 재시작을 시도한다. 이작업은 무선이 시작될 때 까지 계속된다. 키 컴포넌트가 성공적으로 시작될 때까지 노드의 소프트웨어는 실행되지 못한다.무선이 전혀 시작하지 못한다면, 사용자는 LED가 점멸하지 않는다는 것으로 알 수 있다. 디버그필요.4.프로그램 로직과 어플리케이션에서 필요한 used interfaces를 호출하는 부분을 추가한다. 타이머 fires때마다 노드의 id와 카운터 값을 전송하기를 원하므로, Timer0.firedevent handler를 추가하는 것이 필요하다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 79
  • 80. UBee430TM Programming Guideevent void Timer0.fired() {...if (!busy) {BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)(call Packet.getPayload(&pkt, NULL));btrpkt->nodeid = TOS_NODE_ID;btrpkt->counter = counter;if (call AMSend.send(AM_BROADCAST_ADDR, &pkt, sizeof(BlinkToRadioMsg)) == SUCCESS) { busy = TRUE;}}}이 코드는 여러 동작을 수행한다. 첫째로, busy flag를 체크해서 메세지 전송 중인지여부를 확인한다. 그런 후에 패킷의 payload portion을 가져와서 이전에 선언했던BlinkToRadioMsg external type으로 cast한다. 패킷 필드를 초기화하기 위해서 포인터를 사용한다. 그리고 AMSend.send함수를 호출하여 패킷을 전송한다.AM_BROADCAST_ADDR에 수신 주소를 명시함으로써 패킷은 무선을 통해 모든 노드에 보내진다.마지막으로, 성공했는지에 대한 테스트는 AM 레이어가 메시지를 전송하기위해 받아들일 때 성공했다는 것을 확인시켜준다.busy 플래그가 true로 설정되어 있다면 성공한것으로 본다. 전송을 시도하는 기간 동안, 패킷은 무선에서 소유하게 되며 유저 코드는 접근을 할 수 없게 된다.Packet 인터페이스를 사용하는 것을 피하기 위하여getPayload명령이 AMSend와 함께 반복된다.5. 사용할 계획인 인터페이스에 명시된 이벤트를 구현한다.Packet, AMPacket, and AMSend 인터페이스를 살펴 보고나서 다루어야 할 이벤트가하나뿐이라는 것을 알게 될 것이다.AMSend.sendDone: /** * Signaled in response to an accepted send request. msg is * the message buffer sent, and error indicates whether * the send was successful. * * @param msg the packet which was submitted as a send request * @param error SUCCESS if it was sent successfully, FAIL if it was not, * ECANCEL if it was cancelled * @see send * @see cancel */event void sendDone(message_t* msg, error_t error);SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 80
  • 81. UBee430TM Programming Guide이 이벤트는 메시지 전송 시도 후에 발생된다. 메시지 전송이 성공적이었는지 여부에따라 발생하는 것 외에 AMSend.send명령으로 호출되었던 컴포넌트로부터 AMSend로반환되는 msg의ownership을 리턴 한다.This event is signaled after a message transmission attempt. In addition tosignaling whether the message was transmitted successfully or not, the eventalso returns ownership of msg from AMSendback to the component thatoriginally called the AMSend.send command.그러므로 sendDone 핸들러는 메시지 버퍼를 사용하는 것이 가능하다는 것을 나타내기 위해서 busy 플래그를 클리어 하는 것이 필요로 한다.event void AMSend.sendDone(message_t* msg, error_t error) { if (&pkt == msg) { busy = FALSE; }}Note the check to ensure the message buffer that was signaled is the same asthe local message buffer.이 테스트는 필요로 한다.왜냐하면 두개의 컴포넌트가 같은 AMSend에 연결되어 있을 경우, 둘 중 하나가 send명령을 내렸지만 둘 다 SendDone 이벤트를 받게 된다.This test is needed because if two components wire to the same AMSend, bothwill receive a sendDone event after either component issues a send command.컴포넌트 작성자가Since a component writer has no way to enforce that her component will not beused in this manner, a defensive style of programming that verifies that the sentmessage is the same one that is being signaled is required.6. 어플리케이션 설정 파일(BlinkToRadioApp.c)의 implementation 블럭을 사용하기원하는 각 컴포넌트에 대한 components 문장을 추가함으로써 업데이트한다.BlinkToRadioAppC.nc의 implementation 블록 내에 존재하는 components 선언 아래에 다음 줄들을 추가 한다implementation { ... components ActiveMessageC; components new AMSenderC(AM_BLINKTORADIO); ...}SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 81
  • 82. UBee430TM Programming Guide이런 문장들은 필요한 인터페이스에 제공 되어질 ActiveMessageC and AMSenderC2개의 컴포넌트를 나타낸다.그러나 약간 문법상 차이점이 있다. ActiveMessageC는 하드웨어 플랫폼의 각 타입마다 한번 씩 정의된 singleton component를 의미한다. AMSenderC는 일반적이고parameterized component이다.new 키워드는 AMSenderC의 새로운 인스턴스가 곧 생성될 것이라는 것을 나타낸다.AM_BLINKTORADIO parameter는 AMSenderC의 AM 타입이라는 것을 나타낸다.We can extend the enum in the BlinkToRadio.h header file to incorporate thevalue ofAM_BLINKTORADIO:...enum {AM_BLINKTORADIO = 6,TIMER_PERIOD_MILLI = 250};...7. 어플리케이션에서 사용되어지는 인터페이스를 제공된 인터페이스의 컴포넌트에 연결한다.다음 라인들은 used interfaces를 제공되는 컴포넌트와 연결할 것이다.BlinkToRadioAppC.nc의implementation block의 밑에 추가될 것이다.implementation {... App.Packet -> AMSenderC; App.AMPacket -> AMSenderC; App.AMSend -> AMSenderC; App.AMControl -> ActiveMessageC;}Receiving a Message over the Radio이제 메세지를 전송할 수 있는 프로그램을 갖게 되었다. 메세지를 받아서 처리하는 코드를 추가할 수 있다. 수신 받은 메시지를 확인하기 위해 메세지로 받은 카운터 값의하위 3비트를 LED에 표시하도록 할 것이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 82
  • 83. UBee430TM Programming Guide이 어플리케이션을 흥미롭게 만들기 위해서, Timer0.fired 이벤트 핸들러에서 callLeds.set(counter);라인을 지워야 한다. 그렇지 않으면 타이머 이벤트와 패킷 수신 모두 LED를 업데이트 하게 되어 이상한 결과를 보게 될 것이다.두개의 mote에 수정된 어플리케이션을 인스톨시켜서, 다른mote의 카운터 값을 서로출력하도록 할 것이다.mote가 무선 수신 범위를 벗어나면, LED들을 점멸하는 것을 정지한다. mote 의 LED의 점멸이 정지된 동안 다른 mote의 LED는 점멸이 계속되도록 해서 link asymmetry를 연구 해 볼 수 도 있다. 이것은 점멸되지 않는 mote로 부터 점멸되는 mote로의링크는 사용가능한데 반대 채널은 사용불가라는 것을 나타낸다.1. 무선으로의 접근을 제공하는 인터페이스(와 컴포넌트)와 message_t 타입을 다룰수 있게 하는 인터페이스(와 컴포넌트)를 확인한다.여기에서는 Receive 인터페이스를 사용하여 패킷을 수신 받는다.2.BlinkToRadioC.nc파일에서 모듈 블럭을 업데이트한다. 우리가 필요한 인터페이스를uses문을 사용하여 추가한다.module BlinkToRadioC {...uses interface Receive;}3. 새로운 변수를 선언하고 필요한 초기화 코드를 추가한다. 여기에서는 새로운 변수나 무선으로부터의 메시지를 처리하는 것이 필요 없다.4. 어플리케이션에서 필요하는 used interfaces를 위해 프로그램 로직과 호출을 추가한다. 메시지 수신은 event-driven process이다. 그래서 수신상에 commands 호출은 필 요가 없다.5. 사용할 인터페이스에 (non-initialization) 이벤트 구현을 명기한다. 여기에서는 Receive.receive이벤트 핸들러를 구현한다.event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len) { if (len == sizeof(BlinkToRadioMsg)) { BlinkToRadioMsg* btrpkt = (BlinkToRadioMsg*)payload; call Leds.set(btrpkt->counter); }SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 83
  • 84. UBee430TM Programming Guide return msg;}수신 이벤트 핸들러는 간단한 동작으로 수행된다.수신된 메시지가 받기를 원하는 BlinkToRadioMsg구조체와 크기가 일치한다면 일단원하는 메시지를 받은 것으로 보고 메시지 페이로드(payload)를 BlinkToRadioMsg*타입의 구조체 포인터로 형 변환하여 지역변수인 btrpkt가 가리키게 한다. 메시지에 포한된 카운터 값을 세 개의 LED 상태를 위한 값으로 사용하기 위해 Leds.set을 호출한다.이 소스코드에서는 원자적으로 처리하는 것을 신경 쓰지 않고 카운터 변수를 증가시키고 있다. 이것이 가능한 것은 수신 이벤트는 인터럽트 컨택스트가 아닌 태스크 컨택스트에서 실행되기 때문이다. ( 이벤트에 aync키워드를 사용하면 인터럽트 컨택스트에서 실행되게 할 수 있다. )TinyOS 실행 모델에서는 동시에 하나의 태스크만 실행 가능하도록 허용하기 때문에,변수에 대한 모든 접근들은 태스크 컨택스트에서 일어난다. 따라서 변수에 대한 raceconditions이 발생하지 않는다.모든 counter에 대한 접근이 태스크 컨텍스트에서 일어나기 때문에 변수에 접근 시임계구역(critical sections) 이 필요 없다.6. 이전에 선택한 인터페이스를 제공하는 각 컴포넌트마다components 문을 추가하여어플리케이션의 configuration 파일의 implementation 블럭을 업데이트한다.다음 라인들은 BlinkToRadioAppsC.nc 파일의 implementation 블럭에 있는 기존의components 선언들 아래에 새로 사용할 컴포넌트를 위한 줄을 추가한다.implementation {...components new AMReceiverC(AM_BLINKTORADIO);...}이 문의 의미는 AMReceiverC의 새로운 인스턴스를 생성한다는 것이다.AMReceiver는 generic이고 매개변수가 있는 컴포넌트 이다. new 키워드는AMReceiverC의 새로운 인스턴스를 생성할 것이라는 것을 나타낸다.AM_BLINKTORADIO 매개변수는 이전에 사용된 AMSenderC를 위해 사용되었던 것처럼 AMReceiverC의 AM타입이라는 것을 나타낸다.이로써 전송과 수신 모두 똑같은 AM type을 사용하게 되었다. AM_BLINKTORADIO는BlinkToRadio.h 헤더파일에 정의되어 있다.7. 어플리케이션에 의해 사용될 인터페이스와 이런 인터페이스들을 제공하는 컴포넌트를 연결한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 84
  • 85. UBee430TM Programming Guide(wire)BlnikToRadioAppC 파일의 Implementation 블럭에 다음 라인들을 추가함으로써연결(wiring)을 업데이트한다.implementation { ... App.Receive -> AMReceiverC; ...}8. 어플리케이션을 테스트 한다.두 개의 mote가 필요하다. mica2, micaz, telosa, telosb, or tmote로 가능하다.이번 실습에서는 mote로 telosb를 사용한다고 가정한다. (if not, skip past themotelist part and program the mote using whatever the appropriate programmerparameters are for your hardware).apps/tutorials/BlinkToRadio 디렉터리로 이동을 한 후, 첫 번째 mote를 PC의 USB포트에 연결한 후, motelist 명령을 사용하여 연결된 port 번호를 확인한다.컴파일 후 인스톨 시킨다.$ cd /opt/tinyos-2.x/apps/tutorial/BlinkToRadio$ make UBee430 install.1아래와 같은 출력을 보게 될 것이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 85
  • 86. UBee430TM Programming Guide첫 번째 mote를 제가한 후, 베터리를 넣어준다. 그리고 옆에 놓자.두 번째 mote를 usb 포트에 연결 한 후 , motelist를 다시 입력한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 86
  • 87. UBee430TM Programming Guide이 시점에서, 두개의 mote들은 점멸하고 있을 것이다.mote 하나에 있는 리셋버튼을 누르는 동안 다른 mote의 LED는 잠시 점멸을 멈추게된다. 리셋 버튼에서 손을 떼는 순간 mote는 다시 점멸하게 된다.Conclusions이 lesson에서는 TinyOS 2.x에서의 무선 통신을 소개하였다.has introduced radiocommunications TinyOS 2.x.Related Documentation ● (1) TEP 111: message_t ● (2) TEP 116: Packet Protocols(3)Programming Hint 15: 메시지의 포맷을 정의 할때 항상 플랫폼에 비의존 적인타입을 사용하라 From Phil Levis TinyOS ProgrammingSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 87
  • 88. UBee430TM Programming Guide(4)Programming Hint 16: 플랫폼 비 의존적인 타입의 변수로 중요한 계산을 수행해야하거나 여러 번 해당 타입의 변수를 접근해야 한다면, 플랫폼 의존적인 변수에복사하여 사용하는 것이 좋다. From Phil Levis TinyOS ProgrammingSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 88
  • 89. UBee430TM Programming Guide4. Lesson 4: Mote-PC serial communication andSerialForwarderLast updated June 27 2006PC와 mote간에 통신을 어떻게 하는지 보여준다. 네트워크로 부터 데이터를 수집하거나 mote로 명령을 전송하거나 네트워크 트래픽을 모니터하는 것을 할 수 있게 된다.이 튜토리얼에서는 자바 기반의 infrastructure으로 mote와 통신하는 방법을 설명한다.또한 C기반의 infrastructure도 있다. 자세한 내용은 support/sdk/c에서 해당 문서나mig와 ncg에 대한 페이지를 읽어보기 바란다.Packet sources and TestSerialThe first step is to check that you are able to get your PC to communicate witha mote.대부분의 mote들은 시리얼 포트 또는 유사한 인터페이스를 가지고 있다. 예를 들어mica family는 직접 시리얼포트에 연결하여 제어한다. 프로그래밍 보드는 mote의 시리얼 포트 핀을 보드상의 실제 시리얼 포트에 연결한다. Telos mote도 시리얼 인터페이스를 가지고 있으나 실제 PC와의 연결은 USB 인터페이스를 통해 이루어진다.mote와 PC간의 통신에 대한 기본적인 추상화는 packet source이다. 어플리케이션이mote로부터 패킷을 수신하거나 mote로 패킷을 전송할 수 있게 해주는 통신 매체이다. packet source의 예를 들면, 시리얼 포트, TCP 소켓, SerialForwarder 도구들을포함한다.대부분의 TinyOS 통신 도구들은 문자열로 packet source를 지정할 수 있도록 옵션으로 -comm매개변수를 가진다. 예를 들면 telos mote에 적절한 스피드와 윈도우즈 머신의 COM1 시리얼 포트를 사용하여 mote와 통신이 이루어진다는 것을 Listen 도구에게 알려준다.$ java net.tinyos.tools.Listen -comm serial@COM1:telos[ UBee430의 경우 ]$ java net.tinyos.tools.Listen -comm serial@COM1:UBee430반면에 micaz mote에 적절한 스피드로 리눅스 머신에서 /dev/ttyS0 시리얼포트를사용한다SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 89
  • 90. UBee430TM Programming Guide$ java net.tinyos.tools.Listen -comm serial@/dev/ttyS0:micaz시리얼 포트를 테스트하기 위한 첫 번째 단계는 mote에 apps/tests/TestSerial 어플리케이션을 설치하는 것이다. 이 어플리케이션을 패킷을 시리얼 포트로 매 초마다 전송한다. 시리얼포트를 통해 패킷을 수신 받게 되면, 패킷의 sequence number가 LED에표시된다.mote에 설치된 TestSerial 어플리케이션과 PC에서 실행된 자바 어플리케이션이 시리얼을 통해 통신하는 것을 테스트한다.시리얼 테스트를 위한 디렉터리로 이동 후, 자바 어플리케이션을 실행시켜 본다. 아래와 같은 메시지가 나타나면 자바 어플리케이션이 컴파일이 안 된 상태이다. 또는 컴파일 된 자바 어플리케이션이 없는 곳에서 실행시키려 할 때에도 같은 에러가 난다. 또는 CLASSPATH환경변수에 .(현재 디렉터리)를 추가하지 않은 것이다.$ cd /opt/tinyos-2.x/apps/tests/TestSerial$ java TestSerialException in thread "main" java.lang.NoClassDefFoundError: TestSerialmake 명령을 내리면 PC를 위한 자바 소스코드와 tinyOS에서 동작하는 펌웨어 코드를컴파일하게 된다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 90
  • 91. UBee430TM Programming Guide다시 실행을 시켜보자. 아래와 같은 에러 메시지가 출력된다.packet source를 지정하지 않으면 TestSerial은 기본적으로 SerialForwarder와 통신을하게 된다. 하지만 SerialForwarder를 실행시켜 놓지 않았기 때문에, TestSerial은 접속할 곳을 못 찾아 종료되는 것이다.SerialForwarder의 위치는/opt/tinyos-2.x/support/sdk/java/net/tinyos/sf/SerialForwarder.java이며 아래 명령으로 실행 시킬 수 있다.$ java net.tinyos.sf.SerialForwardercygwin을 실행시킨 후, java TestSerial을 실행시키면 바로 종료되지 않고 TestSerial에서 메시지를 전송했는데 SerialForwarder에서 실패 됐다는 응답을 볼 수 있다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 91
  • 92. UBee430TM Programming Guide$ java net.tinyos.sf.SerialForwarder -comm serial@com7:115200mote가 연결된 시리얼 포트관련 설정을 해야 한다. 아래 구문을 사용하여 시리얼 포트 소스를 지정해 준다. PORT는 mote가 연결된 포트 번호로써 현재 PC에서 사용 중인 OS에 따라 약간 차이가 있다. 윈도우즈에서 cygwin을 사용하는 경우에는 COMN에서 N에 대응되는 숫자부분이 포트번호이다.serial@<PORT>:<SPEED>리눅스나 유닉스에서는 /dev/tttSN을 시리얼 포트를 위해 사용한다.또는 /dev/ttyUSBN 또는 /dev/usb/tts/N 을 SerialToUSB 포트를 위해 사용된다. 리눅스에서는 시리얼포트가 쓰기 가능하도록 해줄 필요가 있다. 슈퍼 유저로써 다음 명령을 실행시켜야 한다.chmod 666 serialportSPEED는 숫자 값이나 플랫폼의 이름을 사용하면 된다. 플랫폼의 이름을 적으면플랫폼을 위한 기본 스피드를 사용하여 serial packet source를 지정하게 된다.가능한 플랫폼은 아래와 같다. Platform Speed (baud) telos 115200 telosb 115200 tmote 115200 micaz 57600 mica2 57600 mica2dot 19200 eyes 115200 intelmote2 115200이러한 매핑은 /opt/tinyos-2.x/support/sdk/java/net/tinyos/packet/BaudRate.java에있다. TinyOS 1.x에서와는 다르게 모든 플랫폼은 공통 시리얼 패킷 포맷을 가지고 있다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 92
  • 93. UBee430TM Programming Guide현재 mote가 연결된 포트번호를 motelist명령으로 확인 한 후, tmote(=telosb)에 맞는시리얼 속도와 같이 옵션으로 해서 다시 실행을 시켜보자. 시리얼 속도를 115200로또는 플랫폼 이름인 tmote로 적어도 똑같이 동작하는 것을 볼 수 있다.정상적인 결과를 보기 위해서는 mote에 컴파일 해두었던 tinyos를 설치해야 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 93
  • 94. UBee430TM Programming Guide다시 TestSerial을 실행시켜 정상동작을 했다면 아래와 같은 출력을 볼 수 있다. PC에서 보낸 메시지에 대해 mote가 전송을 잘 받았다는 메시지를 전송한 결과를 볼 수 있다. 또한 mote의 LED도 깜박이게 된다.Cannot find JNI errorIf you try to run TestSerial and receive an error that Java cannot find TOSCommJNI support, this means the Java Native Interface (JNI) files that control theserial port havent been correctly installed. Run the command tos-install-jni(onLinux, do this as the superuser). If this command does not exist, go totinyos-2.x/tools/tinyos/java. If the directory has a Makefile in it, type make andSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 94
  • 95. UBee430TM Programming Guide(again, on Linux, as superuser) make install. If the directory does not have aMakefile, go to tinyos-2.x/tools and type:$ ./Bootstrap$ ./configure$ ./make$ ./make installThen type tos-install-jni. This should install serial support in your system.MOTECOM-comm 매개변수를 적지 않으면, TinyOS에서 제공하는 도구들은 packet source를위해 MOTECOM 환경변수를 체크하게 된다. 만약 MOTECOM이 정의되어 있지 않으면 SerialForwarder이 디폴트가 된다. 시리얼포트를 통해 mote와 통신을 항상 할거라면 MOTECOM 환경변수를 설정하자. -comm 매개변수를 적지 않아도 되게 된다.예를 들어 3대의 mote가 연결된 상태에서 계속 테스트를 할 거라면 다음처럼 하면 된다.export MOTECOM=serial@COM1:19200 # mica baud rateexportMOTECOM=serial@COM1:mica # mica baud rate, againexportMOTECOM=serial@COM2:mica2 # the mica2 baud rate, on a different serialportexport MOTECOM=serial@COM3:57600 # explicit mica2 baud rateMOTECOM환경변수를 설정한 후, TestSerial을 -comm매개변수 없이 실행시켜 보자.BaseStation and net.tinyos.tools.ListenBaseStation은 기본적인 TinyOS 유틸리티 어플리케이션이다. 이 프로그램은 시리얼포트와 무선 네트워크 간에 연결(bridge)역할을 한다. 시리얼 포트로부터 패킷을 수신받으면, 무선으로 신호를 전송한다. 패킷을 무선으로 부터 수신 받게 되면, 시리얼포트로 다시 전송을 해준다.TinyOS는 패킷을 생성하고 시리얼포트를 통해 mote로 전송할 수 있는 툴체인을 가지고 있기 때문에, BaseStation은 PC 도구가 직접 mote 네트워크와 통신할 수 있게 허용한다.두개의 노드를 준비해 하나의 노드에 BlinkToRadio 어플리케이션(Lesson3 참고)을 설치하고 다른 노드에는 BaseStation을 설치한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 95
  • 96. UBee430TM Programming Guide먼저 건전지 장착이 가능한 노드를 PC에 연결하여 BlinkToRadio 어플리케이션을 컴파일하여 설치 한다.다른 노드를 PC에 연결하여 BaseStation을 컴파일 하여 설치한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 96
  • 97. UBee430TM Programming GuideBaseStation이 설치된 mote가 PC와 연결된 상태에서 BlinkToRadio어플리케이션이 설치되어 있는 mote를 켜게 되면, BaseStation이 설치된 mote의 LED1이 점멸하는 것을 볼수 있다.무선상으로 패킷을 전송하게 되면 BaseStation의 LED0이 점멸하게 되며, 시리얼 포트를 통해 패킷을 전송하면 LED1이 점멸한다. 그리고 패킷손실이 생기면 LED2가 점멸한다. this can happen when one of the two receives packets faster than theother can send them: (e.g., receiving micaZ radio packets at 256kbps butsending serial packets at 57.6kbps).SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 97
  • 98. UBee430TM Programming GuidePC에 연결되어 있는 BaseStation은 BlinkToRadio 패킷을 수신하게 되면 시리얼 포트를 통해 그 패킷을 PC로 전송하게 된다.PC에서 패킷내용을 확인하려면 패킷 스나이퍼인 Listen을 실행시키면 된다. PC에서 시리얼포트를 통해 수신된 패킷의 내용을 바이너리로 출력한다.자바 Tools들을 실행시킬 때, 위에서 나온 MOTECOM 환경변수를 미리 설정해두었다면 -comm부분을 적지 않아도 된다.Listen은 mote로부터 오는 패킷들을 출력한다.mote로부터 전송된 각 데이터 패킷은여러 데이터 필드를 포함하고 있다. 첫 번째 바이트(00)는 이 패킷이 AM 패킷이라는것을 나타낸다. 다음 필드는 일반적인 Active Message 필드로,tinyos-2.x/tos/serial/Serial.h에 정의되어 있다. 마지막으로, 나머지 필드들은 메시지의 데이터 페이로드이다. BlinkToRadio.h에 다음과 같이 정의되어 있다.typedef nx_struct BlinkToRadioMsg { nx_uint16_t nodeid; nx_uint16_t counter;} BlinkToRadioMsg;첫 바이트 00을 제외하고 BlinkToRadioC application에서 사용하는 메시지 포맷은다음과 같다. ● Destination address (2 bytes) ● SRC (2 bytes)SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 98
  • 99. UBee430TM Programming Guide ● Message length (1 byte) ● Group ID (1 byte) ● Active Message handler type (1 byte) ● Payload (up to 28 bytes): o source mote ID (2 bytes) o sample counter (2 bytes)따라서 데이터 패킷을 다음처럼 해석 할 수 있다. msg dest addr src groupID handlerID source addr counter len ff ff ff ff 04 22 06 00 02 00 0BSource의 주소는 BlinkToRadio 어플리케이션을 mote에 설치 시 인자로 준 mote ID값에 따라 달라진다. make 도구로 설치시 ID를 지정하지 않았다면 기본적으로 00 01값을 가진다. 여기서 주의할 점은 mote로부터 전송되는 데이터는 빅엔디안 포맷일 경우이다. 예를들어 01 02는 258을 의미한다. ( 256*1 + 2 ). 이 포맷은 프로세서의 엔디안에 의존적이다. 패킷의 포맷이 네트워크 포맷인 nx_struct이기 때문에 빅엔디안이고 바이트 정렬된 상태이다.메시지 페이로드를 위해서 표준 C의 구조체가 아닌 nx_struct구조체를 사용하면 플랫폼에 상관없이 동작한다는 것을 확실 할 수 있게 된다. Listen프로그램이 출력한 패킷들을 보면, BlinkToRadio 어플리케이션에서 카운터 값을 증가시킨 결과로 카운터 필드가 증가했다는 것을 알 수 있다.MIG: generating packet objectsListen 프로그램은 mote와 통신할 수 있는 가장 기본적인 방법이다. 패킷의 내용을 화면에 출력을 해준다. 분명히 프로그램을 사용하여 센서의 데이터를 시각화 하는 것은쉬운 일이 아니다. What wed really like is a better way of retrieving andobserving data coming from the sensor network.물론 출력할 데이터가 정확히 무엇이고, 어떻게 시각화를 할지는 어플리케이션에 따라달라지게 된다. 이런 이유로 TinyOS에서는 센서데이터를 간단히 시각화하는 몇 가지어플리케이션만을 제공하고 있다. ( 다음 Lesson에서 오실로스코프 예제를 사용하게될 것이다. ) 새로운 시각화나 기록 시스템을 만들기 위해 도움이 되는 것들을 제공한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 99
  • 100. UBee430TM Programming GuideListen 프로그램에서 문제는 단지 패킷의 바이너리 데이터를 덤프에서 화면에 출력만한다는 것이다. 사용자는 바이트들을 읽어서 그들을 parse하여 주어진 패킷의 포맷으로 만들어야 한다. TinyOS 툴체인은 패킷 표현으로 부터 자동으로 메세지 오브젝트를생성할 수 있는 도구들을 제공함으로써 이런 처리를 쉽게 할 수 있도록 한다.수동으로 패킷 포맷을 parse 하는 것 보다는, 메시지 구조체로의Java, PyThon, C 인터페이스를 만들기 위해서 mig 도구를 사용할 수 있다.주어지는 일련의 바이트들을(sequence of bytes), MIG로 생성된 코드는 자동으로 packet에서 각 필드들을 parse한다. 그리고 수신된 패킷을 출력하거나 새로운 것을 생성하기 위한 표준 accessorsand mutators를 제공해준다.mig도구는 세 개의 인자를 가진다.- 어떤 프로그래밍 언어로 코드를 생성할 것인지(Java, Python, or C),- 구조체를 찾기 위한 파일,- 구조체의 이름이다.mig도구는 또한 사용되는 라이브러리를 링크하기위한 -l이라든가, 정의를 하기위한-D등의 표준 C옵션을 지원한다.예를 들어 TestSerial 어플리케이션은 시리얼 포트로부터의 패킷을 쉽게 parse하고 구조체를 생성할 수 있도록 mig를 사용한다. TestSerial 어플리케이션의 디렉터리로 이동하여 다시 make clean;make를 해보자.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 100
  • 101. UBee430TM Programming GuideTinyOS 어플리케이션을 빌드하기 전에, Makefile은 TestSerialMsg.java를 생성하기 위한 룰을 가지고 있다. TestSerial.java와 마찬가지로TestSerialMsg.java를 컴파일 한다.그리고 Makefile에서 보이듯이 마지막으로 TinyOS 어플리케이션을 컴파일 한다.Makefile을 살펴보면 BlinkToRadio를 위한 것보다 더 많은 룰을 가졌다는 것을 볼 수있다.COMPONENT=TestSerialAppCBUILD_EXTRA_DEPS += TestSerial.classCLEAN_EXTRA = *.class TestSerialMsg.javaTestSerial.class: $(wildcard *.java) TestSerialMsg.java javac *.javaTestSerialMsg.java: mig java -target=null $(CFLAGS) -java-classname=TestSerialMsg TestSerial.htest_serial_msg -o $@include $(MAKERULES)BUILD_EXTRA_DEPS 줄은 TinyOS application이 추가적인 의존성을 가졌고 이를 만족해야 빌드가 될 수 있다는 것을 TinyOS make system에게 알려준다. Makefile은 자SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 101
  • 102. UBee430TM Programming Guide바 어플리케이션인 TestSerial.class가 시리얼 통신 테스트를 위해 실행될 것이라는 것을 make system에게 알려준다.CLEAN_EXTRA 줄은 사용자가 컴파일 결과물들을 지우기 위해 make clean 명령을 내렸을 때, 필요한 것들을 TinyOS make system에게 알려준다.BUILD_EXTRA_DEPS 줄은 어플리케이션 전에 TestSerial.class를 컴파일 하라고make에게 알려준다. 그 결과 아래 라인들이 수행되게 된다.TestSerial.class: $(wildcard *.java) TestSerialMsg.java javac *.javaTestSerialMsg.java처럼 TestSerial.class도 디렉터리 내에 있는 모든 .java파일에의존성이 걸려있다는 것을 알려준다. 모든 의존성문제가 해결되면 make system은TestSerial.claa를 생성하기 위해 javac *.java를 수행하게 된다.TestSerialMsg.java: mig java -target=null $(CFLAGS) -java-classname=TestSerialMsg TestSerial.htest_serial_msg -o $@make system에게 어떻게 TestSerialMsg.java를 생성할 수 있는지를 알려준다. mote와 PC간에 paket을 전송하는 역활을 하는 java class이다.TestSerialMsg.java 는 TestSerial.class에 대해 의존성이 걸려있기 때문에, make는 우선 TestSerial.class를 생성하게 된다. TestSerialMsg.java를 생성하기 위해 Makefile은mig 도구를 호출한다.매개변수들을 하나씩 살펴보자.mig Invoke migjava Build a Java class-target=null For the nullplatform-java-classname=TestSerialMs Name the Java class TestSerialMsggTestSerial.h The structure is in TestSerial.hTestSerialMsg The structure is named TestSerialMsg Write the file to $@, which is-o $@ TestSerialMsg.javaSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 102
  • 103. UBee430TM Programming Guidenull 플랫폼은 mig 도구를 사용할 때 타켓으로써 사용을 하면 편리한 특별한 플랫폼이다. 모든 표준 시스템 컴포넌트들과 아무것도 없는 dummy implementation을 포함하고 있다. null 플랫폼을 위해 어플리케이션을 만드는 것은 쓸모없으나, mig가 패킷의레이아웃을 추출할 수 있게 해준다.BlinkToRadio를 위한 자바 패킷 오브젝트를 만들어 보자. BlinkToRadio의 Makefile을열어서 의존성을 추가한다.BUILD_EXTRA_DEPS=BlinkToRadioMsg.class.java를 어떻게 .class로 컴파일 할 수 있는지에 대해 설명해주는 단계를 추가한다.BlinkToRadioMsg.class: BlinkToRadioMsg.java javac BlinkToRadioMsg.javajavac앞에 빈칸이 아닌 탭이 들어가야 한다는 것에 주의해야 한다. 마지막으로BlnikToRadioMsg.java를 어떻게 생성하는지 설명하는 부분을 추가 한다BlinkToRadioMsg.java: mig java -target=null -java-classname=BlinkToRadioMsg BlinkToRadio.h BlinkToRadioMsg-o $@javac처럼, mig앞에서 빈칸이 아닌 탭이 반드시 있어야 한다. 이제 BlinkToRadio/디렉터리에서 make 명령을 내리면, make 시스템은 BlinkToRadioMsg.class를 컴파일할것이다. 바이너리 패킷을 메시지 필드로 parse하는 자바 클래스이다.[ 주의사항 ]javac 앞부분과 mig 앞부분은 반드시 탭으로 처리해야 한다. 알맞지 않은 탭으로들어가면 컴파일시 에러가 발생 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 103
  • 104. UBee430TM Programming Guidea Java class that parses a binary packet into message fields that can beaccessed through methods.한 단계가 더 남아있다. 컴파일을 하면, 아래와 같은 경고 메시지를 보게 될 것이다TinyOS 통신 툴체인의 한 부분에서 어떤 종류의 패킷에 해당되는 AM 타입인지를 이해하는 것이 필요하다. 패킷타입의 이름이 X라면, mig는 AM_X 형태의 상수를 찾는다.이 경고는 AM_BLINKTORADIO로 AM 타입을 정의했는데, mig는 AM_BLINKTORADIOMSG를 원하기 때문에 발생한다.BlinkToRadio.h에서 정의를 수정해야 한다.enum { AM_BLINKTORADIOMSG=6, TIMER_PERIOD_MILLI = 250};typedef nx_struct BlinkToRadioMsg { nx_uint16_t nodeid; nx_uint16_t counter;} BlinkToRadioMsg;또한 BlnkToRadioAppC.nc에서 AMSenderC와 AMReceiverC가 변경된 상수를 사용하도록 수정해야 한다.configuration BlinkToRadioAppC {SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 104
  • 105. UBee430TM Programming Guide}implementation {components MainC;components LedsC;components BlinkToRadioC as App;components new TimerMilliC() as Timer0;components ActiveMessageC;//components new AMSenderC(AM_BLINKTORADIO);//components new AMReceiverC(AM_BLINKTORADIO);components new AMSenderC(AM_BLINKTORADIOMSG);components new AMReceiverC(AM_BLINKTORADIOMSG);어플리케이션을 재 컴파일하면, 경고메시지가 안보일 것이다. 컴파일을 해서 mote에설치한다.이제 BaseStation이 설치된 mote를 시리얼포트에 연결하고, BlinkToRadio가 설치된mote를 켜자.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 105
  • 106. UBee430TM Programming Guide이제 BaseStation은 패킷을 시리얼포트를 통해 전송한다. MsgReader가 이를 읽어서AM 타입을 보고, 자바 메시지 클래스에 있는 AM 타입중 하나와 일치하면 커맨드 라인으로 보낸다. 패킷의 내용을 아래처럼 출력하게 된다.SerialForwarder and other packet sources시리얼포트를 이용하여 직접 제어하게 되면 하나의 PC프로그램만 mote와 통신이 가능하게 된다. 또한, 물리적으로 mote가 연결된 PC에서 어플리케이션을 실행시켜야만한다. SerialForwarder 도구는 이런 제한들을 제거할 수 있는 간단한 방법이다.보다 일반적으로,SerialForwarder 프로그램이 packet source를 열고, 많은 어플리케이션들이 packet source를 접근하기 위해 이 프로그램과 연결하여 TCP/IP stream받는다.예를 들어 시리얼포트가 packet source 일 때 SerialForwarder를 실행 시킬 수 있다.직접 시리얼 포트로 연결하는 대신, 어플리케이션들은 패킷을 읽고 쓰는 프록시(proxy) 역할을 하는 SerialForwarder와 연결한다. 어플리케이션들이 TCP/IP를 거쳐SerialForwarder로 연결이 되어 있다면, 어플리케이션은 인터넷을 거쳐서도 연결이 가능하다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 106
  • 107. UBee430TM Programming GuideSerialForwarder is the second kind of packet source.SerialForwarder sources는 다음 구문을 가진다.sf@HOST:PORTHOST와 PORT는 옵션이다. 디폴트가 localhost (the local machine) and 9002이다.예를들어sf@dark.cs.berkeley.edu:1948dark.cs.berkeley.edu에 있는컴퓨터상의SerialForwarder에 1948번 포트로 접속할 것이다 .첫 번째 단계는 SerialForwarder를 실행시키는 것이다. 하나의 packet source를 가지고 이것을 sf source로써 export하기 때문에, 다른 Tinyos 도구처럼 packet source매개변수를 가진다. -comm 매개변수를 넘기거나, MOTECOM 환경변수를 사용하거나, 디폴트값을 그냥 사용할 수도 있다.BaseStation이 설치된 mote를 시리얼포트에 연결한다. MsgReader 어플리케이션이실행되고 있다면 종료해서 더 이상 시리얼 포트를 사용하는 어플리케이션이 없는 상태에서 SerialForwarder를 실행시킨다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 107
  • 108. UBee430TM Programming GuideSerialForwarder는 source로써 어떤 packet source도 가질 수 있기 때문에 아래와 같이 사용할 수 도 있다.$ java net.tinyos.sf.SerialForwarder -port 9003 -comm sf@localhost:9002위 명령은 source로 첫 번째로 실행시킨 SerialForwarder를 사용하도록 두 번째로SerialForwarder를 실행시킨다. 첫 번째로 실행시킨 SerialForwarder에서 클라이언트카운터가 1로 증가된 것을 볼 수 있다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 108
  • 109. UBee430TM Programming GuideIts rare that youd ever want to do this, but itdemonstrates that in the messagesupport libraries you can use a variety of packet sources.두 번째로 실행시켰던 SerialForwarder를 종료시킨다. (Listening for clientconnections on port 9003 메세지가 보이는 윈도우) MsgReader를 다시 실행시켜보면, SerialForwarder에 접속한 것을 확인 할 수 있다. ( Num Clinets가 0에서 1로증가함 )이제 BlinkToRadio가 설치된 mote를 켜자. BaseStation이 설치된 mote에서 신호를받기 시작하면 MsgReader를 실행시킨 창에서 다음과 같은 메시지를 볼 수 있을것이다.또한 Serial Forwarder프로그램에서도 Packs Read 항목의 숫자가 증가되는 것을 볼수 있다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 109
  • 110. UBee430TM Programming GuidePacket SourcesIn addition to serial ports and SerialForwarders, TinyOS messaging library는 세번째 packet source를 지원한다. mote는 Crossbow MIB 600 ethernet board를 통해이더넷 포트와 연결된다.아래는 사용가능한 모든 packet sources들이다.Syntax Sourceserial@PORT:SPEED Serial ports SerialForwarder, TMotesf@HOST:PORT Connectnetwork@HOST:PORT MIB 600network packet source에서 default의 MIB 600 port는 10002이다. The MoteivTMote Connect appliance is a SerialForwarder packet source.The tool sidenet.tinyos.message와 net.tinyos.packet 두 가지 자바 패키지에는 Java messagingtoolchain을 위한 코드가 있다. packet 패키지는 packet source와 그들의 프로토콜(바이트 단위로 읽고 쓴다)에 관련된 모든 것들을 포함하고 있다. message 패키지에는스트림을 의미 있는 메시지로 바꾸는 것과 mote와 통신하기 위해 packet source에비 의존적인 클래스를 제공한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 110
  • 111. UBee430TM Programming Guide패킷을 전송하고 수신하는 키 클래스는 MoteIF이다. packet listeners(callbacks whena packet arrives)를 등록하는 method와 패킷을 전송하는 method를 가지고 있다.MsgReader, Listen, and Send 도구 들은 자바 어플리케이션이 어떻게 mote와 통신하는지 배울 수 있는 좋은 시작점이다.There is also support for python and C.Sending a packet to the serial port in TinyOSTinyOS에서 시리얼포트로 AM 패킷을 전송하는 것은 무선으로 전송하는 것과 동일하다. component는 AMSend 인터페이스를 사용한다. AMSend.send를 호출하고,AMSend.sendDone 이벤트를 다룬다. AM 주소를 지정한 것에 상관없이 시리얼 스택은 시리얼포트로 전송할 것이다.TinyOS 시리얼 스택은 무선 스택과 똑같은 프로그래밍 모델을 따른다.SerialActiveMessageC은 스택을 on/off하고 시리얼을 통해 패킷 송수신을 위한 일반컴포넌트이다. 시리얼 스택이 on된 동안 mote프로세서는 저전력 상태로 들어갈 수 없다.serial stack은 전용 링크로써, 그러나, snooping 인터페이스를 제공하지 않는다. 패킷의 수신 주소를 기초로 필터를 하지 않는다. 다음은 시리얼 통신 컴포넌트와 대응이되는 무선 컴포넌트를 같이 적어 놓은 것이다. Serial RadioSerialActiveMessageC ActiveMessageCSerialAMSenderC AMSenderCSerialAMReceiverC AMReceiverC시리얼 AM 통신은 무선 AM 통신과 같은 인터페이스를 가지기 때문에, 대부분의 상황에서 그들을 교체해서 사용하는 것이 가능하다. 예를 들어, BlinkToRadio예제는 무선을 통해 패킷을 전송한다. BlinkToRadioAppC configuration을 변경해서 시리얼포트로전송하게 바꾸어 보자.Radio Serialcomponents ActiveMessageC; components SerialActiveMessageC;SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 111
  • 112. UBee430TM Programming Guide components new SerialAMSenderCcomponents new (AM_BLINKTORADIOMSG);AMSenderC(AM_BLINKTORADIOMSG); BlinkToRadioC.AMSend -> SerialAMSenderC;BlinkToRadioC.AMSend -> AMSenderC; BlinkToRadioC.AMControl ->BlinkToRadioC.AMControl -> ActiveMessageC; SerialActiveMessageC;이젠 BlinkToRadio가 패킷을 전송하면, BaseStation이 수신해서 시리얼포트를 통해PC로 포워딩하는 것이 아니라 어플리케이션이 직접 시리얼포트로 전송하게 된다. 일어나는 일을 테스트하기 위해 MsgReader를 연결한다. 무선스택에서 시리얼 스택으로바뀌면서 바이너리 코드와 데이터 사이즈는 변하게 될 것이다.CLASSPATH and Java classesCLASSPATH 변수는 tinyos.jar파일의 위치를 가리킨다. 이 말의 의미는 자바가 클래스를 위해 로드 할 때, 자바 디렉터리 support/sdk/java를 찾는 것이 아니라 tinyos.jar에서 찾는다는 것이다. 그러므로 자바 클래스를 변경하거나 재 컴파일해도, 변경된 것을 알 수가 없다. 자바는 오직 jar파일만을 찾기 때문이다. 자바 코드로부터 jar파일을재생성하기 위해서는 support/sdk/java로 이동하여 make tinyos.jar명령을 내린다.$ cd /opt/tinyos-2.x/support/sdk/java/$ lsMakefile Makefile.include net tinyos.jar$ make clean && make tinyos.jarcleaning /opt/tinyos-2.x/support/sdk/javamake[1]: Entering directory `/opt/tinyos-2.x/support/sdk/java/netcleaning /opt/tinyos-2.x/support/sdk/java/netmake[2]: Entering directory `/opt/tinyos-2.x/support/sdk/java/net/tinyoscleaning /opt/tinyos-2.x/support/sdk/java/net/tinyosmake[3]: Entering directory `/opt/tinyos-2.x/support/sdk/java/net/tinyos/packet................................................................................................................javac Crc.javajavac Dump.javajavac Env.javajavac Messenger.javajavac PrintStreamMessenger.javamake[3]: Leaving directory `/opt/tinyos-2.x/support/sdk/java/net/tinyos/utilmake[2]: Leaving directory `/opt/tinyos-2.x/support/sdk/java/net/tinyosmake[1]: Leaving directory `/opt/tinyos-2.x/support/sdk/java/netrm -f tinyos.jarfind . | grep -E "class|jpg|gif" | xargs jar cf tinyos.jarSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 112
  • 113. UBee430TM Programming Guide5. Lesson 5: SensingLast Modified: 16 June 2006이번 lesson에서는 TinyOS에서 센서 데이터를 획득하는 것에 대해 소개한다. 두 가지센서 어플리케이션을 보여준다. 간단한 어플리케이션인 Sense는 주기적으로 센서에서읽어오거나 값을 LED에 출력한다. 좀 더 세련된 어플리케이션인 Oscilloscope가 있다. 노드들이 센서 읽은 값을 주기적으로 베이스스테이션 노드로 브로드캐스트 한다.이전 lesson4에서 설명했던 mote와 PC간의 시리얼 통신을 사용하여, 베이스스테이션이 센서 읽은 값을 PC로 포워드 한다. PC에서는 전용 그래픽 유저 인터페이스를 사용하여 시각화를 하게 된다.Introduction센싱(Sensing)은 센서 네트워크 어플리케이션에서 필수적인 부분이다. TinyOS 1.x에서 센싱은 ADC(analog-to-digital converter)와 관련이 있다 : Oscilloscope 또는Sense와 같은 TinyOS 1.x 어플리케이션은 센서 데이터를 수집하기 위해, ADC 와ADCControl 인터페이스를 사용한다.새로운 플랫폼이 센서들과 시리얼 인터페이스를 통해 읽어오는 것은When new platforms appeared with sensors that were read out via the serialinterface, not only did additional interfaces like ADCError have to be introduced,but it became clear that equating a sensor with an ADC was not always theappropriate thing to do.보통 센싱은 두 개의 태스크와 관련이 있다 : 센서(and/or the hardware module it isattached to, for example the ADC or SPI bus)를 설정하는 것과 센서 데이터를 읽어오는 것이다.Sense같은 센싱 어플리케이션이 어떤 TinyOS 플랫폼에서든 작동되도록 하려고 했기 때문에 센서를 설정하는 태스크는 다루기 힘들다. 붙어있는 센서의ADC 입력 채널, 필요한 reference voltage 같은 세부 설정을 Sense 어플리케이션은어떻게 알 수 있을까? 불가능하다. 플랫폼마다 센서의 세부설정이 다르기 때문이다.Sense가 모든 플랫폼의 모든 센서를 알지 못한다면, configuration 태스크를 수행할수 없을 것이다. 그러나 센서 데이터를 읽어오는 태스크는 해결될 수 있다. 동작하고있는 플랫폼에 대해 모르더라도 센서 어플리케이션은 센서 데이터를 수집할 수 있다.TinyOS 2.0 플랫폼 비 의존적인 센싱 어플리케이션(Oscilloscope, Sense orRadioSenseToLeds)은 ADCControl 같은 설정 인터페이스를 더 이상 사용하지않는다. 대신에 센서 데이터를 수집하기 위해 표준 데이터 획득 인터페이스(Read,ReadStream, ReadNow) 를 사용한다. 모든 세부 설정은 어플리케이션에게는 감추어SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 113
  • 114. UBee430TM Programming Guide져 있다. 그래서 실제 센서와 나머지 시스템간의 연결이 완전히 다른데도 불구하고Sense를 컴파일해서, telosb 또는 micaz 플랫폼에서 센서데이터를 출력할 수 있는 것이다.다음과 같은 질문들이 제기된다.* Sense 어플리케이션 컴포넌트는 표준 데이터 획득 인터페이스만을 사용한다. 누가어떤 센서의 샘플인지 정의하는 것을 담당하는가?* Sense 어플리케이션 컴포넌트는 센서를 설정하지 않는다. 누가 이일을 책임지는가?* 센서 설정에 대해 자세히 알지 못하는 Sense 같은 어플리케이션에서 센서 데이터를어떻게 출력할 수 있는가? 이것은 다음 질문도 포함한다. "센서 데이터의 값 범위는?"또는 "온도를 읽어서 섭씨나 화씨로 해석할 수 있는가?"* 플랫폼 상의 여러 센서들이 있다고 가정 해보자. Sense 또는 Oscilloscope 어플리케이션에서 여러 센서에서 가져온 데이터들을 출력하려면 어떤 단계들이 필요한가?본 튜토리얼을 읽고나면, 질문들에 답변을 할 수 있을 것이다. 예를 들기 위해, Sense와 Oscilloscope 어플리케이션을 사용하여 다음 섹션에서 설명한다. 어떻게 데이터 획득 인터페이스가 사용되어지는지, 설정 절차가 어떻게 동작하는지(예를 들면 telosb플랫폼상에서 디폴트인 하나가 아닌 센서들을 어떻게 연결할 수 있는지)The Sense applicationSense는 간단한 센싱 데모 어플리케이션이다. 기본 센서에서 주기적으로 샘플링해서읽어온 센서 데이터의 하위 비트들을 LED에 출력한다.센서 어플리케션은 /opt/tinyos-2.x/apps/Sense에서 찾을 수 있다.먼저 SenseAppC.ncconfiguratin 파일을 살펴보자.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 114
  • 115. UBee430TM Programming Guideconfiguration SenseAppC{}implementation { components SenseC, MainC, LedsC, new TimerMilliC(); components new DemoSensorC() as Sensor; SenseC.Boot -> MainC; SenseC.Leds -> LedsC; SenseC.Timer -> TimerMilliC; SenseC.Read -> Sensor;}SenseAppC configuration은 lesson 1에서 설명했던 BlinkAppC configuration과 비슷해 보인다. (if you have not done so, read the sections on the Blink applicationin lesson 1). 연결(wiring)을 이해하기 위해 SenseC.nc 모듈의 signature를 살펴보자.module SenseC{ uses { interface Boot; interface Leds; interface Timer<TMilli>; interface Read<uint16_t>; }}BlinkC.nc 모듈처럼 SenseC.nc 모듈은 Boot, Leds and Timer<TMilli>인터페이스를사용하다. 추가적으로 Read<uint16_t>인터페이스를 사용한다. The sequence ofactions in the SenseC.nc implementation is as follows: SenseC.nc는 시스템이 초기화된 후에, 주기적 타이머를 시작하기 위해 Boot 인터페이스를 사용한다. 타이머가만료되는 시점마다 SenseC.nc는 타이머 이벤트 신호를 보낸다. 그리고 데이터를Read<uint16_t> 인터페이스를 통해 읽어온다. 데이터를 읽어 오는 것은 split-phase연산이다. Read.read() 명령과 Read.readDone() 이벤트로 나누어져 있다. 타이머가만료될 때는 시점마다, SenseC.nc는 Read.read()를 호출한다 그리고 Read.readDond()이벤트를 대기한다. Read.readDone() 이벤트에서 데이터가 보내지면, SenseC.nc는LED에 출력한다 : 최하위 비트는 LED0에 출력된다. 두 번째 최하위 비트는 LED1에출력된다. 나머지도 마찬가지..Read 인터페이스는 센서 데이터의 단일 조각을 읽어오는데 사용되어 질 수 있다.자세히 살펴보자./opt/tinyos-2.x/tos/interfaces/Read.ncSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 115
  • 116. UBee430TM Programming Guideinterface Read<val_t> { /** * Initiates a read of the value. * * @return SUCCESS if a readDone() event will eventually come back. */ command error_t read(); /** * Signals the completion of the read(). * * @param result SUCCESS if the read() was successful * @param val the value that has been read */ event void readDone( error_t result, val_t val );}일반 인터페이스에 익숙하지 않다면, <val_t>의 의미와 SenseC.nc의 signature가Read<uint16_t>를 왜 사용하는지에 대해 궁금할 것이다. Read인터페이스는 type 매개변수를 가지기 때문에, 일반 인터페이스 정의라는 것을 알 수 있다. 일반 인터페이스는 nesC Language Reference Manual (version 1.2 and above)에 설명이 되어 있다.이제 일반 인터페이스는 최소한 하나의 type 매개변수를 가진다는 것을 알게 되었을것이다. 같은 타입을 가지고 인터페이스를 제공하거나 사용한다면, 두개의 컴포넌트는서로 연결(wire)될 수 있다.that the readDone event passes a parameter of the<val_t> parameter, which is a placeholder for the actual data type).다시 말하면,SenseC.nc가 Read 인터페이스의 uint16_t 변수를 사용하기 때문에 Read<uint16_t>인터페이스를 제공하는 컴포넌트와만 연결(wire)이 될 수있다. 그래서 SenseC.nc에서는 16비트 부호 없는 정수 센서 데이터를 읽는 것을 예상한다. 예를 들어, SenseC.nc에 Read<uint8_t> 인터페이스를 제공하는 컴포넌트를 연결하면 nesC 컴파일러에서에러가 나게 된다.SenseAppC.nc configuration에서 정의한 연결을 다시 보자. SenseAppC.nc configuration에서 Read<uint16_t>인터페이스를 사용하여 컴포넌트 SenseC.nc이 연결되어지는 것을 다시 살펴보자.흥미로운 줄은SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 116
  • 117. UBee430TM Programming Guidecomponents new DemoSensorC() as Sensor;그리고SenseC.Read -> Sensor;이다.이것의 의미는 일반 DemoSensorC 컴포넌트가 Read<uint16_t>인터페이스를 SenseC.nc에게 제공한다는 것이다.SenseC.nc 모듈이 어떤 센서가 연결되어 있는지 알려줄방법이 없다는 것을 이해하는 것이 중요하다. 사실 센서로부터 데이터를 얻어왔는지여부를 알려줄 수도 없다. 왜냐하면 Read<uint16_t> 인터페이스를 제공하는 어떤 컴포넌트와 연결 될 수 있기 때문이다. micaz 플랫폼처럼 built-in sensors없고 센서보드가 붙어있지 않은 플랫폼 상에서는 DemoSensorC 컴포넌트는 상수 값을 단순히 리턴하게 된다.마지막 문장의 힌트는 DemoSensorC 컴포넌트는 플랫폼마다 다르다는 것이다: 그러므로 TinyOS 라이브러리에서 DemoSensorC.nc를 찾을 수 없다. 대신에 플랫폼마다다른 DemoSensorC.nc가 작성되어 있다 , 예를 들어 telosb 플랫폼을 위한 DemoSensorC.nc implementation은 micaz 플랫폼을 위한 것과 다를 것이다.이것은 introduction 세션의 첫번째 질문에 대한 답변이다 : 플랫폼에 비의존적인DemoSensorC 컴포넌트는 Sense 또는 Oscilloscope 어플리케이션이 어느 센서를 샘플링하는지 정의한다. 센싱 어플리케이션(Oscilloscope, Sense or RadioSenseToLeds)들은 실행되길 원하는 플랫폼마다 고유 버전 DemoSensorC를 제공한다. 다시 말하면, 센서 보드에는 그들 고유의 DemoSensorC 버전이 딸려있다. (e.g., the basicsbsensorboard for the mica-family of motes define DemoSensorC.nc to be thatboards light sensor)The DemoSensorC componentDemoSensorC 컴포넌트를 조금 더 자세히 살펴보자. DemoSensorC 컴포넌트마다 다음 signature를 가지고 있다.generic configuration DemoSensorC(){ provides interface Read<uint16_t>;}그러나 implementation세션은 플랫폼마다 DemoSensorC가 다르다. 예를 들어, telosb플랫폼에서 DemoSensorC는 MCU 내부 전압 센서로부터 값을 읽어오는 VoltageC라고 불리는 컴포넌트를 초기화한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 117
  • 118. UBee430TM Programming Guidemicaz는 built-in sensors를 가지고 있지 않기 때문에, micaz의 DemoSensorC는 가짜 센서 데이터를 리턴하는 ConstantSensorC 또는 SineSensorC 같은 시스템 라이브러리 컴포넌트를 사용한다.그래서 DemoSensorC는 플랫폼 의존적인 센서 컴포넌트로부터 얻은 센서데이터를Sense 또는 Oscilloscope같은 플랫폼 비의존적인 어플리케이션에서 받을 수 있도록하는 간접적인 센서 데이터 획득하는 수단이다. 일반적으로 센서의 설정은 DemoSensorC에서 예시한 컴포넌트에서 이루어진다.어떻게 플랫폼의 디폴트 센서가 아닌 다른 센서에서 샘플링하기 위해 센서를 바꿀 수있을까? 보통 이 경우 DemoSensorC의 코드 중 한줄 바꾸는 것만 요구된다. telosb플랫폼의 constant 센서 컴포넌트로써 VoltageC 컴포넌트를 ConstantSensorC 컴포넌트로 바꾸기를 원한다면 DemoSensorC에서 다음 라인들만 바꾸면 된다.components new VoltageC() as DemoSensor; ->components new ConstantSensorC(uint16_t, 0xbeef) as DemoSensor;이용 가능한 센서들은 플랫폼에 의존적이다. 센서 컴포넌트들은 보통 각각의 플랫폼서브 디렉터리(tinyos-2.x/tos/platforms) 위치해 있다. 마이크로프로세서에 내장된센서의 경우에는 각각의 칩 서브디렉터리에(tinyos-2.x/tos/chips) 위치한다.ConstantSensorC와 SineSensorC는 tinyos-2.x/tos/system에서 발견 할 수 있다.Running the Sense applicationSense 어플리케이션을 컴파일하기 위해서,/opt/tinyos-2.x/apps/Sense 디렉터리로 이동한다. 컴파일 후 mote에 설치를 한다.$ cd/opt/tinyos-2.x/apps/Sense$ make tmote install[ UBee430의 경우 ]$ cd/opt/tinyos-2.x/apps/Sense$ make UBee430 install다음과 같은 에러가 났다면 해당 플랫폼은 ConstantSensorC컴포넌트를 지원하지 않는 것이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 118
  • 119. UBee430TM Programming GuideSenseAppC.nc:50: component DemoSensorC not foundSenseAppC.nc:50: component `DemoSensorC is not genericSenseAppC.nc:55: no match빠른 해결방법은 tinyos-2.x/tos/platforms/micaz에 있는 DemoSensorC.nc를 현재 사용 중인 플랫폼의 디렉터리로 복사하는 것이다. (어떻게 센서 컴포넌트를 생성하는지에 대한 좋은 시작점은 아마도 TEP 101 and TEP 114이다)mica-family mote와 "basic" (mda100) 센서보드를 사용한다면, 보다 흥미로운 테스트를 할 수 있다. 아래와 같이 컴파일을 해보자.SENSORBOARD=basicsb make platform installmda100s light 센서를 사용하도록 Sense를 컴파일 한다.[UBee430의 경우]UBee430이 USB 포트에 연결되어 있다면, 분리해 본다. 그러면 LED들의 출력이 변하는 것을 확인 할 것이다.센서에서 읽은 하위 세 비트를 출력하는 어플리케이션을 인스톨했다면 노드의 LED들에 출력될 것이다. (0 = off, 1 = on). 하위비트들은, Sense 어플리케이션이 센서에서읽은 리턴 된 정확한 값의 범위를 알 수 없기 때문이다. 그리고 예를 들어, 센서가 읽어 샘플링 된 uint16_t에서 최상위 3비트들은 12비트 ADC에서 의미가 없다. (unlessthe value was left-shifted)읽는 것이 변동되는 센서를 DemoSensorC에서 나타낼 때, LED들의 토클을 보게 될것이다. 그렇지 않으면 Sense는 인상적이지 않을 것이다. 좀 더 흥미로운 어플리케이션인 Oscilloscope를 살펴보자.The Oscilloscope applicationOscilloscope는 센서에서 읽는 것을 PC에서 시각화하는 어플리케이션이다.Oscilloscope가 설치되어 있는 각 노드들은 주기적으로 디폴트 센서에서 샘플링을 한다(DemoSensorC를 통해서). 그리고 10번 센서 값을 읽은 것을 모아서 메시지를 무선으로 브로드캐스트한다.BaseStation 어플리케이션이 실행중인 노드는 메시지를 시리얼통신을 사용하여 PC로포워드를 하게 된다. 따라서 Oscilloscope를 실행하기 위해선 최소한 두 개의 노드가필요하다. BaseStation 어플리케이션이 실행되는 노드는 PC에 연결된다. (BaseStationcan be found at tinyos-2.x/apps/BaseStation and was introduced in the previous lesson) 그리고 Oscilloscope가 실행되는 하나 이상의 다른 노드들이 있어야 한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 119
  • 120. UBee430TM Programming GuideOscilloscopeAppC.nc configuration을 살펴보자.configuration OscilloscopeAppC{}implementation{ components OscilloscopeC, MainC, ActiveMessageC, LedsC, new TimerMilliC(), new DemoSensorC() as Sensor, new AMSenderC(AM_OSCILLOSCOPE), new AMReceiverC(AM_OSCILLOSCOPE); OscilloscopeC.Boot -> MainC; OscilloscopeC.RadioControl -> ActiveMessageC; OscilloscopeC.AMSend -> AMSenderC; OscilloscopeC.Receive -> AMReceiverC; OscilloscopeC.Timer -> TimerMilliC; OscilloscopeC.Read -> Sensor; OscilloscopeC.Leds -> LedsC;}어플리케이션의 실제 implementation은 OscilloscopeC.nc에 있다.아래는 OscilloscopeC.nc의 signature이다.module OscilloscopeC{ uses { interface Boot; interface SplitControl as RadioControl; interface AMSend; interface Receive; interface Timer; interface Read; interface Leds; }}Oscilloscope는 이전 튜토리얼에서 소개되었던 블럭 코드들을 조합한 것이다. Sense어플리케이션처럼 Oscilloscope는 DemoSensorC와 타이머를 사용한다. 그리고 주기적으로 플랫폼의 디폴트 센서로부터 샘플링을 한다. 10번 센서의 값을 읽은 것이 모아지면 OscilloscopeC는 데이터들을 메시지에 넣는다.그리고 AMSend 인터페이스를 통해 메시지를 브로드 캐스트 한다. OscilloscopeC는동기화목적으로 Receive인터페이스를 사용한다. 그리고 SplitControl인터페이스는 무선을 켜기 위해 사용되어진다. mote간의 무선통신에 대해 더 알고 싶다면 Lesson3을읽어보면 된다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 120
  • 121. UBee430TM Programming GuideRunning the Oscilloscope applicationOscilloscope어플리케이션을 설치하기위해 /opt/tinyos-2.x/apps/Oscilloscope로 이동한다. 하드웨어에 맞도록 컴파일 후 mote에 인스톨한다.$ cd /opt/tinyos-2.x/apps/Oscilloscope$ make tmote install,1[ UBee430 ]$ cd /opt/tinyos-2.x/apps/Oscilloscope$ make UBee430 install,1",1"는 노드의 ID를 1로 지정한다. 노드에 ID를 할당하는 것은 GUI상에서 mote들을구별하는데 도움이 된다. 따라서 Oscilloscope가 설치된 모든 노드들에 다른 ID를 지정해야 한다. (예를 들어 두 번째 노드에 Oscilloscope를 설치 할 때는 make tmoteinstall,2를 사용한다. 다른 모트들도 이런 식으로 진행한다. )Oscilloscope가 설치된 노드는 메시지를 전송할 때 마다 두 번째 LED가 점멸된다. 그리고 Oscilloscope 메시지를 다른 노드로 부터 받을 때 마다 세 번째 LED가 점멸된다. : 들어오는 메시지들은 다른 것보다 늦게 켜진 노드들이 따라잡기 위해 연속 숫자동기화를 사용한다. 또한 얼마나 자주 센서 값을 읽었는지 정의를 해서 샘플 레이트를바꾸는데 사용되어진다. 무선연결과 관련된 문제가 생긴 경우 첫 번째 LED가 점멸된다. 또 다른 노드에 BaseStation을 설치한 후 PC에 연결한다. 무선에서 시리얼로 브리지 된 메시지마다 두 번째 LED가 점멸하는 것을 볼 수 있을 것이다.Running the Java GUIPC상에서 센서에서 읽은 값을 시각화하기 위해서 /opt/tinyos-2.x/apps/Oscilloscope/java로 이동한 후 make 명령을 내린다. 필요한 메시지 클래스들과 OscilloscopeJava GUI가 생성/컴파일 된다. 이제 SerialForwarder를 실행시킨다.BaseStation 어플리케이션이 설치된 노드가 PC에 연결되어 있어야한다.(4장 참고)JAVA컴파일 이나 시리얼 연결관련 문제가 있으면 4장을 참고바란다. SerialForwarder가 실행중인 상태에서 ./run 명령을 내려 GUI를 실행시킬 수 있다. (in tinyos-2.x/apps/Oscilloscope/java). 아래와 유사한 윈도우를 보게 될 것이다 .SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 121
  • 122. UBee430TM Programming Guide각 노드들은 다른 색의 라인으로 나타내진다. (you can change the color byclicking on it in the mote table). x축은 packet counter number이고 y축은 센서에서 읽은 값이다. 샘플 레이트를 변경하려면Sample period 입력 박스에 숫자를 수정하면 된다. 엔터를 누르면, 새로운 샘플레이트를 포함한 메시지가 만들어지고BaseStation note를 통해 네트워크상의 다른 노드들로 브로드 캐스트 된다.Clear data 버튼을 클릭함으로써 그래픽 디스플레이상의 수신데이터들을 지울 수 있다.Oscilloscope (or Sense) 어플리케이션은 Read.readDone()이벤트로부터 보내진 raw데이터를 출력한다.어플리케이션의 스코프를 넘어서는 값을 해석하기 위해서는 GUI의오른쪽 아래에 있는 슬라이더바를 조정하여 Y축의 범위를 조정하면 된다.Related Documentation ● nesC reference manual ● TEP 101: ADC ● TEP 114: SIDs: Source and Sink Independent Drivers ● TinyOS Programming GuideSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 122
  • 123. UBee430TM Programming Guide6. Lesson 6: TinyOS Boot and System InitializationLast updated 30 October 2006IntroductionTinyOS에 대해 자주 묻는 질문 중의 하나가 main() 함수가 어디에 있냐는 것이다. 이전 lesson에서, TinyOS boot sequence에 대한 자세한 논의를 미루었었다. 어플리케이션은 Boot.booted 이벤트를 사용한다. 그리고 여기에서부터 시작된다. 이 튜토리얼은 이벤트가 일어나기 전과 후에 일어나는 단계들을 기술하고 있고 컴포넌트를 어떻게 초기화하는지 보여준다.Boot SequenceTinyOS boot sequence는 네 단계로 되어 있다.1. 스케줄러 초기화2. 컴포넌트 초기화3. 부트 프로세스가 완료되면 신호를 보낸다.4. 스케줄러를 실행한다.어플리케이션 레벨의 부트 시컨스 컴포넌트는 MainC이다.(/opt/tinyos-2.x/tos/system/MainC.nc) MainC는 Boot 인터페이스를 제공하고 Init 인터페이스를 SoftwareInit라는 이름으로 사용한다. boot sequences는 2단계의 일부로써SoftwareInit.init()를 호출한다. 3단계에서 Boot.booted 이벤트 신호를 보낸다.디폴트 부트 시컨스는 RealMainP컴포넌트이다. 이름 끝에 P가 있는 것은 이 컴포넌트로 직접 연결을 할 수 없다는 것을 나타낸다. 아래는 RealMainP의 signature이다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 123
  • 124. UBee430TM Programming Guide module RealMainP { provides interface Booted; uses { interface Scheduler; interface Init as PlatformInit; interface Init as SoftwareInit; } }MainC는 Boot인터페이스를 제공하고 SoftwareInit 인터페이스를 사용한다. RealMainP컴포넌트는 두개의 추가적인 인터페이스를 사용한다 PlatformInit and Scheduler.MainC는 어플리케이션으로부터 이 인터페이스들을 숨기기 위해 시스템의 스케줄러와플랫폼의 초기화 sequence를 위해 이 인터페이스들을 자동으로 연결한다.PlatformInit 와 SoftwareInit의 차이점은 하나는 하드웨어, 다른 하나는 소프트웨어로현저하다.PlatformInit은 코어 플랫폼 서비스를 의미 있는 상태로 두어야 하는 책임이 있다.mica플랫폼의 PlatformInit은 clocks을 측정한다.This is the code of RealMainP: implementation { int main() __attribute__ ((C, spontaneous)) { atomic { call Scheduler.init(); call PlatformInit.init(); while (call Scheduler.runNextTask()); call SoftwareInit.init(); while (call Scheduler.runNextTask()); } __nesc_enable_interrupt(); signal Boot.booted(); call Scheduler.taskLoop(); return -1; } default command error_t PlatformInit.init() { return SUCCESS; } default command error_t SoftwareInit.init() { return SUCCESS; } default event void Boot.booted() { } }이 코드는 위에서 기술한 네 단계를 보여준다.Scheduler InitializationSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 124
  • 125. UBee430TM Programming Guide최초의 부트 단계는 스케줄러를 초기화하는 것이다. 컴포넌트가 초기화되기 전에 스케줄러가 초기화되지 못하면 컴포넌트 초기화 루틴을 post task 할 수 없다. 모든 컴포넌트들이 태스크가 포스트 되는 것을 요구하는 것은 아니지만, 컴포넌트들이 할 수 있도록 필요한 융통성을 준다. 장기 실행 연산을 허용하기 위해 각 초기화 단계 후에 부트 시컨스는 태스크를 실행한다. 오직 한번만 일어난다. TEP 106에서 TinyOS 스케줄러에 대해 스케줄러를 교체하는 방법을 포함하여 자세히 기술하고 있다.Component initialization.RealMainP가 스케줄러를 초기화 한 후에, 플래폼을 초기화 한다. Init 인터페이스는하나의 명령 Init()로 구현되 있다.tos/interfaces/Init.nc:interface Init { command error_t init();}플랫폼 초기화 단계는 플랫폼 구현하는 사람의 책임이다. 그래서 PlatformInit은 플랫폼 종속적인 초기화 컴포넌트인 PlatformC에 연결된다. 어떤 다른 컴포넌트도PlatformInit에 연결될 수 없다. 초기화를 요구하는 컴포넌트는 Init 인터페이스를 제공하고 그 자신을 MainC의 SoftwareInit 인터페이스에 연결한다.tos/system/MainC.nc:configuration MainC { provides interface Boot; uses interface Init as SoftwareInit;}implementation { components PlatformC, RealMainP, TinySchedulerC; RealMainP.Scheduler -> TinySchedulerC; RealMainP.PlatformInit -> PlatformC; // Export the SoftwareInit and Booted for applications SoftwareInit = RealMainP.SoftwareInit; Boot = RealMainP;}초기화 코드에서 일반적인 문제는 서로 다른 시스템 부분들 사이에 의존성이다.TinyOS에서는 세 가지 방식으로 다룬다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 125
  • 126. UBee430TM Programming Guide ● 하드웨어 종속적 초기화 문제는 각 플랫폼의 PlatformC 컴포넌트 간에 직접 다루어진다. ● 시스템 서비스(예. 타이머, 무선)는 전형적으로 독립적으로 초기화가 가능하도 록 작성된다. 예를 들어, 무선은 타이머를 사용하지만 무선 초기화 할 때 타이 머를 셋업하지 않는다. 오히려 동작을 무선이 시작될 때로 연기한다. 다시 말해 초기화는 서비스에 의해 소유되는 소프트웨어 상태와 하드웨어 상태를 셋업하 기 위해 사용된다. ● 서비스가 여러 개의 컴포넌트들로 나누어졌을 때, 이런 컴포넌트들 중의 하나 를 위한 Init인터페이스는 서비스를 구성하는 다른 컴포넌트의 Init(와 다른)인터 페이스를 호출할 것이다.Signal that the boot process has completed.모든 초기화가 완료되면, MainC의 Boot.booted() 이벤트가 발생된다. 이제 컴포넌트들은start함수를 호출하고 다른 컴포넌트상의 명령을 호출해도 된다.Blink 어플리케이션을 다시 보면, booted() 이벤트에서 타이머가 시작 되어 진다. 이 booted 이벤트는TinyOS에서 유닉스 어플리케이션의 main함수와 대등한 것이다.Run the scheduler loop.시스템이 부트 되고 필요한 서비스들을 시작했다는 것을 어플리케이션이 알리면,TinyOS는 코어 스케줄링 루프에 들어간다. 스케줄러는 테스크가 큐에 있는 한 실행한다. 비어있는 큐가 탐지되자마자, 스케줄러는 마이크로컨트롤러를 하드웨어 자원애서허용하는 최하위 전력 상태에 들어가게 한다. 타이머를 가지고 실행이 될 때에만UART같은 주변장치버스가 아닌 최하위 전력 상태를 허용한다. TEP 112 에 이 프로세스가 어떻게 동작하는지 기술되어 있다.인터럽트가 처리될 때까지 프로세서는 슬립모드로 전환한다. 인터럽트가 도착하면,MCU는 슬립상태에서 나와 인터럽트 핸들러를 수행한다. 이로 인해 스케줄러 루프가다시 실행된다. 인터럽트 핸들러가 여러 태스크를 포스트하게 되면, 스케줄러는 태스크유에 있는 태스크들을 모두 수행한 후, 다시 슬립상태가 된다.Boot and SoftwareInitFrom the perspective of an application or high-level services, 부트시컨스의 중요한 두개의 인터페이스들은( the two important interfaces in the boot sequence arethose which MainC exports: Boot and SoftwareInit.) Boot 인터페이스는 전형적으로SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 126
  • 127. UBee430TM Programming Guide상위 수준의 어플리케이션에 의해서만 다루어진다. : Boot인터페이스는 타이머와 무선같은 서비스를 시작한다. 대조적으로 SoftwareInit은 시스템의 많은 다른 부분들을 관계한다. 상태나 설정을 초기화하기 위해 컴포넌트가 한번 실행되는 코드를 필요로 하면, SoftwareInit와 연결되어야 한다.전형적으로, 초기화가 필요한 서비스 컴포넌트들은 자신을 SoftwareInit에 연결한다.(Typically, service components that require intialization wire themselves toSoftwareInit rather than depend on the application writer to do so) 어플리케이션개발자가 크고 복잡한 시스템을 작성 중일 때, 모든 초기화 루틴들을 추적하는 것은어렵다. 그리고 하나가 호출되지 않았을 때 디버깅 하는 것도 매우 힘들다. 버그를 방지하고 어플리케이션 개발을 단순하게 하기 위해서, 일반적으로 서비스들은auto-wiring을 사용한다. auto-wiring이라는 용어는 어플리케이션을 만드는 사람이 해결하도록 보내주는 것이 아니라 컴포넌트가 자동적으로 의존성 있는 것들과 연결하는것을 가리킨다.이런 경우, Init 인터페이스를 제공하기 보다는, 서비스 컴포넌트를 해당되는 것의 Init인터페이스를 RealMainC으로 연결한다. 예를 들어 PoolC는 일반 메모리 풀 추상화이다. PoolC는 동적 할당을 위해서 메모리 오브젝트의 모음을 선언하는 것을 허용한다.Underneath, 이것의 구현은(PoolP) 데이터 구조체를 초기화하는 것을 필요로 한다.컴포넌트가 올바르게 동작하기 위해서는 구조체 초기화가 반드시 필요하다. 어플리케이션을 만드는 사람이 이것에 대해 걱정을 하지 않도록 한다. PoolC컴포넌트는 PoolP인스턴스를 생성한다. 그리고 이것을 MainC.SoftwareInit에 연결한다.generic configuration PoolC(typedef pool_t, uint8_t POOL_SIZE) { provides interface Pool;}implementation { components MainC, new PoolP(pool_t, POOL_SIZE); MainC.SoftwareInit -> PoolP; Pool = PoolP;}실제로는, MainP가 SoftwareInit.init를 호출할 때를 의미한다, 수많은 컴포넌트들에서Init.init을 호출한다. 전형적인 큰 프로젝트에서, 초기화 시컨스는 30개의 컴포넌트를필요로 한다. 그러나 어플리케이션 개발자는 이것에 대해 걱정 할 필요가 없다.: 정확하게 작성된 컴포넌트는 자동으로 이것들을 처리한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 127
  • 128. UBee430TM Programming GuideRelated Documentation ● TEP 106: Schedulers and Tasks ● TEP 107: Boot SequenceProgramming Hint 8: 소프트웨어 추상화의 상위 레벨 설정에서, Init을 MainC에 자동연결한다(auto-wire). 이것은 프로그래머가 Init에 연결하는 짐을 덜어준다. 부트 시컨스에서 불필요한 작업을 제거해 주며, 연결하는 것을 잊어서 발생할 수 있는 버그를제거한다. From TinyOS ProgrammingSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 128
  • 129. UBee430TM Programming Guide7. Lesson 7: Permanent Data StorageLast Modified: April 13, 2007이번 lesson에서는 TinyOS상에서 비휘발성 데이터 스토리지에 대해 소개한다. 전원공급이 끊기거나 노드가 새로운 이미지로 재 프로그래밍 되더라도 비휘발성 스토리지는 데이터를 지속시키는 것을 허용한다.작은 오브젝트들, 로그파일들, 커다란 오브젝트들을 포함하는 데이터 스토리지에 친숙해 질것이다. mote상에 비휘발성 데이터 스토리지를 지원하는 TinyOS의 인터페이스들과 컴포넌트들에 대해 접하게 될 것이다. 그리고 어떻게 사용 하는지에 대해 배우게될 것이다.* 다수의 다양한 타입의 데이터를 저장할 수 있도록 플래시 칩을 볼륨으로 나눈다.* power cycle에도 남도록 설정 데이터를 저장한다.* 로깅(logging) 추상화를 사용하여 패킷들을 저장한다. 그리고 power cycle 이후에오버헤드 패킷들을 재전송한다.IntroductionTinyOS 2.x에서는 세 가지 기본적인 스토리지 추상화을 제공한다 : 작은 오브젝트, 순환 로그, 큰 오브젝트( small objects, circular logs, and large objects ) 또한,TinyOS 2.x에서는 근원적인 스토리지 서비스를 추상화하기위한 인터페이스와 이런 인터페이스들을 제공하는 컴포넌트들을 제공한다.Interfaces스토리지 시스템의 전체 기능에 익숙해지기 위해서 tos/interfaces 디렉터리에 있는일부 인터페이스들과 tos/tpes 디렉터리에 정의된 타입들을 살펴보자. ● BlockRead ● BlockWrite ● Mount ● ConfigStorage ● LogRead ● LogWrite ● Storage.hComponentsSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 129
  • 130. UBee430TM Programming Guide컴포넌트는 인터페이스에 대한 구체적인 구현을 제공한다. 이런 컴포넌트들과 익숙해져야 한다. 인터페이스를 제공하는 컴포넌트와 어플리케이션에서 사용하는 인터페이스를 소스코드에서 명시하는 것이 필요하기 때문이다. ● ConfigStorageC ● LogStorageC ● BlockStorageCImplementations앞에 나온 컴포넌트들은 이런 추상화에 대한 플랫폼 종속적인 구현들이다. TinyOS에서 다수의 플랫폼을 지원하므로, 각각의 플랫폼은 스토리지 드라이버에 대한 자신만의구현을 가지고 있어야 한다. 스토리지 클라이언트들을 내부적인 칩 종속적인 구현에연결할 수 있도록 플랫폼 종속적인 상수들 또는 다른 세부사항들(e.g. erase size)을알고 있는 것이 필요 할 것이다.예를 들어, 앞에 나온 컴포넌트나 인터페이스들은 Telos와Tmote Sky mote들에서 사용되는 플래시 메모리인ST Microelectronics M25Pxx family에 한정된 것들이다.TinyOS 의 make 시스템에서 적절한 드라이버를 자동으로 포함시키기 때문에 이런 파일들이 어디에 있는지에 대해 걱정을 할 필요는 없다. 그러나 어떤 컴포넌트들이 호출되는지는 알고 있는 것이 필요하다. 왜냐하면 컴포넌트 선언에서 해당 컴포넌트들을나열해야 하기 때문이다.좀더 알고 싶다면, 다음 링크들은 Mica2/MicaZ motes에서 사용되어지는 플래시 메모리인 Atmel AT45DB family의 구현을 열람할 수 있게 할 것이다. ● ConfigStorageC ● LogStorageC ● BlockStorageC마지막으로, 다음 링크들은 인텔 imote2 플래시 메모리에 대한 구현을 열람할 수 있게 할 것이다. ● ConfigStorageC ● LogStorageC ● BlockStorageCSOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 130
  • 131. UBee430TM Programming GuideVolumesTinyOS 2.x는 플래시 칩을 하나 이상의 고정된 크기의 볼륨으로 나눈다. XML파일을사용하여 컴파일 시간에 명시한다. 볼륨 테이블이라고 불리는 파일은 어플리케이션 개발자가 이름, 크기, 옵션으로 플래시에서 각 볼륨의 베이스 주소를 명시 하는 것을 허용한다. 각 볼륨은 단일 타입의 스토리지 추상화를 제공한다. (예를 들면 설정, 로그,블록 스토리지). 추상화 타입은 플래시 메모리상 데이터의 물리적 레이아웃을 정의한다. 볼륨 테이블은 아래와 같을 것이다.<volume_table> <volume name="CONFIGLOG" size="65536"/> <volume name="PACKETLOG" size="65536"/> <volume name="SENSORLOG" size="131072"/> <volume name="CAMERALOG" size="524288"/></volume_table>특정 어플리케이션을 위한 볼륨테이블은 어플리케이션 디렉터리에 위치해 있다.(make명령을 사용하여 어플리케이션을 컴파일하는 곳) 볼륨테이블의 이름은 volumes-CHIPNAME.xml이어야 한다. CHIPNAME에는 플랫폼 종속적인 플래시 칩의 이름이 오면 된다. 예를 들어 Telos mote는 플래시 메모리ST Microelectronics M25P family를 사용한다 .이들 칩을 위한 드라이버들은 tos/chips/stm25p 디렉터리에서 찾을 수 있다. 그러므로, 스토리지 추상화를 사용하는 Telos기반의 어플리케이션은 volumes-stm25p.xml이름의 파일이 필요하다.size 매개변수는 특정 플래시 칩을 위한 erase unit의 배수이다. 좀 더 자세한 내용은TEP103의 세션 4.1을 보기 바란다.Storing Configuration Data이번 lesson은 비휘발성 스토리지에 어떻게 설정 데이터를 쓰고 읽을 수 있는지를 알려준다. 일반적으로 설정 데이터는 다음 특성들의 일부분을 보여준다. 설정파일은 수십 바이트부터 수백바이트까지로 사이즈가 제한되어 있다. 설정 값들은 노드마다 동일하지 않다. 설정 값들은 이전에 설정항목의 배치가 알려져 있지 않고 노드 상에 실행되고 있는 소프트웨어를 위한 것이기 보다는 하드웨어 의존적인 값들이다.설정 데이터들은 노드마다 동일하지 않거나 설정 항목의 배치가 알려져 있지 않기 때문에 컴파일 시간에 설정 값을 지정하는 것을 어렵다. 설정 데이터들이 하드웨어에 의존적이므로 재 컴파일해도 남아있어야 한다. 프로그램 이미지에서 값들을 엔코딩 하는것은 간단한 접근이 아니다. 리셋 또는 power cycle 후에 데이터가 남아있지 않기 때문에 휘발성 메모리에 설정데이터를 저장하는 것은 문제가 된다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 131
  • 132. UBee430TM Programming Guide요약하면, 설정 데이터는 반드시 노드의 리셋, power cycle 또는 재 프로그래밍을 하더라도 지속되어야 한다. 그리고 나중에 복구가 되어야 한다. 이런 방식으로 설정데이터를 지속하고(persist ) 복구하는 능력은 많은 시나리오에서 유용하다. ● Calibration. 센서를 위한 Calibration coefficients은 공장 출하 시 설정되고 지 속 된다.그래서 선적을 위해 전원을 제거하거나 노드가 post-calibration을 재 프로그램 할 때 소실되지 않는다. 예를 들어, hypothetical temperature sensor 는 매개변수들이 하드웨어 종속적이기 때문에 측정된 offset과 gain을 가지고 있어야 한다. 그리고 출력 전압을 온도의 보다 유용한 섭씨로 변환하는 것이 필요하기 때문에 저장되어야 한다. 이런 센서를 위한 측정 데이터는 다음과 같 다. typedef struct calibration_config_t { int16_t temp_offset; int16_t temp_gain; } calibration_config_t; ● Identification. IEEE-compliant MAC addresses나 TinyOS의 TOS_NODE_ID 매 기변수처럼 디바이스 식별 정보는 노드들이 하드웨어 종속적이지 않음에도 불 구하고 노드들마다 동일하지 않다. 노드에 지정이 되고 나면, 이 값은 리셋, power cycle, 연산을 재 프로그래밍 하더라도 지속된다. 소실되거나 다른 노드 에게 재 지정되지 않는다. typedef struct radio_config_t { ieee_mac_addr_t mac; uint16_t tos_node_id; } radio_config_t; ● Location. 노드 위치 정보는 컴파일 시간에는 알려져 있지 않는다. 노드들을 배 치 할 때 알수있다. 예를 들어, 어플리케이션은 노드의 좌표를 다음처럼 저장할 것이다. 그리고 필드에서 이런 값들을 업데이트한다. typedef struct coord_config_t { uint16_t x; uint16_t y; uint16_t z; } coord_config_t;SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 132
  • 133. UBee430TM Programming Guide ● Sensing. 샘플링 주기, 필터 계수, 검출 thresholds 같은 Sensing and signal processing 매개변수들은 필드 상에서 보정되어야 한다. 이런 어플리케이션을 위한 설정 데이터는 다음과 같을 것이다. typedef struct sense_config_t { uint16_t temp_sample_period_milli; uint16_t temp_ema_alpha_numerator; uint16_t temp_ema_alpha_denominator; uint16_t temp_high_threshold; uint16_t temp_low_threshold; } sense_config_t;스토리지의 타입을 왜 사용하는지에 대해 토의했으니, 이제 어떻게 사용하는지 알아보자. Mount와 ConfigStorage 추상화를 어떻게 사용하는지 설명하기 위해 간단한 데모어플리케이션을 구현할 것이다.타이머 주기는 플래시로부터 데이터를 읽어오는 것과 플래시에 다시 기록하는 것으로나눌수 있다. 타이머의 시간이 만료될 때 마다 LED는 토클 된다. 코드를 나누기 전에,약간의 high-level design 고려해야 할 사항에 대해 얘기해보자.See tinyos-2.x/apps/tutorials/BlinkConfig/ for the accompanying code.처음 사용하기 전에, 볼륨은 어떤 유효한 데이터를 포함하고 있지 않다. 그래서 코드에서는 볼륨의 첫 번째 사용을 감지하고 적절한 조치를 취해야 한다.(e.g. preload itwith default values). Similarly, 볼륨의 데이터 레이아웃이 변경 되었을 때 (forexample, if the application requires new or different configuration variables), 어플리케이션 코드는 이것을 감지하고 적절한 조치를 취해야 한다.(e.g. migrate the olddata to the new layout or erase the volume and reload the defaults). 이런 요구로인해 볼륨 버전을 추적하는 방법을 가지고 있어야 한다. 버전 숫자를 이런 목적을 위해 사용해야 한다. (and will need to maintain a discipline of updating the versionnumber when the data layout changes incompatibly). 설정 구조체는 버전 번호와blink period를 위해 다음과 같은 항목들을 가지고 있을 것이다.typedef struct config_t { uint16_t version; uint16_t period;} config_t; 1. volumes-CHIPNAME.xml파일을 생성하고 파일에 볼륨 테이블을 입력한다. 그 리고 파일을 어플리케이션 디렉터리에 둔다.CHIPNAME은 타겟 플랫폼에서 사SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 133
  • 134. UBee430TM Programming Guide 용되는 플래시 칩의 이름이라는 것에 유의하라. 예를 들어, Telos 플랫폼을 위 한 stm25p나 MicaZ 플랫폼을 위한 at45db가 될수 있다. 우리가 살펴보고 있 는 파일은 다음과 같은 내용으로 되어 있을 것이다. <volume_table> <volume name="LOGTEST" size="262144"/> <volume name="CONFIGTEST" size="131072"/> </volume_table> 이 볼륨 정보는 툴체인에 의해 헤더파일을 생성하기 위해 사용되어진다. 그러 나 자동 생성된 파일은 수작업으로 포함시켜야 한다. 다음 줄을 ConfigStorage C 컴포넌트를 선언한 설정파일에 추가해야 한다. (e.g. BlinkConfigAppC.nc): #include "StorageVolumes.h" 2. BlinkConfigC는 Mount와 ConfigStorage 인터페이스를 사용하는 간단한 데모 를 위한 어플리케이션 코드이다. ( ConfigStorage을 Config으로 이름을 변경하 는 것에 유의하라). module BlinkConfigC { uses { ... interface ConfigStorage as Config; interface Mount; ... } } 3. 각 인터페이스는 제공 되어질 구현과 연결되어야 한다. configuration BlinkConfigAppC { } implementation { components BlinkConfigC as App; components new ConfigStorageC(VOLUME_CONFIGTEST); ... App.Config -> ConfigStorageC.ConfigStorage; App.Mount -> ConfigStorageC.Mount; ... } 4. 플래시 칩이 사용되기 전에, mount/mountDone 두 단계 명령을 사용하여 마 운트 해야 한다. boot sequence에 어떻게 연속적으로 실행시켜야 하는지 보자SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 134
  • 135. UBee430TM Programming Guide event void Boot.booted() { conf.period = DEFAULT_PERIOD; if (call Mount.mount() != SUCCESS) { // Handle failure } } 5. Mount.mount가 성공적이었다면, Mount.mountDone이벤트 신호가 된다.다음 코드는 볼륨이 유효한지를 어떻게 검사하는지를 보여준다. 유효하다면 ConfigStore.read명령을 사용하여 볼륨에서 어떻게 읽는것을 개시해야할지를 보여준다. 볼륨이 유효하지 않다면 Config.commit 호출하는 것이 볼륨을 유효하게 만든다. ( 유닉스 시스템의 fsync 시스템 호출이 버퍼에 있던 데이터를 비우고 디스크에 기록하는 것처럼 이 호출은 버퍼에 저장되어 있던 데이터를 비우는데 사용되어 진다.) event void Mount.mountDone(error_t error) { if (error == SUCCESS) { if (call Config.valid() == TRUE) { if (call Config.read(CONFIG_ADDR, &conf, sizeof(conf)) != SUCCESS) { // Handle failure } } else { // Invalid volume. Commit to make valid. call Leds.led1On(); if (call Config.commit() == SUCCESS) { call Leds.led0On(); } else { // Handle failure } } } else{ // Handle failure } } 6. 읽기가 성공하면,Config.readDone 이벤트가 일어난다. 이런 경우, 성공적인 읽기였는지 검사를 해야 한다. 성공적이었다면 버전 번호를 검사한다. 기대했던 버전 번호와 일치하면 설정데이터를 지역변수로 복사한다. 그리고 설정 값을 조정 한다.버전번호가 일치하지 않으면, 설정 정보의 값을 기본 값으로 설정한 다. 마지막으로 Config.write 함수를 호출한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 135
  • 136. UBee430TM Programming Guide event void Config.readDone(storage_addr_t addr, void* buf, storage_len_t len, error_t err) __attribute__((noinline)) { if (err == SUCCESS) { memcpy(&conf, buf, len); if (conf.version == CONFIG_VERSION) { conf.period = conf.period/2; conf.period = conf.period > MAX_PERIOD ? MAX_PERIOD : conf.period; conf.period = conf.period < MIN_PERIOD ? MAX_PERIOD : conf.period; } else { // Version mismatch. Restore default. call Leds.led1On(); conf.version = CONFIG_VERSION; conf.period = DEFAULT_PERIOD; } call Leds.led0On(); call Config.write(CONFIG_ADDR, &conf, sizeof(conf)); } else { // Handle failure. } } 7. ConfigStore.write가 호출되고 Config.writeDone 이벤트가 발생하면 데이터가 플래시에 기록될 필요가 없다. 데이터가 플래시에 기록되는 것을 확실하게 하 기위해선ConfigStore.commit 호출이 요구된다. event void Config.writeDone(storage_addr_t addr, void *buf, storage_len_t len, error_t err) { // Verify addr and len if (err == SUCCESS) { if (call Config.commit() != SUCCESS) { // Handle failure } } else { // Handle failure } } 8. 마지막으로, Config.commitDone event이벤트 신호가 발생하면, 데이터는 플 래시에 기록된다. 노드 power cycle에도 남게 된다SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 136
  • 137. UBee430TM Programming Guide event void Config.commitDone(error_t err) { call Leds.led0Off(); call Timer0.startPeriodic(conf.period); if (err == SUCCESS) { // Handle failure } }Logging Data이벤트의 신뢰성 있는 로깅(logging)과 작은 데이터 아이템은 일반적인 어플리케이션의 요구조건이다. 로그 된 데이터는 시스템 충돌이 일어나도 소실되면 안 된다. 로그는 선형(볼륨이 꽉 차면 로깅을 중단한다.) 또는 환형(볼륨이 꽉 차면 오래전에 기록된데이터에 재기록을 한다.)이 될 수 있다.TinyOS의 LogStorage 추상화는 이런 요구조건들을 지원한다. 로그는 기록 기반이다.:각각의 LogWrite.append호출은 새로운 레코드를 생성한다. 시스템이 고장 나면(충돌또는 power cycle), 로그의 끝에 있는 레코드가 소실된다. 환형 로그가 다시 처음부터재기록될 때, 로그의 시작부분에 있는 레코드만 소실된다.데모 어플리케이션 PacketParrot은 어떻게 LogRead 추상화를 사용하는지 알려 준다.노드는 수신된 패킷을 환형 로그에 기록한다. 그리고 power is cycled 되었을 때 로그에 기록되었던 패킷(or at least the parts of the packets above the AM layer)들을 재전송한다.발취된 코드의 전체소스코드는 tinyos-2.x/apps/tutorials/PacketParrot/ 에 있다.무선으로부터 플래시로 패킷을 받으면 어플리케이션은 패킷을 로그에 기록 한다.연속적인 power cycle에서 어플리케이션은 로그에 기록되었던 패킷을 전송하고, 로그의내용을 지운다. 그리고 패킷을 로그에 기록하는 것을 계속 한다.레드 LED는 로그가지워질 때 켜진다. 블루(옐로) LED는 패킷이 수신될 때 켜졌다가 패킷이 성공적으로로그에 기록되면 꺼진다. 블루(옐로) LED는 패킷이 수신되었지만 로그에 기록되지 못하면 계속 켜져 있게 된다. power cycle이후로 로그에 기록되었던 패킷이 전송될 때그린 LED는 빠르게 깜박인다. 1. 첫 단계는 로그를 사용할 때 어떤 데이터를 로그에 저장하기를 원하는지 결정하는 것이다. 이 경우, 타입의 구조체를 선언한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 137
  • 138. UBee430TM Programming Guide typedef nx_struct logentry_t { nx_uint8_t len; message_t msg; } logentry_t; 2. Config 스토리지와는 다르게, 로그 스토리지는 어플리케이션에 의해 마운트 된 볼륨을 필요로 하지 않는다. 대신, 버퍼에서 읽는 것으로 충분하다. 수 바이트 읽은 것은 LogRead.read에게 넘겨진다. (Instead, a simple read suffices in which a buffer and the number of bytes to read are passed to LogRead.read:) event void AMControl.startDone(error_t err) { if (err == SUCCESS) { if (call LogRead.read(&m_entry, sizeof(logentry_t)) != SUCCESS) { // Handle error } } else { call AMControl.start(); } } 3. LogRead.read를 호출했을 때 SUCCESS를 리턴하면, 바로 LogRead.readDon e 이벤트가 발생하게 된다. 이벤트가 발생되면, 예상하는 길이와 똑같은 길이 인지 데이터를 검사한다. 만약 그렇다면, 데이터를 사용하고, 그렇지 않다면 로 그파일이 비었거나 동기화를 잃어서 로그가 지워진 것으로 가정한다. event void LogRead.readDone(void* buf, storage_len_t len, error_t err) { if ( (len == sizeof(logentry_t)) && (buf == &m_entry) ) { call Send.send(&m_entry.msg, m_entry.len); call Leds.led1On(); } else { if (call LogWrite.erase() != SUCCESS) { // Handle error. } call Leds.led0On(); } } 4. PacketParrot 어플리케이션은 처음 저장된 message_t구조체로써 무선을 통해 수신된 패킷들을 플래시에 저장한다. 저장되는 크기는 log_entry_t 구조체의 크 기이다. 그리고 나서 LogWrite.append를 호출한다.SOC・Embedded System・Ubiquitous Sensor Network・ARMCopyrightⒸ Huins All rights reserved. 138
  • 139. UBee430TM Programming Guide event message_t* Receive.receive(message_t* msg, void* payload, uint8_t len){ call Leds.led2On(); if (!m_busy) { m_busy = TRUE; m_entry.len = len; m_entry.msg = *msg; if (call LogWrite.append(&m_entry, sizeof(logentry_t)) != SUCCESS) { m_busy = FALSE; } } return msg; } 5. LogWrite.write가 SUCCESS를 리턴하고, 짧은 시간이 지난 후에,LogWrite.app endDone이벤트가 발생하게 된다. 이 이벤트는 쓰기에 대한 세부사항을 리턴 한다. 소스 버퍼, 기록된 데이터의 길이, 환형 &#x