임베디드 SW 프로그래밍을 하다보면 __IO, __O로 선언된 것들을 볼 수 있는데 일반적으로 이것들을 define된 곳으로 들어가보면 volatile 또는 const volatile type인 것을 확인할 수 있다.
일반적으로 Volatile type을 붙이면 해당 변수를 최적화에서 제외하여 항상 메모리에서 접근하도록 한다. 즉, volatile 변수를 참조할 경우 레지스터에 로드된 값을 사용하지 않고 매번 메모리를 참조한다.
Volatile이 필요한 이유
*(unsigned int *)0x888F = 0x0001;
*(unsigned int *)0x888F = 0x0002;
*(unsigned int *)0x888F = 0x0003;
*(unsigned int *)0x888F = 0x0004;
*(unsigned int *)0x888F = 0x0005; // 이 라인만 실행됨
컴파일러는 최적화가 기본으로 설정되어 있으며 메모리 쓰기가 모두 같은 주소에서 이루어질 경우 최종적인 코드 라인만 실행되게 되는데 이때 수행속도 면에서의 이득이 커지게 된다.
하지만 하드웨어의 순차적인 실행이 필요한 임베디드 프로그래밍에서는 이가 치명적인 오류를 일으킬 수도 있기 때문에 Volatile을 붙여 항상 모든 코드 라인들이 실행되게 한다.
이러한 기능덕분에
volatile 키워드는 크게 3가지 경우에 흔히 사용된다.
(1) MIMO(Memory-mapped I/O)
(2) Interrupt Service Routine의 사용
(3) Multi Thread 환경
프로그램의 수행흐름과 상관 없이 외부요인이 변수값을 변경할 수 있을때 Volatile을 적절히 활용하여 임베디드 프로그래밍을 완성할 수 있다.