임베디드에서의 입출력 (I/O) 처리 방식은 2가지입니다. 하나는 메모리랑 입출력을 동일취급해서, 메모리 조작으로 입출력을 조작하는 경우 (Memory Mapped I/O) 이고요, 다른 한 쪽은 I/O 명령어가 따로 있는 쪽이죠. (Isolated I/O)
요새라면 보통 메모리를 조작해서 입출력을 조작하는 전자쪽입니다.
이러다보면 문제가 생기는데요, CPU안에 있는 레지스터 (일종의 저장소) 에 비해서 메모리는 미치도록 속도가 느리기 때문에, 그 점을 극복하기 위해서 캐시를 씁니다. 메모리의 내용을 조금 더 빠른 캐시에 가져다놓고 쓰는거죠. 하지만 입출력이 등장하면 어떨까요?!
입출력의 상태를 메모리 (메모리 취급하고 있지만 사실 I/O) 로부터 캐시로 가져온 다음에 그걸 갱신하지 않게 되면, 그대로 프로그램이 멈춰버리는 거죠. [ CPU : 슬라이드 스위치야, 넌 ON 상태니? 캐시 : 응! / (OFF로 바뀐 뒤에) CPU : 슬라이드 스위치야, 넌 ON 상태니? (캐시로부터 읽어온 뒤에) 캐시 : 응! ] 같은 상황이 벌어지는 거죠. (자세한 건 컴퓨터 구조를 공부하세요)
그래서, volatile이라는 키워드를 씁니다. 변수를 선언할 때 이 키워드를 사용하면, 컴파일러가 이 변수를 최적화하지 않게 됩니다. 그러면 입출력 정보를 캐시에 넣어놓고 읽어오는 바보같은 짓은 안 하게 되겠죠.
volatile unsigned char * Leds = (unsigned char *) (0x81400000 + 3);
ps. C에 이런 키워드가 있는지도 몰랐다는 게 참...