Vector Table: 각각의 Exception이 일어 났을 때 정해진 곳으로 branch
> 그 용도에 맞는 처리 routine들이 들어 있으면 됨.
Low Vector를 기준
;----------------------------------------------------------------------------;
; ADDRESS EXCEPTION MODE ON ENTRY
;----------------------------------------------------------------------------;
; 0x00000000 Reset Supervisor
; 0x00000004 Undefined Exception Undefined
; 0x00000008 Software Interrupt Supervisor
; 0x0000000C Abort (prefetch) Abort
; 0x00000010 Abort (data) Abort
; 0x00000014 Nothing Nothing
; 0x00000018 IRQ IRQ
;----------------------------------------------------------------------------;
Reset > 0x0, Undef Exception 나면 0x4 뭐 이런 식으로 32bit씩 자리 차지
4byte씩만 가지고 Exception을 처리하기에는 너무 비좁음
> Instruction 한 개 들어갈만한 공간 가지고 Exception을 처리하기에는 너무나 버거움.
AREA INIT_VECTOR, CODE, READONLY → INIT_VECTOR라는 부분 기억
CODE32 ; 32-bit ARM instruction set
ENTRY
; Vector Table
0x00 B Reset_Handler ; 0x0
0x04 LDR PC, 0x30 ; 0x4
0x08 LDR PC, 0x34 ; 0x8
0x0C LDR PC, 0x38 ; 0xC
0x10 LDR
각 주소별로 어디론가 branch하는 코드가 들어 있음. : 각각의 Handler로 Jump
4byte씩 ARM mode에서 돌게 하기 위해 > 위에 CODE32가 자리 잡음.
Exception에 진입 > ARM의 기본 state = ARM state.
Reset > Reset_Handler,
Data Abort > Abort_Handler로 Jump!
다른 곳에 각각의 Handler를 구현 > Exception Vector에서 Jump하도록 구현.
어떻게 0x0부터 차례로 메모리에 자리잡게 할지?
: Scatter Loading을 이용 > 컴파일 할 때 0x0부터 자리잡게 하고서, Flash에 저장할 때 0x0부터 차례대로
or SDRAM이 0x0부터 시작하는 거라면 0x0부터 복사 Vector Table을 vectors.s에 만들어 놓고서 컴파일한 후
> Scatter Loading File에 아래와 같이 적어주면 0x0부터 만들어짐
BOOT_ROM 0x0 {
BOOT_RAM 0x0 0x4000 ; 0x0부터 시작 {
vectors.o (INIT_VECTOR, +FIRST) ; vectors.s를 컴파일하는데, INIT_VECTOR AREA를 맨 앞에 두어라.
(참고 +LAST는 맨 마지막에 놓으라는뜻 ) ..........
}
}
High Vector로 만들고 싶으면?
BOOT_ROM 0x0 {
BOOT_RAM 0xFFFF0000 0x4000 ; 0xFFFF0000 부터 시작 {
vectors.o (INIT_VECTOR, +FIRST) ; vectors.s를 컴파일하는데, INIT_VECTOR AREA를 맨 앞에
}
}
각 Handler들을 그때 그때 막 바꾸고 싶을땐..
branch하라는 명령어 말고 다른 거 넣으면됨
0x00 B Reset_Handler ; 0x0
0x04 LDR PC, 0x30 ; 0x4
0x08 LDR PC, 0x34 ; 0x8
0x0C LDR PC, 0x38 ; 0xC
0x10 LDR PC, 0x3C ; 0x10
0x14 LDR PC, 0x40 ; 0x14
0x18 LDR PC, 0x44 ; 0x18
0x1C LDR PC, 0x48 ; 0x1C
; Handlers Address (Data)
0x30 DCD 0x1000 ; Undefined Handler
0x34 DCD 0x2000 ; SWI Handler
0x38 DCD 0x3000 ; Prefetch Handler
0x3C DCD 0x4000 ; Abort Handler
0x44 DCD 0x6000 ; IRQ Handler
0x48 DCD 0x7000 ; FIQ Handler
0x30, 0x34, 0x38, 0x3C, 0x44, 0x48에 들어 있는 값을 바꿔주면 그때 그때 상황에 맞추어 handler를 바꿀 수 있음.
Reset Handler는 그대로 쓴이유 > Entry point니까, 그냥 두는 매너
Handler에 무엇을 채워 넣으면 될까?
1. Reset Handler : Power On이 되면 진입하게 되는 Default Handler 처리X
2. Undefined Handler
Undefined Exception이 발생하는 이유: ARM core가 Memory에서 Op code를 decode했더니 모르는 Op code더라.. 라는 상황
> a) XIP Memory, Software가 실행되고 있는 Memory, 가 Corrupt 되었거나, Software가 저장된 저장 매체가 Corrupt될때.
>> Design Review부터 다시 -> Memory를 제대로 control 하고 있는 것인지 timing이 적당한 건지 확인
> b) 일부러 Undefined Exception
ex) ARM Core 혼자 만으로는 Computing Power가 다 나오지 않을 때
> Co processor를 달아서 ARM이 혼자 해야 할 일을 덜어줌
> Co processor에게 뭔가 명령을 내려주고 싶을 때,
> Undef Exception의 경우 자기 전용 Register가 R13_und, R14_und, SPSR_und 뿐, -> backup
>> UNDEF_Handler stmfd sp!, {r0-r12, r14} ; 구현해 넣고 싶은 내용들~~~
ldmfd sp!, {r0-12, pc}^ ; Register들을 다시 Restore.
Undef Exception: LR에 Undef exception이 난 명령어 바로 다음을 가리키는 값이 들어감
> Handler에 들어와서 현재 Register들만 backup하면됨
3. Prefetch Abort Handler :
문제가 발생했다는 것을 외부에 알리는 일, information을 남겨놓는 일을 남겨 놓음.
> 안 만나면 좋은 Exception이니까 어떻게든 만천하에 알려서 문제가 수정될 수 있도록 하는 routine 끼워놓음.
> Debugging 용도의 Code들이 삽입
MMU를 쓰는 경우에서 Prefetch Abort의 경우 : 스와핑으로 잘 알려진 Demand Loading을 사용하느라 발생
Demand Loading : XIP를 하는 Memory가 너무 작음, Software를 모두 Loading X , 실제 실행 해야 하는 부분만 XIP Memory에 Loading
PAbort : 진입했다가 복귀할 때는 Undef Exception과 같은 처리를 하면 됨
PAbort_Handler stmfd sp!, {r0-r12, r14} ; Register들을 backup 해
구현해 넣고 싶은 내용들
ldmfd sp!, {r0-12, pc}^ ; Register들을 다시 Restore-
4. Data Abort Handler DAbort : Align이 안 맞는 Data를 Access할 때 발생,
>강제로 맞춰서 원상 복구하는 형태의 Handler를 넣어놓음.
Abort mode : 자기 전용 Register가 R13_abt, R14_abt, SPSR_abt 3개,
> Handler 진입 시 R0~R12를 bakcup하고요, 이전 mode로 돌아가기 위하여 LR을 backup
DAbort Handler : 임무를 마치고 돌아갈 시점이 LR - 8 > 맨 앞에 lr을 교정하는 명령어가 하나.
DAbort_Handler sub lr, lr, #8 ; 돌아갈 주소 교정
stmfd sp!, {r0-r12, r14} ; Register들을 backup 해 두고요.
구현해 넣고 싶은 내용들~
ldmfd sp!, {r0-12, pc}^ ; Register들을 다시 Restore
5. FIQ : IRQ는 FIQ,
IRQ : LR-8를 해주면, Exception이 발생한 시점에 처리된 명령어의 알아 낼 수 있음
> Handler에 진입하자마자 LR을 가공.
> Exception 발생 당시에 처리된 명령어의 다음 바로 주소가 Interrupt를 처리하고 난 후에 계속 진행되어야 할 명령어
> LR-4 : 다음 처리할 명령어를 찾을 수 있음.
FIQ : R8~R14하고 SPSR 갖고있음
>진입 : R0~R7까지만 backup
IRQ : R13, R14, SPSR 갖고 있음, R0~R12를 backup
> FIQ,IRQ : 돌아갈 주소 LR을 backup
IRQ_Handler sub lr, lr, #4
stmfd sp!, {r0-r12, r14} ; Register들을 backup
구현해 넣고 싶은 내용들~
ldmfd sp!, {r0-r12, r14}^
FIQ_Handler sub lr, lr, #4
stmfd sp!, {r0-r7,lr} 구현해 넣고 싶은 내용들~
ldmfd sp!, {r0-r7,pc}^
6. SWI SWI_Handler는 Undef Exception Handler랑 똑같이 처리
7. SWI_Handler
stmfd sp!, {r0-r12, r14} ; Register들을 backup
구현해 넣고 싶은 내용들~
ldmfd sp!, {r0-12, pc}^ ; Register들을 다시 Restore
Pipe line과 Exception관계에서의 Table을 수시로 보시고 생각해 봐야함..
// R14는 레지스터 예외 발생시 사용하려고 안전하게 백업
'임베디드 > 임베디드 레시피' 카테고리의 다른 글
Reset Handler에서 main까지 (Entry Point) (0) | 2024.12.01 |
---|---|
Coprocessor Assembly (0) | 2024.11.27 |
SWI 의 진실 (0) | 2024.11.26 |
Pipe line과 Exception 관계 그리고 ^접미사 (0) | 2024.11.21 |
Inline Assembly와 INTLOCK의 구현 (0) | 2024.11.20 |