Programmable Interrupt Controller (PIC)
01. Programmable Interrupt Controller (PIC)
PC에서 모든 외부로 부터의 하드웨어 인터럽트는 8259A라는 칩을 통해서 입력을 받는다. 이 칩을 보통 PIC라고 부른다.
PIC에 대해서 간단히 언급하면 Programmable Interrupt Controller의 약자이며, 하나의 컨트롤러의 개념을 가지고 있어며 여러가지의
모드의 연산을 제공해주어 조그마한 프로그램을 넣어서 조작할 수 있다. 그렇지만 PC에서의 이 칩의 사용은 인터럽트에 대한 것에만 사용이 되고 있다.
PIC 프로그램에는 초기화, 다수의 PIC 연결 방법, 인터럽트를 받아들이는 방법, 받아 들인 인터럽트에 대해 CPU에게 알려주는 방법 등이 기재가 되어있어야 한다.
02. PIC의 구성
PIC는 Master, Slave의 개념으로 여러개를 연결해서 여러 device에대한 처리가 가능하지만, 일반적으로 PC에서는 2개의 PIC(Master, Slave)를 사용한다.
PIC의 구성을 살펴 보면 아래와 같다.
< PIC 구성 >
< IRQ 번호에 대한 인터럽트 >
위의 그림과 같이 구성이 되어있으며, Master / Slave PIC에 연결되어있는 각 IRQ핀에는 여러 가지 장치들의 인터럽트 선이 연결되어 있다. 번호에 대한 하드웨어 인터럽트를 확인할 수가 있다.
03. Master / Slave PIC의 동작
두개로 구성된 PIC에서 Master / Slave PIC 의 동작이 약간은 차이가 난다. 우선 Master PIC의 동작에 대해서 살펴보자.
하나의 예로 마스터 PIC에 연결된 장치 중 하나에서 인터럽트가 발생하였다고 가정을 하면,
-
마스터 PIC는 자신의 INT 핀에 신호를 실어 CPU의 INT핀에 신호를 준다.
-
신호를 받은 CPU는 EFLAG 레지스터의 IE 비트가 1로 세트되어있는지 확인하고 인터럽트가 허용된 상태라면 /INTA를 통해
-
신호를 잘받았다는 확인 신호를 보낸다.
-
마스터 PIC는 /INTA 신호를 받으면 몇 번째 IRQ에 연결된 장치에서 인터럽트가 발생했는지를 숫자로 데이터 버스를 통해 CPU로
전달한다. -
CPU는 이 데이터를 참조하여 Protected Mode로 실행 중이라면 IDT에서 번호에 맞는 디스크립터를 찾아 인터럽트 핸들러를 실행한다.
슬레이브 PIC에 연결된 장치 중 하나에서 인터럽트가 발생하였다고 가정을 하면,
-
슬레이브 PIC는 자신의 INT 핀에 신호를 실어 마스터 PIC의 IRQ 2번핀에 인터럽트 신호를 보낸다.
-
마스터 PIC는 자신의 IRQ 핀에서 인터럽트가 발생했으므로 자신의 INT핀에 신호를 실어 CPU에게 알린다.
-
CPU가 /INTA 신호를 주면 데이터 버스에 숫자를 실어 CPU에게 몇 번째 IRQ에서 인터럽트가 발생했는지를 알려준다.
( 이 경우 번호는 8~15 사이 )
04. IBM PC의 PIC Port Number
IBM호환 PC에서 PIC 관련 포트 번호는 아래와 같고 읽기/쓰기에 따라 용도가 다르다.
<Master 용 포트 번호>
<Slave 용 포트 번호>
위와 같이 Master/Slave 각각 2개의 포트만 할당해 놓고 읽고 쓰고에 따라서 레지스터가 다르다. 일단 ICW1, OCW2와 같은 컨트롤러의 커맨드 레지스터에 대한 설명은 뒤에서 하도록 하고, 포트 0x20 번지에 값이 쓰여졌을 때 어떻게 구분가능한지를 알아보자.
포트에 값을 쓸때 과연 어떤 용도인지(ICW1인지 OCW2인지...) 알 수 있을까?
답은 커맨드 레지스터의 특정 필드 셋팅에 있다.
04.1 Port 0x20 or 0xA0 처리
일단 0x20/0xA0을 같이 사용하고 있는 ICW1/OCW2/OCW3를 한번 보자.
<ICW1>
<OCW2>
<OCW3>
위에서 붉은 부분에 대해서 정리하면 아래와 같다.
- ICW1 : 4bit가 반드시 1로 설정
- OCW2 : 3bit가 반드시 0으로, 4bit가 반드시 0으로 설정
- OCW3 : 3bit가 반드시 1로, 4bit가 반드시 0으로 설정
즉 가운데 3~4bit의 값을 보면 어떤 커맨드 레지스터로 값을 쓰는지 알 수 있는 것이다.
읽기 같은 경우는 IRR과 ISR로 나누어지는데 이것은 스펙에 보면 OCW3 레지스터에 특정한 명령을 내려서 IRR 또는 ISR을 선택하고 읽을 수 있도록 되어있다.
조금 복잡한데... 플래그/순서/레지스터 선택 명령 을 잘 조합해서 사용한다고 생각하면 된다.
04.2 Port 0x21 or 0xA1 처리
그럼 0x21/0xA1을 같이 사용하고 있는 ICW2/ICW3/ICW4/IMR은 어떻게 구분할까? 따로 필드라도 있는 것일까?
그렇지 않다. PIC는 값을 설정할 때 특정 순서대로 넣어줘야 한다. ICW2/ICW3/ICW4는 PIC를 리셋하고 다시 값을 설정할때 사용하는 커맨드 레지스터로 ICW1에 리셋 명령이 들어가면 자동으로 0x21에 들어가는 명령은 ICW2로 사용된다. 그후 값을 쓰면 ICW3로 설정되고 마지막으로 ICW4까지 값이 보내진다.
그럼 ICW1에 리셋 명령이 들어가지 않으면 어떻게 될까? 당연히 IMR 레지스터로 사용되게 되는 것이다.
05. Initialization Command Word (ICW)
Master / Slave 두개의 PIC가 제대로 동작도록 하려면 두개의 PIC를 초기화시켜 주어야 한다.
초기화에 해당하는 과정은 Master와 Slave PIC 설정, 어떤 모드로 동작할지 등등을 프로그램 해주어야 한다.
이 프로그램의 순서는 ICW1, ICW2, ICW3, ICW4의 순서로 이루어지며, PIC에 프로그램할 때는 I/O명령어인 out을 사용하여 Master PIC는 I/O주소 0x20, 0x21 Slave PIC는 0xA0, 0xA1 포트번호를 이용하여 프로그램 한다. 포트 번호0x20과 0xA0은 PIC를 초기화 할때 사용하며(ICW1), 0x21과 0xA1은 ICW2, ICW3 ,ICW4 명령어에서 각 비트를 설정할때 쓰인다.
이제 각 단계별 ICW에 대해서 알아보자.
-
ICW1
PIC를 초기화 하는 명령어이다. 0x20(Master), 0xA0(Slave) 포트를 이용한다.
70
- 4 ~ 7비트는 정해진 것이므로 위 그림의 설정에 맞게 하면된다.
- LTIM은 인터럽트발생의 인정을 신호의 엣지에서 인정할 것인지, HIGH LEVEL로 신호가 모두 올라간 상태에서 인정할 것인지를 정한다.
- SNGL은 현재의 PIC가 Master/Slave로 구성되어있는지, Master한개만을 사용할 것인지를 설정한다.(0: Master/Slave방식, 1: 마스터 한개)
- IC4는 ICW4가 추가적으로 필요한지를 나타낸다. (0: 필요 없음, 1: 필요) -
ICW2
PIC가 인터럽트를 받았을때 IRQ번호에 얼마를 더해서 CPU에게 알려줄 것인지 지정한다.
70
- 0 ~ 2비트가 0인것은 8단위로 기재해야 한다는 뜻이다.
- 이렇게 하는 이유는 하드웨어 장치에서 들어오는 IRQ번호 그대로 CPU에게 보내 주게 되면, CPU에 설정된 Exception(예외)번호와 PC의 메인보드에서의
인터럽트 관련 회로 구현에서 충돌이 일어나기 때문에 하드웨어 인터럽트 번호를 바꾸어 주어야 된다. -
ICW3 (Master)
각 PIC의 Master / Slave로서의 연결 방법을 나타낸다.
70
- S0 ~ S7은 마스터 PIC의 각 IRQ 선에 해당 된다.
- 각각의 비트에 0을 넣게 되면 그 IRQ선은 하드웨어 장치에 연결되어 있다는 것을 의미한다.
- 각각의 비트에 1을 넣게 되면 그 IRQ선은 Slave PIC에 연결되어 있다는 것을 의미한다. -
ICW3 (Slave)
70
- 3 ~ 7비트는 0으로 해둔다. ID0 ~ ID2의 3비트를 사용하여 Slave PIC가 Master PIC의 몇 번째 IRQ 핀에 연결되어 있는지를 나타내는 것으로
- 해당 비트위치를 설정하는 것이 아니라 몇 번째인지 숫자(10진수->2진수)를 넣어주면 된다. -
ICW4
이것은 추가 명령어로 ICW1 명령을 내릴 때 ICW4 추가 명령을 내리는 것을 설정하였다면 이 ICW4 명령을 추가 해야된다.
70
- 여기서는 AEOI 비트에 대해서만 알아본다. AEOI비트는 PIC의 Reset을 자동으로 할 것인지, 수동으로 할 것인지를 설정하는 것이다.
- PIC 인터럽트가 발생하고 CPU에게 알린 후 리셋을 해주어야 다른 인터럽트를 받아들일 수 있다. 이것을 자동으로 할경우 CPU에게 IRQ번호를
보낸 후 바로 리셋을 하며, 수동으로 했을 경우는 CPU에서 인터럽트 핸들러에서 해당 인터럽트를 처리한 후 PIC에 명령을 주는 형식으로 초기를
해야 한다. .( 수동 설정후 인터럽트 처리 루틴에서 PIC초기화를 해주지 않으면 다음 인터럽트 처리는 못하게 되는 상황에 빠지게 된다...ㅡㅡㅋ )
- UPM은 MCS-80/85('0') 또는 8086('1')모드를 중 수행되는 환경을 설정하는 것으로 8086일 경우 '1'을 넣는다.
06. 예제 코드
06.1 PIC 초기화 및 재설정
아래의 코드는 ICW1, ICW2, ICW3, ICW4 순으로 코드를 작성한 것이다. 이 코드가 수행하는 동안에는 인터럽트를 막아주어야된다. 중간에 보이는 jmp $ + 2 ( dw 0x00eb )는 하나의 명령을 주고 약간의 시간 지연을 주기 위함이다.
- ; ( ICW1 )
- mov al, 0x11 ; PIC의 초기화
- out 0x20, al ; 마스터 PIC
- dw 0x00eb, 0x00eb ; jmp $+2, jmp $+2
- out 0xA0, al ; 슬레이브 PIC
- dw 0x00eb, 0x00eb
- ; (ICW2)
- mov al, 0x20 ; 마스터 PIC 인터럽트 시작점
- out 0x21, al
- dw 0x00eb, 0x00eb
- mov al, 0x28 ; 슬레이브 PIC 인터럽트 시작점
- out 0xA1, al
- dw 0x00eb, 0x00eb
- ; ( ICW3 )
- mov al, 0x04 ; 마스터 PIC의 IRQ 2번에
- out 0x21, al ; 슬레이브 PIC이 연결되어있다.
- dw 0x00eb, 0x00eb
- mov al, 0x02 ; 슬레이브 PIC이 마스터 PIC의
- out 0xA1, al ; IRQ 2번에 연결되어 있다.
- dw 0x00eb, 0x00eb
- ; ( ICW4 )
- mov al, 0x01 ; 8086모드를 사용한다.
- out 0x21, al
- dw 0x00eb, 0x00eb
- out 0xA1, al
- dw 0x00eb, 0x00eb
06.2 EOI(End Of Interrupt) 설정
Automatic End Of Interrupt 설정을 PIC 재설정 시에 해주었다면 Interrupt 발생 후 굳이 EOI를 날려줄 필요 없다. 하지만 그렇지 않은 경우는 Interrupt가 발생한 컨트롤러에 EOI를 날려줘야 한다.
주의할 점은 Master의 경우 0x20으로만 날리면 되지만 Slave 같은 경우는 Master와 Slave 모두 날려줘야 하는 부분이다.
- ; (Master EOI)
- mov al, 0x20
- out 0x20, al
- ; (EOI)
- mov al, 0x20
- out 0xa0, al
07. 참고 자료 및 첨부
- 8259A_PIC_Datasheet.pdf : 데이터 시트
- CP_interupt.pdf : 데이터 시트
- 만들 면서 배우는 OS 커널의 구조와 원리
- 8259A Interrupt Controller on the PC
- The Art of Assembley Language