이번엔 타이머 인터럽트를 통해 컨텍스트 스위칭이 이루어지는 인터럽트 서비스 루틴에 관한
코드를 살펴볼까 한다.
씨에서는 interrupt란 예약어로 함수를 인터럽트 콜이 가능한 함수를 만들 수 있다.
이럴 경우 컴파일을 해 보면 펑션의 호출이 RET가 아닌 IRET로 끝나게 된다.
그럴 경우 IRET 로 끝날 경우 CS:IP FLAGS를 스택에서 PUSH하게 된다.
PS RET로 끝날 경우 CS:IP만 PUSH하게 된다.
코드를 살펴볼까 한다.
씨에서는 interrupt란 예약어로 함수를 인터럽트 콜이 가능한 함수를 만들 수 있다.
이럴 경우 컴파일을 해 보면 펑션의 호출이 RET가 아닌 IRET로 끝나게 된다.
그럴 경우 IRET 로 끝날 경우 CS:IP FLAGS를 스택에서 PUSH하게 된다.
PS RET로 끝날 경우 CS:IP만 PUSH하게 된다.
하하 넘 오래간만에 봤더니 나도 무슨 함순지 모르는 것이 있군..
~cpp
void interrupt LIB_ISR(...){
LIB_ENTER_CRITICAL();
(*oldtimer)();
LIB_INT_COUNT++;
/////////////// Decrease Time Dly
for ( int i = 0 ; i < suspend_tcb_ptr + 1; i++ ){
pSuspend_heap[i]->delay--;
if ( High_Task->priority < pSuspend_heap[i]->priority && pSuspend_heap[i]->delay < 0 ) {
pSuspend_heap[i]->delay = 0;
LIB_resume_task(pSuspend_heap[i]->priority);
}
}
/////////////// CONTEXT SWITCHING
asm {
MOV S_SEG,SS
MOV S_OFF,SP
}
High_Task->StackSeg = S_SEG;
High_Task->StackOff = S_OFF;
LIB_Schedul();
S_SEG = High_Task->StackSeg;
S_OFF = High_Task->StackOff;
asm {
MOV SS,S_SEG
MOV SP,S_OFF
}
///////////////////////////////////
LIB_EXIT_CRITICAL();
}
인터럽트 서비스 루틴을 초기화 해주는 함수로
시작 태스크를 초기화 하고 인터럽트 벡터 테이블에서 타이머의 CS:IP의
부분을 위의 LIB_ISR로 바꿔준다.
타이머 벡터의 위치를 구해 그 부분의 타이머를 저장해 둔다..만약의 복귀를 위해..^^;
우선 가장 상위의 태스크를 찾겠지?? 아마 그건
High_Task 로 지정된 태스크일 것이다. 그 태스크의 스택 위치를 찾아 스택 포인트를 바꿔준다.
시작 태스크를 초기화 하고 인터럽트 벡터 테이블에서 타이머의 CS:IP의
부분을 위의 LIB_ISR로 바꿔준다.
~cpp
void LIB_INIT_ISR(){
LIB_INT_NESTING = 0;
INT16U Time_Vect = 0x08 * 4;
High_Task = &START_TCB;
START_TCB.priority = 0;
START_TCB.StackSeg = 0;
START_TCB.StackOff = 0;
겟 벡터에서 0x08 번째의 타이머 백터 그리고 4바이트가 필요해서 *4를 해서타이머 벡터의 위치를 구해 그 부분의 타이머를 저장해 둔다..만약의 복귀를 위해..^^;
~cpp
// Get Vecter Table oldtimer
asm {
MOV BX,Time_Vect
MOV AX,0
MOV DS,AX
MOV SI,BX
MOV AX,DS:[SI]
MOV DX,DS:[SI+2]
MOV DI,offset oldtimer
MOV BX,seg oldtimer
MOV ES,BX
MOV ES:[DI],AX
MOV ES:[DI+2],DX
}
이제 셋 타이머를 해준다...~cpp
// Set Timer Vector Table
asm {
MOV AX,0
MOV ES,AX
MOV DI,Time_Vect
MOV AX,offset LIB_ISR
MOV ES:[DI],AX
MOV AX,seg LIB_ISR
MOV ES:[DI+2],AX
}
}
이 프로그램이 복귀 가능하게 만들 경우 TSR을 이용한다..근데 지금은 필요 없는듯...~cpp
void LIB_TSR() {
union REGS regs;
regs.x.dx=4000;
int86(0x27,®s,®s);
}
이제 여기서부터 실제적인 컨텍스트 스위칭이 일어난다.우선 가장 상위의 태스크를 찾겠지?? 아마 그건
High_Task 로 지정된 태스크일 것이다. 그 태스크의 스택 위치를 찾아 스택 포인트를 바꿔준다.
~cpp
void interrupt LIB_context_sw(){
LIB_ENTER_CRITICAL();
/////////////// CONTEXT SWITCHING
asm {
MOV S_SEG,SS
MOV S_OFF,SP
}
High_Task->StackSeg = S_SEG;
High_Task->StackOff = S_OFF;
LIB_Schedul();
S_SEG = High_Task->StackSeg;
S_OFF = High_Task->StackOff;
asm {
MOV SS,S_SEG
MOV SP,S_OFF
}
///////////////////////////////////
LIB_EXIT_CRITICAL();









