麦麦手机铺有假货吗:linux内核gpiolib文档
来源:百度文库 编辑:中财网 时间:2024/05/04 09:26:07
linux内核gpiolib文档
分类: linux驱动 2011-05-16 18:01 666人阅读 评论(2) 收藏 举报自己翻译的内核gpiolib文档,是2.6.38版本的。原文在:http://lxr.linux.no/linux+v2.6.38/Documentation/gpio.txt
内核文档
2011/05/08
标识端口 -------------
gpio使用0~MAX_INT之间的整数标识,不能使用负数。 使用以下函数检查一个端口号的合法性: int gpio_is_valid(int number);
使用gpio ------------- 使用io的第一步是分配端口,使用 gpio_request()。 接下来要做的是标记它的方向。 /*设为输入或者输出,成功返回零或者失败返回负的错误值*/ int gpio_direction_input(unsigned gpio); int gpio_direction_output(unsigned gpio, int value); 通常应该检查它们的返回值。通常应该假定这两个接口会在线程上下文中调用。但是 对于自旋锁安全的gpio也可以在线程出现之前的早期初始化之间使用。
对于输出的gpio,提供的值作为输出的初始值。
使用自旋锁安全的gpio ---------------------------------- 大部分gpio控制器可以使用内存读写指令来访问,不需要睡眠,可以在中断上下文访问。
对于gpio_cansleep返回假的gpio可以使用下面的接口访问: /*读取输入,返回零或非零*/ int gpio_get_value(unsigned gpio); /*输出*/ void gpio_set_value(unsigned gpio, int value); 返回的值是布尔值,零代表低,非零代表搞电平。当读取输出引脚的值,返回值应该是引脚上的实际状态, 这个值不一定等于配置的输出值,因为从设定信号到信号稳定需要一定时间。
不是所有的平台可以读取输出的引脚值,这些平台不能总是返回零。用这两这两个函数访问 不能非在睡眠的上下文中安全访问的gpio将是一个错误。
可被休眠上下文中访问的GPIO ---------------------------------------------- 一些gpio控制器必须使用基于信息的总线,比如i2c和spi.读写gpio值的命令需要在队列中等待。 操作这些gpio可能会睡眠,不能在中断上下文中调用。
支持这种gpio的平台为了通过在这个函数中返回非零来区分其它 类型的gpio(需要一个已经被gpio_request申请的gpio号): int gpio_cansleep(unsigned gpio);
为了访问这些端口,定义了另一组函数接口: /*输入端口:返回零或非零,可能睡眠*/ int gpio_get_value_cansleep(unsigned gpio); /*输出端口:可能睡眠*/ void gpio_set_value_cansleep(unsigned gpio, int value); 只能在允许睡眠的上下文中访问这些端口,比如线程化的中断中, 必须使用这些接口而不是没有cansleep前缀的自旋锁安全接口。
除了这些接口可能睡眠这个事实之外,它们操作那些不能在中断处理函数中访问的端口,这些调用的表现和 自旋锁安全的调用表现一致。
另外:调用安装和配置这样的gpio必须是在可睡眠的上下文中,因为他们可能需要访问gpio控制器。 gpio_direction_input() gpio_direction_output() gpio_request()
## gpio_request_one() ## gpio_request_array() ## gpio_free_array()
gpio_free() gpio_set_debounce()
申请和释放gpio ------------------------ 为了获取系统配置错误,定义了两个调用: /*申请gpio,返回0或负的错误值 * 非空的lables指针有助于诊断*/ int gpio_request(unsigned gpio, const char *label); /*释放之前申请的gpio*/ void gpio_free(unsigned gpio); 应该假设这两个函数实在进程上下文中调用的,但对于自旋锁安全的gpio也可从 在进程建立之前的早期启动过程中调用。
考虑到大多数情况下gpio会在申请过后立即需要被配置,下面三个接口负责这些工作: /*申请一个单独的gpio,使用“flag”作为初始的配置参数*/ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); /*在一个调用中申请多个gpio*/ int gpio_request_array(struct gpio *array, size_t num); /*释放多个端口*/ void gpio_free_array(struct gpio *array, size_t num);
“falg”用来配置下面的特性: * GPIOF_DIR_IN - 配置方向为输入 * GPIOF_DIR_OUT -配置方向为输出 * GPIOF_INIT_LOW - 做输出引脚,输出低电平 * GPIOF_INIT_HIGH - 做输出引脚,输出高电平
为了同时处理多个gpio,定义了一个专门结构体: struct gpio { unsigned gpio; unsigned long flags; const char *label; };
典型的使用如下: 327 static struct gpio leds_gpios[] = { 328 { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */ 329 { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* default to OFF */ 330 { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* default to OFF */ 331 { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* default to OFF */ 332 { ... }, 333 }; 334 335 err = gpio_request_one(31, GPIOF_IN, "Reset Button"); 336 if (err) 337 ... 338 339 err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios)); 340 if (err) 341 ... 342 343 gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
- GPIO映射到IRQ
gpio_to_irq()返回的中断编号可以传给request_irq()和free_irq()。 irq_to_gpio()返回的gpio编号通常用来调用gpio_get_value(),比如在沿触发的中断中获取引脚的状态。 有些平台不支持这种映射,应该避免调用映射函数。
模拟漏极开路 ------------------ gpio可能支持也可能不支持漏极开路输出。如果硬件不支持,可以模拟漏极开路输出的输入或者输出: LOW: gpio_direction_output(gpio, 0) 忽略上拉电阻。 HIGH: gpio_direction_input(gpio) 关闭输出,上拉电阻控制信号。 如果驱动输出高电平但是gpio_get_value(gpio)报告的电平是低电平(经过一定延迟之后),可以断定 其它部分正在信号线上输出低电平。
GPIO 的框架(可选) =============== GPIO的框架在gpiolib中实现。 如果使能了 debugfs,系统下会出现 /sys/kernel/debug/gpio这个文件。这个文件内 将会列出所有注册在框架内的控制器和当前使用的gpio的状态。
控制器驱动:gpio_chip ------------------------------- 在gpio框架中使用"struct gpio_chip"表示每个控制器的所有信息: --设置gpio方向的方法 --访问gpio状态的方法 --表示是否会睡眠的标志 --可选的debugfs方法 --诊断用的标签lable(char指针) 当然还有每个实例的独有数据(可能来自dev.platform_data);第一个gpio的编号和管理的gpio数量。
gpiolib支持多个gpio控制器的实例,使用gpiochip_add()来注册,使用gpiochip_remove()注销。 gpio_chip的debugfs方法将会忽略未被申请的gpio。使用gpiochip_is_requested()将会返回NULL(未被申请)或者 lable(已被申请)
平台支持 ------------ 为了支持gpio框架,必须选择Kconfig中的选项:ARCH_REQUIRE_GPIOLIB 或者 ARCH_WANT_OPTIONAL_GPIOLIB。并且 在
ARCH_REQUIRE_GPIOLIB表示gpiolib代码总是会编译进内核中。 ARCH_WANT_OPTIONAL_GPIOLIB表示gpiolib默认是关闭的,但是用户可以使能它并把它编译进内核。 如果这两个选项一个都未被选中,gpiolib则不能被用户使能。
通常那三个函数接口可以直接使用框架内的代码(通过gpio_chip来调用): #define gpio_get_value __gpio_get_value #define gpio_set_value __gpio_set_value #define gpio_cansleep __gpio_cansleep
用户空间的sysfs接口(可选) ==================
在sysfs下的路径 --------------------- 在/sys/class/gpio下有三种类型的入口: --用户空间控制GPIO的接口(第一类) --对应具体GPIO --GPIO控制器("gpio_chip"的实例)(第三类) 以上接口不包括标准“device”文件和它们的链接。
控制接口(第一类)是只写的: /sys/class/gpio/ "export" 用户空间通过写入gpio的编号来向内核申请将某个gpio的控制权导出到用户空间 比如“echo 19 > export ”将会为19号gpio创建一个节点“gpio19”,前提是没有内和代码申请了这个端口。 “unexport” 和导出的效果相反。 比如“echo 19 > unexport”将会移除“gpio19”这个节点。 GPIO管脚的路径类似于/sys/class/gpio/gpio42/ (for GPIO #42)的形式,并且有以下可读写的属性: /sys/class/gpio/gpioN/ (第二类) “direction” 读取结果是“in”或者“out”。也可以往其中写入。写入“out”默认将引脚值初始化为低。 写入“low”或“high”可以初始化作为输出时的初始值。 如果内核不支持或者内核代码不愿意,将不会存在这个属性。 “value” 读取结果是0(低电平)或1(高电平)。如果GPIO被配置为输出,这个值是可写的, 任何非零的值都将输出高电平。 如果某个引脚能并且已经被配置为产生中断,可以在它的节点上调用poll(2)并且poll(2)将在中断触发后返回。 如果使用poll(2),设置事件类型为POLLPRI和POLLERR。如果使用sellect(2),将文件描述符加入exceptfds。 在poll(2)返回后,可以使用lseek(2)移动到文件开头读取新的值或者关闭它再重新打开读取新值。 “edge” 读取改节点将会得到以下值: "none", "rising", "falling",或者 "both"。写如这些字符串到这个节点中将会选择 唤醒在“value”上的poll(2)的信号沿。 这个文件节点只有在引脚能被配置为输入中断引脚的时候才存在。 "active_low" 读取值是0(假)或者1(真)。写入任何非零的值都将反转“value”中读取和写入的值。 已经在使用和之后使用poll(2)的“edge”节点的“rasing”和“falling”值将会受"active_low" 的影响。 (自己的理解:这个值实际是将高变为0,低变为1。也就是实现了逻辑反转。)
GPIO控制器的路径类似于/sys/class/gpio/gpiochip42/(这个控制器的最小端口是42)并且有以下的读写属性: /sys/class/gpio/gpiochipN/ “base” 和N相同,也就是控制器管理的最小的端口编号。 “lable” 诊断使用的标志(并不总是唯一的) “ngpio” 控制器管理的端口数量(端口范围是:N ~ N+ngpio-1)
从内核空间中导出 ------------------------ 内核可以对已经被 gpio_request()申请的gpio的导出进行明确的管理。 /* 导出GPIO到用户空间的sysfs,当允许用户空间修改gpio的方向,第二个参数是真 */ int gpio_export(unsigned gpio, bool direction_may_change); /* 撤销GPIO的导出 */ void gpio_unexport(); /* 创建到导出GPIO的 sysfs link ,第一个参数是在哪个dev下创建,第二个参数名字,第三个是gpio编号 */ int gpio_export_link(struct device *dev, const char *name, unsigned gpio) /* 改变sysfs中GPIO节点的极性,也就是将高低电平的逻辑反转。可以在export之前和之后进行。之前设置的 enabled poll(2)也会相应改变 */ int gpio_sysfs_set_active_low(unsigned gpio, int value);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 以上内容是内核文档的内容,下面分析gpio_chip的内容,这是一个控制器。 48/** 49 * struct gpio_chip - 一个 GPIO 控制器的抽象 50 * @label: 诊断用的标签(名字) 51 * @dev: 可选的设备结构体 52 * @owner: 拥有者模块指针 53 * @request: 可选的激活回调函数,就像电源管理的接口一样。可以睡眠 55 * @free: 可选的释放回调函数,可以睡眠。 57 * @direction_input: 配置某个偏移对应的端口为输入引脚,可能返回错误。 58 * @get: 返回相应偏移引脚的值; 如果是输出引脚则返回输出引脚的状态,或者返回零。 60 * @direction_output: 配置输出引脚的输出值,或者返回错误 61 * @set: 设置指定引脚的输出值。 62 * @to_irq: 可选的回调函数,支持非静态的 gpio_to_irq()映射, 不可以睡眠 ; 64 * @dbg_show: 可选的 debugfs接口; 如果不设置,内核会使用默认函数赋给这个指针。 67 * @base: gpiogpio_chip所管理的第一个gpio的编号;如果注册期间是负值,将会动态申请一个值。 69 * @ngpio: GPIO控制器管理的IO数目,最后一个IO的号码是 (base + ngpio - 1). 71 * @can_sleep: 如果get()/set() 方法会睡眠这个标志必须被设置 73 * @names:如果设置了这个成员,它必须是大小为 ngpio的字符指针数组,每个成员可以指向相应引脚的特殊的名字,也可以为空。 name影响的是exportGPIO到sysfs的名字,如果不设置的话名字就是“gpioN”(N是IO对应的编号)。 当然这个成员可以不初始化。
gpio_chip使用offset(0~(ngpio - 1))来分辨不同的引脚。 */
struct gpio_chip { 91 const char *label; 92 struct device *dev; 93 struct module *owner; 94 95 int (*request)(struct gpio_chip *chip, 96 unsigned offset); 97 void (*free)(struct gpio_chip *chip, 98 unsigned offset); 99 100 int (*direction_input)(struct gpio_chip *chip, 101 unsigned offset); 102 int (*get)(struct gpio_chip *chip, 103 unsigned offset); 104 int (*direction_output)(struct gpio_chip *chip, 105 unsigned offset, int value); 106 int (*set_debounce)(struct gpio_chip *chip, 107 unsigned offset, unsigned debounce); 108 109 void (*set)(struct gpio_chip *chip, 110 unsigned offset, int value); 111 112 int (*to_irq)(struct gpio_chip *chip, 113 unsigned offset); 114 115 void (*dbg_show)(struct seq_file *s, 116 struct gpio_chip *chip); 117 int base; 118 u16 ngpio; 119 const char *const *names; 120 unsigned can_sleep:1; 121 unsigned exported:1; 122 123#if defined(CONFIG_OF_GPIO) 124 /* 125 * If CONFIG_OF is enabled, then all GPIO controllers described in the 126 * device tree automatically may have an OF translation 127 */ 128 struct device_node *of_node; 129 int of_gpio_n_cells; 130 int (*of_xlate)(struct gpio_chip *gc, struct device_node *np, 131 const void *gpio_spec, u32 *flags); 132#endif 133};
gpio_chip的接口:extern const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset); 如果offet对应的gpio已经被申请了则返回NULL,否则返回lable指针或者“??”
extern int __must_check gpiochip_reserve(int start, int ngpio); 将start开始的ngpio个编号保留 这个函数是在全局范围内预留一段编号,将来供某个gpio_chip使用。
分享到:
LINUX内核UML图
怎样更新linux内核
linux 内核 最新版
怎样修改linux内核?
关于linux内核
linux内核编译
如何升级linux的内核?
linux最新内核版本是多少?
linux最新内核版本是多少?
linux内核代码的问题~
linux内核代码的问题~
linux内核代码的问题~
linux内核指的是什么?
怎么样看linux内核文件?
怎样升级linux的内核?
请问linux的内核如何编辑哪?
linux的版本debian的内核
求助,升级内核后进不了linux了
哪里有redhat linux最新内核下载???
linux的内核升级的问题
谁告诉我内核linux有什么不一样?
求一个讲linux内核的视频
linux 如何查看显卡内核的版本号
Linux内核编译,步骤及截图.