gpfdriver
时间:2009-08-19 来源:sure_priterand
//==================gpfdriver.c============================================
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h> /* printk() */
#include <linux/init.h> /* __init __exit */
#include <linux/types.h> /* size_t */
#include <linux/fs.h> /* file_operation */
#include <linux/errno.h> /* Error number */
#include <linux/delay.h> /* udelay */
#include <asm/uaccess.h> /* copy_to_user, copy_from_user */
#include <asm/hardware.h>
#include <asm/arch/S3C2410.h>
#include "gpio.h"
#define DRIVER_NAME "gpf"
#ifdef DEBUG
#define PRINTK(fmt, arg...) printk(KERN_NOTICE fmt, ##arg)
#else
#define PRINTK(fmt, arg...)
#endif
/*
KERN_EMERG 用于紧急事件,一般是系统崩溃前的提示信息
KERN_ALERT 用于需要立即采取动作的场合
KERN_CRIT 临界状态,通常设计验证的硬件或软件操作失败
KERN_ERR 用于报告错误状态.设备驱动程序通常会用它报告来自硬件的问题
KERN_WARNING 就可能出现的问题提出警告.这些问题通常不会对系统造成严重破坏
KERN_NOTICE 有必要提示的正常情况.许多安全相关的情况用这个级别汇报
KERN_INFO 提示性信息.有很多驱动程序在启动时用这个级别打印相关信息
KERN_DEBUG 用于调试的信息
*/
static int gpfDriver_Major = 0; /* Driver Major Number */
static unsigned char gpfDriver_inMask = 0x0;
/* Driver Operation Functions */
static int gpfDriver_open(struct inode *inode, struct file *filp)
{
// int Minor = MINOR(inode->i_rdev);
// filp->private_data = 0;
MOD_INC_USE_COUNT;
PRINTK("gpfDriver open called!\n");
return 0;
}
static int gpfDriver_release(struct inode *inode, struct file *filp)
{
// int Minor = MINOR(inode->i_rdev);
MOD_DEC_USE_COUNT;
PRINTK("gpfDriver release called!\n");
return 0;
}
static ssize_t gpfDriver_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
unsigned char ioData;
ioData = GPFDAT;
ioData &= gpfDriver_inMask;
copy_to_user(buf, &ioData, sizeof(ioData));
PRINTK("gpfDriver read called!\n");
return sizeof(ioData);
}
static ssize_t gpfDriver_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
{
unsigned char ioData[2];
copy_from_user(ioData, buf, sizeof(ioData[0]));
ioData[0] &= ~gpfDriver_inMask;
ioData[1] = GPFDAT;
ioData[1] &= gpfDriver_inMask;
ioData[0] |= ioData[1];
GPFDAT = ioData[0];
PRINTK("gpfDriver write called!\n");
return sizeof(ioData);
}
static int gpfDriver_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned int Temp;
PRINTK("gpfDriver ioctl called(%d)!\n", cmd);
switch(cmd)
{
case GPIO_SET_PIN:
if(gpfDriver_inMask & (1 << arg))
break;
Temp = GPFDAT;
Temp |= (1 << arg);
GPFDAT = Temp;
break;
case GPIO_SET_ALL_PIN:
Temp = GPFDAT;
Temp |=(~gpfDriver_inMask);
GPFDAT = Temp;
break;
case GPIO_CLR_PIN:
if(gpfDriver_inMask & (1 << arg))
break;
Temp = GPFDAT;
Temp &= ~(1 << arg);
GPFDAT = Temp;
break;
case GPIO_CLR_ALL_PIN:
Temp = GPFDAT;
Temp &=gpfDriver_inMask;
GPFDAT = Temp;
break;
case GPIO_SET_PIN_OUT:
Temp = GPFCON;
Temp &= ~(0x03 << (arg << 1));
Temp |= (0x01 << (arg << 1));
gpfDriver_inMask &= ~(1 << arg);
GPFCON = Temp;
break;
case GPIO_SET_PIN_IN:
Temp = GPFCON;
Temp &= ~(0x03 << (arg << 1));
gpfDriver_inMask |= (1 << arg);
GPFCON = Temp;
break;
case GPIO_SET_MULTI_PIN_OUT:
{
int i;
for(i = 0; i < 8; i++)
{
if(arg & (1 << i))
{
Temp = GPFCON;
Temp &= ~(0x03 << (i << 1));
Temp |= (0x01 << (i << 1));
GPFCON = Temp;
}
}
gpfDriver_inMask &= ~(arg);
}
break;
case GPIO_SET_MULTI_PIN_IN:
{
int i;
for(i = 0; i < 8; i++)
{
if(arg & (1 << i))
{
Temp = GPFCON;
Temp&= ~(0x03 << (i << 1));
GPFCON= Temp;
}
}
gpfDriver_inMask |= arg;
}
break;
default:
return -ENOTTY;
}
return 0;
}
/* Driver Operation structure */
static struct file_operations gpfDriver_fops = {
owner: THIS_MODULE,
write: gpfDriver_write,
read: gpfDriver_read,
ioctl: gpfDriver_ioctl,
open: gpfDriver_open,
release: gpfDriver_release,
};
/* Module Init & Exit function */
#ifdef CONFIG_DEVFS_FS
devfs_handle_t devfs_gpfDriver_dir;
devfs_handle_t devfs_gpfDriver_raw;
#endif
static int __init s3c2410_gpf_init(void)
{
/* Module init code */
PRINTK("s3c2410_gpf_init\n");
GPFCON = 0x5555;
/* Driver register */
gpfDriver_Major = register_chrdev(0, DRIVER_NAME, &gpfDriver_fops);
if(gpfDriver_Major < 0)
{
PRINTK("register char device fail!\n");
return gpfDriver_Major;
}
PRINTK("register gpfDriver OK! Major = %d\n", gpfDriver_Major);
#ifdef CONFIG_DEVFS_FS
devfs_gpfDriver_dir = devfs_mk_dir(NULL, "gpfDriver", NULL);
devfs_gpfDriver_raw = devfs_register(devfs_gpfDriver_dir, "raw0", DEVFS_FL_DEFAULT, gpfDriver_Major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &gpfDriver_fops, NULL);
PRINTK("add dev file to devfs OK!\n");
#endif
return 0;
}
static void __exit s3c2410_gpf_exit(void)
{
/* Module exit code */
PRINTK("s3c2410_gpf_exit\n");
/* Driver unregister */
if(gpfDriver_Major > 0)
{
#ifdef CONFIG_DEVFS_FS
devfs_unregister(devfs_gpfDriver_raw);
devfs_unregister(devfs_gpfDriver_dir);
#endif
unregister_chrdev(gpfDriver_Major, DRIVER_NAME);
}
return;
}
int request_irq(unsigned int irq,void(*handler)(int,void*,struct pt_regs*),unsigned long irqflag,const char *devname, void *dev_id);
MODULE_AUTHOR("Lijian");
MODULE_LICENSE("Dual BSD/GPL");
module_init(s3c2410_gpf_init);
module_exit(s3c2410_gpf_exit);
//========================gpio.h=============================================
#ifndef __GPFDRIVER_H__
#define __GPFDRIVER_H__
#define GPIO_SET_PIN 0
#define GPIO_SET_ALL_PIN 1
#define GPIO_CLR_PIN 2
#define GPIO_CLR_ALL_PIN 3
#define GPIO_SET_PIN_OUT 4
#define GPIO_SET_PIN_IN 5
#define GPIO_SET_MULTI_PIN_OUT 6
#define GPIO_SET_MULTI_PIN_IN 7
#endif//__GPFDRIVER_H__
//=====================Makefile==============================================
OUTPUT = gpfDriver.o
OUTPUT_DIR = output
KERNEL = /home/lhaoyu/dengwei/kernel_2.4.18
CROSSPREFIX = /usr/local/arm/2.95.3/bin/arm-linux-
CFLAGS = -Wall -I$(KERNEL)/include -c
#CFLAGS += -DEXPORT_SYMTAB -DMODVERSIONS -include $(KERNEL)/include/linux/modversions.h
DEST = $(foreach fn, $(OUTPUT), $(OUTPUT_DIR)/$(fn))
ECHO_OK = echo -e "\x1b[40G\x1b[34m[ OK ]\x1b[0m"
ECHO_FAILED = echo -e "\x1b[40G\x1b[31m[ FAILED ]\x1b[0m"
all: $(OUTPUT_DIR) $(OUTPUT_DIR)/$(OUTPUT)
$(OUTPUT_DIR):
@mkdir $@
@chmod 777 -R $@
$(OUTPUT_DIR)/%.o: %.c
@echo -n "Compling $^..."
@if $(CROSSPREFIX)gcc $(CFLAGS) $^ -o $@; then $(ECHO_OK); else $(ECHO_FAILED); fi
clean:
@find . \( -name '*.[oas]' -o -name install.sh \) -type f -print | xargs rm -f
@echo "Cleaned!"
//==============================out_test.c=========================================
//GPIO跑马灯实验
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "gpio.h"
int main()
{
int i;
int gpf;
char led=0x01;
gpf= open("/dev/gpfDriver/raw0", O_RDWR);
ioctl(gpf, GPIO_SET_MULTI_PIN_OUT, 0xff);
while(1)
{
led= 0x1;
for (i=0;i<8;i++)
{
write(gpf,&led,1);
led = led << 1;
usleep(300*3000);
}
}
}
//====================in_test.c================================================
//GPIO练习KEY & LED
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "gpio.h"
int main(void)
{
unsigned char KEY = 0;
int gpf = open("/dev/gpfDriver/raw0", O_RDWR);
ioctl(gpf, GPIO_SET_MULTI_PIN_IN, 0x0f); //Key1~3
while(1)
{
read(gpf, &KEY, sizeof(KEY));
printf("KEY = 0x%02x\n", KEY);
}
}
相关阅读 更多 +