More actions
imported>Unknown No edit summary |
(Repair batch-0002 pages from live compare) |
||
| (One intermediate revision by the same user not shown) | |||
| Line 1: | Line 1: | ||
이번엔 타이머 인터럽트를 통해 컨텍스트 스위칭이 이루어지는 인터럽트 서비스 루틴에 관한 | 이번엔 타이머 인터럽트를 통해 컨텍스트 스위칭이 이루어지는 인터럽트 서비스 루틴에 관한 <br /> | ||
코드를 살펴볼까 한다. | 코드를 살펴볼까 한다. | ||
씨에서는 interrupt란 예약어로 함수를 인터럽트 콜이 가능한 함수를 만들 수 있다. | 씨에서는 interrupt란 예약어로 함수를 인터럽트 콜이 가능한 함수를 만들 수 있다.<br /> | ||
이럴 경우 컴파일을 해 보면 펑션의 호출이 RET가 아닌 IRET로 끝나게 된다. | 이럴 경우 컴파일을 해 보면 펑션의 호출이 RET가 아닌 IRET로 끝나게 된다.<br /> | ||
그럴 경우 IRET 로 끝날 경우 [[CS]]: | 그럴 경우 IRET 로 끝날 경우 [[CS]]:IP FLAGS를 스택에서 PUSH하게 된다.<br /> | ||
PS RET로 끝날 경우 [[CS]]: | PS RET로 끝날 경우 [[CS]]:IP만 PUSH하게 된다.<br /> | ||
하하 넘 오래간만에 봤더니 나도 무슨 함순지 모르는 것이 있군.. | 하하 넘 오래간만에 봤더니 나도 무슨 함순지 모르는 것이 있군..<br /> | ||
void interrupt LIB_ISR(...){ | void interrupt LIB_ISR(...){ | ||
| Line 14: | Line 14: | ||
/////////////// Decrease Time Dly | /////////////// Decrease Time Dly | ||
for ( int i = 0 ; i < suspend_tcb_ptr + 1; i++ ){ | for ( int i = 0 ; i < suspend_tcb_ptr + 1; i++ ){ | ||
pSuspend_heap | pSuspend_heap[i]->delay--; | ||
if ( High_Task->priority < pSuspend_heap | if ( High_Task->priority < pSuspend_heap[i]->priority && pSuspend_heap[i]->delay < 0 ) { | ||
pSuspend_heap | pSuspend_heap[i]->delay = 0; | ||
LIB_resume_task(pSuspend_heap | LIB_resume_task(pSuspend_heap[i]->priority); | ||
} | } | ||
} | } | ||
| Line 38: | Line 38: | ||
} | } | ||
인터럽트 서비스 루틴을 초기화 해주는 함수로 | 인터럽트 서비스 루틴을 초기화 해주는 함수로 <br /> | ||
시작 태스크를 초기화 하고 인터럽트 벡터 테이블에서 타이머의 [[CS]]: | 시작 태스크를 초기화 하고 인터럽트 벡터 테이블에서 타이머의 [[CS]]:IP의 | ||
부분을 위의 LIB_ISR로 바꿔준다. | 부분을 위의 LIB_ISR로 바꿔준다. | ||
void LIB_INIT_ISR(){ | void LIB_INIT_ISR(){ | ||
| Line 56: | Line 56: | ||
MOV DS,AX | MOV DS,AX | ||
MOV SI,BX | MOV SI,BX | ||
MOV AX,DS: | MOV AX,DS:[SI] | ||
MOV DX,DS: | MOV DX,DS:[SI+2] | ||
MOV DI,offset oldtimer | MOV DI,offset oldtimer | ||
MOV BX,seg oldtimer | MOV BX,seg oldtimer | ||
MOV ES,BX | MOV ES,BX | ||
MOV ES: | MOV ES:[DI],AX | ||
MOV ES: | MOV ES:[DI+2],DX | ||
} | } | ||
이제 셋 타이머를 해준다... | 이제 셋 타이머를 해준다... | ||
| Line 71: | Line 71: | ||
MOV DI,Time_Vect | MOV DI,Time_Vect | ||
MOV AX,offset LIB_ISR | MOV AX,offset LIB_ISR | ||
MOV ES: | MOV ES:[DI],AX | ||
MOV AX,seg LIB_ISR | MOV AX,seg LIB_ISR | ||
MOV ES: | MOV ES:[DI+2],AX | ||
} | } | ||
} | } | ||
| Line 83: | Line 83: | ||
} | } | ||
이제 여기서부터 실제적인 컨텍스트 스위칭이 일어난다. | 이제 여기서부터 실제적인 컨텍스트 스위칭이 일어난다. | ||
우선 가장 상위의 태스크를 찾겠지?? 아마 그건 | 우선 가장 상위의 태스크를 찾겠지?? 아마 그건 <br /> | ||
High_Task 로 지정된 태스크일 것이다. 그 태스크의 스택 위치를 찾아 스택 포인트를 바꿔준다. | High_Task 로 지정된 태스크일 것이다. 그 태스크의 스택 위치를 찾아 스택 포인트를 바꿔준다. | ||
| Line 106: | Line 106: | ||
---- | ---- | ||
[[REAL_LIBOS]] | [[REAL_LIBOS]] | ||
Latest revision as of 00:16, 27 March 2026
이번엔 타이머 인터럽트를 통해 컨텍스트 스위칭이 이루어지는 인터럽트 서비스 루틴에 관한
코드를 살펴볼까 한다.
씨에서는 interrupt란 예약어로 함수를 인터럽트 콜이 가능한 함수를 만들 수 있다.
이럴 경우 컴파일을 해 보면 펑션의 호출이 RET가 아닌 IRET로 끝나게 된다.
그럴 경우 IRET 로 끝날 경우 CS:IP FLAGS를 스택에서 PUSH하게 된다.
PS RET로 끝날 경우 CS:IP만 PUSH하게 된다.
하하 넘 오래간만에 봤더니 나도 무슨 함순지 모르는 것이 있군..
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로 바꿔준다.
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를 해서 타이머 벡터의 위치를 구해 그 부분의 타이머를 저장해 둔다..만약의 복귀를 위해..^^;
// 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
}
이제 셋 타이머를 해준다...
// 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을 이용한다..근데 지금은 필요 없는듯...
void LIB_TSR() {
union REGS regs;
regs.x.dx=4000;
int86(0x27,®s,®s);
}
이제 여기서부터 실제적인 컨텍스트 스위칭이 일어난다.
우선 가장 상위의 태스크를 찾겠지?? 아마 그건
High_Task 로 지정된 태스크일 것이다. 그 태스크의 스택 위치를 찾아 스택 포인트를 바꿔준다.
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();