이번엔 타이머 인터럽트를 통해 컨텍스트 스위칭이 이루어지는 인터럽트 서비스 루틴에 관한
코드를 살펴볼까 한다.
씨에서는 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();