首页 > 技术知识 > 正文

可以通过导出gpio sys节点到用户空间,在用户空间操作。 内核的gpio驱动基于gpio子系统的实现,所以其他驱动程序可以通过内核提供的 libgpio 接口很方面的控制,例如,gpio_request_one,gpio_get_value,gpio_set_value

如果用gpio的方式控制led,需要改哪些呢? 驱动中选中gpioled,板级里找到LED_GPIO的宏,改成您自己用的gpio

X1000 的gpio 控制器有五组,A,B,C,D,Z。 支持输入输出和设备复用功能。内核的gpio 驱动程序是基于gpio 子系统架构编写的。应用 程序可以使用gpio_demo 进行测试。内核驱动可以在内核空间使用,也可以通过导出gpio sys 节点到用户空间,在用户空间进行操作

内核空间

文件介绍 gpio 一般在进行开发板设计的时候就已经固定好了,有的gpio 只能作为设备复用功能管脚,有的gpio 作为普通的输入输出和中断检测功能,对于固定设备复用的功能管脚在以下文件中定义:

arch/mips/xburst/soc-x1000/include/mach/platform.h 在arch/mips/xburst/soc-x1000/common/platform.c 会根据驱动配置,选中相应的设备功能管脚。

内核的gpio 驱动基于gpio 子系统实现,所以其它驱动程序可以通过内核提供的libgpio 接口,很方便的进行gpio 控制 例如gpio_request_one, gpio_get_value,gpio_set_value 等。

gpio 驱动文件所在位置: arch/mips/xburst/soc-x1000/common/gpio.c

编译配置 内核通过配置CONFIG_GPIOLIB 选项可以使用gpio 功能,默认必须选上。 CONFIG_GPIOLIB: Symbol: GPIOLIB [=y] Type : boolean Prompt: GPIO Support Location: -> Device Drivers Defined at drivers/gpio/Kconfig:38 Depends on: ARCH_WANT_OPTIONAL_GPIOLIB [=n] || ARCH_REQUIRE_GPIOLIB [=y]

通过配置CONFIG_GPIO_SYSFS 选项,可以将gpio 导出到用户节点/sys/class/gpio 下,对该节点下的文件操作,可以控制gpio 输入输出。 Symbol: GPIO_SYSFS [=y] Type : boolean Prompt: /sys/class/gpio/… (sysfs interface) Location: -> Device Drivers -> GPIO Support (GPIOLIB [=y]) Defined at drivers/gpio/Kconfig:69 Depends on: GPIOLIB [=y] && SYSFS [=y]

用户空间 在内核导出gpio 节点的前提下,可以操作/sys/class/gpio 节点,控制gpio 输入输出。 /sys/class/gpio/”export” … 用户空间可以通过写其编号到这个文件,要求内核导出一个GPIO 的控制到用户空间。 例如: 如果内核代码没有申请GPIO #19,”echo 19 > export” 将会为GPIO #19 创建一个”gpio19″ 节点。

“unexport” … 导出到用户空间的逆操作。 例如: “echo 19 > unexport” 将会移除使用”export”文件导出的”gpio19″ 节点。 GPIO 信号的路径类似/sys/class/gpio/gpio42/ (对于GPIO #42 来说),并有如下的读/写属性: /sys/class/gpio/gpioN/

“direction” … 读取得到”in” 或”out”。这个值通常运行写入。 写入”out” 时,其引脚的默认输出为低电平。为了确保无故障运行,”low” 或”high” 的电平值应该写入GPIO 的配置,作为初始输出值。 注意:如果内核不支持改变GPIO 的方向,或者在导出时内核代码没有明确允许用户空间可以重新配置GPIO 方向,那么这个属性将不存在。

“value” … 读取得到0 (低电平) 或1 (高电平)。如果GPIO 配置为输出,这个值允许写操作。任何非零值都以高电平看待。

如果引脚可以配置为中断信号,且如果已经配置了产生中断的模式(见”edge”的描述),你可以对这个文件使用轮询操作(poll(2)),且轮询操作会在任何中断触发时返回。如果你使用轮询操作(poll(2)),请在events 中设置POLLPRI 和POLLERR。如果你使用轮询操作 (select(2)),请在exceptfds 设置你期望的文件描述符。在轮询操作(poll(2))返回之后,既可以通过lseek(2)操作读取sysfs 文件的开始部分,也可以关闭这个文件并重新打开它来读取数据。

“edge” … 读取得到“none”、“rising”、“falling”或者“both”。 将这些字符串写入这个文件可以选择沿触发模式,会使得轮询操作(select(2))在”value”文件中返回。 这个文件仅有在这个引脚可以配置为可产生中断输入引脚时,才存在。 “active_low” … 读取得到0 (假) 或1 (真)。写入任何非零值可以翻转这个属性的(读写)值。已存在或之后通过”edge”属性设置了”rising”

gpio操作 查看Documentation/gpio.txt文档

GPIO 模块

X1000的gpio 控制器有五组,A,B,C,D,Z。 支持输入输出和设备复用功能。内核的gpio 驱动程序是基于gpio 子系统架构编写的。应用程序可以使用gpio_demo 进行测试。内核驱动可以在内核空间使用,也可以通过导gpiosys 节点到用户空间,在用户空间进行操作。

内核空间 对于固定设备复用的功能管脚在以下文件中定义: arch/mips/xburst/soc-x1000/include/mach/platform.h 在arch/mips/xburst/soc-x1000/common/platform.c 会根据驱动配置,选中相应的设备功能管脚。Platform.h中

/* * Copyright (C) 2010 Ingenic Semiconductor Inc. * * Inthis file, here are some macro/device/function to * to help the board special file to organizeresources * on the chip. */ #ifndef __SOC_x1000_H__ #define __SOC_x1000_H__ /* devio define list */ /****************************************************************************************/ #define I2S_PORTB \ {.name = “i2s”, .port = GPIO_PORT_B, .func =GPIO_FUNC_1, .pins = 0x1f, } /****************************************************************************************/ #define UART0_PORTC \ {.name = “uart0”, .port = GPIO_PORT_C, .func =GPIO_FUNC_0, .pins = 0x0f << 10, } #define UART1_PORTA \ {.name = “uart1-pa”, .port = GPIO_PORT_A, .func =GPIO_FUNC_2, .pins = 0x3 << 4, } #ifndef CONFIG_PRODUCT_X1000_BEETHOVEN #define UART1_PORTD {.name = “uart1-pd”, .port = GPIO_PORT_D, .func =GPIO_FUNC_1, .pins = 0xf << 2, } #else #define UART1_PORTD \ { .name = “uart1-pd”, .port =GPIO_PORT_D, .func = GPIO_FUNC_1, .pins = 0x3 << 2, } #endif #define UART2_PORTA \ {.name = “uart2-pa”, .port = GPIO_PORT_A, .func =GPIO_FUNC_2, .pins = 0x3 << 2, } #define UART2_PORTD \ {.name = “uart2-pd”, .port = GPIO_PORT_D, .func =GPIO_FUNC_0, .pins = 0x3 << 4 } #define UART2_PORTC \ {.name = “uart2-pc”, .port = GPIO_PORT_C, .func =GPIO_FUNC_1, .pins = 0x1 << 31 } /****************************************************************************************/ /* JZ SoC on Chip devices list*/ extern struct platform_device jz_codec_device; extern struct platform_device jz_fb_device; extern struct platform_device jz_uart0_device; extern struct platform_device jz_uart1_device; extern struct platform_device jz_uart2_device; int jz_device_register(structplatform_device *pdev,void *pdata); #endif
<

http://blog.csdn.net/ghostyu/article/details/6908805 在kernel/include/linux/platform.h中定义结构体

struct platform_device { const char *name; int id; bool id_auto; struct device dev; u32 num_resources; struct resource *resource; const struct platform_device_id *id_entry; /* MFD cell pointer */ struct mfd_cell *mfd_cell; /* arch specific additions */ struct pdev_archdata archdata; }; 函数extern intplatform_device_register(struct platform_device *);在文件kernel/drivers/base/platform.c中 /** * platform_device_register – add aplatform-level device * @pdev: platform device were adding */ int platform_device_register(structplatform_device *pdev) { device_initialize(&pdev->dev); arch_setup_pdev_archdata(pdev); return platform_device_add(pdev); } EXPORT_SYMBOL_GPL(platform_device_register);
<
文件arch/mips/xburst/soc-x1000/common/platform.c根据配置选项选中相应的设备功能引脚 #ifdef CONFIG_SERIAL_JZ47XX_UART2 //如果定义该选项 //在该板级配置文档中kernel/arch/mips/configs/halley2_nor_v10_linux_defconfig static struct resource jz_uart2_resources[] = { [0] = { .start = UART2_IOBASE,//基地址arch/mips/xburst/soc-x1000/include/soc //#defineUART0_IOBASE 0x10030000 .end = UART2_IOBASE + 0x1000 – 1, .flags = IORESOURCE_MEM, }, [1] = { .start = IRQ_UART2, .end = IRQ_UART2, .flags = IORESOURCE_IRQ, }, #ifdef CONFIG_SERIAL_JZ47XX_UART2_DMA [2] = { .start = JZDMA_REQ_UART2, .flags = IORESOURCE_DMA, }, #endif }; struct platform_device jz_uart2_device = { .name = “jz-uart”, .id = 2, .num_resources =ARRAY_SIZE(jz_uart2_resources), .resource = jz_uart2_resources, }; #endif
<

platform_device和platform_driver(一) 首先介绍一下注册一个驱动的步骤: 1、定义一个platform_driver结构 2、初始化这个结构,指定其probe、remove等函数,并初始化其中的driver变量 3、实现其probe、remove等函数 看platform_driver结构,定义于include/Linux/platform_device.h文件中:

struct platform_driver { int (*probe)(structplatform_device *); int (*remove)(structplatform_device *); void (*shutdown)(structplatform_device *); int (*suspend)(structplatform_device *, pm_message_t state); int (*resume)(structplatform_device *); struct device_driver driver; const struct platform_device_id *id_table; };

猜你喜欢