LINUX 驱动例程总结
目录
-
- 主次设备号手动创建设备文件
- 自动创建设备文件
- 混杂设备驱动例程
- 软中断之tasklet例程
- 驱动之工作队列例程
- 内核之timer_list软件定时器
- 内核竟态之4种解决方法
- 内核之等待队列例程
- 内核驱动内存映射
- 无设备树平台框架驱动例程
- 驱动模型之MMA 8653 驱动
1. 使用主次设备号手动创建设备文件
首先了解下什么是主设备号和次设备号
主设备号作用: 应用程序根据字符设备文件的主设备号在茫茫的内核驱动中找到对应的唯一的设备驱动,一个设备驱动仅有唯一的主设备号。
**次设备号作用:**设备驱动根据次设备号能够找到应用程序要访问的硬件外设个体。
设备号包含主,次设备号linux内核用dev_t(unsigned int)数据类型描述设备号信息设备号的高12位用来描述主设备号设备号的低20位用来描述次设备号设备号和主,次设备号之间的转换操作宏:
设备号=MKDEV(已知的主设备号,已知的次设备号);
主设备号=MAJOR(已知的设备号);
次设备号=MINOR(已知的设备号);
下面附上一个创建的例程
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
struct led_resource {
int gpio;
char *name;
};
static struct led_resource led_info[] = {
{
.gpio = PAD_GPIO_C + 12,
.name = "LED1"
}
};
#define LED_ON 0x100001
#define LED_OFF 0x100002
static long led_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
int kindex;
copy_from_user(&kindex, (int *)arg, sizeof(kindex));
switch(cmd) {
case LED_ON:
gpio_set_value(led_info[kindex-1].gpio, 0);
break;
case LED_OFF:
gpio_set_value(led_info[kindex-1].gpio, 1);
break;
default:
return -1;
}
return 0;
}
static struct file_operations led_fops = {
.unlocked_ioctl = led_ioctl,
};
static dev_t dev;
static struct cdev led_cdev;
static int led_init(void)
{
int i;
alloc_chrdev_region(&dev, 0, 1, "nishishengma");
cdev_init(&led_cdev, &led_fops);
cdev_add(&led_cdev, dev, 1);
for(i = 0; i < ARRAY_SIZE(led_info); i++) {
gpio_request(led_info[i].gpio,
led_info[i].name);
gpio_direction_output(led_info[i].gpio, 1);
}
return 0;
}
static void led_exit(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(led_info); i++) {
gpio_set_value(led_info[i].gpio, 1);
gpio_free(led_info[i].gpio);
}
unregister_chrdev_region(dev, 1);
cdev_del(&led_cdev);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
2自动创建设备文件
2.1例程分享
#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <mach/platform.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/device.h>
struct led_resource {
int gpio;
char *name;
};
static struct led_resource led_info[] = {
{
.gpio = PAD_GPIO_C + 12,
.name = "LED1"
}
};
#define LED_ON 0x100001
#define LED_OFF 0x100002
static long led_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
int kindex;
copy_from_user(&kindex, (int *)arg, sizeof(kindex));
switch(cmd) {
case LED_ON:
gpio_set_value(led_info[kindex-1].gpio, 0);
break;
case LED_OFF:
gpio_set_value(led_info[kindex-1].gpio, 1);
break;
default:
return -1;
}
return 0;
}
static struct file_operations led_fops = {
.unlocked_ioctl = led_ioctl,
static dev_t dev;
static struct cdev led_cdev;
static struct class *cls;
static int led_init(void)
{
int i;
alloc_chrdev_region(&dev, 0, 1, "nishishui");
cdev_init(&led_cdev, &led_fops);
cdev_add(&led_cdev, dev, 1);
for(i = 0; i < ARRAY_SIZE(led_info); i++) {
gpio_request(led_info[i].gpio,
led_info[i].name);
gpio_direction_output(led_info[i].gpio, 1);
}
cls = class_create(THIS_MODULE, "meimei");
device_create(cls, NULL, dev, NULL, "yourled");
return 0;
}
static void led_exit(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(led_info); i++) {
gpio_set_value(led_info[i].gpio, 1);
gpio_free(led_info[i].gpio);
}
unregister_chrdev_region(dev, 1);
cdev_del(&led_cdev);
device_destroy(cls, dev);
class_destroy(cls);
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
3. 混杂设备驱动例程
3.1混杂设备的其实就是往dev路径下创建驱动文件
3.2 分享例程
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/gpio.h>
#include <mach/platform.h>
struct led_resource {
int gpio;
char *name;
};
static struct led_resource led_info[] = {
{
.gpio = PAD_GPIO_C + 12,
.name = "LED1"
}
};
#define LED_ON 0x100001
#define LED_OFF 0x100002
static long led_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
int kindex;
copy_from_user(&kindex, (int *)arg, sizeof(kindex));
switch(cmd) {
case LED_ON:
gpio_set_value(led_info[kindex-1].gpio