• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

驱动开发-day9

武飞扬头像
三只小鸹貔
帮助1

学新通

 驱动代码:

  1.  
    #include <linux/cdev.h>
  2.  
    #include <linux/device.h>
  3.  
    #include <linux/fs.h>
  4.  
    #include <linux/gpio.h>
  5.  
    #include <linux/init.h>
  6.  
    #include <linux/interrupt.h>
  7.  
    #include <linux/module.h>
  8.  
    #include <linux/of_gpio.h>
  9.  
    #include <linux/of_irq.h>
  10.  
    #include <linux/slab.h>
  11.  
    #include <linux/uaccess.h>
  12.  
    struct cdev* cdev;
  13.  
    unsigned int major = 500;
  14.  
    unsigned int minor = 0;
  15.  
    dev_t devno;
  16.  
    struct class* cls;
  17.  
    struct device* dev;
  18.  
    struct device_node* dnode;
  19.  
    struct device_node* dnode_led;
  20.  
    unsigned int irqno;
  21.  
    unsigned int number = 0;
  22.  
    // 定义等待队列头
  23.  
    wait_queue_head_t wq_head;
  24.  
    unsigned int condition = 0;
  25.  
    // 分配对象
  26.  
    struct work_struct work;
  27.  
    char kbuf[128] = { 0 };
  28.  
    struct gpio_desc* gpiono;
  29.  
    int mycdev_open(struct inode* inode, struct file* file)
  30.  
    {
  31.  
     
  32.  
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
  33.  
    return 0;
  34.  
    }
  35.  
    ssize_t mycdev_read(struct file* file, char* ubuf, size_t size, loff_t* lof)
  36.  
    {
  37.  
    int ret;
  38.  
     
  39.  
    wait_event_interruptible(wq_head, condition);
  40.  
     
  41.  
    if (size > sizeof(number)) {
  42.  
    size = sizeof(number);
  43.  
    }
  44.  
     
  45.  
    ret = copy_to_user(ubuf, (void*)&number, size);
  46.  
    if (ret) {
  47.  
    printk("copy_to_user filed\n");
  48.  
    return -EIO;
  49.  
    }
  50.  
    condition = 0;
  51.  
    return size;
  52.  
    }
  53.  
    ssize_t mycdev_write(struct file* file, const char* ubuf, size_t size, loff_t* lof)
  54.  
    {
  55.  
     
  56.  
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
  57.  
    return 0;
  58.  
    }
  59.  
    int mycdev_close(struct inode* inode, struct file* file)
  60.  
    {
  61.  
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
  62.  
    return 0;
  63.  
    }
  64.  
    long mycdev_ioctl(struct file* file, unsigned int cmd, unsigned long arg)
  65.  
    {
  66.  
    return 0;
  67.  
    }
  68.  
    struct file_operations fops = {
  69.  
    .open = mycdev_open,
  70.  
    .unlocked_ioctl = mycdev_ioctl,
  71.  
    .read = mycdev_read,
  72.  
    .write = mycdev_write,
  73.  
    .release = mycdev_close,
  74.  
    };
  75.  
     
  76.  
    // 中断触发函数
  77.  
    irqreturn_t myirq_handler(int irqno, void* dev_id)
  78.  
    {
  79.  
    if (!gpio_get_value(gpiono)) {
  80.  
    number = !number;
  81.  
    gpiod_set_value(gpiono, number);
  82.  
    condition = 1;
  83.  
    wake_up_interruptible(&wq_head);
  84.  
    }
  85.  
     
  86.  
    return IRQ_HANDLED;
  87.  
    }
  88.  
    // 解析led设备树
  89.  
    int myled_init(void)
  90.  
    {
  91.  
    // 解析led灯的设备树节点
  92.  
    dnode_led = of_find_node_by_path("/led_key");
  93.  
    if (dnode_led == NULL) {
  94.  
    printk("解析设备led树节点失败\n");
  95.  
    return -ENXIO;
  96.  
    }
  97.  
    printk("解析设备树节点成功 \n");
  98.  
    // 根据设备树节点解析led1gpio编号
  99.  
    gpiono = gpiod_get_from_of_node(dnode_led, "led1-gpios", 0, GPIOD_OUT_LOW, NULL);
  100.  
    if (IS_ERR(gpiono)) {
  101.  
    printk("gpio编号解析失败\n");
  102.  
    return -PTR_ERR(gpiono);
  103.  
    }
  104.  
    return 0;
  105.  
    }
  106.  
    // 解析按键设备树
  107.  
    int myirq_init(void)
  108.  
    {
  109.  
    int wet;
  110.  
    dnode = of_find_node_by_name(NULL, "led_key");
  111.  
    if (dnode == NULL) {
  112.  
    printk("解析设备树key节点失败\n");
  113.  
    return -ENXIO;
  114.  
    }
  115.  
    printk("设备树节点解析成功\n");
  116.  
    // 获取软中断号
  117.  
    irqno = irq_of_parse_and_map(dnode, 0);
  118.  
    if (!irqno) {
  119.  
    printk("软中断号获取失败\n");
  120.  
    return -ENOMEM;
  121.  
    }
  122.  
    printk("软中断号获取成功irqno=%d\n", irqno);
  123.  
    // 注册中断
  124.  
    wet = request_irq(irqno, myirq_handler, IRQF_TRIGGER_FALLING, "key1-gpios", NULL);
  125.  
    if (wet) {
  126.  
    printk("注册失败\n");
  127.  
    return wet;
  128.  
    }
  129.  
    return 0;
  130.  
    }
  131.  
    static int __init mycdev_init(void)
  132.  
    {
  133.  
    int ret, i;
  134.  
    // 初始化等待队列头
  135.  
    init_waitqueue_head(&wq_head);
  136.  
    // 分配字符设备驱动对象空间
  137.  
    cdev = cdev_alloc();
  138.  
    if (cdev == NULL) {
  139.  
    printk("申请字符设备驱动空间失败\n");
  140.  
    ret = -EFAULT;
  141.  
    goto out1;
  142.  
    }
  143.  
    // 字符设备驱动对象部分初始化
  144.  
    cdev_init(cdev, &fops);
  145.  
    // 静态申请设备号
  146.  
    if (major > 0) {
  147.  
     
  148.  
    ret = register_chrdev_region(MKDEV(major, minor), 3, "mykey");
  149.  
    if (ret) {
  150.  
    printk("静态指定设备号失败\n");
  151.  
    goto out2;
  152.  
    }
  153.  
    } else { // 动态申请设备号
  154.  
    ret = alloc_chrdev_region(&devno, minor, 3, "mykey");
  155.  
    if (ret) {
  156.  
    printk("动态指定设备号失败\n");
  157.  
    goto out2;
  158.  
    }
  159.  
    major = MAJOR(devno);
  160.  
    minor = MINOR(devno);
  161.  
    }
  162.  
    // 注册字符设备驱动对象
  163.  
    ret = cdev_add(cdev, MKDEV(major, minor), 3);
  164.  
    if (ret) {
  165.  
    printk("注册字符设备驱动对象失败\n");
  166.  
    goto out3;
  167.  
    }
  168.  
    printk("注册字符设备驱动对象成功\n");
  169.  
    // 向上提交目录
  170.  
    cls = class_create(THIS_MODULE, "mykey");
  171.  
    if (IS_ERR(cls)) {
  172.  
    printk("向上提交目录失败\n");
  173.  
    ret = -PTR_ERR(cls);
  174.  
    goto out4;
  175.  
    }
  176.  
    printk("向上提交目录成功\n");
  177.  
    // 向上提交设备节点
  178.  
    for (i = 0; i < 3; i ) {
  179.  
    dev = device_create(cls, NULL, MKDEV(major, i), NULL, "mykey%d", i);
  180.  
    if (IS_ERR(dev)) {
  181.  
    printk("向上提交节点信息失败\n");
  182.  
    ret = -PTR_ERR(dev);
  183.  
    goto out5;
  184.  
    }
  185.  
    }
  186.  
    printk("向上提交设备节点信息成功\n");
  187.  
     
  188.  
    // 解析设备树节点
  189.  
    myled_init();
  190.  
    // 解析设备树节点
  191.  
    myirq_init();
  192.  
    return 0;
  193.  
    out5:
  194.  
    for (--i; i > 0; i--) {
  195.  
    // 销毁提交的设备信息
  196.  
    device_destroy(cls, MKDEV(major, i));
  197.  
    }
  198.  
    class_destroy(cls);
  199.  
    out4:
  200.  
    cdev_del(cdev);
  201.  
    out3:
  202.  
    unregister_chrdev_region(MKDEV(major, minor), 3);
  203.  
    out2:
  204.  
    kfree(cdev);
  205.  
    out1:
  206.  
    return ret;
  207.  
    }
  208.  
    static void __exit mycdev_exit(void)
  209.  
    {
  210.  
    // 注销中断
  211.  
    free_irq(irqno, NULL);
  212.  
    // 销毁设备信息
  213.  
    int i;
  214.  
    for (i = 0; i < 3; i ) {
  215.  
    device_destroy(cls, MKDEV(major, i));
  216.  
    }
  217.  
    // 销毁目录
  218.  
    class_destroy(cls);
  219.  
    // 注销对象
  220.  
    cdev_del(cdev);
  221.  
    // 释放设备号
  222.  
    unregister_chrdev_region(MKDEV(major, minor), 3);
  223.  
    // 释放对象空间
  224.  
    kfree(cdev);
  225.  
    }
  226.  
    module_init(mycdev_init);
  227.  
    module_exit(mycdev_exit);
  228.  
    MODULE_LICENSE("GPL");
学新通

测试代码:

  1.  
     
  2.  
    #include <fcntl.h>
  3.  
    #include <stdio.h>
  4.  
    #include <stdlib.h>
  5.  
    #include <string.h>
  6.  
    #include <sys/ioctl.h>
  7.  
    #include <sys/stat.h>
  8.  
    #include <sys/types.h>
  9.  
    #include <unistd.h>
  10.  
    int main(int argc, char const* argv[])
  11.  
    {
  12.  
    int fd;
  13.  
     
  14.  
    unsigned int number;
  15.  
     
  16.  
    fd = open("/dev/mykey0", O_RDWR);
  17.  
    if (fd < 0) {
  18.  
    printf("打开设备文件失败\n");
  19.  
    exit(-1);
  20.  
    }
  21.  
     
  22.  
    while (1) {
  23.  
     
  24.  
    read(fd, &number, sizeof(number));
  25.  
    printf("number=:%d\n", number);
  26.  
    }
  27.  
    close(fd);
  28.  
    return 0;
  29.  
    }
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakcbf
系列文章
更多 icon
同类精品
更多 icon
继续加载