제어/전자HW설계

Lab5

KAU 2020. 10. 14. 02:28

인터럽트 IO를 실습해볼 것이다.

Exception 

말 그대로 예외

내부에서 혹은 외부에서 이벤트가 발생할 때 

0으로 나눈다거나 

컴파일러의 버그나 해킹을 당해서 

없는 instruction set을 

undefined instruction 

혹은 

외부 인터럽트가 있을 때 (키보드나 마우스의 푸쉬버튼,센서 등등)

이러한 exceptional한 이벤트들이 들어오는게 인터럽트

 

hardware interrupt에 대해서 주로 다룰것 입니다.

trap이라는 명령어가 있는데 이것을 사용하면 인터럽트가 발생합니다.

운영체제에서(?) 쭉 하다가 프로세스 동작하는것을 끊고 넘겨준다거나 

시스템 콜을 할 때 exeption을 발생시킬 때 trap을 사용하곤 합니다.

 

하드웨어,소프트웨어,언디파인드 세가지로 분류한다.

 

인터럽트가 발생했을 경우 내부적으로 자동적으로 실제로 수행하고 돌아오는지를 나타낸 그림입니다. 

인터럽트가 발생하면 main에서 ISR으로 점프한다. 

가는 동안에 어떤일이 일어나는가 main루틴은 유저모드에서 일어난다.

ISR이 발생하면 슈퍼바이저 모드에서 동작하는데

 

 

1.pc값을 ea에 세이브를 합니다. (원래 수행했던 부분의 pc값을 저장해두는것)

2.현재 상태도 저장하기 위해 status를 estatus에 저장을 합니다.

(컨트롤 레지스터가 있었는데 그중에 하나가 status 레지스터였다. )

3. 비트가 U비트인데 U비트가 유저인지 슈퍼바이저 모드인지 결정 (0으로 넣어서 슈퍼바이저 모드로)

4. PIE 전반적으로 글로벌하게 발생할지 ~ 할지 0으로 한다는것은 disable한다는것 

하나의 인터럽트가 발생하면 다음 인터럽트가 발생하는것을 막는것 

다른 인터럽트가 발생못하기에 빠르게 처리해줘야 다른 인터럽트가 누락이 안된다.

5. 실제로 ISR에 가서 수행을 한다. pc값을 반대로 옮긴다. ISR로 pc값을 집어 넣어서 그다음것을 수행

 

ISR에 코드를 실제로 집어넣어줘야한다. 

그것을 위해서

ISR에서 하고 싶은것을 excption handling에 메인을 넣어주고

앞 뒤로 context saving과 context restoring 하는데 

스택을 만들어서 거기에 레지스터가 겹쳐지는 애들을 피신시켜놓는데 

이것이 contex saving입니다. 

끝나고 restoring하는것은 피신시켰던 애들을 되돌려 놓는것 입니다.

 

eret을 만나면 다시 메인 루트로 온다.

 

6.pc<-ea값을 넣어줘서 돌아 온다.

 

 

우리는 exception handling 부분을 짜야 하는데 레지스터 부분을 복습할게요

기본적으로 32비트 제너럴 퍼포스 레지스터가 있다.

excption temporary와 

익셉션 하던 와중에 공간이 필요하면 r24를 사용하는것인데 

그래서 컴파일러가 쓸수 있더록 안쓰는게 좋다.

exception return address : pc값을 저장했다가 복원하는것

 

컨트롤 레지스터 

오늘 내용 중 가장 중요한것이 컨트롤 레지스터

컨트롤 레지스터도 32비트이고 6개가 있다

위에 3개는 상태에 관한 레지스터이고 

status레지스터를 인터럽트가 발생하면 estatus로 간다고 했죠 (컨0를 컨1로 카피)

우리가 하는것은 아니고 자동적으로 이뤄진다. 

읽거나 쓰거나 해야하는데 rdctl wrctl을 사용해서 컨트롤 레지스터를 셋업한다.

 

유저모드와 슈퍼바이저 모드가 있는데

유저모드에서 다 처리를 하는데  

슈퍼바이저 모드에서 인터럽트를 처리하는데 

슈퍼바이저 모드에서는 '좀 더 강한 권한'을 갖는다

하드웨어 크리티컬한 것들을 다룰 수 있다.

 

원래는 슈퍼바이저 모드가 어떻게 쓰이나 

운영체제에서 핵심부분이 있는데 

그것을 kernel이라고 한다 OS의 핵심 코어

커널이 슈퍼바이저 모드에서 돌아가는 경우가 많다. 

위의 것들이 슈퍼바이저 모드로 진입할 수 있는 입구가 된다.

 

 

U비트가 슈퍼바이저에서는 0 

유저모드에서는 1

한 비트로 하나씩 표현한다고 하면 

32개의 서로 다른것들을 표현할 수 있는데

32개의 디바이스 혹은 인터럽트를 다룰 수 있다.

 

인터럽트가 어디서 발생했는가?

어떻게 동작을 할것인가 

이것이 인터럽트리퀘스트 IRQ

 

32개의 IRQ를 다룰 수 있다. 

인터럽트 소스가 여러개 있는데 

푸쉬버튼,타이머,토글스위치,오디오~.. 많습니다. 

각각의 IO가 구별이 되어야하는데 IO각각이 IRQ넘버가 할당이 되어있다.

자주쓰는 애들이 테이블로 되어있고 외울필요는 없다.

 

IRQ넘버가 비트 위치와 일치한다고 생각하면 된다.

 

위에서 썻던것들을 읽어오고 쓰는것은 

rdctl,wrctl 

컨트롤 레지스터 기준으로 얘기하는것 입니다. 

 

하드웨어 트랩 언디파인드 

세가지가 있었는데 

세개 중에 어떤것인지 판단해야 합니다.

여러개 중에 하나가 발생했으면 하드웨어 인터럽트가 발생 했구나 

 

Trap은 컨3과 컨4에 값이 올라오지 않아요.

ea레지스터에 가서 값을 읽어오고

멈춘곳이 ea에 저장되어있는데

ㅁ멈춘곳에 다시가서 Trap인지 보는것이죠

그럼이게 소프트웨어 인터럽트였다. 이런식으로 아는것이죠

 

이도저도 아니면 =>undefined

 

패러럴 포트들이 많은데 이것들이 다 인터럽트의 소스가 될 수 있다.

어떤 IO를 사용할것인지 결정할 수 있어야 한다.

푸쉬버튼도 있고 토글 스위치도 있는데 

각각의 인터럽트를 선택하려면 

IRQ로 대변되는 소스들을 어떻게 컨트롤 하느냐?

인터럽트 마스크 레지스터를 사용해서 컨트롤하겠다.

 

저번 시간에 디렉션 비트, 마스크비트,엣지 비트 있다고 했죠?

 

마스크 비트는 0~31까지 있으면 어떻게 인터럽트를 발생시킬지에

각각의 개별 푸쉬버튼이 있으면 이 푸쉬버튼을 모두 사용할지

밑에 두개만 사용할지? 이런것을 설정해주는게 마스트 비트입니다.

하위두개만 사용한다 하면 

마스크는 세팅해주는거라서 write입니다.

 

엣지는 위에 중에서 하나가 1로 떠있을 텐데

어떤것이 눌렸는지 알 수 있게 해주는것 

읽어보는것이라서 R(state)

읽어오는거에요.

 

Edge 캡처 레지스터를 어떻게 클리어 하는가?

write 용도는 아니었는데 만약에 어떤값이든 쓰고 나면 

000000~으로 클리어 된다.

 

타이머도 인터럽트로 사용할 수 있다.

전에는 타임아웃 비트가 1로 바뀌는지 안바뀌는지 봤는데

컨트롤 비트의 ITO를 1로 세팅해두면 

그때 타이머 인터럽트가 인에이블 된다. 

 

세가지 파일로 구성되어있는데 

첫번째는 메인 

두번째는 서비스 

세번째는 key_isr

 

키 제로가 눌렸을 때 

카운터가 증가시킬 때 할거고 

카운터 벨류가 LED에 디스플레이 하려고 한다.

 

인터럽트를 사용해서 할 것인데, 

 

메인에서는 셋업을 한다.

두번째에서는 다른일을 하는데

이코드에서는 다른일을 하지 않는다.

idle루프를 무한대로 도는것 말고는 하는일이 없다.

 

서비스에서는 

인터럽트 발생시 

인터럽트 서비스 루틴이 호출된다. 

 

인터럽트가 여러개 발생하는데

어떤놈이 나를 발생시켰는지 찾는것 까지 

실제로 우리가 일하고 싶은것은 key ISR- 이쪽에 실제 코드를 작성한다.

set up하는 부분 이것이 어떻게

main을 먼저 보면 

셋업 하는 부분이 쭉 있는데 

스타트해서 스택 잡고 LEDR BASE값을 r22에 저장

r22에 다 리셋한다. 0으로 

 

인터럽트 관련해서 셋업하는 부분인데 

인터럽트 관련해서 셋업해야하는것이 세가지이다. 

 

 

첫번째 컨트롤 레지스터 0번 

PIE 비트가 1로 되어있어야 한다. 

이것은 스위치 중에서 글로벌한 스위치라고 생각하면 된다.

두꺼비 집과 같은 존재'라고 생각하면 된다. 

 

어떤 인터럽트를 사용할지 IRQ(종류)

컨트롤 3 ienable 레지스터에 IRQ에 해당하는 비트를 1로 한다.

인터럽트를 두개를 받을 수는 있다. 

 

세번째 종류가 세팅되었으면 

어느 push 버튼을 사용할지 결정해야 한다. 

Interrupt.hit=1로 한다. 

 

내려가면 내려갈수록 작아진다. 

스코프가 작아진다. 

 

1번 2번 3번이 스위치로 따지면 

집 거실 방 ==> 해당되는 영역이 작아진다. 

 

1,2,3 모두 셋업 되어야 한다. 

 

실제로 프로그램 할 때는 3,2,1 해준다. 

작은것 부터 해주는것 이다.

 

3번 셋팅

 

2번 셋팅

IRQ 1번이면 000010이 되어야 한다. ==>2를 집어넣어야 한다.

 

3번 셋팅

==>인터럽트가 인에이블 됬다.

 

IDLE 만 돌게된다. 

원래 

 

첫번째 버튼을 누르면 서비스로 간다.

익셉션과 관련된 섹션

어떤일이 일어나든 인터럽트가 발생하면 

ISR로 가서 실행이 된다.

 

ISR에서는 스택 포인트를 세이브 한다. 

레지스터 4개를 세이브 하고 

컨트롤 4에 있는 데이터를 읽어와서 et에 저장한다

 

컨트롤 4는 아이팬딩 레지스터인데 

읽어와서 r0랑 비교한다.

아이팬딩이 0이면 하드웨어 인터럽트가 아니라고 해석할 수 있다. 

 

하드웨어 인터럽트일 경우 4를 빼준다.

 

하드웨어 인터럽트는 실행이 끝났는지 안끝났는지 모른다. 

그래서 하던거 다시하라는 의미에서 4를 빼줍니다.

 

ea도 세이브하고 ra도 세이브하고 

0과 맞는지 체크를 하라 체크를 해서 

0이 아니면 하드웨어 인터럽트이기 때문에 ON_EXT_INT로 점프해라 

 

ORQ를 체크해서 ISR을 불러주는것 

그래서 et에서 체크를 하면 

푸쉬버튼이었으면 IRQ가 푸시버튼이 1인데 

0000010이되어야 하는데 이진수로 하면 0b10 

et랑 0b랑 비트 마스킹해서 r22에 넣는다. 

 

1인지 0인지 판별합니다. 

0이면 발생을 안한것이니 END_ISR로 갑니다.

 

1이면 ON_KEY_PRESS로 갑니다.

 

끝나고 돌아오면 END_ISR

=>스택포인터를 이용해서 복원한다.

 

 

 

 

키베이스 레지스터를 넣어두고 

12(r22)를 넣어두고 첫번째 비트가 0인지 1인지 판별합니다.

r23에 잘 세이브 한 후에 엣지캡처 레지스터에 스토어를 하는데

이 이유는 아무값이나 넣으면 0으로 만든다.

r22에 어떤값이 있는지 읽어와서 1을 더하고 

다시 r22에 저장한다. 

 

키를 두개이상 눌렀으면 어떤 키가 눌렸는지 확인해줘야 할것이다. 

디스플레이 해줬으니 복원해주고 끝난다.

 

인터럽트를 사용해서 IO를 할것인데 

각각 0123을 토글을 합니다.

키 4개를 모두 인에이블 해줘야하고 

 

파트2는 타이머를 사용하는것 입니다. 

타이머를 사용해서 0.25초마다 카운트 변수를 하나씩 증가시킵니다.

인터벌 타이머를 이용해서 0.25초마다 타이머가 걸리게 만들고

인터럽트 서비스 루틴에서 1이 증가하게 하는것

증가된 값을 LEDR 디스플레이 시키는것

 

키 인터럽트도 같이 쓴다.

키인터럽트도 써서 아무거나 눌리면 토글런

=>타이머가 돌다가 스톱했다가 다시 돌다가 

 

인터럽트를 두개를 사용하라는것이다.

 

메뉴얼 16-23p 를 참고하세요 ^~^ 아디오스 

'제어 > 전자HW설계' 카테고리의 다른 글

Lab7  (0) 2020.10.30
Lab6  (0) 2020.10.26
Lab4  (0) 2020.10.12
[전자HW설계] LAB3  (0) 2020.09.30
[전자HW설계] LAB2  (0) 2020.09.22