제16강 fpga 디바이스 제어 - koreatech · : 기본 하단의 sw7스위치 #1 off (하향)...
TRANSCRIPT
RaspberryPi FPGA디바이스 1
제16강
FPGA 디바이스 제어( Achro-EM Kit 활용 )
카메라 모듈 테스트
동영상 스트리밍
FPGA 디바이스 제어(LED, BTN)
Qt Creator에 의한 GUI 환경
GUI 환경에서의 디바이스 제어(LED)
RaspberryPi FPGA디바이스 2
시스템 전환
* 기존 라즈베리파이보드에서 SD 카드 뽑아,
Achro-EM kit에 삽입하고 전원 투입
RaspberryPi FPGA디바이스 3
카메라 모듈
* 카메라 인터페이스 활성화
$ sudo raspi-config
* 기본 제공 명령
$ raspistill // 정지영상
$ raspivid // 동영상
RaspberryPi FPGA디바이스 4
카메라 모듈(계속)
* 카메라 정지영상(jpg 포맷) 생성
: jpg 포맷으로 이미지 캡춰할 때
$ raspistill –v -o image.jpg // 5초 미리보기후
$ ls // image.jpg 파일 생성 확인
* 카메라 동영상(h264 포맷) 생성
: h264 포맷의 동영상을 5초동안 캡춰할 때
$ raspivid -o video.h264 -fps 30 -t 5000
-o : 출력파일이름, -fps : 초당프레임,
-t : 촬영시간(msec, 5000 = 5초)
$ ls // video.h264 파일 생성
RaspberryPi FPGA디바이스 5
카메라 모듈(계속)
* 영상 파일 포맷 관련 패키지 설치
: 플레이어 및 포맷 변환 툴
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install mplayer netcat ffmpeg gpac
RaspberryPi FPGA디바이스 6
카메라 모듈(계속)
* 동영상 포맷 변환( h264 -> mkv )
: ffmpeg을 이용
$ ffmpeg –r 30 –i video.h264 –vcodec copy video.mkv
* 동영상 포맷 변환( h264 -> mp4 )
: MP4Box 사용
$ MP4Box –add video.h264 video.mp4
* 동영상 플레이어 ( mplayer )
$ mplayer –zoom –x 200 –y 200 video.mp4
RaspberryPi FPGA디바이스 7
카메라 모듈(계속)
* 동영상 스트리밍 ( mjpg-streamer )
: 라즈베리파이 카메라모듈을 이용한 웹스트리밍 서비스
: 관련 라이브러리 및 cmake 패키지 설치
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install git cmake libjpeg8-dev imagemagick -y
: videodev2.h 헤더파일 소프트 링크(생략 가능, 2019.1.29)
$ sudo ln -s /usr/include/linux/videodev2.h
/usr/include/linux/videodev.h
RaspberryPi FPGA디바이스 8
카메라 모듈(계속)
: mjpg-streamer 소스 다운로드
$ cd ./IFC415/16_FPGA/camera
$ git clone https://github.com/liamfraser/mjpg-streamer
: mjpg-streamer 소스 컴파일
$ cd ./mjpg-streamer/mjpg-streamer-experimental
$ make clean
$ make
RaspberryPi FPGA디바이스 9
카메라 모듈(계속)
: 스크립트를 작성하여 웹스트리밍 서비스 시작
$ pwd
/home/pi/IFC415/16_FPGA/camera
$ sudo nano mjpg.sh
export
STREAMER_PATH=$HOME/IFC415/16_FPGA/camera/mjpg-streamer/mjpg-streamer-experimental
export LD_LIBRARY_PATH=$STREAMER_PATH
$STREAMER_PATH/mjpg_streamer -i "input_raspicam.so -d 200" -o "output_http.so
-w $STREAMER_PATH/www"
주의) 마지막줄은 한 라인으로 작성(전체 3라인되게)
적색 경로를 각자 상황에 맞게 변경....
: 웹스트리밍 서비스 시작 ( 내정 포트 8080 )
$ sh mjpg.sh // 웹스트리밍을 위한 실행
RaspberryPi FPGA디바이스 10
카메라 모듈(계속)
* 웹스트리밍 확인
: 웹브라우저의 주소창에서 http://192.168.0.40:8080/
: Javascript 메뉴 클릭
: 웹스트리밍 서비스 종료시 터미널 창에서 Ctrl-c 눌러 종료
RaspberryPi FPGA디바이스 11
RaspberryPi FPGA디바이스 12
FPGA 디바이스
* Achro-EM Kit
: 기본 하단의 SW7스위치 #1 OFF (하향) 설정시
각 디바이스를 독자 구동토록 설계 됨
: 실습시, 하단의 SW7스위치 #1을 ON(상향)하여
사용자 모드로 전환할 것
RaspberryPi FPGA디바이스 13
FPGA 디바이스(계속)
* FPGA 디바이스의 어드레스 맵 ( 자체 주소체계 )
: 물리주소, 노드명, 주번호
순 장치 어드레스 Node Major
1 LED 0x016 /dev/fpga_led 260
2 Seven Segment (FND) 0x004 /dev/fpga_fnd 261
3 Dot Matrix 0x210 /dev/fpga_dot 262
4 Text LCD 0x090 /dev/fpga_text_lcd 263
5 Buzzer 0x070 /dev/fpga_buzzer 264
6 Push Switch 0x050 /dev/fpga_push_switch 265
7 Dip Switch 0x000 /dev/fpga_dip_switch 266
8 Step Motor 0x00C /dev/fpga_step_motor 267
EN Demo Register 0x300 N/A N/A
RaspberryPi FPGA디바이스 14
FPGA 디바이스(계속)
* FPGA 디바이스 제어
: 제시된 소스는 커널 모듈로 구현
: 실행할 커널 버전의 커널 소스가 필요함
: linux-rpi-4.9.y에서 진행
$ ls /usr/src -l
total 12
lrwxrwxrwx 1 root root 18 Aug 1 11:51 linux -> ./linux-rpi-4.9.y/
drwxr-xr-x 24 pi pi 4096 Oct 22 2018 linux-rpi-4.13.34
drwxr-xr-x 25 pi pi 4096 Aug 2 12:17 linux-rpi-4.9.y
drwxr-xr-x 3 root root 4096 Nov 13 2018 sense-hat
: 컴파일시 Makefile에서 KDIR 환경변수에 소스 경로 지정
KDIR :=/usr/src/linux/
RaspberryPi FPGA디바이스 15
FPGA 디바이스(계속)
* FPGA 인터페이스 모듈
: ./fpga_interface_driver/ 소스
: FPGA디바이스와 라즈베리파이 GPIO 핀간 매핑을 위한 모듈
: 각 디바이스 제어시 필히 미리 커널과 링크되어야 함
$ sudo insmod fpga_interface_driver.ko
$ cat fpga_interface_driver.c/* FPGA LED Ioremap ControlFILE : fpga_fpga_itf_driver.c*/
#include <linux/module.h>#include <linux/kernel.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/gpio.h>#include <asm-generic/bitsperlong.h>
#define CTRL_nWE 0#define CTRL_nOE 1
RaspberryPi FPGA디바이스 16
#define CTRL_nCS 2
static struct gpio iom_fpga_address[] = { // A1 ~ A11, A0=LOW /*{ 10, GPIOF_OUT_INIT_LOW, "ADDRESS 00" },*/
{ 11, GPIOF_OUT_INIT_LOW, "ADDRESS 01" }, { 12, GPIOF_OUT_INIT_LOW, "ADDRESS 02" },
{ 13, GPIOF_OUT_INIT_LOW, "ADDRESS 03" }, { 14, GPIOF_OUT_INIT_LOW, "ADDRESS 04" },
{ 15, GPIOF_OUT_INIT_LOW, "ADDRESS 05" }, { 16, GPIOF_OUT_INIT_LOW, "ADDRESS 06" },
{ 17, GPIOF_OUT_INIT_LOW, "ADDRESS 07" }, { 18, GPIOF_OUT_INIT_LOW, "ADDRESS 08" },
{ 19, GPIOF_OUT_INIT_LOW, "ADDRESS 09" }, { 20, GPIOF_OUT_INIT_LOW, "ADDRESS 10" },
{ 21, GPIOF_OUT_INIT_LOW, "ADDRESS 11" },};
static struct gpio iom_fpga_data[] = { { 2, GPIOF_OUT_INIT_LOW, "DATA 0" },
{ 3, GPIOF_OUT_INIT_LOW, "DATA 1" }, { 4, GPIOF_OUT_INIT_LOW, "DATA 2" },
{ 5, GPIOF_OUT_INIT_LOW, "DATA 3" }, { 6, GPIOF_OUT_INIT_LOW, "DATA 4" },
{ 7, GPIOF_OUT_INIT_LOW, "DATA 5" }, { 8, GPIOF_OUT_INIT_LOW, "DATA 6" },
{ 9, GPIOF_OUT_INIT_LOW, "DATA 7" },};
RaspberryPi FPGA디바이스 17
static struct gpio iom_fpga_control[] = { { 22, GPIOF_OUT_INIT_LOW, "nWE" }, { 23, GPIOF_OUT_INIT_LOW, "nOE" }, { 25, GPIOF_OUT_INIT_LOW, "nCS" },};
static void iom_fpga_itf_set_default(void) { int i = 0;
gpio_set_value(10, 0); // A0: always set to LOW
for (i=0; i<ARRAY_SIZE(iom_fpga_address); i++) { gpio_set_value(iom_fpga_address[i].gpio, 0); }
for (i=0; i<ARRAY_SIZE(iom_fpga_data); i++) { gpio_set_value(iom_fpga_data[i].gpio, 0); }
for (i=0; i<ARRAY_SIZE(iom_fpga_control); i++) { gpio_set_value(iom_fpga_control[i].gpio, 1); }}
static int iom_fpga_itf_open(void) { int ret = 0;
ret = gpio_request_array(iom_fpga_address,
RaspberryPi FPGA디바이스 18
ARRAY_SIZE(iom_fpga_address)); if (ret) { printk(KERN_ERR "Unable to request address GPIOs: %d\n",
ret); return ret; }
ret = gpio_request_array(iom_fpga_data, ARRAY_SIZE(iom_fpga_data));
if (ret) { printk(KERN_ERR "Unable to request data GPIOs: %d\n", ret); return ret; }
ret = gpio_request_array(iom_fpga_control, ARRAY_SIZE(iom_fpga_control));
if (ret) { printk(KERN_ERR "Unable to request control GPIOs: %d\n",
ret); return ret; }
iom_fpga_itf_set_default(); return ret;}
static int iom_fpga_itf_release(void) { iom_fpga_itf_set_default();
RaspberryPi FPGA디바이스 19
gpio_free_array(iom_fpga_address, ARRAY_SIZE(iom_fpga_address));
gpio_free_array(iom_fpga_data, ARRAY_SIZE(iom_fpga_data)); gpio_free_array(iom_fpga_control, ARRAY_SIZE(iom_fpga_control));
return 0;}
ssize_t iom_fpga_itf_write(unsigned int addr, unsigned char value) { size_t length = 1; int i = 0;
printk("FPGA WRITE: address = 0x%x, data = 0x%x \n", addr, value);
for (i=0; i<ARRAY_SIZE(iom_fpga_address); i++) { gpio_set_value(iom_fpga_address[i].gpio, (addr >> i) & 0x1); }
for (i=0; i<ARRAY_SIZE(iom_fpga_data); i++) { gpio_set_value(iom_fpga_data[i].gpio, (value >> i) & 0x1); }
gpio_set_value(iom_fpga_control[CTRL_nCS].gpio, 0); udelay(1); gpio_set_value(iom_fpga_control[CTRL_nWE].gpio, 0); udelay(5); //printk("CS:%d, ", gpio_get_value(iom_fpga_control[CTRL_nCS].gpio));
RaspberryPi FPGA디바이스 20
//printk("WE:%d, ", gpio_get_value(iom_fpga_control[CTRL_nWE].gpio)); //printk("\n"); gpio_set_value(iom_fpga_control[CTRL_nWE].gpio, 1); gpio_set_value(iom_fpga_control[CTRL_nCS].gpio, 1);
/* // Debugging... for (i=0; i<ARRAY_SIZE(iom_fpga_address); i++) { printk("Address(%d):%d, ", i, gpio_get_value(iom_fpga_address[i].gpio)); }
printk("\n"); for (i=0; i<ARRAY_SIZE(iom_fpga_data); i++) { printk("Data(%d):%d, ", i, gpio_get_value(iom_fpga_data[i].gpio)); }
printk("\n"); printk("CS:%d, ", gpio_get_value(iom_fpga_control[CTRL_nCS].gpio)); printk("WE:%d, ", gpio_get_value(iom_fpga_control[CTRL_nWE].gpio)); printk("\n"); */
return length;
RaspberryPi FPGA디바이스 21
}EXPORT_SYMBOL(iom_fpga_itf_write);
unsigned char iom_fpga_itf_read(unsigned int addr) { unsigned char value = 0; int i = 0;
for (i=0; i<ARRAY_SIZE(iom_fpga_address); i++) { gpio_set_value(iom_fpga_address[i].gpio, (addr >> i) & 0x1); }
gpio_set_value(iom_fpga_control[CTRL_nCS].gpio, 0); udelay(1); gpio_set_value(iom_fpga_control[CTRL_nOE].gpio, 0); udelay(1);
for (i=0; i<ARRAY_SIZE(iom_fpga_data); i++) { value += gpio_get_value(iom_fpga_data[i].gpio) << i; }
gpio_set_value(iom_fpga_control[CTRL_nCS].gpio, 1); gpio_set_value(iom_fpga_control[CTRL_nOE].gpio, 1);
printk("FPGA READ: address = 0x%x, data = 0x%x \n", addr, value);
return value;}EXPORT_SYMBOL(iom_fpga_itf_read);
RaspberryPi FPGA디바이스 22
int __init iom_fpga_itf_init(void) { printk("init module: %s\n", __func__); iom_fpga_itf_open(); return 0;}
void __exit iom_fpga_itf_exit(void) { printk("exit module: %s\n", __func__); iom_fpga_itf_release();}
module_init(iom_fpga_itf_init);module_exit(iom_fpga_itf_exit);
MODULE_LICENSE("GPL");
$ cat Makefile#Makefile for a basic kernel module
obj-m := fpga_interface_driver.oKDIR :=/usr/src/linux/PWD :=$(shell pwd)..........
RaspberryPi FPGA디바이스 23
: FPGA 인터페이스 모듈 컴파일
$ make
$ ls
Makefile fpga_interface_driver.ko .........
: 인터페이스 모듈 링크 (각 디바이스 제어에 앞서 필히 )
$ sudo insmod fpga_interface_driver.ko
RaspberryPi FPGA디바이스 24
FPGA LED
* LED 디바이스 ( ./fpga_led/ )
: 회로도 (Low 신호 인가시 LED ON)
: 1바이트 데이터 (MSB..LED0..D1, ..., LSB..LED7..D8)
: 주의) Achro-EM(rPi)은 High신호 출력시 인버팅하도록 설계
RaspberryPi FPGA디바이스 25
FPGA LED(계속)
: LED 디바이스 드라이버 소스
$ cat fpga_led_driver.c /* FPGA LED Ioremap ControlFILE : fpga_led_driver.c AUTH : [email protected] */
#include <linux/module.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/platform_device.h>#include <linux/delay.h>
#include <asm/io.h>#include <asm/uaccess.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/version.h>
#define IOM_LED_MAJOR 260 // ioboard led device major number#define IOM_LED_NAME "fpga_led" // ioboard led device name
RaspberryPi FPGA디바이스 26
#define IOM_LED_ADDRESS 0x016 // pysical address
//Global variablestatic int ledport_usage = 0;
// define functions...ssize_t iom_led_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what);ssize_t iom_led_read(struct file *inode, char *gdata, size_t length, loff_t *off_what);int iom_led_open(struct inode *minode, struct file *mfile);int iom_led_release(struct inode *minode, struct file *mfile);
// define file_operations structure struct file_operations iom_led_fops = {
.owner = THIS_MODULE,
.open = iom_led_open,
.write = iom_led_write,
.read = iom_led_read,
.release = iom_led_release,};
// when led device open ,call this functionint iom_led_open(struct inode *minode, struct file *mfile) {
if(ledport_usage != 0) return -EBUSY;ledport_usage = 1;return 0;
}
// when led device close ,call this function
RaspberryPi FPGA디바이스 27
int iom_led_release(struct inode *minode, struct file *mfile) {ledport_usage = 0;return 0;
}
// when write to led device ,call this functionssize_t iom_led_write(struct file *inode, const char *gdata, size_t length, loff_t *off_what) {
unsigned char value;const char *tmp = gdata;if (copy_from_user(&value, tmp, 1))
return -EFAULT;
iom_fpga_itf_write((unsigned int)IOM_LED_ADDRESS,value);return length;
}
// when read to led device ,call this functionssize_t iom_led_read(struct file *inode, char *gdata, size_t length, loff_t *off_what) {
unsigned char value = 0;char *tmp = gdata;
value = iom_fpga_itf_read((unsigned int)IOM_LED_ADDRESS);if (copy_to_user(tmp, &value, 1))
return -EFAULT;return length;
}int __init iom_led_init(void) {
int result;
RaspberryPi FPGA디바이스 28
result = register_chrdev(IOM_LED_MAJOR, IOM_LED_NAME, &iom_led_fops);
if(result < 0) {printk(KERN_WARNING"Can't get any major\n");return result;
}printk("init module %s, major number %d, minor nuber %d\n",
IOM_LED_NAME, IOM_LED_MAJOR, result);return 0;
}
void __exit iom_led_exit(void) {unregister_chrdev(IOM_LED_MAJOR, IOM_LED_NAME);
}
module_init(iom_led_init);module_exit(iom_led_exit);
MODULE_LICENSE("GPL");MODULE_AUTHOR("Huins");
RaspberryPi FPGA디바이스 29
FPGA LED(계속)
: LED 응용 프로그램 소스
- 1바이트 데이터를 정수형으로 명령행에서 입력
$ cat fpga_test_led.c /* FPGA LED Test ApplicationFile : fpga_test_led.c */
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>
#define LED_DEVICE "/dev/fpga_led"
int main(int argc, char **argv) {int dev;int data;int retval;
if(argc!=2) {printf("please input the parameter! \n");
RaspberryPi FPGA디바이스 30
printf("ex)./test_led 7 (0~255)\n");return -1;
}
data = atoi(argv[1]);if((data<0)||(data>0xff)) {
printf("Invalid range!\n"); exit(1); }
dev = open(LED_DEVICE, O_RDWR); if (dev<0) { printf("Device open error : %s\n",LED_DEVICE); exit(1); }
retval=write(dev, &data, 1); if(retval<0) { printf("Write Error!\n"); return -1; }
sleep(1);
data=0; retval=read(dev, &data, 1); if(retval<0) { printf("Read Error!\n"); return -1; }
RaspberryPi FPGA디바이스 31
printf("Current LED Value : %d\n",data);
printf("\n");
close(dev);
return(0);}
: Makefile
$ cat Makefile#Makefile for a basic kernel module
obj-m := fpga_led_driver.o
KDIR :=/usr/src/linux/
PWD :=$(shell pwd)
all: driver appdriver: $(MAKE) -C $(KDIR) SU
RaspberryPi FPGA디바이스 32
FPGA LED(계속)
* 소스 컴파일 및 실행
: 컴파일 및 링크
$ cd fpga_led
$ make
// 필히 FPGA 인터페이스 모듈이 먼저 링크되어 있어야 함!!!!
$ sudo insmod fpga_led_driver.ko
$ sudo mknod /dev/fpga_led c 260 0
: 실행
$ sudo ./fgpa_test_led 1
RaspberryPi FPGA디바이스 33
FPGA BTN
* Push switch 디바이스 ( ./fpga_push_switch/ )
: 회로도 (Press시 High 신호 출력)
: 9개 푸쉬버튼 스위치
RaspberryPi FPGA디바이스 34
FPGA BTN(계속)
: BTN 모듈 소스
$ cat fpga_push_switch_driver.c/* FPGA PUSH SWITCH Ioremap ControlFILE : fpga_push_switch_driver.c AUTH : [email protected]*/
#include <linux/module.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/slab.h>#include <linux/platform_device.h>#include <linux/delay.h>
#include <asm/io.h>#include <asm/uaccess.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/module.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/version.h>
#define MAX_BUTTON 9
RaspberryPi FPGA디바이스 35
#define IOM_FPGA_PUSH_SWITCH_MAJOR 265 // ioboard led device major number#define IOM_FPGA_PUSH_SWITCH_NAME "fpga_push_switch" // ioboard led device name
#define IOM_FPGA_PUSH_SWITCH_ADDRESS 0x050 // pysical address
extern unsigned char iom_fpga_itf_read(unsigned int addr);extern ssize_t iom_fpga_itf_write(unsigned int addr, unsigned char value);
//Global variablestatic int fpga_push_switch_port_usage = 0;static unsigned char *iom_fpga_push_switch_addr;static unsigned char *iom_demo_addr;
// define functions...ssize_t iom_fpga_push_switch_read(struct file *inode, char *gdata, size_t length, loff_t *off_what); int iom_fpga_push_switch_open(struct inode *minode, struct file *mfile);int iom_fpga_push_switch_release(struct inode *minode, struct file *mfile);
// define file_operations structure struct file_operations iom_fpga_push_switch_fops ={
owner: THIS_MODULE,open: iom_fpga_push_switch_open,read: iom_fpga_push_switch_read,release: iom_fpga_push_switch_release,
};
RaspberryPi FPGA디바이스 36
// when fpga_push_switch device open ,call this functionint iom_fpga_push_switch_open(struct inode *minode, struct file *mfile) {
if(fpga_push_switch_port_usage != 0) return -EBUSY;fpga_push_switch_port_usage = 1;return 0;
}
// when fpga_push_switch device close ,call this functionint iom_fpga_push_switch_release(struct inode *minode, struct file *mfile) {
fpga_push_switch_port_usage = 0;return 0;
}
// when read from fpga_push_switch device ,call this functionssize_t iom_fpga_push_switch_read(struct file *inode, char *gdata, size_t length, loff_t *off_what) {
int i;unsigned char push_sw_value[MAX_BUTTON];
unsigned char value;
for(i=0;i<=length;i++) {
value = iom_fpga_itf_read((unsigned int)IOM_FPGA_PUSH_SWITCH_ADDRESS+i); push_sw_value[i] = value &0xFF;
RaspberryPi FPGA디바이스 37
}
if (copy_to_user(gdata, push_sw_value, length))return -EFAULT;
return length;}
int __init iom_fpga_push_switch_init(void){
int result;
result = register_chrdev(IOM_FPGA_PUSH_SWITCH_MAJOR, IOM_FPGA_PUSH_SWITCH_NAME, &iom_fpga_push_switch_fops);
if(result < 0) {printk(KERN_WARNING"Can't get any major\n");return result;
}
printk("init module, %s major number : %d\n", IOM_FPGA_PUSH_SWITCH_NAME, IOM_FPGA_PUSH_SWITCH_MAJOR);
return 0;}
void __exit iom_fpga_push_switch_exit(void) {
u n r e g i s t e r _ c h r d e v ( I O M _ F P G A _ P U S H _ S W I T C H _ M A J O R , IOM_FPGA_PUSH_SWITCH_NAME);
RaspberryPi FPGA디바이스 38
}
module_init(iom_fpga_push_switch_init);module_exit(iom_fpga_push_switch_exit);
MODULE_LICENSE("GPL");MODULE_AUTHOR("Huins");
: BTN 응용 프로그램 소스
$ cat fpga_test_push.c/* FPGA Push Switch Test ApplicationFile : fpga_test_push.cAuth : [email protected] */
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/ioctl.h>#include <signal.h>
#define MAX_BUTTON 9
RaspberryPi FPGA디바이스 39
unsigned char quit = 0;
void user_signal1(int sig) { quit = 1;}
int main(void) { int i; int dev; int buff_size;
unsigned char push_sw_buff[MAX_BUTTON];
dev = open("/dev/fpga_push_switch", O_RDWR);
if (dev<0){ printf("Device Open Error\n"); close(dev); return –1;
}
(void)signal(SIGINT, user_signal1);
buff_size=sizeof(push_sw_buff); printf("Press <ctrl+c> to quit. \n"); while(!quit){ usleep(400000); read(dev, &push_sw_buff, buff_size);
RaspberryPi FPGA디바이스 40
for(i=0;i<MAX_BUTTON;i++) { printf("[%d] ",push_sw_buff[i]); } printf("\n"); } close(dev);}
: Makefile
$ cat Makefile#Makefile for a basic kernel moduleobj-m := fpga_push_switch_driver.o
KDIR :=/usr/src/linux/PWD :=$(shell pwd)
..............
RaspberryPi FPGA디바이스 41
FPGA BTN(계속)
* 소스 컴파일, 링크 및 실행
$ cd fpga_push_switch
$ make // 컴파일
$ sudo insmod fpga_push_switch_driver.ko // 링크
$ sudo mknod /dev/fpga_push_switch c 261 0 // 노드 생성
$ sudo ./fpga_test_push_switch // 실행
Press <ctrl+c> to quit.[0] [0] [0] [0] [0] [0] [0] [0] [0][0] [0] [0] [0] [0] [0] [0] [0] [0][0] [0] [0] [0] [1] [0] [0] [0] [0][0] [0] [0] [0] [1] [0] [0] [0] [0][0] [0] [0] [0] [0] [0] [0] [0] [0][0] [0] [0] [1] [0] [1] [0] [0] [0][0] [0] [0] [1] [0] [1] [0] [0] [0][0] [0] [0] [1] [0] [1] [0] [0] [0][0] [0] [0] [0] [0] [0] [0] [0] [0][0] [0] [0] [0]................
RaspberryPi FPGA디바이스 42
RaspberryPi FPGA디바이스 43
Qt Creator 설치
* Qt Creator 설치
: Windows 프로그래밍과 흡사한 GUI 환경 제공
: 관련 패키지 설치
$ sudo apt-get update
$ sudo apt-get install build-essential
$ sudo apt-get install cmake
$ sudo apt-get install qtcreator
$ sudo apt-get install qt5-default
* 라즈베리보드 연결 툴 : mstsc 접속
: Kit의 디스플레이의 기본 해상도 낮음
RaspberryPi FPGA디바이스 44
qt_test 프로젝트
* qt_test 프로젝트
: 단순한 창을 표시하는 프로그램
: 이 과정을 통해 관련 환경설정도 살펴봄
* Qt Creator 실행
: 시작-Programming 메뉴에 Qt Creator 아이콘 클릭
RaspberryPi FPGA디바이스 45
: 새 프로젝트 항목 선택후, .....
RaspberryPi FPGA디바이스 46
: 기본 포맷의 소스 자동 생성
: 자동 생성 파일들
$ pwd
/home/pi/IFC415/16_FPGA/gui
$ ls qt_test/
main.cpp mainwindow.h qt_test.pro
mainwindow.cpp mainwindow.ui qt_test.pro.user
RaspberryPi FPGA디바이스 47
qt_test 프로젝트(계속)
* 환경설정
: 메뉴의 Tools – Options – Build& Run 선택
: 컴파일러 등등 설정, 각 탭에서의 경고표시 해결과정임
RaspberryPi FPGA디바이스 48
: Compilers 탭에서
-Add – GCC - C을 선택, path항에 /usr/bin/gcc 입력
-Add – GCC - C++을 선택, path항에 /usr/bin/gcc입력
: Kits 탭에서
-compiler C: 항에 앞서 설정한 GCC 선택
-compiler C++: 항에 앞서 설정한 GCC 선택
: 설정이 완료되면 ( 경고 표시 없으면) OK 버튼 클릭하여 닫음
RaspberryPi FPGA디바이스 49
qt_test 프로젝트(계속)
* qt_test 컴파일 및 실행
: 메뉴-Build 클릭 혹은 좌하단 삼각형 아이콘 클릭
: 컴파일후 실행하여 빈 창이 나타남
: 빌드 후의 결과 파일들
$ pwd/home/pi/IFC415/16_FPGA/gui$ ls build-qt_test-Desktop-Debug/main.o Makefile moc_mainwindow.o ....mainwindow.o moc_mainwindow.cpp qt_test
RaspberryPi FPGA디바이스 50
qt_test 프로젝트(계속)
* 바탕화면에서 실행
: 실행 파일을 유저의 바탕화면으로 이동
$ cp build-qt_test-Desktop-Debug/qt_test ~/Desktop/
: ~/Desktop/ 확인
$ cd
$ ls ./Desktop/
pcmanfm.desktop qt_test
: 바탕화면의 gt_test 아이콘 더블클릭하여 실행
// 환경설정에서 실행디바이스를 Desktop 선택의 이유로
RaspberryPi FPGA디바이스 51
GUI 통한 LED 제어
* FPGA LED 제어 ( ./gui/qt_fpga_led/ )
: Qt Creator 초기화면에서 Open Project 선택
: qt_fpga_led 프로젝트 개방하고, 빌드함
: 빌드 결과
$ pwd
/home/pi/IFC415/16_FPGA/gui
$ ls build-qt_fpga_led-Desktop-Debug/
main.o Makefile moc_mainwindow.o .....
mainwindow.o moc_mainwindow.cpp qt_fpga_led
: 실행파일을 바탕화면으로 복사 및 확인
$ cp build-qt_fpga_led-Desktop-Debug/qt_fpga_led ~/Desktop/
$ cd
$ ls ./Desktop/
pcmanfm.desktop qt_fpga_led
RaspberryPi FPGA디바이스 52
GUI 통한 LED 제어(계속)
* 실행
: 바탕화면에 아이콘 생성
: 실행에 앞서 다음 모듈들이 링크되어 있어야 함
$ sudo insmod fpga_interface_driver.ko
$ sudo insmod fpga_led_driver.ko
$ sudo mknod /dev/fpga_led c 260 0
: 실행은 바탕화면의 해당 아이콘 더블 클릭
RaspberryPi FPGA디바이스 53
응용과제
[응용1] FPAG 디바이스 제어
: 기타의 FPGA 디바이스 동작 확인
: