ARM System Developer's Guide
- Designing and Optimizaing System Software
#####
Exception Handling
Interrupts
Interrup Handiling Schemes
### 9.2. Interrupts
> 인터럽트의 두가지 종류
- 외부 주변장치에 의해 exceptions을 발생시키는 Interrupt : IRQ, FIQ
- 특정 명령어로 exceptions을 발생시키는 SWI 명령어
## 9.2.1. Assigning Interrupts
- 인터럽트 할당
- 인터럽트 컨트롤러 : ARM 인터럽트 요청 포트 중 하나에 여러 오부 인터럽트를 연결
복잡한 컨트롤러는 외부 인터럽트 소스가 IRQ나 FIQ exceptions을 발생시킬 수 있도록 프로그래밍 할 수 있음
> 인터럽트 할당에 대한 표준설계 방침
- 소프트웨어 인터럽트는 보통 특권을 가진 OS routin을 위해 예약
ex. SWI 명령어는 user 모드에서 특권 모드로 변경하는데 사용될 수 있음 (11장)
- IRQ는 보통 범용 인터럽트를 위해 예약
ex. context switching을 위한 주기적인 타이머 인터럽트는 IRQ Exception으로 할당 가능
IRQ Exception은 FIQ Exception보다 낮은 우선순위와 높은 인터럽트 지연시간을 가짐
- FIQ는 보통 빠른 응답시간을 요하는 하나의 인터럽트 소스
ex. 메모리 블럭을 이동하기 위해 사용되는 DMA를 위하여 예약되어있음
* 임베디드 운영체제 설계 시, FIQ Exception은 특정 Application을 위해서만 사용하고,
그 외의 많은 범용 운영 시스템을 위해서는 IRQ를 사용
## 9.2.2. Interrupt Latecy
- 인터럽트 지연시간 : 외부에서 인터럽트 요청 신호가 들어왔을 때부터
인터럽트 서비스 루틴(ISR)의 첫 명령어를 수행할 때까지의 시간 간격을 의미
> 인터럽트 지연시간을 줄이기위한 소프트웨어 핸들어의 2가지 방법
1. 중첩을 허용한 인터럽트 핸들러
: 인터럽트 서비스 루틴을 실행하고 있을 때조차 다르 인터럽트가 발생할 수 있도록 허용
2. 우선순위 적용
: 인터럽트 컨트롤러는 인터럽트에 우선순위를 적용하여, 높은 우선순위를 가진 태스크만 중첩 인터럽트를 허용
* 우선순위가 더 높은 인터럽트가 발생하기 전까지 낮은 우선순위의 인터럽트가 처리되는데,
우선순위가 낮은 인터럽트들은 평균적으로 좀 더 낮은 인터럽트 지연시간을 가지므로,
시간에 민감항 인터럽트에 대해서는 속도를 향상시켜 시간의 지연을 줄임
## 9.2.3. IRQ and FIQ Exceptions
> IRQ와 FIQ exceptions은 cpsr의 특정 인터럽트 마스크 비트가 0인 경우에만 발생
> IRQ와 FIQ exceptions 발생 시 프로세서 하드웨어의 표준 과정
1. 인터럽트 발생 시 프로세서는 특정 인터럽트 모드로 변환, 인터럽트 발생을 알림
2. 이전 모드의 cpsr값을 새로운 인터럽트 모드의 spsr에 저장
3. 새로운 인터럽트 모드의 lr에 pc값을 저장
4. 인터럽트 disable. 같은 유형의 인터럽트 발생을 막기위한 작업
5. 프로세서는 벡테이블의 특정 엔트리로 분기
> 프로세서가 user모드일 때, IRQ exceptions이 발생한 경우
* cpsr의 IRQ와 FIQ익셉션 비트가 모두 활성화
- IRQ는 프로세서를 두번째 단계로 변환
IRQ 비트가 1이되어 다른 IRQ 익셉션이 발생하지 못하게 함.
FIQ 익셉션은 FIQ를 갖기 때문에 계속 활성화 상태를 유지.
- cpsr 프로세서 모드는 IRQ 모드로 변환. user 모드에서의 cpsr은 자동으로 spsr_irq로 복사
- 인터럽트가 발생하면 레지스터 r13_irq에 pc 값이 저장
- pc는 벡터 테이블의 IRQ 엔트리 +0x18로 설정
- 세번째 단계에서 소프트웨어 핸들러는 인터럽트의 소스를 서비스하기 위한 적절한 인터럽트 서비스 루틴이 호출
- 모든 작업이 완료되면 프로세서 모드는 첫번째 단계의 user 모드로 되돌아감
> FIQ exception의 예
- 세번째 단계의 소프트웨어 핸들러로 진입할 때 IRQ, FIQ 인터럽트 모두 비활성화
-FIQ 모드로 변환할 때, r8에서 r12를 저장할 필요 없음. IRQ모드에서 뱅크됨
- 해당 레지스터들은 bp(buffer pointer)나 counter와 같은 임시데이터를 저장하는데 사용
- 소스가 하나이고 우선순위가 가장높음
- 지연시간이 ㅈ가장 짧은 인터럽트를 서비스 하기에는 FIQ가 가장 이상적임
# 9.2.3.1. FIQ/IRQ exception의 활성화와 비활성화
- ARM 프로세서 코어는 프로세서가 특권모드에 있을때 cpsr을 수정하여 인터럽트를 활성화/비활성화 시킴
> FIQ/IRQ 인터럽트를 활성화하는 ARM 명령어 3가지
MRS |
cpsr의 내용을 레지스터 r1에 복사 |
BIC |
IRQ와 FIQ 마스크 비트를 클리어 |
MSR |
r1의 내용을 cpsr로 다시 업데이트. 인터럽트 활성화 |
* _c는 업데이트 될 비트필드가 cpsr의 제어필드비트[7:0]이라는 것을 의미
* 인터럽트 요청은 MSR명령어가 파이프라인의 실행단계를 완료했을 떄 활성화/비활성화 됨
* 데이터처리 명령어인 BIC나 ORR 명령어에 상수값으로 0xc0을 사용하면 두 인터럽트를 동시에 활성화/비활성화 할수 있음
## 9.2.4. 기보적인 인터럽트 스택 설계 및 구현
- Exception 핸들러는 상당한 스택을 사용
- 각 sp를 포함하는 레지스터를 가짐
> Exception을 위한 스택 설계에 고려사항
1. OS의 요구사항 : 각각의 운영체제는 스택 설계시 어떤 요구사항을 가지고 있음
2. 타켓 하드웨어 : 타겟 하드웨어는 스택크기의 물리적인 제한과 메모리 안에서의 스택 위치를 제한
> 스택 설계시 필요한 2가지 결정사항
1. 위치 : 메모리 맵의 어느 위치에서 시작하는지
2. 스택사이크 : 핸들러의 유형/ 중첩/비중첩에 따라 크기가 결정
> 스택 오버플로우를 알아내는 소프트웨어 기술 : 메모리 깨짐 현상이 발생하기전 스택의 보정 작업을 진행
- 메모리 보호장치의 사용
- 각 루틴의 시작에서 스택 체크 함수를 호출
> IRQ 모드 스택의 셋업
: 인터럽트 활성화 전, 셋업되어 있어야 함.
간단한 임베디드 시스템에서는 펌웨어가 부트업 초기 단계에서 스택크기를 할당하기 때문에 최대 크기를 알수 있음
> 전형적인 두가지 메모리 레이아웃
> A
- 코드 세그먼트 아래에 인터럽트 스택이 저장되는 전통적인 레이아웃
> B
- User 스택 위에 위치한 메모리의 맨 위쪽에 인터럽트 스택이 존재
- A에 비해 스택 오버플로우가 발생해도 벡터 테이블이 깨지지 않음
-> 오버플로우의 원인을 찾아 보정할 기회가 있음
> 스택의 셋업 방법
1. Supervisor mode Stack
- processor core는 supervisor mode에서 시작
- SVC Stack setup을 위해 r13_svc에 SVC_NewStack(스택값)이 가리키는 주소를 저장
LDR r13, SVC_NewStack ; r13_svc
...
SVC_NewStack
DCD SVC_Stack
2. IRQ mode Stack
- IRQ mode Stack을 setup하기 위해서는 processor mode를 IRQ mode로 변경
- mode변경을 하려면 r2에 cpsr 비트패턴을 저장 후 r2를 cpsr에 저장
-> r13_irq에 액세스가 가능해지며, IRQ_Stack값을 저장하면 됨
MOV r2, #NoInt|IRQ32md
MSR cpsr_c, r2
LDR r13, IRQ_NewStack ; r13_irq
...
IRQ_NewStack
DCD IRQ_Stack
3. User mode Stack
- User mode stack은 보통 가장 나중에 설정
- 프로세서는 user모드를 system 모드로 변경 후, user 모드의 스택을 설정할 수있음
=> system mode와 user mode는 같은 레지스터를 공유해서 사용하기 때문
MOV r2, #NoInt|Sys32md
MSR cpsr_c, r2
LDR r13, USER_NewStack ; r13_usr
...
USR_NewStack
DCD USR_Stack
* 각 모드별로 분리된 스택의 사용 : 하나의 스택을 사용하여 처리하지 않고 각 모드별로 분리된 스택의 사용하면,
오류가 발생한 시스템의 나머지 부분과 분리하여 디버깅을 수행할 수 있음
### 9.3. Interrupt Handling Schemes
- 인터럽트 처리 방법
- 중첩을 허용하지 않는 인터럽트 처리 방법(Nonnested Interrupt Handler)
- 중첩을 허용한 인터럽트 처리 방법(Nested Interrupt Handler)
- 재진입 인터럽트 처리 방법(Reentrant Interrupt Handler)
- 우선순위를 적용한 간단한 인터럽트 처리 방법(Prioritized Simple Interrupt Handler)
- 우선순위를 적용한 표준 인터럽트 처리 방법(Prioritized Standard Interrupt Handler)
- 우선순위를 적용한 다이렉트 인터럽트 처리 방법(Prioritized Direct Interrupt Handler)
- 우선순위를 적용한 그룹 인터럽트 처리 방법(Prioritized Grouped Interrupt Handler)
- VIC PL190 기반의 인터럽트 서비스 루틴
: 벡터 인터럽트 컨트롤러(VIC, Vector Interrupt Controller)
## 9.3.1 중첩을 허용하지 않는 인터럽트 처리 방법
- Nonnested Interrupt Handler
- 한번에 하나의 인터럽트만 처리
1. Disable Interrupt
- IRQ가 발생하면 ARM프로세서는 다른 인터럽트가 발생하지 못하게 함
- 적절한 IRQ 모드로 프로세서 모드가 변경
- 이전의 cpsr은 새로운 모드의 spsr_[인터럽트 모드]로 복사
- 프로세서는 pc를 벡터 테이블의 해당 엔트리의 값으로 변경하고 그 명령어를 실행
-> pc가 특정 인터럽트 핸들러를 가리키도록 함
2. Save Context
: 현재 프로세서 모드의 레지스터 값들을 저장
3. Interrupt Handler
: ISR을 실행
4. ISR, Interrupt Service Routin
: 해당 인터럽트 서비스 루틴을 실행한 후 인터럽트를 초기화
5. Restore Context
: ISR에서 인터럽트 핸들러로 되돌아간 후, 기존에 저장된 레지스터 값들을 복원
6. Enable Interrupt
: spsr_{인터럽트 모드}를 cpsr로 복사하여 pc는 인터럽트가 발생했던 시점의 다음 명령어를 가리킴
> Example 9.8 <
interrupt_handler
SUB r14, r14 #4 ; lr
STMFD r13!, {r0-r3, r1, r14} ; 레지스터 백업
<ISR>
LDMFD r13, {r0-r3, r2, pc}^ ; 레지스터 복원 및 복귀
- r14(lr) : 파이프라인 때문에 IRQ 핸들러로의 엔트리에서는 lr의 복귀주소에서 4bytes 떨어진 지점. lr은 스택에 저장되었다가 복원되어 pc로 저장됨
- r0-r3, r12는 ATPCS 때문에 보존되어야 함. ATPCS 호환 서브륀이 핸들러내에서 호출될 수 있도록 함
- STMFD : 사용되는 레지스터 세트들을 스택에 저장(문맥저장). 인터럽트 지연을 줄이기위해 해당 레지스터들의 수를 최소화할 필요가 있음.
레지스터들은 r13_{인터럽트모드}인 SP가 가리키는 스택에 저장장
- 중첩을 허용하지 않는 인터럽트 핸들러 안에서는 spsr을 저장할 필요가 없음.
이후에 호출되는 인터럽트에 의해 깨지는 일이 없기 때문
- LDMFD : 문맥을 복원한 다음, 인터럽트 핸들러에서 복귀.
- "^" : 명령어에 pc가 나오면 cpsr이 spsr로 복원. 만약 pc가 로드되지 않으면 user 뱅크 레지스터를 복원
<ISR>
LDR r0, =IRQStatus ; 인터럽트 상태 레지스터의 주소
LDR r0, [r0] ; 인터럽트 상태를 알아냄
TST r0, #0x0080 ; 만약 카운터 타이머라면,
BNE timer_isr ; timer_ISR로 분기
TST r0, #0x0001 ; 만약 버튼이 잘못 눌린 것이라면
BNE button_isr ; button_IST로 분기
LDMFD sp!, {r0-r3, r12, r14} ; 문맥복원
LDR pc, =debug_monitor ;둘다아니면 debug_monitor로 분기
- 장점 : 구현 및 디버깅이 상대적으로 쉬움
- 단점 : 다중 우선순위를 가지는 복잡한 임베디드 시스템에서 사용할 수 없음
## 9.3.2. 중첩을 허용한 인터럽트 처리 방법
- Nested Interrupt Handler
- 현재 호출되어있는 핸들러내에서 또 다른 인터럽트가 발생할 수 있도록 해주는 것
- 인터럽트 핸들러가 현재의 인터럽트를 완전히 처리하기 전 인터럽트를 다시 활성화하여 다른 인터럽트를 받아들임
- 복잡도는 증가하지만 성능 향상에 도움
- 목적
1. 인터럽트에 재빨리 반응
2. 다양한 인터럽트들이 서비스되는 동안 규칙적으로 동시에 발생하는 코드의 실행을 지연시키지 않기 위함
- 핸들러를 종료할 때 ISR에 의해 업데이트 되는 플래그를 확인
- 플래그 : 다른 인터럽트를 처리해야 하는지의 여부
없다면 인터럽트 서비스 루틴은 완료. 인터럽트가 있다면 인터럽트를 활성화 시키고 문맥전환 등의 작업을 수행
- 인터럽트 활성화 : IRQ 모드에 SVC나 System 모드로 변환하는 작업을 포함
- IRQ모드에서는 r14_irq만 액세스가 가능, BL 명령어를 사용하여 인터럽트를 발생 했을 때,
IRQ를 다시 활성화 시키면 레지스터의 새로운 값이 덮여쓰여 값이 깨질 수 있음 (9.3.3.)
- IRQ 스택에 데이터가 있는 동안 핸들러가 문맥전환을 수행할 수 없음
IRQ 스택을 비워야 함. IRQ 스택에 저장되어 있는 모든 레지스터들은 스택, 보통 SVC 스택으로 전송
"Stack Frame" 이라는 스택상에 할당된 메모리 블록으로 전송
> Example 9.9 <
- 스택프레임의 구조
FRAME_LR, FRMAE_PC : 해당 프레임의 맨 마지막에 나오는 레지스터여야 함.
나머지 레지스터들은 "LDMIA"명령어로 복귀할 것이므로 순서는 중요치 않음.
- 사용하는 Applications이나 OS에 따라 스택 프레임 쪽에 붙어야 하는 레지스터들
1. OS가 user 모드와 SVC 모드 둘다 지원해야 하는 경우, r13_user, r14_user를 저장
2. 시스템이 하드웨어 부동소수점을 사용할 때 부동소수점 레지스터들을 저장
- 여러가지 정의들의 선언
1. 여러가지 cpsr/spsr 변화값을 특정 레이블에 매핑(I_Bit)
2. frame pointer offset으로 다양한 frame registers를 매핑
-> 인터럽트들을 다시 활성화 시키거나 레지스터들이 스택 프레임쪽으로 저장될 때 유용
- 인터럽트 서비스 루틴은 인터럽트 서비스를 수행
- 서비스 완료 후엔 제어권은 핸들러에게 넘어가며 핸들러는 read_RescheduleFlag라는 함수를 호출
또 다른 처리과정이 남아있는지 확인
- 추가 처리사항이 없으면 r0은 0이 아닌 값을 리턴, 추가 처리사항이 있으면 0을 리턴
- r0에서 리턴되는 플래그 값이 확인됨
- 0이 아니라면 문맥을 복원한 후 중단된 태스크에게 제어권이 넘어감.
- 0이라면 처리할 과정이 남아있음을 알려주기 위해, spsr값을 저장하고 해당 복사본은 r2에 저장
- spsr은 코드에서 나중에 나오는 핸들러에 의해 stack frame에 저장될 수 있음
- r13_irq의 값인 IRQ 스택 주소는 나중에 사용되기 위해 r0에 복사
- IRQ stack을 비우기위해 스택의 맨위 6*4 bytes를 더함
=> 아래 방향으로 스택이 자라고 ADD 명령어는 스택 설정을 위해 사용될 수 있기 때문
* 인터럽트 핸들러는 IRQ 스택안의 데이터가 복원될 때까지 인터럽트를 다시 활성화 시키지 않고 비활성화 상태를 유지
- cpsr은 r1에 저장되며 프로세서 몯를 SVC 모드로 설정하여 변경
- 새로운 cpsr의 복사본은 나중에 사용하기 위해 r1에 유지
- 스택프레임의 크기만큼 스택을 확장시켜 스택프레임을 생성
r4-r11까지 스택프레임에 저장될 수 있으며,
r0가 가리키는 IRQ 스택으로부터 남아있는 레지스터들을 복원 할 수 있을만큼 충분한 공간이 됨
- 스택프레임은 해당 표의 정보를 포함
- 프레임 안에 없는 레지스터들만 IRQ 핸들러로 진입할 때 저장
- 기존의 IRQ 레지스터에 상응하는 SVC 모드안에 있는 레지스터들
- 핸들러는IRQ스택에서 모든 데이터를 복원할 수 있고 인터럽트들을 다시 활성화해도 안전할 수 있게됨
- IRQ Exception이 다시 활성화 되고 핸들러는 모든 중요한 레지스터들을 저장
- 핸들러는 스택 프레임을 완료할 수 있음
- 인터럽트 서비스 루틴의 남은 부분이 처리됨
- 현재의 PCB안에 레지스터 r13의 현재 값을 저장 후,
새로운 태스크의 PCB에 r13을 위한 새로운 값을 로드하면서 문맥전환이 수행됨
* 문맥전환이 발생하면 인터럽트가 발생했던 태스크/핸들러나 또 다른 태스크로 복귀가 가능해짐
- 장점 : 인터럽트 지연을 줄이기 위해 각 인터럽트의 서비스가 완료되기 전에 인터럽트를 활성화 시킬 수 있음
- 단점 : 인터럽트의 우선순위를 다루지 않아,
낮은 우선순위의 인터럽트가 더 높은 우선순위를 갖는 인터럽트보다 우선적으로 처리될 수 있음
# 9.3.3. 재진입 인터럽트 처리 방법
- Reentrant Interrupt Handler
- 우선순위에 의해 걸러질 수 있는 다중 인터럽트 처리 방법
- 더 높은 우선순위를 가진 인터럽트가 더 낮은 인터럽트 지연을 갖도록 함
- 재 진입 인터럽트 핸들러 안에서 핸들러가 다시 활성화 됨
- "모드변환"의 필요
: 모드 변환이 없이 r14_irq에 복귀 주소를 저장하면, 인터럽트 서비스 루틴이 BL 서브 루틴 호출 명령어를 호출하였을 때,
다음 인터럽트의 복귀주소가 r14_irq에 중첩되어 데이터 깨짐이 발생하게 됨
- 모드는 system 혹은 SVC로 mode로 변경할 수 있음. (r14_svc 레지스터를 이용하면 중첩을 피할 수 있음)
- 처리 과정이 완료되고 인터럽트 소스가 비활성화되기 전에 인터럽트가 cpsr안에서 다시 활성화가 되면,
인터럽트는 즉시 다시 발생 => "race condition"이라는 무한 인터럽트 서비스 루틴 상태에 빠짐
=> 대부분의 인터럽트 컨트롤러는 "인터럽트 마스크 레지스터"를 사용하여,
하나 이상의 인터럽트들을 마스크 하고 남은 인터럽트를 여전히 활성화 시킬 수 있음
- SVC 모드 안에서 서비스 되므로 인터럽트 스택을 사용하지 않고,
임시로 레지스터 몇개를 저장하기 위한 12 bytes 구조체를 사용하고자 이를 가리키는 r13을 사용됨
> Example 9.10 <
- 장점 : 다른 우선순위를 가진 인터럽트들을 처리할 수 있음
- 단점 : 코드가 더욱 복잡해짐
## 9.3.4. 우선순위를 적용한 간단한 인터럽트 처리 방
- Prioritized Simple Interrupt Handler
- 특정 인터럽트 소스에게 우선순위를 부여
- 우선순위
1. 하드웨어 우선순위 방식
: 인터럽트 컨트롤러가 현재 서비스를 필요로하는 가장 높은 웃건순위 인터럽트가 무엇인지 알려주기 때문에 간단히 구현이 가능
시스템이 변경됮기 전 인터럽트와 관련 우선순위 테이블 설정이 필요하며 그만큼 초기화 코드가 길어짐
2. 소프트웨어 우선순위 방식
: 외부의 인터럽트 컨트롤러의 추가적인 도움을 필요로 함
마스크를 제어하고 인터럽트 상태 및 소스코드를 읽어내는 최소한의 함수들을 제공해야 함
- IRQRawStatus : 인터럽트 컨트롤러가 가지는 순수한 인터럽트의 상태를 저장하는 레지스터
* 순수한 인터럽트 상태 : 컨트롤러에 의해 마스크되기 전의 인터럽트 신호의 상태
- IREnable 레지스터 : 어떤 인터럽트가 프로세서로부터 마스크 되어 있는지 결정함
IRQEnableSet, IRQEnableClear를 통해서 set/clear 됨
> Example 9.11 <
- 장점 : 우선순위 레벨이 어떤 것인지 먼저 알아낸 다음, 더 낮은 우선순위의 인터럽트를 마스크 한 후 서비스 루틴히 호출 됨
=> 인터럽트 지연이 확정적
- 단점 : 낮은 우선순위의 서비스 루틴을 얻는 데 걸리는 시간이 가장 높은 우선순위의 루틴을 위한 것과 같음
# 9.3.5. 우선순위를 적용한 표준 인터럽트 처리 방법
- Prioritized Standard Interrupt Handler
- 우선순위 레벨이 정해진 후, 가장 높은 우선순위의 인터럽트를 찾았을 때, pc 값을 설정하여 즉시 분기
- 인터럽트 레벨을 결정 -> 즉시 더 낮은 우선순위 인터럽트 마스크를 처리하는 루틴으로 분기
-> 적절한 ISR를 가리키는 분기 테이블에 의해 다시 분기
- 더 높은 우선순위를 가진 인터럽트를 먼저 처리. 우선순위 비교.
일치하는 인터럽트 소스를 찾으면 핸들러는 더 낮은 인터럽트들을 마스크 하기위한 루틴으로 분기
- r14 : 인터럽트 컨트롤러의 베이스를 가리키도록 할당. 동일하거나 더 낮은 순위의 인터럽트의 비활성화를 위함
- r10 : 인터럽트 컨트롤러 상태 레지스터를 로드.
r10은 새로운 마스크를 포함. r12와 AND연산 후, 결과를 IRQEnableClear 레지스터에 저장하여 낮은 우선순위 인터럽트를 0으로 clear
- 핸들러가 다시 사용될 수 있도록 하기위해 pc가 가리키는 현재 주소를 r11에 저장
* 가장 높은 우선순위 인터럽트를 포함
- 장점 : 높은 우선순위의 인터럽트는 외부 인터럽트 마스크를 1로 설정하기 위한 코드의 복사본 없이 더 긴급하게 처리됨
- 단점 : 핸들러는 두번의 분기가 필요. 분기가 필요할 때마다 파이프라인이 지워지기 때문에 시간면에서 손해
# 9.3.6. 우선순위를 적용한 다이렉트 인터럽트 처리 방법
- Prioritized Direct Interrupt Handler
- 처리되는 부분 중 일부가 핸들러에서 각각의 ISR로 이동
- 우선순위를 적용한 direct exception handler는 적절한 ISR로 직접 분기
- 각 ISR은 인터럽트를 다시 활성화 시키기 위해 cpsr을 수정해주기 전, 낮은 순위의 인터럽트의 비활성하는 일을 담당
=> ISR이 마스크 작업을 수행해 주므로 상대적으로 간단, ISR이 같은 작업을 효율적으로 수정해야 하므로 작은 코드 복사본을 자짐
> 높은 우선순위를 가진 인터럽트를 보다 짧은 시간 안에 처리. 더 짧은 인터럽트 지연시간을 가짐
- 장점 : ISR로 이동하기 위해 한번만 부팅, 여러 사이클이 절약
- 단점 : 각 ISR은 낮은 우선순위의 이너럽트가 현재 ISR을 중ㅈ시키지 못하게 하기위해 외부 인터럽트를 1로 세트
# 9.3.7. 우선순위를 적용한 그룹 인터럽트 처리 방법
- Prioritized Grouped Interrupt Handler
- 그룹별로 한꺼번에 설계
- 여러 인터럽트들을 하나로 묶어서 서브 그룹을 형성 후 적절한 인터럽트 우선순위를 부여하여 구현
- 인터럽트 우선순위를 결정하기 위해 모든 인터럽트들을 검색할 필요가 없어지므로 핸들러의 복잡도 감소
- 장점 : 임베디드 시스템이 아주 많은 인터럽트를 처리하는 경우 유용함
우선 순위 레벨을 정하는 시간이 보다 짧아 반응 시간을 줄일 수 있음
- 단점 : 인터럽트를 어떻게 그룹화 할지를 결정하기 힘듬
# 9.3.8. VIC PL190 기반의 인터럽트 서비스 루틴
- 벡터 인터럽트 컨트롤러(VIC, Vector Interrupt Controller)
- 벡터 인터러브 컨트롤러의 사용
: IRQ Vector Entry의 수정이 필요
0x00000018 LDR pc, [pc, #-0xff0] ; IRQ pc = mem32[0xfffff030]
=> 0xfffff030 번지의 메모리에서 ISR 주소값을 읽어서 pc에 저장
- 하드웨어로부터 인터럽트 소스를 직접 알아낼 수 있음.
- 소프트웨어 인터럽트 핸들러는 거치지 않음
- 특정 ISR로 한번만 분기하면 되므로 인터럽트 지연도 줄어들게 됨
* VIC는 하드웨어 인터럽트 핸들러임. VIC가 활성화 되기 전 ISR주소 목록이 프로그래밍 되어있어야 함
'System > Embedded' 카테고리의 다른 글
[ARM] 캐시 (0) | 2015.11.12 |
---|---|
[ARM] 펌웨어 (0) | 2015.11.12 |
[ARM] 익셉션과 인터럽트 처리 (0) | 2015.11.10 |
[ARM] 최적화된 C프로그래밍 (0) | 2015.11.10 |
[ARM] 32비트 ARM 명령어 2 (0) | 2015.11.09 |