글에 틀린 부분이 있을 수도 있습니다. 피드백은 언제나 환영입니다. 감사합니다.
1. Intro
LEDR(RED LED)에 값을 출력하는 프로그램이나 banner scroll이나 모두 주어진 입력을 출력시키는 프로그램이다. 그러나 입력을 받아서 출력하는 프로그램을 만들기 위해서는 Interrupt 방식
을 이용할지 polled I/O 방식
을 사용할지 결정해야 한다. Interrupt 방식을 이용하면, CPU는 다른 작업을 처리하고 있다가 context switching을 통해 interrupt request를 처리해주고 그것이 끝나면 다시 원래 작업을 재시작하거나 아니면 다른 작업을 시작하거나 한다. polled I/O 는 busy-waiting
을 이용한다. 그렇기 때문에 CPU Idle time은 interrupt 방식이 더 많고, 이는 남은 CPU idle time 동안 다른 작업을 할 수 있다는 뜻이므로 interrupt방식이 polled I/O 방식보다 CPU를 효율적으로 사용한다는 것을 알 수 있다.
아무튼 교수님께서 내주신 과제는 Polled I/O를 이용한 프로그램을 만드는 것이었다. 그래서 이번 포스트에서는 Polled I/O를 이용하여 만든 Calculator 프로그램에 대해 적어보려 한다.
2. 동작원리
2.1 사용되는 FPGA peripheral
calculator 프로그램을 위해서 HEX0에서부터 HEX3(즉 7-segment 4개)
, slide switch 3개(SW0-SW2)
, pushbutton key 1개(KEY0)
, LEDR 10개
가 사용된다.
2.2 순서도
위의 순서도를 글로 설명해보면 다음과 같다. calculator를 위해서는 slide switch가 3개가 사용된다(SW0-SW2). 첫번째 피연산자를 입력받기 위해 slide switch 전부를 내리고 KEY0로 피연산자를 입력받는다. push button을 누를 때 HEX3-HEX0에 피연산자 값이 출력된다. 이후에 SW0를 on으로 바꾸고 연산자를 입력받는다. 한 번 누르면 A가 표시되고, 두 번 누르면 S가 표시되며, 세 번 누르면 P가 표시된다.그 후에 SW1만 on 시키고 나머지 slide switch는 off 시킨 후 두번째 피연산자를 입력받는다. 피연산자 입력과 연산자 입력이 다 끝났으니, 이제 SW2만 on 시키고 나머지 slide switch는 다 off 시키면, 연산결과가 HEX3-HEX0에 출력된다.
3. 구현방법설명
지난 포스트의 banner scroll source code 에서처럼 이번 calculator source code에도 7-segment에 출력될 10진수에 해당하는 code를 반환하는 각각의 함수를 정의해주었다. 추가로 Add, Sub, Power
에 해당하는 모습도 HEX에 출력하기 위해 A,S,P에 해당하는 code를 반환하는 함수들도 정의해주었다.
그리고 polled I/O를 위하여 가장 바깥의 큰 while 문 안에서 *SW 값
에 따라 작은 while 문 안에 진입할 수 있도록 만들었다. 또한 pushbutton key가 눌렸을 때 debouncing 문제
를 해결하기 위해 Figure2의 ㄱ처럼 구현하여, key를 눌렀다가 떼는 시점에 operand 값이 증가하도록 하였다.
while((*SW)&0b010){ // select what is b -> sw0
while((*key)&0x1){
while((*key)&0x1);
pressed2+=1;
}
if (pressed2>=10){
int ten = segment(pressed2/10);
int one = segment(pressed2%10);
int all = (ten<<8) | one;
*HEX3_HEX0_ptr = all;
}
else {
new_num= segment(pressed2);
*HEX3_HEX0_ptr = new_num;
}
}
%와 / 연산자를 이용하여, 피연산자 값이 10 미만 일때와 10 이상일 때를 나누어 7-segment에 적절하게 표현되도록 구현하였다. 이로 인해 피연산자가 입력받을 수 있는 범위는 maximum 99로 제한된다.
while((*SW)&0b100){
int result;
if (operand==1)
result = pressed+pressed2;
else if (operand==2)
result = pressed-pressed2;
else if (operand==3){
int j;
int p=1;
for (j=0; j<pressed2; j++){
p = p * pressed;
}
result = p;
}
if (result>=10 && result<100 ){
int ten = segment(result/10);
int one = segment(result%10);
int all = (ten<<8) | one;
*HEX3_HEX0_ptr = all;
}
else if (result<10 && result>=0){
new_num= segment(result);
*HEX3_HEX0_ptr = new_num;
}
else if (result>=100 && result<1000){
int hun = segment(result/100);
result = result - 100*(result/100);
int ten = segment(result/10);
int one = segment(result%10);
int all = (hun<<16) | (ten<<8) | one;
*HEX3_HEX0_ptr = all;
}
else if {
*HEX3_HEX0_ptr = 0b00000000;
*ledr = 0b1111111111;
}
}
연산결과는 %와 / 연산자를 이용하여 일의 자리수, 십의 자리수, 백의 자리수 를 각각 출력하도록 구현하였다. 백의 자리수까지만 출력하도록 구현하였으므로 연산결과의 maximum값은 999이다. 연산결과가 1000이상이면 overflow
가 발생했음을 알리기 위해 LEDR 10개가 켜지도록 하였다.
4. 결과
첫번째 영상은 21+14=35(Add) 하는 영상이고, 두번째 영상은 15-7=8(Sub) 하는 영상이고, 세번째 영상은 2^8=256(Power) 하는 영상이고, 네번째 영상은 10^6=1,000,000(overflow) 영상이다. 모두 정상적으로 동작함을 확인할 수 있다.
'과제 및 프로젝트 > 임베디드 시스템 설계' 카테고리의 다른 글
Memory-Mapped IO in Linux-Based Systems(3) (0) | 2024.12.23 |
---|---|
Memory-Mapped IO in Linux-Based Systems(2) (0) | 2024.12.22 |
Memory-Mapped IO in Linux-Based Systems(1) (0) | 2024.12.22 |