• 转:gpio_request


    今天再次学习SD卡驱动,遇到pgio_request这个函数,始终不知道其什么意思,看了几遍源代码才有了点感觉。现将其关键部分再此说明一下,以备自己以后复习,或是路客参考。

     

    一般gpio_request封装了mem_request(),起保护作用,最后要调用mem_free之类的。主要是告诉内核这地址被占用了。当其它地方调用同一地址的gpio_request就会报告错误,该地址已被申请。在/proc/mem应该会有地址占用表描述。
    这种用法的保护作用前提是大家都遵守先申请再访问,有一个地方没遵守这个规则,这功能就失效了。好比进程互斥,必需大家在访问临界资源的时候都得先获取锁一样,其中一个没遵守约定,代码就废了。


     

    其原型为 int gpio_request(unsigned gpio, const char *label)先说说其参数,gpio则为你要申请的哪一个管脚,label则是为其取一个名字。

    其具体实现如下:

    int gpio_request(unsigned gpio, const char *label)
    {
     struct gpio_desc *desc;//这个自己看源码
     struct gpio_chip *chip;//这个自己看源码
     int   status = -EINVAL;
     unsigned long  flags;

     spin_lock_irqsave(&gpio_lock, flags);//屏蔽中断

     if (!gpio_is_valid(gpio))//判断是否有效,也就是参数的取值范围判断
      goto done;
     desc = &gpio_desc[gpio];//这个是关键gpio_desc为定义的一个全局的数组变量,这个函数的实值也就是,用gpio_desc里面的一个变量来表示数组中的这个元素

                                                  已经被申请了,而这个变量就是下面会看到的desc->flags。
     chip = desc->chip;按理说这个这个全局的gpio_desc如果没有初始化的话,这个chip就为空了,随后就直接返回-EINVAL了。
     if (chip == NULL)如果不为空继续往下走
      goto done;

     if (!try_module_get(chip->owner))
      goto done;

     /* NOTE:  gpio_request() can be called in early boot,
      * before IRQs are enabled, for non-sleeping (SOC) GPIOs.
      */

     if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {这里测试并设置flags的第FLAG_REQUESTED位,如果没有被申请就返回该位的原值0,分析到这儿,

                                                                                                                     也差不多满足了我的个人要求。
      desc_set_label(desc, label ? : "?");
      status = 0;
     } else {
      status = -EBUSY;
      module_put(chip->owner);
      goto done;
     }

     if (chip->request) {
      /* chip->request may sleep */
      spin_unlock_irqrestore(&gpio_lock, flags);
      status = chip->request(chip, gpio - chip->base);
      spin_lock_irqsave(&gpio_lock, flags);

      if (status < 0) {
       desc_set_label(desc, NULL);
       module_put(chip->owner);
       clear_bit(FLAG_REQUESTED, &desc->flags);
      }
     }

    done:
     if (status)
      pr_debug("gpio_request: gpio-%d (%s) status %d ",
       gpio, label ? : "?", status);
     spin_unlock_irqrestore(&gpio_lock, flags);
     return status;
    }

  • 相关阅读:
    你不是真正的快乐
    春天里
    一生有你
    故乡
    第一天
    直来直往
    恋恋风尘
    烦恼歌
    because of you
    从头再来
  • 原文地址:https://www.cnblogs.com/yfz0/p/6095258.html
Copyright © 2020-2023  润新知