본문 바로가기

Programming/Embedded

Chapter6. IO Programming

 

- 외부 IO 장치는 이들의 응답 시간을 결정하는 물리적 이동 속도는 Computer CPU Memory 속보도다 배는 느리다.

- IO 데이터 전송 속도의 병목은 주로 외부 장치의 속도이므로, 컴퓨터가 장치가 처리할 있는 것보다 데이터를 빨리 전송하지 않도록 주의해야 한다.

- 모든 IO 장치는 CPU 대해서 비동기적으로 동작한다.

- 다시 말해서 입력 장치에 데이터가 있거나 출력 장치에 데이터가 필요함을 알리는 Event 발생 시기는 CPU 독립적이다.

- 따라서 대부분의 IO 프로그래밍은 안정된 데이터 전송을 위해서 CPU IO 장치 간의 상당량의 Handshaking 필요하다.

- IO 소프트웨어는 IO 장치의 요구사항과 제약사항을 세심하게 고려해서 설계해야 한다.

- 설계 방식은 Polling waiting loop, Interrupt driven IO, DMA(Direct Memory Access) 방식이다.

 

1. 인텔 IO 명령어

 

- 많은 IO 포트 번호가 0 ~ 255 범위에 들기 때문에 1 Byte 안에 넣을 있다.

- 하지만 IO 포트 주소 버스의 폭은 12 bit 이기 때문에 포트 번호는 4095까지 있다.

 

- 포트 번호가 1 Byte 들어가지 않는 경우에는 포트를 접근하기 전에 포트 번호를 DX Register 넣어둬야 한다.

- IN, OUT, INSB, OUTSB

 

2. 동기화, 전송 속도, 대기 시간

 

- 입력 데이터는 IO 장치에 있지만 장치가 출력 데이터를 받을 준비가 되어 있는 지를 가리키는 Event 발생은 컴퓨터의 제어 밖에 있다.

- IO 장치과 데이터를 주고 받으려면 장치의 상태를 조사하고 준비될 때까지 기다림으로써 CPU IO 장치에 동기화해야 한다.

 

- 전송 속드는 단순히 CPU 외부 장치 사이에 1 동안 전송된 Byte 수다.

- 인터럽트 구동 IO 인터럽트가 발생할 때마다 Byte 이상 전송하지 않는다면, 기계의 상태를 저장하고 복원하는 Load 때문에 심각하게 성능이 저하된다.

- 대기 시간(latency) 장치가 준비된 시점부터 데이터 Byte 전송될 때까지의 지연 시간이다.  --> 대기 시간은 응답 시간과 같다.

 

3. 폴링 대기 루프

 

- 각각의 데이터 바이트를 전송하기 전에 장치의 상태를 S/W 테스트 한다.

 

 

- 성능을 제한하는 주된 병목은 메모리 대역폭이다.

- Serial_Input 명령어를 가져오고 Stack에서 Return Address 4 Byte 가져오는 것을 제외하면 메모리 접근을 하지 않는다.

- 게다가 IO 전송을 수행해야 한다.

 

추가 정리 필요

 

 

4. 인터럽트 구동 I/O

 

- 예문

- 집에서 소득세를 계산하고 있을 전화가 오면(인터럽트), 세금 계산을 멈추고 전화를 받는다(인터럽트를 받아들인다.)

- 전화는 친구가 자신의 자동차 수리를 위해서 자동차 수리공의 이름과 전화번호를 묻는 것이었다.

- 자동차 수리공의 이름과 전화번호를 준다(인터럽트 요청을 즉시 처리한다.)

 

 

- 인터럽트를 이용하려면 소프트웨어가 이점을 활용할 있도록 구성하기 위해서 먼저 CPU Interrupt 어떻게 처리하는지를 이해해야 한다.

 

4.1 하드웨어 응답

 

- IO 장치는 전송할 데이터가 생기면 CPU 인터럽트 요청을 보낸다.

- 인터럽트가 허용되어 있으면(IF Flag 1 Setting), CPU 현재 명령어의 실행을 마치고 EFlags Return Address(CS EIP) Stack 넣은 다음, 이후의 Interrupt 금지하고(Disable) 해당 ISR 점프한다.

- ISR 진입하면 인터럽트를 다시 허용해서 우선순위가 높은 인터럽트가 현재의 ISR 선점할 있도록 한다.

- CPU Register 현재값을 모두 보존하고 IO 데이터를 전송한 다음, 낮은 우선순위의 인터럽트를 다시 허용하고 CPU 레지스터의 원래 값을 복원한다.

- 마지막으로 IRET 명령어는 EIP, CS, EFlags Register를 POP 하고 Interrupt Code에게 제어를 돌려준다.

- ISR 모든 CPU Register 내용을 보존/복원해서 Interrupt Code 약간의 시간 지연 외에는 아무 일도 없었던 것처럼, 떠낫떤 지점에서 계속할 있어야 한다.

 

 

아래는 H/W Interrupt 처리 순서이다.

 

1. H/W Interrupt 요청 발생

- CPU 현재 명령어를 마친 인터럽트 대응 절차를 시작한다.

 

2. Interrupt 대응 절차

- CPU는 EFlags 복귀주소(CS EIP) PUSH하고, Interrupt 금지하고, 인터럽트를 요청한 장치에서 인터럽트 종류 코드를 읽고, 제어를 해당하는 ISR 넘긴다.

 

3. Interrupt Service Routine

- 우선 순위가 높은 Interrupt 다시 허용

- CPU Register 보존

- 데이터 전송(그리고 인터럽트 요청 삭제)

- 우선순위가 낮은 Interrupt 다시 허용

- CPU Register 복원

- EIP, CS, EFlags  POP 하고 Interrupt Code 복귀

 

 

- CPU Interrupt 요청을 받아들이면, 요청한 장치는 Interrupt 종류 코드 1 Byte 데이터 버스에 올려 놓는다.

- CPU Byte IDT 대한 Index 사용해서 호출할 ISR Entry Address 얻는다.

- Interrupt 종류 Code IDTR Register 있는 IDT 주소와 AND 연산을 통해서 Interrupt Descriptor Table 있는 ISR Physical Address 알아낸다.

- Interrupt Descriptor Table ISR Main Memory 존재한다.

 

 

추가 정리 필요

 

- 인터럽트는 진행 중인 명령어를 방해할 수는 없으므로, 명령어 실행 사이에만 인식된다.

- 따라서 인터럽트 요청부터 하드웨어 응답 완료까지의 최대 대기 시간은 가장 느린 명령어의 실행 시간 + 하드웨어 응답에 필요한 메모리 전송 시간이다.

-