본문 바로가기

Hacked Brain/embeddedland.net

80c196kc - (4) 인터럽트

출처 :
임베디드 커뮤니티 [W.O.E]
cafe.naver.com/okh0217

 .인터럽트

인터럽트

해당 번지로 점프하여 일을수행하고 원래자리로 돌아온다. 

인터럽트벡터테이블

인터럽트가 발생되면 어디로 가서 인터럽트 처리 루틴을 수행해야 되는지 기록되어 있는 곳으로 80c196kc는 2000H 번지부터 시작된다.

(CPU 설계한 사람 마음)

 

..


..

    

2004H


2002H

A/D 변환 완료

2000H

타이머 오버플로


인터럽트 발생 후 무슨 일이 벌어지는가...

만약 타이머 오버플로 인터럽트가 발생하면 그것에 해당하는 2000H로 간다.

그런데 여기는 ROM영역이라 사용자가 인터럽트 처리 루틴을  써넣을 수가 없다.

이곳엔 그냥 16비트 주소값이 저장되어있고 그 번지로 점프한다.

점프할 주소는 사용자가 모니터프로그램에서 설정해주면 된다.

아래와 같이...

CSEG           AT  2000H

        DCW 0FF00H     ; INT00:TIMER OVERFLOW

        DCW 0FF10H     ; INT01:A/D CONVERSION

        DCW 0FF20H     ; INT02:HSI DATA

                    ....






2004H

FF20

2002H

FF10

2000H

FF00

  16비트 번지를 저장하기위해 2번지씩 증가


그러나 FFOOH 번지로 점프했다고해서 인터럽트 서비스 루틴이 바로 실행되는 것은 아니다.

직접 서비스 루틴을 만들지 않는 이유는? 서비스 루틴의 내용이 어느정도 될지도 모르고 또 영역이 띄엄띄엄있으면 좀 그렇지 않나...정확한 이유는 모르겠다.

여기서 다시 실제 인터럽트 서비스 루틴이 있는곳으로 점프하는데 이러한 처리과정을 ‘이중 벡터링 처리’라고 한다. 

그러면 두 번째로 점프할 목적지는 어디로 할것이냐...

그것 역시 프로그래머 맘인데 바로 스타트업 코드해서 설정하면 된다.

CSEG    AT 0ff00H

EXTRN   INT00_timer_over

LJMP    INT00_timer_over    소스에서 INT00_timer_over함수의 시작번지로 점프한다.

CSEG    AT 0ff10H   

EXTRN   INT01_ad_int

LJMP    INT01_ad_int


☞롬 영역의 인터럽트 벡터 간격은 2byte 였는데 여기는 무려 16바이트나 된다.

LJMP를 하려면 우선 3바이트가 필요하다.(SJMP는 2바이트) 또 경우에 따라서는 여기서 PUSHA, POPA 명령을 사용할 수도 있으니 약간 메모리 공간을 넓게 잡는 것이 좋다. 그러나 너무 넓게 잡으면 그만큼 사용자가 사용하지 못하는 RAM 영역이 커진다.


☞이와 같이 이중 벡터링 처리를 하기위해서 스타트업 파일에서 처리하여 C소스를 번역한 오브젝트와 링크하는 약간 복잡한 방법을 써야한다.

그러나 이건 ic96이라는 컴파일러가

이중벡터링을 지원하지 않기 때문에 그런것이지 다른 CPU도 이렇게 하는 것은 아니다. 


☞8051 전용인 Keil 컴파일러는 이중 벡터링기능을 손쉽게 할수 있는 옵션을 지원한다 .

아래와 같이.. 

#pragma intvector(0xFF00)

라고만 적어주면 된다.


인터럽트 관련 레지스터 및 명령

PSW

2바이트 레지스터. PSW.1로 인터럽트 전체 enable or disable 되는지 결정된다.

-상위 바이트 :  상태 레지스터로 SFR에 해당되지 않는다. -->직접적인 access 불가

-하위 바이트 :  SFR의 int_mask 레지스터

pushf or pusha 로 스택에 꺼낼수 있다.


pushf

PSW를 스택에 저장하고(int_mask도) 그 값을 0으로 만든다. PSW.1이 0이 되므로 인터럽트가 금지된다.

→이 명령이 실행되는 동안 인터럽트를 허용하지 않고 모든 인터럽트 플래그를 clear 한다.


②pusha(push all)

pushf 기능 + int_mask1/WSR를스택에 저장하고  

int_mask1은 0으로

→인터럽트 금지


③popf,popa

서비스 루틴에서 psw,int_mask1,wsr등 push했던값들을 다시 꺼낸다.

int_mask1 레지스터는 pupa 명령으로 이를 스택에 저장할수 있고 popa 명령으로 스택으로부터 다시 꺼낼수 있다.


우선 순위

----윤덕용 교수님말씀 그대로 옮겨적음

인터럽트 우선순위라는 것은 CPU마다 상당히 그 의미가 다르다는 것을 아셔야 합니다.

어느 CPU에서는 우선순위를 단지 2개 이상의 인터럽트가 동시에 발생되었을 때 그 처리순서를 지정하는 정도로만 정의합니다.

이 경우에는 높은 순위의 인터럽트가 처리되고 있는 동안에 그보다 낮은 인터럽트가 걸릴 수도 있습니다.


하지만, 다른 CPU에서는 동시에 발생된 것들의 처리순서는 물론이고 높은 순위의 인터럽트가 처리되는 동안에는 아예 낮은 순위의 인터럽트가 걸리지 못하는 경우도 있습니다.

관련 레지스터

①int_mask , int_mask1

개개의 인터럽트를 enable/disable 시킨다.

비트는 단지 인터럽트 서비스를 제어함.clear 되었을 때 일어나는 인터럽트 요청은 인터럽트 대기 레지스터가 가지고 있다.