Linux驱动开发:gpio子系统

这篇具有很好参考价值的文章主要介绍了Linux驱动开发:gpio子系统。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1、GPIO配置流程

2、GPIO子系统API

2.1 of_find_node_by_path

2.2 of_get_named_gpio

2.3 gpio_request 与 gpiod_get 与 gpiod_get_index

2.4 gpio_direction_input 与 gpiod_direction_input

2.5 gpio_direction_output 与 gpiod_direction_output

2.6 gpio_get_value 与 gpiod_get_value

2.7 gpio_set_value 与 gpiod_set_value

2.8  gpiod_get_from_of_node

2.9 gpio_free 与 gpiod_put

3、GPIO子系统驱动程序

3.1 没有platform总线前怎么得到gpio节点

3.1.1 修改设备树

3.1.2 驱动程序:老版接口

3.1.3 驱动程序:新版接口

3.2 platform总线下得到

3.2.1 修改设备树:配置pinctrl

3.2.2 修改设备树:配置自己的节点

3.2.3 驱动程序


1、GPIO配置流程

        如果要操作GPIO引脚的话,需要先将所用引脚配置为GPIO功能,这需要通过Pinctrl子系统来实现。

        在Pinctrl子系统将引脚配置为GPIO功能后,就可以使用GPIO子系统来设置GPIO的方向等。

        在设备树中,“GPIO组”就是一个GPIO Controller,这通常都由芯片厂家设置好。我们要做的是找到它名字,比如“gpio1”,然后指定要用它里面的哪个引脚,比如<&gpio1 0>。

        我们需要关心里面的这2个属性:

#gpio-controller; 表示这个节点是一个GPIO Controller,它下面有很多引脚。

#gpio-cells = <2>; 表示这个控制器下每一个引脚要用2个32位的数(cell)来描述。

普遍的用法是,用第1个cell来表示哪一个引脚,用第2个cell来表示有效电平:

GPIO_ACTIVE_HIGH : 高电平有效

GPIO_ACTIVE_LOW : 低电平有效

可参考的帮助文档

Linux-4.9.88/Documentation/devicetree/bindings/gpio/gpio.txt 

Linux-4.9.88/Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt

2、GPIO子系统API

2.1 of_find_node_by_path

struct device_node *of_find_node_by_path(const char *path)
/**/
功能:通过路径或者节点结构体
参数:
    @path:路径
返回值:成功返回节点的首地址,失败返回NULL

2.2 of_get_named_gpio

int of_get_named_gpio(struct device_node *np,const char *propname, int index)
/*
功能:根据节点结构体解析gpio编号
参数:
    @np:节点指针
	@propname:键
    @index:索引号
返回值:成功返回gpio的编号,失败返回错误码
*/

2.3 gpio_request 与 gpiod_get 与 gpiod_get_index

int gpio_request(unsigned gpio, const char *label)
/*
功能:申请要使用的gpio
参数:
    @gpio:gpio的编号
    @label:标签名
返回值:成功返回0,失败返回错误码
*/
//如果是一个GPIO就用gpiod_get,如果有多个就用gpiod_get_index
struct gpio_desc *__must_check gpiod_get(struct device *dev, 
    const char *con_id, enum gpiod_flags flags)

struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
					       const char *con_id,
					       unsigned int idx,
					       enum gpiod_flags flags)
/*
功能:申请要使用的gpio
参数:
    @dev: device结构体,如果有platform,则 &pdev->dev
    @con_id: 键
    @idx: 索引号
    @flags: 0
返回值:成功返回gpio_desc 结构体,失败返回错误码
*/

2.4 gpio_direction_input 与 gpiod_direction_input

int gpio_direction_input(unsigned gpio)
/*
功能:设置gpio的为输入
参数:
    @gpio:gpio的编号
返回值:成功返回0,失败返回错误码
*/
int gpiod_direction_input(struct gpio_desc *desc)
/*
功能:设置gpio为输入
参数:
    @desc:gpio_desc结构体
返回值:成功返回0,失败返回错误码
*/

2.5 gpio_direction_output 与 gpiod_direction_output

int gpio_direction_output(unsigned gpio, int value)
/*
功能:设置gpio的为输出
参数:
    @gpio:gpio的编号
    @value:默认电平的状态 1高电平  0低电平
返回值:成功返回0,失败返回错误码
*/
int gpiod_direction_output(struct gpio_desc *desc, int value)
/*
功能:设置gpio为输出
参数:
    @desc:gpio_desc结构体
返回值:成功返回0,失败返回错误码
*/

2.6 gpio_get_value 与 gpiod_get_value

int gpio_get_value(unsigned gpio)
/*
功能:读取管脚的值
参数:
    @gpio:gpio的编号
返回值:1高电平  0低电平
*/
int gpiod_get_value(const struct gpio_desc *desc)
/*
功能:读取管脚的值
参数:
    @desc: gpio_desc结构体
返回值:1高电平  0低电平
*/

2.7 gpio_set_value 与 gpiod_set_value

void gpio_set_value(unsigned gpio, int value)    
/*
功能:设置输出电平的值
参数:
     @gpio:gpio的编号
	 @value:1高电平  0低电平
返回值:无
*/
void gpiod_set_value(struct gpio_desc *desc, int value)
/*
功能:设置输出电平的值
参数:
    @desc: gpio_desc结构体
    @value: 1高电平  0低电平
返回值:无
*/

2.8  gpiod_get_from_of_node

struct gpio_desc *gpiod_get_from_of_node(struct device_node *node, 
const char *propname, int index, enum gpiod_flags dflags, const char *label)
/*
功能:在设备树节点信息结构体中获取并申请要使用的gpio编号,然后输出
    此函数一个函数就完成了申请加上输出的功能
参数:
    @node:设备树节点信息结构体指针
    @propname:键名
    @index:索引
    @dflags:gpio状态值
        GPIOD_OUT_LOW
        GPIOD_OUT_HIGH
    @label:标签,填写NULL
返回值:成功返回gpio描述结构体指针,失败返回错误码指针
*/

2.9 gpio_free 与 gpiod_put

void gpio_free(unsigned gpio)
/*
功能:释放gpio
参数:
     @gpio:gpio的编号
返回值:无   
*/
void gpiod_put(struct gpio_desc *desc)
/*
功能:释放gpio
参数:
     @desc:gpio_desc结构体
返回值:无   
*/

3、GPIO子系统驱动程序

3.1 没有platform总线前怎么得到gpio节点

3.1.1 修改设备树

设备树文件在

arch/arm/boot/dts/100ask_imx6ull-14x14.dts

 在根节点下写自己的节点

myleds{ 
	led1=<&gpioe 10 0>; 
	led2=<&gpiof 10 0>; 
	led3=<&gpioe 8 0>;  
};

3.1.2 驱动程序:老版接口

struct device_node *node;
int gpiono;
static int __init mycdev_init(void)
{
	//1.获取节点
	node = of_find_node_by_path("/myleds");

	//2.解析得到gpio
	gpiono = of_get_named_gpio(node, "led1", 0);

	//3.申请使用的gpio
	gpio_request(gpio,NULL));

	//4.通过gpio申请设备
	gpio_direction_output(gpiono, 0);

	return 0;
}

static void __exit mycdev_exit(void) 
{
	gpio_set_value(gpiono,0);
	gpio_free(gpiono);
}

3.1.3 驱动程序:新版接口

static int __init mycdev_init(void)
{
	//1.获取节点
	node = of_find_node_by_path("/myleds");
	
    //2、申请GPIO
    //此函数一个函数就完成了申请加上输出的功能
	desc = gpiod_get_from_of_node(node, "led2", 0, GPIO_OUT_HIGH, 0);

	return 0;
}


static void __exit mycdev_exit(void) 
{
	gpiod_set_value(desc,0);
	gpiod_put(desc);
}

3.2 platform总线下得到

3.2.1 修改设备树:配置pinctrl

使用imx图形化界面来配置引脚

//在pinctrl下设置引脚
&iomuxc_snvs

myled_for_gpio_subsys: myled_for_gpio_subsys{       
    fsl,pins = <
        MX6ULL_PAD_SNVS_TAMPER3__GPIO5_IO03        0x000110A0
    >;
};

3.2.2 修改设备树:配置自己的节点

在根节点下写自己的节点文章来源地址https://www.toymoban.com/news/detail-525200.html

myled {
    compatible = "100ask, leddrv" ;
    pinctrl-names = "default";
    pinctrl-0 = <&myLed_for_gpio_subsys>;
    led-gpios = <&gpio5 3 GPIO_ACTIVE_HIGH>;
};

3.2.3 驱动程序

static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	gpiod_set_value(led_gpio, status);

}

static struct file_operations led_drv = {
	.write   = led_drv_write,
};

static int chip_demo_gpio_probe(struct platform_device *pdev)
{	    
    led_gpio = gpiod_get(&pdev->dev, "led", 0);
    register_chrdev(0, "100ask_led", &led_drv);
    	
    return 0;
}

static int chip_demo_gpio_remove(struct platform_device *pdev)
{
    unregister_chrdev(major, "100ask_led");
	gpiod_put(led_gpio);
    
    return 0;
}


static const struct of_device_id ask100_leds[] = {
    { .compatible = "100ask,leddrv" },
    { },
};

/* 1. 定义platform_driver */
static struct platform_driver chip_demo_gpio_driver = {
    .probe      = chip_demo_gpio_probe,
    .remove     = chip_demo_gpio_remove,
    .driver     = {
        .name   = "100ask_led",
        .of_match_table = ask100_leds,
    },
};

static int __init led_init(void)
{    
    platform_driver_register(&chip_demo_gpio_driver); 
}

static void __exit led_exit(void)
{
    platform_driver_unregister(&chip_demo_gpio_driver);
}

到了这里,关于Linux驱动开发:gpio子系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【IMX6ULL驱动开发学习】14.Linux驱动开发 - GPIO中断(设备树 + GPIO子系统)

    代码自取 【14.key_tree_pinctrl_gpios_interrupt】: https://gitee.com/chenshao777/imx6-ull_-drivers 主要接口函数: 1. of_gpio_count (获得GPIO的数量) 2. kzalloc (向内核申请空间) 3. of_get_gpio (获取GPIO子系统标号) 4. gpio_to_irq (根据GPIO子系统标号得到软件中断号) 5. request_irq (根据软件中断号

    2024年02月12日
    浏览(49)
  • 驱动开发作业3——GPIO子系统

    作业1:在内核模块中启用定时器,定时1s,让LED1以1s为周期实现流水灯  myled.c(驱动文件)    作业2:基于GPIO子系统完成LED灯驱动的注册,并利用应用程序测试  chrdevled.c(驱动文件) test.c(测试文件)

    2024年02月16日
    浏览(35)
  • <Linux开发>驱动开发 -之-Linux INPUT 子系统

    <Linux开发>驱动开发 -之-Linux INPUT 子系统 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移植可参考以下: <Linux开发> -之-系统移植 uboot移植过程详细记录(第一部分) <Linux开发> -之-系统移植 uboot移植过程详细记录(第二部分) <Linux开发

    2024年02月09日
    浏览(48)
  • Linux驱动开发:SPI子系统

    MISO:主设备数据输入,从设备数据输出。 MOSI:主设备数据输出,从设备数据输入。 SCLK:时钟信号,由主设备产生。 CS:    从设备片选信号,由主设备控制。 CPOL(时钟极性) :   0:时钟起始位低电平      1:时钟起始为高电平   CPHA(时钟相位) :0:第一个时钟周期采样   1

    2024年02月06日
    浏览(48)
  • 【Linux驱动开发】010 pinctrl子系统

    上一章我们编写了基于设备树的 LED 驱动,但是驱动的本质还是没变,都是配置 LED 灯所使用的 GPIO 寄存器,驱动开发方式和裸机基本没啥区别。本章我们就来学习一下如何借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发。   Linux 内核针对 PIN 的配置推出了 pinctrl 子系统,对于

    2024年02月14日
    浏览(43)
  • [驱动开发]gpio子系统及中断实现led亮灭

    编写LED灯的驱动,使用GPIO子系统,里面添加按键的中断处理 1.应用程序发送指令控制发光二极管亮灭 2.按键1按下,led1电位反转;按键2按下,led2电位反转;按键3按下,led3电位反转   

    2024年02月14日
    浏览(76)
  • 【LED子系统深度剖析】一、开篇词|Linux驱动开发必读

    我的圈子: 高级工程师聚集地 我是董哥,高级嵌入式软件开发工程师,从事嵌入式Linux驱动开发和系统开发,曾就职于世界500强公司! 创作理念:专注分享高质量嵌入式文章,让大家读有所得!

    2024年02月09日
    浏览(40)
  • Linux GPIO 和 Pinctrl 子系统的使用(十四)

     个人名片: 🦁作者简介:学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755@qq.com 🦉个人WeChat:Vir2021GKBS 🐼 本文由妄北y原创,首发CSDN 🎊🎊🎊 🐨座右铭:大多数人想要改造这个世界,但却罕有人想改造自己。 专栏导航: 妄北y系列专栏导航: C/C++的基

    2024年04月26日
    浏览(36)
  • 【IMX6ULL驱动开发学习】21.Linux驱动之PWM子系统(以SG90舵机为例)

    首先在 imx6ull.dtsi 文件中已经帮我们定义好了一些pwm的设备树节点,这里以pwm2为例 我们要在设备树(.dts)文件中引用和使能该节点,同时指定好pwm映射到的GPIO引脚(即pinctrl子系统,我这里映射到了GPIO1_9上) 使用pwm 只需要在设备树节点中添加两条属性信息,如下所示 pwms :属

    2024年02月12日
    浏览(129)
  • Linux Mii management/mdio子系统分析之三 mii_bus注册、注销及其驱动开发流程

    (转载)原文链接:https://blog.csdn.net/u014044624/article/details/123303174       本篇是mii management/mdio模块分析的第三篇文章,本章我们主要介绍mii-bus的注册与注销接口。在前面的介绍中也已经说过,我们可以将mii-bus理解为mdio总线的控制器的抽象,就像spi-master、i2c-adapter一样。 本

    2024年01月16日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包