硬件平台: OK2440-III
系统平台:linux-2.6.12
软件环境:vim
/*************************************************************************
> File Name: led.c
> Author: dongzhihong
> Mail: hnaydzh@gmail.com
> Created Time: 2012年12月01日 星期六 10时32分53秒
************************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/delay.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <linux/cdev.h>
#include <linux/ioport.h>
#include <linux/fs.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/arch-s3c2410/regs-gpio.h>
#include <asm/arch-s3c2410/hardware.h>
#define LED_MAJOR 115
#define DEVICE_NAME "led_dev"
#define SUCCESS 0
#define LED_ON _IO('g', 33)//6721
#define LED_OFF _IO('g', 34)//6722
static int Device_Open = 0;
unsigned long gpf_con,gpf_dat;
int led_init(void);
void led_cleanup(void);
static int device_open(struct inode *,struct file *);
static int device_release(struct inode *,struct file *);
static int device_ioctl(struct inode * fnode, struct file* filp, unsigned int cmd,unsigned long param);
static int Major;
struct file_operations led_ops =
{
owner : THIS_MODULE,
open: device_open,
ioctl: device_ioctl,
release: device_release,
};
struct cdev led_cdev;
int led_init(void)
{
int err;
dev_t devnum = MKDEV(LED_MAJOR,0);
gpf_con = (unsigned long)ioremap(0x56000050,4);
gpf_dat = (unsigned long)ioremap(0x56000054,4);
*(unsigned long *)gpf_con &= ~(0xff<<6);
*(unsigned long *)gpf_con |= 0x1540;
// 注册设备号
#if 0
Major = register_chrdev_region(devnum,1,DEVICE_NAME);
#endif
Major = register_chrdev(LED_MAJOR,DEVICE_NAME,&led_ops);
if(Major <0)
{
printk("key init_module:failed with %d\n",Major); //涓昏澶囧彿灏忎簬0锛屽垯娉ㄥ唽澶辫触
return Major;
}
Major = LED_MAJOR;
#if 0
//注册完设备号,该向内核添加设备了
cdev_init (&led_cdev , &led_ops);//初始化设备
led_cdev.owner = THIS_MODULE; //表示谁拥有这个驱动程序
led_cdev.ops = &led_ops;
err = cdev_add(&led_cdev , devnum, 1);//对于已经知道类设备号,就用cdev_add()来添加设备
/**
* 由此可见,使用register_chrdev_region()比使用register_chrdev()多了一步,
* 就是向内核注册添加设备的步骤
* */
if (err) printk("Key init Error %d\n", err);
#endif
printk("LED_MAJOR registred: Major = %d\n",Major);
devfs_mk_cdev(MKDEV(LED_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);
return 0;
}
static int device_ioctl(struct inode * fnode, struct file* filp, unsigned int cmd,unsigned long param)
{
switch (cmd)
{
case LED_ON:
*(unsigned long *)gpf_dat &= ~(0xf<<3);
break;
case LED_OFF:
*(unsigned long *)gpf_dat |= 0xf<<3;
break;
default:
return -EINVAL;
}
return SUCCESS;
}
static int device_open(struct inode * inode,struct file *file)
{
if(Device_Open)
{
return -EBUSY;
}
Device_Open++;
return SUCCESS;
}
static int device_release(struct inode * inode,struct file *file)
{
Device_Open --;
return 0;
}
void led_cleanup(void)
{
unregister_chrdev_region(MKDEV(LED_MAJOR,0),1);
devfs_remove(DEVICE_NAME);
printk(DEVICE_NAME" delete cdev\n");
}
module_init(led_init);
module_exit(led_cleanup);
MODULE_AUTHOR("dzh");
MODULE_LICENSE("GPL");
一下附上测试程序
/*************************************************************************
> File Name: ledtest.c
> Author: dongzhihong
> Mail: hnaydzh@gmail.com
> Created Time: 2012年12月01日 星期六 13时56分23秒
************************************************************************/
#include<stdio.h>
#include<sys/types.h>
#include<sys/ioctl.h>
#include<stdlib.h>
#include<termios.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/time.h>
#define LED_ON 0x6721
#define LED_OFF 0x6722
int main(void)
{
char str;
int fd = open("/dev/led_dev",O_RDWR);
if(fd < 0)
{
printf("can't open device");
return 0;
}
printf("*********************************************************************\n");
printf("** LED TEST BEGIN **\n");
printf("** Please input N (to open led)or F(to getoff led) **\n");
printf("** Input E to exit LED Test **\n");
printf("*********************************************************************\n");
while(1){
printf("Enter:");
scanf("%c",&str);
if(str == 'N'){
ioctl(fd,LED_ON);
}
else if(str == 'F')
{
ioctl(fd,LED_OFF);
}
else if(str == 'E')
{
break;
}
}
return 0;
}