LINUX 驱动例程总结

本文总结了LINUX驱动的相关知识,包括手动创建设备文件、自动创建设备文件、混杂设备驱动、软中断tasklet、工作队列、TIMER_LIST软件定时器、内核竞态条件的解决方案、等待队列、内存映射、无设备树平台框架驱动和I2C驱动模型的实例。内容涵盖设备号、软中断、工作队列的特点和使用,以及各种内核定时器的原理和应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LINUX 驱动例程总结
目录

    1. 主次设备号手动创建设备文件
    2. 自动创建设备文件
    3. 混杂设备驱动例程
    4. 软中断之tasklet例程
    5. 驱动之工作队列例程
    6. 内核之timer_list软件定时器
    7. 内核竟态之4种解决方法
    8. 内核之等待队列例程
    9. 内核驱动内存映射
    10. 无设备树平台框架驱动例程
    11. 驱动模型之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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值