가장 쓰이지 않는 C/C++ 언어의 volatile 이라는 키워드가 있다.
이 키워드는 대부분의 참고 서적들이 컴파일러의 최적화를 막아준다고만 적어둘 정도로 사용 빈도수가 적기도하고 중요도 까지도 낮은 그런 키워드인 셈이다. 하지만 이 키워드가 임베디드 소프트웨어 에서는 중요한 키워드중 하나가 된다. 거의 하드웨어가 사용하는 메모리 선언 시에 사용되고 다음과 같은 경우에 사용되는 편이다.
이렇게 3가지에 사용되는데 임베디드에서는 주로 아래와 같은 예시들과 같은 경우에 주로 사용된다.
예시 1)
unsigned int* test;
test = (unsigned int*)0x1020;test = (unsigned int*)0x1028;
예를 들어서 다음과 같은 코드가 있을때 컴파일러는 중간 문장은 필요 없는 것으로 판단하고 제거한뒤 컴파일 할것이다.
unsigned int* test;
test = (unsigned int*)0x1028;
결과 적으로는 위 문장만 실행되는데 volatile 키워드를 사용하면 이것들이 전부 컴파일 되서 전부의미를 가지게 된다
volatile unsigned int* test;
test = (volatile unsigned int*)0x1020;test = (volatile unsigned int*)0x1028;
예시 2)
예를 들어 0x1234에 8비트의 status 레지스터가 있고, 이 레지스터가 0이 아닌 값을 가질때까지 폴딩하기 위해서 아래와 같은 코드를 작성했다.(루시퍼님 블로그의 예시가 적당해서 가져왔다)
INT8U *ptr = (INT8U *)0x1234;
while (*ptr == 0)
만약 옵티마이징을 키게 된다면 이것은
move ptr, #0x1234
move a, @ptr
loop bz loop
이렇게 다시는 0x1234값을 받아오지 않게 어셈블리 코드가 짜여진다.결국에는 무한 루프에 빠지게 된다. 이럴때 volatile 을 사용하게 되는데
INT8U volatile * ptr = (INT8U volatile *)0x1234;
위 코드를 컴파일 시키면 아래와 같이 어셈블리 코드가 짜여진다.
mov ptr, #0x1234
loop mov a, @ptr
bz loop
코드 상에서 보이듯계속해서 0x1234의 값을 받아와서 루프문을 돌게 되고 위 코드와는 다르게 언젠가 status 가 0이 된다는 가정하에 루프를 탈출할수 있게된다.
더 자세한 내용은 http://m.blog.naver.com/eslectures/80143556699 <- 요기 가서 보면 될듯....
참고)
https://ko.wikipedia.org/wiki/Volatile_%EB%B3%80%EC%88%98
http://blog.naver.com/gas16/10012367708
이 키워드는 대부분의 참고 서적들이 컴파일러의 최적화를 막아준다고만 적어둘 정도로 사용 빈도수가 적기도하고 중요도 까지도 낮은 그런 키워드인 셈이다. 하지만 이 키워드가 임베디드 소프트웨어 에서는 중요한 키워드중 하나가 된다. 거의 하드웨어가 사용하는 메모리 선언 시에 사용되고 다음과 같은 경우에 사용되는 편이다.
- 메모리 맵 입출력(MMIO)을 제어
- 인터럽트 서비스 루틴 사용
- 멀티 쓰레드 환경
이렇게 3가지에 사용되는데 임베디드에서는 주로 아래와 같은 예시들과 같은 경우에 주로 사용된다.
예시 1)
unsigned int* test;
test = (unsigned int*)0x1020;test = (unsigned int*)0x1028;
예를 들어서 다음과 같은 코드가 있을때 컴파일러는 중간 문장은 필요 없는 것으로 판단하고 제거한뒤 컴파일 할것이다.
unsigned int* test;
test = (unsigned int*)0x1028;
결과 적으로는 위 문장만 실행되는데 volatile 키워드를 사용하면 이것들이 전부 컴파일 되서 전부의미를 가지게 된다
volatile unsigned int* test;
test = (volatile unsigned int*)0x1020;test = (volatile unsigned int*)0x1028;
예시 2)
예를 들어 0x1234에 8비트의 status 레지스터가 있고, 이 레지스터가 0이 아닌 값을 가질때까지 폴딩하기 위해서 아래와 같은 코드를 작성했다.
INT8U *ptr = (INT8U *)0x1234;
while (*ptr == 0)
만약 옵티마이징을 키게 된다면 이것은
move ptr, #0x1234
move a, @ptr
loop bz loop
이렇게 다시는 0x1234값을 받아오지 않게 어셈블리 코드가 짜여진다.결국에는 무한 루프에 빠지게 된다. 이럴때 volatile 을 사용하게 되는데
INT8U volatile * ptr = (INT8U volatile *)0x1234;
위 코드를 컴파일 시키면 아래와 같이 어셈블리 코드가 짜여진다.
mov ptr, #0x1234
loop mov a, @ptr
bz loop
코드 상에서 보이듯계속해서 0x1234의 값을 받아와서 루프문을 돌게 되고 위 코드와는 다르게 언젠가 status 가 0이 된다는 가정하에 루프를 탈출할수 있게된다.
더 자세한 내용은 http://m.blog.naver.com/eslectures/80143556699 <- 요기 가서 보면 될듯....
참고)
https://ko.wikipedia.org/wiki/Volatile_%EB%B3%80%EC%88%98
http://blog.naver.com/gas16/10012367708
댓글
댓글 쓰기