E D R , A S I H C RSS

LIB_2

No older revisions available

No older revisions available



이번엔 타이머 인터럽트를 통해 컨텍스트 스위칭이 이루어지는 인터럽트 서비스 루틴에 관한

코드를 살펴볼까 한다.
씨에서는 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로 바꿔준다.
~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,&regs,&regs);
}
이제 여기서부터 실제적인 컨텍스트 스위칭이 일어난다.
우선 가장 상위의 태스크를 찾겠지?? 아마 그건

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();
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:23:38
Processing time 0.0190 sec