하드웨어
EZ-S3C6410 보드에서 부져를 구동하는 소스입니다.
부져는 GPIO의 GPN12 에 연결되어 있다고 가정하에 설명합니다.
1. 디바이스 드라이버
#] vi dev_gpio.c
/*-----------------------------------------------------------------------------
파 일 : dev_gpio.c
설 명 :
작 성 :
날 짜 :
주 의 :
-------------------------------------------------------------------------------*/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/ioctl.h>
#include <asm/unistd.h>
#include <asm/delay.h>
#include <mach/map.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <plat/regs-gpio.h>
#include "dev_gpio.h"
/// 로컬상수 정의 --------------------------------------------------------------*/
#define ON 1
#define OFF 0
/// 로컬변수 정의 --------------------------------------------------------------*/
static int usage = 0;
static int showmsg = 0;
static int major = GPIO_MAJOR_DEF;
//------------------------------------------------------------------------------
/** @brief 하드웨어 초기화
@remark 인터럽트 설정은 반드시 초기화 순서를 지켜야 함
*///----------------------------------------------------------------------------
static void hw_gpio_init( void )
{
/// 출력설정 GPF12
s3c_gpio_cfgpin (S3C64XX_GPN(12), S3C64XX_GPN_OUTPUT(12)); /* GPN12 to OUTPUT12 */
s3c_gpio_setpull(S3C64XX_GPN(12), S3C_GPIO_PULL_NONE); /* */
}
//------------------------------------------------------------------------------
/** @brief read
@remark
*///----------------------------------------------------------------------------
static ssize_t gpio_read(struct file *filp, char *buf, size_t count, loff_t *ppos)
{
return 1;
}
//------------------------------------------------------------------------------
/** @brief write
@remark
*///----------------------------------------------------------------------------
static ssize_t gpio_write(struct file *filp, char *buf, size_t count, loff_t *ppos)
{
return 1;
}
//------------------------------------------------------------------------------
/** @brief BUZZER ON/OFF 출력 제어
@remark
*///----------------------------------------------------------------------------
void set_buzzer_onoff( unsigned char val )
{
printk("TRACE %s %d>-------------- val : %d\n", __FUNCTION__, __LINE__, val);
gpio_set_value( S3C64XX_GPN(12), val );
}
//------------------------------------------------------------------------------
/** @brief ioctl 함수
@remark
*///----------------------------------------------------------------------------
static int gpio_ioctl( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg )
{
if( _IOC_TYPE( cmd ) != GPIO_IOCTL_MAGIC ) return -EINVAL;
if( _IOC_NR ( cmd ) >= GPIO_IOCTL_MAGIC ) return -EINVAL;
switch (cmd)
{
case IOCTL_BUZZER_ON : set_buzzer_onoff( 0 ); return 0;
case IOCTL_BUZZER_OFF : set_buzzer_onoff( 1 ); return 0;
}
return -EINVAL;
}
//------------------------------------------------------------------------------
/** @brief 어플리케이션에서 디바이스를 open 하였을때 호출되는 함수
@remark
*///----------------------------------------------------------------------------
static int gpio_open( struct inode *inode, struct file *filp )
{
usage ++;
if (showmsg) printk(" %s OPEN (%d)\n", DEV_NAME, usage );
return 0;
}
//------------------------------------------------------------------------------
/** @brief 어플리케이션에서 디바이스를 close를 하였을때 호출되는 함수
@remark
*///----------------------------------------------------------------------------
static int gpio_release( struct inode *inode, struct file *filp)
{
usage --;
if (showmsg) printk(" %s CLOSE\n", DEV_NAME );
return 0;
}
//------------------------------------------------------------------------------
/** @brief 드라이버에 사용되는 접근 함수에 대한 함수 포인터 구조체를 정의 한다.
이 구조체는 fs.h에 정의 되어 있다.
@remark
*///----------------------------------------------------------------------------
static struct file_operations gpio_fops =
{
open : gpio_open,
release : gpio_release,
read : gpio_read,
write : gpio_write,
ioctl : gpio_ioctl,
};
//------------------------------------------------------------------------------
/** @brief init
@remark
*///----------------------------------------------------------------------------
static __init int gpio_init( void )
{
int ret;
/// 장치를 등록한다. ============================================
major &= 0xff;
if( !register_chrdev( major, DEV_NAME, &gpio_fops ) )
{
printk("\n register device %s OK (major=%d)\n\n", DEV_NAME, major );
}
else
{
printk("\n unable to get major %d for %s \n\n", major, DEV_NAME );
return -EBUSY;
}
/// 하드웨어 초기화
hw_gpio_init();
return 0;
}
//------------------------------------------------------------------------------
/** @brief exit
@remark
*///----------------------------------------------------------------------------
static __exit void gpio_exit( void )
{
/// 장치등록을 해지한다.
unregister_chrdev( major, DEV_NAME );
printk("\n unregister %s OK\n\n", DEV_NAME );
}
module_init(gpio_init);
module_exit(gpio_exit);
module_param(major, int, 0);
module_param(showmsg, int, 0);
MODULE_AUTHOR("tsheaven@falinux.com");
MODULE_LICENSE("GPL");
/* end */
2. 헤더파일
#] vi dev_gpio.h
3. 어플리케이션
#] vi app_gpio.c
//------------------------------------------------------------------------------
// 파일명 : main.c
// 프로젝트 :
// 작성자 :
// 작성일 :
// 수정일 :
//
// 설 명 :
//
//------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "dev_gpio.h"
#define VERSION_STR "Ver 1.00"
int dev_fd; // 파일핸들
//------------------------------------------------------------------------------
// 설명 : 디바이스 드라이버 열기
// 주의 : 없음
//------------------------------------------------------------------------------
int dev_open( char *fname, unsigned char major, unsigned char minor )
{
int dev;
dev = open( fname, O_RDWR|O_NDELAY );
if (dev == -1 )
{
mknod( fname, (S_IRWXU|S_IRWXG|S_IFCHR), (major<<8)|(minor) );
dev = open( fname, O_RDWR|O_NDELAY );
if (dev == -1 )
{
printf( " Device OPEN FAIL %s\n", fname );
return -1;
}
}
return dev;
}
//------------------------------------------------------------------------------
// 설명 : main함수를 정의 한다.
// 주의 : 없음
//------------------------------------------------------------------------------
int main( int argc, char **argv )
{
printf( "\n Program Ver %s %s %s\n", VERSION_STR, __DATE__, __TIME__ );
dev_fd = dev_open("/dev/gpio", GPIO_MAJOR_DEF, 0 );
ioctl( dev_fd, IOCTL_BUZZER_ON );
sleep(1);
ioctl( dev_fd, IOCTL_BUZZER_OFF );
close( dev_fd );
return 0;
}
4. Makefile
#] vi app_gpio.c
#
# kernel 2.6 driver Makefile
#
obj-m := dev_gpio.o
KDIR := /kernel/linux
PWD := $(shell pwd)
APP = app_gpio
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
arm-generic-linux-gnueabi-gcc -o $(APP) $(APP).c
clean :
rm -rf *.ko
rm -rf *.mod.*
rm -rf .*.cmd
rm -rf *.o
[주의]
1. Makefile 에서 KDIR := /kernel/linux 은 S3C610 커널이 있는 디렉토리 위치를 써야 합니다.
2. 크로스 컴파일러가 설치되어 있어야 합니다. 현재 사용된 GCC 크로스 컴파일러는 arm-generic-linux-gnueabi-gcc 입니다.
다음에는 디바이스 드라이버 방식이 아닌 어플리케이션에서 직접 mmap를 이용하여 부져를 구동해 보도록 하겠습니다.