'directive'에 해당되는 글 2건

  1. 2017.03.18 인터럽트와 volatile 지시자 1
  2. 2014.06.26 Assembly어의 문장 형식 6
Embedded Lecture/Arduino2017. 3. 18. 16:33


AVR 칩을 사용하는 Arduino Uno 보드 혹은 다른 임베디드(Embedded) 시스템에서 전역 변수(globlal variable)는 주메모리인 SRAM에 저장되고, 지역 변수(local variable)는 레지스터(register) 영역에 저장됩니다. 그러나 인터럽트 서비스 루틴(ISR)에서의 지역 변수는 SRAM의 Stack 영역에 저장되므로 빠른 인터럽트 처리를 위해서 루틴 내에 잦은 지역 변수의 사용은 바람직하지 않다는 것입니다.


사용자의 코드를 컴파일러(Compiler)는 나름데로 최적화시키는데, 예를 들어 사용자가 전역 변수 지정을 하였지만 그 값이 시종일관 변하지 않는 변수는 컴파일러가 임의로 상수처럼 여겨 레지스터 영역에 저장하게 한다는 것입니다. 물론 한정된 레지스터 영역의 리소스를 낭비하는 것 아니냐고 생각할 수 있지만, 컴파일러 입장에서는 빠른 실행 속도를 위해서 SRAM 보다는 레지스터 영역에 저장한다는 것입니다.


그러나 임베디드 시스템의 경우에 인터럽트 서비스 루틴에서 전역 변수의 갱신이 있었다 하더라도, 컴파일러는 실제 런타임 시 처럼 외부에서 인터럽트가 걸리는 상황이 아니므로 그 값은 변하지 않는다고 생각하여 결국 레지스터에 저장하고 주메모리 상에 변경된 값의 반영이 없다는 것입니다.


이런 상황을 위해서 지시자(directive)인 'volatile'의 선언은 변수형 앞에 두어 컴파일러가 임의로 판단하여 그 변수를 레지스터에 할당하지 못하도록 한다는 것입니다. 즉, 어떤 변수를 volatile로 지정하면 그 변수는 레지스터의 임시 저장소가 아니라 SRAM에서 직접 읽어오도록 컴파일한다는 것입니다.


결론적으로 Arduino 코딩의 경우 보통은 volatile로 정의할 필요는 없으나 인터럽트 서비스 루틴 내부에서 그 값이 변경되는 변수는 반드시 volatile로 선언해야 실시간으로 변경되는 데이터 값을 ISR 루틴 외부에서 읽어올 수 있게 된다는 것입니다.


int pin = 13;

volatile int state = LOW;


void setup()

{

  pinMode(pin, OUTPUT);

  attachInterrupt(0, blink, CHANGE);

}


void loop()

{

  digitalWrite(pin, state);

}


void blink()

{

  state = !state;

}


위의 예제에서 blink() 함수는 인터럽트 서비스 루틴으로 0번 인터럽트 핀의 상태가 변할 때마다 13번에 연결된 LED를 교대로 점멸하게 됩니다. 만일 state 변수에 volatile 선언이 없었다면, 비록 blink() 함수 내에 state 값이 변하더라도 이 함수를 벗어나서는 state 값이 갱신되지 않기 때문에 0번 인터럽트의 상태 변화에 LED의 토글(toggle) 현상이 보이지 않는다는 것입니다.



'Embedded Lecture > Arduino' 카테고리의 다른 글

아날로그 입력 및 온도계 예제  (0) 2017.03.19
아날로그 입력  (0) 2017.03.18
아두이노의 TWI(I2C) 통신  (0) 2017.03.18
아두이노의 시리얼 통신  (0) 2017.03.18
인터럽트의 처리(1)  (0) 2017.03.12
Posted by Nature & Life



Assembly어의 문장 형식

- AVR Assembly어 문장은 총 4부분으로 나누어집니다.

- Comment를 제외하고 120문자까지 사용할 수 있습니다.



1) Label(레이블)

- ':(콜론)'으로 끝납니다.

- 점프할 곳이나 서브루틴의 위치, 데이터 메모리와 RAM에서 데이터가 저장된 위치(주소)의 이름입니다.

- 내부적으로는 label은 16비트 주소값을 갖는 포인터 변수입니다.


2) Instruction(명령어)

- mnemonic(니모닉)과 directive(지시어)로 구별됩니다.

    • mnemonic - 실질적인 명령을 수행하는 명령어입니다(예제1을 참고).

    • directive - 주변 환경변수 등을 지정하는 명령어입니다(예제2를 참고).


3) Operand(오퍼런드)

mnemonic에 대응하는 피연산자입니다.

- 숫자 상수 혹은 directive에 사용되는 수식 등이 옵니다.

- 명령어에 따라서 연산자의 갯수가 0~2개가 되며, 2개 연산자를 사용할 경우 ',(쉼표)'로 분리합니다.


4) Comment(코멘트)

- ';(세미콜론)'으로 시작되며 컴파일시 Assembler는 이를 무시합니다.

- 프로그램에 대한 주석을 넣는 부분입니다.

- C-언어와는 달리 Assembly어는 특히 가독성이 떨어짐으로 비록 스스로 짠 프로그램일지라도 나중에 유지 및 관리를 위하여 반드시 주석을 다는 습관을 들여야 합니다.







'Embedded Programming > Assembler' 카테고리의 다른 글

식별자와 상수  (0) 2014.06.16
Assembler의 장점  (0) 2014.06.14
Posted by Nature & Life