1. 编写LED驱动(初始化所有子设备号)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;
int led_driver_open(struct inode *p_node, struct file *fp)
{
printk("open\n");
return 0;
}
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{
printk("read\n");
return 0;
}
void ledOn(unsigned int n)
{
*regGPBDAT |= (0x0F << 5);
if(n < 1 || n > 4)
{
return;
}
*regGPBDAT &= ~(1 << (n + 4));
}
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{
char s[10];
copy_from_user(s, user_buffer, n);
ledOn(s[0]);
printk("write\n");
return n;
}
int led_driver_close(struct inode *p_node, struct file *fp)
{
printk("close\n");
return 0;
}
struct file_operations fops =
{
.owner = THIS_MODULE,
.release = led_driver_close,
.open = led_driver_open,
.read = led_driver_read,
.write = led_driver_write,
};
static int __init led_driver_init(void)
{
int ret;
printk("init\n");
ret = register_chrdev(200, "first driver", &fops);
if(ret != 0)
{
return ret;
}
regGPBCON = ioremap(GPBCON, 4);
regGPBDAT = ioremap(GPBDAT, 4);
*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
*regGPBDAT |= (0x0F << 5);
return 0;
}
static void __exit led_driver_exit(void)
{
iounmap(regGPBDAT);
iounmap(regGPBCON);
unregister_chrdev(200, "first driver");
printk("exit\n");
}
module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PuTe");
2. 编写LED驱动(初始化一个子设备号)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;
static dev_t dev_num;
struct cdev led_dev;
int led_driver_open(struct inode *p_node, struct file *fp)
{
printk("open\n");
return 0;
}
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{
printk("read\n");
return 0;
}
void ledOn(unsigned int n)
{
*regGPBDAT |= (0x0F << 5);
if(n < 1 || n > 4)
{
return;
}
*regGPBDAT &= ~(1 << (n + 4));
}
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{
char s[10];
copy_from_user(s, user_buffer, n);
ledOn(s[0]);
printk("write\n");
return n;
}
int led_driver_close(struct inode *p_node, struct file *fp)
{
printk("close\n");
return 0;
}
struct file_operations fops =
{
.owner = THIS_MODULE,
.release = led_driver_close,
.open = led_driver_open,
.read = led_driver_read,
.write = led_driver_write,
};
static int __init led_driver_init(void)
{
int ret;
ret = alloc_chrdev_region(&dev_num, 0, 1, "first device");
if(ret)
{
printk("alloc_chrdev_region is error\n");
return ret;
}
printk("major = %u, minior = %u\n", MAJOR(dev_num), MINOR(dev_num));
cdev_init(&led_dev, &fops);
ret = cdev_add(&led_dev, dev_num, 1);
if(ret)
{
unregister_chrdev_region(dev_num, 1);
printk("cdev_add is error\n");
return ret;
}
regGPBCON = ioremap(GPBCON, 4);
regGPBDAT = ioremap(GPBDAT, 4);
*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
*regGPBDAT |= (0x0F << 5);
return 0;
}
static void __exit led_driver_exit(void)
{
iounmap(regGPBDAT);
iounmap(regGPBCON);
cdev_del(&led_dev);
unregister_chrdev_region(dev_num, 1);
printk("exot\n");
}
module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PuTe");
3. LED标准字符设备驱动(省去在linux终端mknod的过程,直接insmod的即可运行程序)
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;
static dev_t dev_num;
struct cdev led_dev;
static struct class *p_class;
static struct device *p_device;
int led_driver_open(struct inode *p_node, struct file *fp)
{
printk("open\n");
return 0;
}
ssize_t led_driver_read(struct file *fp, char __user *user_buffer, size_t n, loff_t * offset)
{
printk("read\n");
return 0;
}
void ledOn(unsigned int n)
{
*regGPBDAT |= (0x0F << 5);
if(n < 1 || n > 4)
{
return;
}
*regGPBDAT &= ~(1 << (n + 4));
}
ssize_t led_driver_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t *offset)
{
char s[10];
copy_from_user(s, user_buffer, n);
ledOn(s[0]);
printk("write\n");
return n;
}
int led_driver_close(struct inode *p_node, struct file *fp)
{
printk("close\n");
return 0;
}
struct file_operations fops =
{
.owner = THIS_MODULE,
.release = led_driver_close,
.open = led_driver_open,
.read = led_driver_read,
.write = led_driver_write,
};
static int __init led_driver_init(void)
{
int ret;
ret = alloc_chrdev_region(&dev_num, 0, 1, "first device");
if(ret)
{
printk("alloc_chrdev_region is error\n");
goto alloc_chrdev_region_err;
}
printk("major = %u, minior = %u\n", MAJOR(dev_num), MINOR(dev_num));
cdev_init(&led_dev, &fops);
ret = cdev_add(&led_dev, dev_num, 1);
if(ret)
{
printk("cdev_add is error\n");
goto cdev_add_err;
}
p_class = class_create(THIS_MODULE, "Led class");
if(IS_ERR(p_class))
{
printk("class_create is error!");
goto class_create_err;
}
p_device = device_create(p_class, NULL, dev_num, NULL, "led");
if(p_device == NULL)
{
printk("device_create is error\n");
goto device_create_err;
}
regGPBCON = ioremap(GPBCON, 4);
regGPBDAT = ioremap(GPBDAT, 4);
*regGPBCON &= ~((3 << 10) | (3 << 12) | (3 << 14) | (3 << 16));
*regGPBCON |= (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);
*regGPBDAT |= (0x0F << 5);
return 0;
device_create_err:
class_destroy(p_class);
class_create_err:
cdev_del(&led_dev);
cdev_add_err:
unregister_chrdev_region(dev_num, 1);
alloc_chrdev_region_err:
return ret;
}
static void __exit led_driver_exit(void)
{
iounmap(regGPBDAT);
iounmap(regGPBCON);
device_destroy(p_class, dev_num);
class_destroy(p_class);
cdev_del(&led_dev);
unregister_chrdev_region(dev_num, 1);
printk("exit\n");
}
module_init(led_driver_init);
module_exit(led_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("PuTe");
4. 蜂鸣器——混杂设备驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define GPBCON (0x56000010)
#define GPBDAT (0x56000014)
static unsigned int *regGPBCON;
static unsigned int *regGPBDAT;
int beep_open(struct inode *p_node, struct file *fp)
{
return 0;
}
int beep_release(struct inode *p_node, struct file *fp)
{
return 0;
}
ssize_t beep_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t * offset)
{
int ret;
copy_from_user(&ret, user_buffer, 4);
printk("kernel : %d",ret);
if(ret)
{
*regGPBDAT |= (1 << 0);
}
else
{
*regGPBDAT &= ~(1 << 0);
}
return 4;
}
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = beep_open,
.release = beep_release,
.write = beep_write
};
static struct miscdevice beep_device =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "beep",
.fops = &fops,
};
static int __init beep_init(void)
{
int ret;
ret = misc_register(&beep_device);
if(ret)
{
printk("misc_register is error");
return ret;
}
regGPBCON = ioremap(GPBCON, 4);
regGPBDAT = ioremap(GPBDAT, 4);
*regGPBCON &= ~(3 << 0);
*regGPBCON |= (1 << 0);
return 0;
}
static void __exit beep_exit(void)
{
iounmap(regGPBCON);
iounmap(regGPBDAT);
misc_deregister(&beep_device);
}
module_init(beep_init);
module_exit(beep_exit);
MODULE_LICENSE("GPL");
5. 按键(轮询查看按键)——混杂设备驱动
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define GPGCON (0x56000060)
#define GPGDAT (0x56000064)
#define GPGUP (0x56000068)
static unsigned int *regGPGCON;
static unsigned int *regGPGDAT;
static unsigned int *regGPGUP;
int key_open(struct inode *p_node, struct file *fp)
{
return 0;
}
int key_release(struct inode *p_node, struct file *fp)
{
return 0;
}
ssize_t key_write(struct file *fp, const char __user *user_buffer, size_t n, loff_t * offset)
{
return 0;
}
ssize_t key_read(struct file *fp, char __user *user_buffer, size_t n, loff_t *offset)
{
int ret = -1;
if (0 == (*regGPGDAT & (1 << 0)))
{
ret = 1;
}
else if (0 == (*regGPGDAT & (1 << 3)))
{
ret = 2;
}
else if (0 == (*regGPGDAT & (1 << 5)))
{
ret = 3;
}
else if (0 == (*regGPGDAT & (1 << 6)))
{
ret = 4;
}
else if (0 == (*regGPGDAT & (1 << 7)))
{
ret = 5;
}
else if (0 == (*regGPGDAT & (1 << 11)))
{
ret = 6;
}
if (ret != (-1))
{
copy_to_user(user_buffer, &ret, 4);
}
return 0;
}
static struct file_operations fops =
{
.owner = THIS_MODULE,
.open = key_open,
.release = key_release,
.write = key_write,
.read = key_read,
};
static struct miscdevice key_device =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "key",
.fops = &fops,
};
static int __init key_init(void)
{
int ret;
ret = misc_register(&key_device);
if(ret)
{
printk("misc_register is error");
return ret;
}
regGPGCON = ioremap(GPGCON, 4);
regGPGDAT = ioremap(GPGDAT, 4);
regGPGUP = ioremap(GPGUP, 4);
*regGPGCON &= ~((3 << 0) | (3 << 6) | (3 << 10) | (3 << 12) | (3 << 14) | (3 << 22));
*regGPGDAT |= ((1 << 0) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 11));
*regGPGUP |= ((1 << 0) | (1 << 11));
*regGPGUP &= ~((1 << 3) | (1 << 5) | (1 << 6) | (1 << 7));
return 0;
}
static void __exit key_exit(void)
{
iounmap(regGPGCON);
iounmap(regGPGDAT);
iounmap(regGPGUP);
misc_deregister(&key_device);
}
module_init(key_init);
module_exit(key_exit);
MODULE_LICENSE("GPL");