강좌 & 팁
안녕하세요~ 이우영 입니다.
벌써 2월입니다. 입사한지 한달이 지나갔내요 ㅎㅎ.
오늘은 arm에서 인터럽트 금지를 하기위해서 어떻게 구현을 했는지 알아 보도록 하겠습니다.
그럼 복습부터 해보겠습니다!!!
1. 복습!
저번 시간에는 인터럽트를 금지하고 해제하는 함수를 소개 했었는데요. 기억나시나요?
기억이 가물가물 하실꺼 같아 다시 간단하게 보고 넘어 가겠습니다.
▪ local_irq_disable(void) : 프로세서의 인터럽트 처리를 금지
▪ local_irq_enable(void) : 프로세서의 인터럽트 처리를 허가
▪ local_save_flags(unsigned long frags) : 현재의 프로세스의 상태를 저장
▪ local_irq_restore(unsigned long frags) : 저장된 프로세스의 상태를 복구
다시 기억이 나시겠죠? 사용하실려면 <asm/system.h> <- 꼭 추가하셔야 해요!!
그럼 본론으로 넘어 가겠습니다.
2. ARM CPSR
소스를 보기 전에 우선 arm에 대해서 어느정도 공부가 필요합니다.
(다 어셈블러로 구현되어 있습니다 ㅠㅠ)
arm에는 레지스터가 기본으로 16개(R0~R15) + 상태레지스터(CPSR)이 있습니다.
여기서 중요한 것은 CPSR 입니다. 이 CPSR에는 다양한 정보들을 담고 있습니다.
여기서 중요한건 7번 비트 입니다.
이 비트가 0으로 설정되면 인터럽트가 가능한것이고 1로 설정되면 모든 인터럽트는 금지 됩니다.
(소스코드에서 제어를 하겠죠?)
그럼 리눅스의 소스코드를 확인 해보겠습니다.
(arm 번전에 따라 추가된 상태가 있을 수도 있습니다.)
3. ARM에서 구현 방법
커널 2.6.29 버전에서 arm에 대한 구현은 /arch/arm/include/asm/irqflas.h 에 정의 되어 있습니다.
우선 local_irq_disable() 은 실제로 raw_local_irq_disable() 함수가 호출됩니다.
소스코드는 다음과 같습니다.
62#define raw_local_irq_disable() \ 63 ({ \ 64 unsigned long temp; \ 65 __asm__ __volatile__( \ 66 "mrs %0, cpsr @ local_irq_disable\n" \ 67" orr %0, %0, #128\n" \ 68" msr cpsr_c, %0" \ 69 : "=r" (temp) \ 70 : \ 71 : "memory", "cc"); \ 72 })
보시는것과 같이 어셈블러로 작성 되어 있습니다. mrs 명령을 통해 cpsr 값을 얻어옵니다.
그리고 orr 명령을(or 연산) 통해128(이진수 1000 0000 입니다.)과 7번 비트를 1로 설정해 줍니다.
마지막으로 msr 명령을 통해 다시 cpsr에 저장 합니다.
(의외로 심플합니다. 하지만 명령어를 모르면 어렵겠죠? ㅎㅎ)
local_irq_enable() 함수는 raw_local_irq_enable()이 호출 됩니다.
47#define raw_local_irq_enable() \ 48 ({ \ 49 unsigned long temp; \ 50 __asm__ __volatile__( \ 51 "mrs %0, cpsr @ local_irq_enable\n" \ 52" bic %0, %0, #128\n" \ 53" msr cpsr_c, %0" \ 54 : "=r" (temp) \ 55 : \ 56 : "memory", "cc"); \ 57 })
이것도 아까와 비슷합니다.
역시 mrs 명령을 통해 cpsr 값을 얻어옵니다.
여기서 달라지는데요 bic 명령으로 통해 해당비트를 (128,7번째 비트) 0으로 만들어 줍니다.
그리고 다시 msr 명령을 통해 cpsr에 저장 합니다.
local_save_flags() 와 local_irq_restore() 는 더 간단 합니다.
(다만 방법을 모르면 완전 어렵습니다 ㅎㅎㅎ)
109#define raw_local_save_flags(x) \ 110 ({ \ 111 __asm__ __volatile__( \ 112 "mrs %0, cpsr @ local_save_flags" \ 113 : "=r" (x) : : "memory", "cc"); \ 114 })
간단하게 x로 들어온 변수에 mrs 명령으로 얻은 cpsr 값을 저장 합니다.
119#define raw_local_irq_restore(x) \ 120 __asm__ __volatile__( \ 121 "msr cpsr_c, %0 @ local_irq_restore\n" \ 122 : \ 123 : "r" (x) \ 124 : "memory", "cc")
이건 반대로 x로 넘어온 값을 msr 명령을 통해 cpsr에 저장 합니다.
이렇게 간단하게 arm에서 구현한 소스코드를 보았습니다.
(인터럽트 관련 다른 함수들도 있으니 더 살펴 보시기 바랍니다.)
그럼 오늘은 여기서 끝이구요 다음 시간에는 직접 테스트를 해보도록 하겠습니다.
그럼 다음시간에 만나요~~
빠른만남을 원하시면 http://ms-osek.org/ 여기로 찾아오세요~