일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 쉽게 배우는 운영체제
- 맛집
- Project Euler 해답
- hg
- OS 구조와 원리
- 운영체제 문제 풀이
- 운영체제 만들기
- OS 제작
- OS강의
- rg
- 건담 프라모델
- 건담 엑스포
- 운영체제 정리
- OS
- Gundam
- os 만들기
- OS 그래픽 처리
- 건프라
- 운영체제
- project euler
- 쉽게 배우는 운영체제 솔루션
- 프라모델
- Project Euler Problem
- 운영체제 제작
- 쉽게 배우는 운영체제 풀이
- 쉽게 배우는 운영체제 연습문제
- 건담
- 30일
- OS 강의
- 맛집 추천
- Today
- Total
밤색모자이크의 개발이야기
7일차. FIFO와 마우스 제어 본문
안녕하세요. 밤색모자이크입니다.
7일차에는 마우스 인터럽트와 키보드 인터럽트 처리를 마무리합니다.
글자가 입력되고 마우스가 움직이는건 아니지만, 해당 디바이스의 정보가 인터럽트 처리되어 들어오는 것을 확인 할 수 있습니다.
인터럽트를 할 때, 큐를 사용했는데 선형큐는 데이터가 밀어들어오면 다 저장을 못하고 한번 쓰면 버려야하기 때문에 원형큐를 구현하였습니다. 큐를 구현한 소스코드는 fifo.c 입니다.
별 다른 용어는 없습니다.
개발환경
운영체제 : Windows10
텍스트 편집기 : Atom
PC 에뮬레이터 : QEMU
소스코드
수정된 파일
bootpack.c : 키보드와 마우스 인터럽트 후 처리 코드 추가
bootpack.h : fifo.c의 관련 함수 추가
int.c : 인터럽트 실행을 빠르게 하기위해 인터럽트 실행 함수 변경
Makefile : fifo.c 관련 파일 규칙 추가
추가된 파일
fifo.c : 인터럽트 버퍼인 fifo 관련 함수 추가
fifo.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | /* FIFO 라이브러리 */ #include "bootpack.h" #define FLAGS_OVERRUN 0x0001 void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf) /* FIFO 버퍼의 초기화 */ { fifo->size = size; fifo->buf = buf; fifo->free = size; /* 빈 곳 */ fifo->flags = 0; fifo->p = 0; /* write 위치 */ fifo->q = 0; /* read 위치 */ return; } int fifo8_put(struct FIFO8 *fifo, unsigned char data) /* FIFO에 데이터를 보내 쌓는다 */ { if (fifo->free == 0) { /* 빈 곳이 없어서 넘쳤다 */ fifo->flags |= FLAGS_OVERRUN; return -1; } fifo->buf[fifo->p] = data; fifo->p++; if (fifo->p == fifo->size) { fifo->p = 0; } fifo->free--; return 0; } int fifo8_get(struct FIFO8 *fifo) /* FIFO로부터 데이터를 1개 가져온다 */ { int data; if (fifo->free == fifo->size) { /* 버퍼가 비어있을 때는 우선 -1이 주어진다 */ return -1; } data = fifo->buf[fifo->q]; fifo->q++; if (fifo->q == fifo->size) { fifo->q = 0; } fifo->free++; return data; } int fifo8_status(struct FIFO8 *fifo) /* 어느 정도 데이터가 모여 있을까를 보고한다 */ { return fifo->size - fifo->free; } |
fifo에 관련 함수들을 모아놨습니다.
fifo는 선입력 선출력이고, 버퍼를 계속 재사용하기 위해서 원형큐를 구현하였습니다.
bootpack.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | /* bootpack의 메인 */ #include "bootpack.h" #include <stdio.h> extern struct FIFO8 keyfifo, mousefifo; void enable_mouse(void); void init_keyboard(void); void HariMain(void) { struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO; char s[40], mcursor[256], keybuf[32], mousebuf[128]; int mx, my, i; init_gdtidt(); init_pic(); io_sti(); /* IDT/PIC의 초기화가 끝났으므로 CPU의 인터럽트 금지를 해제 */ fifo8_init(&keyfifo, 32, keybuf); fifo8_init(&mousefifo, 128, mousebuf); io_out8(PIC0_IMR, 0xf9); /* PIC1와 키보드를 허가(11111001) */ io_out8(PIC1_IMR, 0xef); /* 마우스를 허가(11101111) */ init_keyboard(); init_palette(); init_screen8(binfo->vram, binfo->scrnx, binfo->scrny); mx = (binfo->scrnx - 16) / 2; /* 화면 중앙이 되도록 좌표 계산 */ my = (binfo->scrny - 28 - 16) / 2; init_mouse_cursor8(mcursor, COL8_008484); putblock8_8(binfo->vram, binfo->scrnx, 16, 16, mx, my, mcursor, 16); sprintf(s, "(%d, %d)", mx, my); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 0, COL8_FFFFFF, s); putfonts8_asc(binfo->vram, binfo->scrnx, 30, 50, COL8_FFFFFF, "Hi, Chestnut Mosaic OS"); enable_mouse(); for (;;) { io_cli(); if (fifo8_status(&keyfifo) + fifo8_status(&mousefifo) == 0) { io_stihlt(); } else { if (fifo8_status(&keyfifo) != 0) { i = fifo8_get(&keyfifo); io_sti(); sprintf(s, "%02X", i); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s); } else if (fifo8_status(&mousefifo) != 0) { i = fifo8_get(&mousefifo); io_sti(); sprintf(s, "%02X", i); boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 32, 16, 47, 31); putfonts8_asc(binfo->vram, binfo->scrnx, 32, 16, COL8_FFFFFF, s); } } } } #define PORT_KEYDAT 0x0060 #define PORT_KEYSTA 0x0064 #define PORT_KEYCMD 0x0064 #define KEYSTA_SEND_NOTREADY 0x02 #define KEYCMD_WRITE_MODE 0x60 #define KBC_MODE 0x47 void wait_KBC_sendready(void) { /* 키보드 컨트롤러가 데이터 송신이 가능하게 되는 것을 기다린다 */ for (;;) { if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) { break; } } return; } void init_keyboard(void) { /* 키보드 컨트롤러의 초기화 */ wait_KBC_sendready(); io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE); wait_KBC_sendready(); io_out8(PORT_KEYDAT, KBC_MODE); return; } #define KEYCMD_SENDTO_MOUSE 0xd4 #define MOUSECMD_ENABLE 0xf4 void enable_mouse(void) { /* 마우스 유효 */ wait_KBC_sendready(); io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE); wait_KBC_sendready(); io_out8(PORT_KEYDAT, MOUSECMD_ENABLE); return; /* 잘되면 ACK(0xfa)가 송신되어 온다 */ } |
키보드와 마우스를 인터럽트를 처리할 때
원래는 문자열 표시를 인터럽트가 발생하면 받는 함수에서 했는데 이렇게 처리하게 되면 인터럽트에서 출력을 하는 것이므로 인터럽트 처리에 많이 느려지게 됩니다.
따라서, 인터럽트 발생과 신호를 버퍼에 넣어두고 추후에 처리하도록 구현합니다.
bootpack.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | /* asmhead.nas */ struct BOOTINFO { char cyls; char leds; char vmode; char reserve; short scrnx, scrny; char *vram; }; #define ADR_BOOTINFO 0x00000ff0 /* naskfunc.nas */ void io_hlt(void); void io_cli(void); void io_sti(void); void io_stihlt(void); int io_in8(int port); void io_out8(int port, int data); int io_load_eflags(void); void io_store_eflags(int eflags); void load_gdtr(int limit, int addr); void load_idtr(int limit, int addr); void asm_inthandler21(void); void asm_inthandler2c(void); /* fifo.c */ struct FIFO8 { unsigned char *buf; int p, q, size, free, flags; }; void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf); int fifo8_put(struct FIFO8 *fifo, unsigned char data); int fifo8_get(struct FIFO8 *fifo); int fifo8_status(struct FIFO8 *fifo); /* graphic.c */ void init_palette(void); void set_palette(int start, int end, unsigned char *rgb); void boxfill8(unsigned char *vram, int xsize, unsigned char c, int x0, int y0, int x1, int y1); void init_screen8(char *vram, int x, int y); void putfont8(char *vram, int xsize, int x, int y, char c, char *font); void putfonts8_asc(char *vram, int xsize, int x, int y, char c, unsigned char *s); void init_mouse_cursor8(char *mouse, char bc); void putblock8_8(char *vram, int vxsize, int pxsize, int pysize, int px0, int py0, char *buf, int bxsize); #define COL8_000000 0 #define COL8_FF0000 1 #define COL8_00FF00 2 #define COL8_FFFF00 3 #define COL8_0000FF 4 #define COL8_FF00FF 5 #define COL8_00FFFF 6 #define COL8_FFFFFF 7 #define COL8_C6C6C6 8 #define COL8_840000 9 #define COL8_008400 10 #define COL8_848400 11 #define COL8_000084 12 #define COL8_840084 13 #define COL8_008484 14 #define COL8_848484 15 /* dsctbl.c */ struct SEGMENT_DESCRIPTOR { short limit_low, base_low; char base_mid, access_right; char limit_high, base_high; }; struct GATE_DESCRIPTOR { short offset_low, selector; char dw_count, access_right; short offset_high; }; void init_gdtidt(void); void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar); void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar); #define ADR_IDT 0x0026f800 #define LIMIT_IDT 0x000007ff #define ADR_GDT 0x00270000 #define LIMIT_GDT 0x0000ffff #define ADR_BOTPAK 0x00280000 #define LIMIT_BOTPAK 0x0007ffff #define AR_DATA32_RW 0x4092 #define AR_CODE32_ER 0x409a #define AR_INTGATE32 0x008e /* int.c */ void init_pic(void); void inthandler21(int *esp); void inthandler2c(int *esp); #define PIC0_ICW1 0x0020 #define PIC0_OCW2 0x0020 #define PIC0_IMR 0x0021 #define PIC0_ICW2 0x0021 #define PIC0_ICW3 0x0021 #define PIC0_ICW4 0x0021 #define PIC1_ICW1 0x00a0 #define PIC1_OCW2 0x00a0 #define PIC1_IMR 0x00a1 #define PIC1_ICW2 0x00a1 #define PIC1_ICW3 0x00a1 #define PIC1_ICW4 0x00a1 |
fifo에 관련된 함수 정의로 구조체를 추가했습니다.
int.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | /* 인터럽트 관계 */ #include "bootpack.h" #include <stdio.h> void init_pic(void) /* PIC의 초기화 */ { io_out8(PIC0_IMR, 0xff ); /* 모든 인터럽트를 받아들이지 않는다 */ io_out8(PIC1_IMR, 0xff ); /* 모든 인터럽트를 받아들이지 않는다 */ io_out8(PIC0_ICW1, 0x11 ); /* edge trigger 모드 */ io_out8(PIC0_ICW2, 0x20 ); /* IRQ0-7은, INT20-27으로 받는다 */ io_out8(PIC0_ICW3, 1 << 2); /* PIC1는 IRQ2에서 접속 */ io_out8(PIC0_ICW4, 0x01 ); /* non buffer모드 */ io_out8(PIC1_ICW1, 0x11 ); /* edge trigger 모드 */ io_out8(PIC1_ICW2, 0x28 ); /* IRQ8-15는, INT28-2 f로 받는다 */ io_out8(PIC1_ICW3, 2 ); /* PIC1는 IRQ2에서 접속 */ io_out8(PIC1_ICW4, 0x01 ); /* non buffer모드 */ io_out8(PIC0_IMR, 0xfb ); /* 11111011 PIC1 이외는 모두 금지 */ io_out8(PIC1_IMR, 0xff ); /* 11111111 모든 인터럽트를 받아들이지 않는다 */ return; } #define PORT_KEYDAT 0x0060 struct FIFO8 keyfifo; void inthandler21(int *esp) { unsigned char data; io_out8(PIC0_OCW2, 0x61); /* IRQ-01 접수 완료를 PIC에 통지 */ data = io_in8(PORT_KEYDAT); fifo8_put(&keyfifo, data); return; } struct FIFO8 mousefifo; void inthandler2c(int *esp) /* PS/2 마우스로부터의 인터럽트 */ { unsigned char data; io_out8(PIC1_OCW2, 0x64); /* IRQ-12 접수 완료를 PIC1에 통지 */ io_out8(PIC0_OCW2, 0x62); /* IRQ-02 접수 완료를 PIC0에 통지 */ data = io_in8(PORT_KEYDAT); fifo8_put(&mousefifo, data); return; } |
인터럽트에서 출력하는 기능을 빼고 fifo 버퍼에 통지하는 것으로 수정했습니다.
Makefile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \ int.obj fifo.obj TOOLPATH = ../z_tools/ INCPATH = ../z_tools/haribote/ MAKE = $(TOOLPATH)make.exe -r NASK = $(TOOLPATH)nask.exe CC1 = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet GAS2NASK = $(TOOLPATH)gas2nask.exe -a OBJ2BIM = $(TOOLPATH)obj2bim.exe MAKEFONT = $(TOOLPATH)makefont.exe BIN2OBJ = $(TOOLPATH)bin2obj.exe BIM2HRB = $(TOOLPATH)bim2hrb.exe RULEFILE = $(TOOLPATH)haribote/haribote.rul EDIMG = $(TOOLPATH)edimg.exe IMGTOL = $(TOOLPATH)imgtol.com COPY = copy DEL = del # 디폴트 동작 default : $(MAKE) img # 파일 생성 규칙 ipl10.bin : ipl10.nas Makefile $(NASK) ipl10.nas ipl10.bin ipl10.lst asmhead.bin : asmhead.nas Makefile $(NASK) asmhead.nas asmhead.bin asmhead.lst hankaku.bin : hankaku.txt Makefile $(MAKEFONT) hankaku.txt hankaku.bin hankaku.obj : hankaku.bin Makefile $(BIN2OBJ) hankaku.bin hankaku.obj _hankaku bootpack.bim : $(OBJS_BOOTPACK) Makefile $(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \ $(OBJS_BOOTPACK) # 3MB+64KB=3136KB bootpack.hrb : bootpack.bim Makefile $(BIM2HRB) bootpack.bim bootpack.hrb 0 haribote.sys : asmhead.bin bootpack.hrb Makefile copy /B asmhead.bin+bootpack.hrb haribote.sys haribote.img : ipl10.bin haribote.sys Makefile $(EDIMG) imgin:../z_tools/fdimg0at.tek \ wbinimg src:ipl10.bin len:512 from:0 to:0 \ copy from:haribote.sys to:@: \ imgout:haribote.img # 일반 규칙 %.gas : %.c bootpack.h Makefile $(CC1) -o $*.gas $*.c %.nas : %.gas Makefile $(GAS2NASK) $*.gas $*.nas %.obj : %.nas Makefile $(NASK) $*.nas $*.obj $*.lst # 커맨드 img : $(MAKE) haribote.img run : $(MAKE) img $(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin $(MAKE) -C ../z_tools/qemu install : $(MAKE) img $(IMGTOL) w a: haribote.img clean : -$(DEL) *.bin -$(DEL) *.lst -$(DEL) *.obj -$(DEL) bootpack.map -$(DEL) bootpack.bim -$(DEL) bootpack.hrb -$(DEL) haribote.sys src_only : $(MAKE) clean -$(DEL) haribote.img |
추가된 fifo.c파일을 파일 생성 규칙에 추가했습니다.
실행
실행 전 파일 목록입니다.
컴파일 후 화면 모습입니다.
컴파일 후 파일 목록입니다.
결과
9D와 03이 부분인 각각 키보드, 마우스 인터럽트 결과입니다.
키보드와 마우스를 건더리면 계속 변하는 것을 확인 하실 수 있습니다.
참고 자료
OS 구조와 원리, 카와이 히데미 저, 한빛미디어 출판
링크 : http://www.hanbit.co.kr/store/books/look.php?p_code=B9833754652
링크 : http://godrjsmgl.tistory.com/66
'Embedded > OS제작 with OS구조와원리' 카테고리의 다른 글
8일차. 마우스 제어와 32비트 모드 전환 (4) | 2017.08.08 |
---|---|
6일차. 분할 컴파일과 인터럽트 처리 (0) | 2017.08.01 |
5일차. 문자 표시와 마우스를 위한 GDT/IDT 초기화 (0) | 2017.07.10 |
4일차. C언어와 화면 표시 - (3) OS 화면 구성 (0) | 2017.07.09 |
4일차. C언어와 화면 표시 - (2) 사각형 띄우기 (0) | 2017.07.09 |