Hardware없이 interrupt를 거는 방법?
SoftWare Interrupt : Asynchronous(비동기식) 하게 암때나 걸리는 게 Interrupt
Software Interrupt != Interrupt
> Software적으로 Exception을 거는것임.
> User mode에 있던 System > Supervisor mode로 전환,
> Software Interrupt를 거는 순간부터는 Privileged Mode로 전환 System을 마음대로 주무를 수 있는 권한이 생김.
왜 이런 SWI( software interrupt) 사용? : compatibility.
> kernel service를 이용할 때 많이 사용
a) Privileged mode로 들어갈 수 있음,
b) Kernel service : 입구가 하나로 한정
> Kernel 입장에서는 SWI 부분만 수정을 잘하면 되는 장점.
SWI가 이용 예
1. System Call (Kernel)
2. Semi hosting
1. System Call : Kernel등에서 많이 사용되는 개념
>Kernel: SVC mode에서 동작
<>일반 application : User Mode에서 동작
> User Mode의 일반 application이 Kernel에게 service를 요청할 때 사용.
SWI를 > Kernel Mode로 System mode를 바꾸는것
2. Semi hosting :
Target에서의 I/O에 관련된 것들을 경로를 바꿈
> Target에서 실행되어야 하는 I/O
> Debugger를 실행하고 있는 Host system에서 대신 수행하게함
ex) UART로 Message를 뿌리던 target의 routine > Semi hosting routine
> UART가 아닌 Debugger로 target의 Reporting을 직접 받을 수 있음
SWI, Handler 어떻게 구현?
1. Software Interrupt를 걸려면 ?
SWI {condition} ;
assembly를 삽입 : SWI 명령어를 만나는 순간 Exception 발생
> SWI Exception Vector (0x0008)번지로 branch.
이렇게 SWI 명령어 자체로 Exception을 걸어 User mode에서 강제로 SVC mode로 갈 수 있음
SWI {condition} ;
> SWI에 대해서 여러 가지 종류의 SWI를 걸 수 있음,
SWI 뒤에 number > Handler에서 뒤에 parameter로 준 condition을 switch > 여러 가지 case 처리
ARM에서는 Exception이 발생 > Exception Vector로 jump해서 곧바로 Handler로 branch
> 어떻게 parameter를 줌??
SWI 명령자체가 답.
SWI 명령어의 32bit binary 형태
cond 1111 24bit (interrupted) immediate
MSB 4bit : 조건을 나타내는 명령어 (EQ, NEQ 등) > condition flag에 대한 조건 명령
1111 : SWI 명령.
24bit : parameter가 들어감 >여러 가지 종류의 SWI
// 순수하게 System Software Engineer가 구현해야 하는 몫
LSB 24bit와는 아무 상관없이 일단 1111 (SWI)가 있으면
>Processor : Exception 발생
Software Interrupt > R14_SVC에 돌아갈 주소가 저장
돌아갈 주소를 안다 == 돌아갈 주소에서 한 칸만 이전을 가져올 수만 있다면 SWI가 걸린 위치를 가져올 수 있음.
그러면 SWI가 걸린 위치를 가져와서 LSB 24bit만 Masking해내면 끝
LDR r0, [r14, #-4]
BIC r0, r0, #0xFF000000 // 8*4 = 32byte , 32- 8 = 24
r14 에서 그 전 주소를 뺌 ( -4 byte) 그걸 하위 24bit 에 저장
ex)
1. SWI 호출과 Handler의 구현
2. C Level의 SWI 의 직접 호출 구현
1. 일반적인 SWI 호출하는 방법
c file에서 SWI를 호출,
SWI_OOOPS()
{
.............
SWI_Exception(); SWI_OOOPS()라는 함수에서 SWI 호출
.............
}
Assembly file 하나에서 SWI_Exception 함수를 구현
> SWI {condition} 명령어를 사용하기 위해
SWI_Exception
SWI 0x121212 // SWI에 parameter 0x121212 할당
SWI 0x121212 를 만나면 SWI_EXception > Exception Vector로 branch
0x8번지에 쓰여진 형태 // Vector Table
b SWI_Handler // b : branch
C Level의 SWI Handler를 부르기 위한 Handler를 만듬 + 여기에서 LSB 24 bit도 건짐
SWI_Handler
STMFD sp!, {lr} ; 돌아갈 주소 저장
LDR r0, [lr, #-4] ; SWI 주소의 값을 가져옴.
BIC r0, r0, #0xFF000000 ; LSB 24bit 건져냄. // 0x12121212
BL SWI_C_Handler ; r0에 넣었으니까, AAPCS에 의하여 첫번째 argument로
//r0에 SWI 인자값(하위 24비트)이 들어 있음 > 이를 첫 번째 인자로 하여 SWI_C_Handler를 호출
LDMFD sp!, {lr} ; 다 처리하고 왔으면 돌아가야지~
SWI_C_Handler만 잘 구현하면 됨
void SWI_C_Handler (int OPTion)
{
switch(option)
{
case 0x123432:
UART_MESSAGE ("SWI 0x123432");
break ;
case 0x121212 :
LCD_MESSAGE ("SWI 0x121212");
break ;
case 0x654321:
USB_MESSAGE ("SWI 0x654321");
break ;
}
}
r0에 LSB 24 bit를 넣었음 > 그 값은 int option으로 넘어오게 되고, 그 option에 대해서 switch를 걸었음
> 결국 LCD_MESSAGE 를 찍음
2. 다른 종류의 LSB 24bit를 걸기 위해서 SWI_Exception() 함수를 Assembly로 따로따로 구현해야 하느냐!
>함수를 SWI와 번호로 선언할 수 있음
__swi(0x123432) void UART_OUT (void)라고 선언
SWI_OOOPS()
{
.............
SWI_Exception();
UART_OUT();
.............
}
LCD MESSAGE와 UART MESSAGE가 실행
> UART_OUT() 함수 자체가 SWI 0x123432으로 compile
결국 SWI_OOOPS()함수는
SWI_OOOPS
........
SWI 0x121212
SWI 0x123432
.........
이런 식으로 컴파일됨
'임베디드 > 임베디드 레시피' 카테고리의 다른 글
Reset Handler에서 main까지 (Entry Point) (0) | 2024.12.01 |
---|---|
Coprocessor Assembly (0) | 2024.11.27 |
vector table의 구현과 실제 (0) | 2024.11.26 |
Pipe line과 Exception 관계 그리고 ^접미사 (0) | 2024.11.21 |
Inline Assembly와 INTLOCK의 구현 (0) | 2024.11.20 |