首页 > 系统相关 >【linux-IMX6ULL-pinctrl和gpio子系统】

【linux-IMX6ULL-pinctrl和gpio子系统】

时间:2024-06-05 19:59:06浏览次数:28  
标签:pin 引脚 pinctrl GPIO gpio IMX6ULL 子系统

目录

1. pinctrl子系统

1.1 pinctrl子系统简介

  pinctrl和gpio子系统就是驱动分离与分层思想下的产物,驱动分离与分层其实就是按照面向对象编程的设计思想而设计的设备驱动框架;
  在我的上篇博客利用设备树点灯中:链接,我点灯的流程就是把控制引脚gpio1_io03的相关初始化需要的寄存器地址放到了设备树reg中,比如gpio的地址信息等。但是我在进行驱动编写时,我假装不知道这些寄存器的地址,然后从设备树中进行获取这些寄存器的地址,获取到地址后进行寄存器配置初始化的一系列的操作,就像在裸机开发中对于寄存器的操作一样,而且我们每使用一个引脚就要进行一系列的初始化和复用,这显然是效率低下的。
  对比图如下:左边是方式1,右边是方式2,这里只是按照gpio的驱动流程进行简要归类,实际上pinctr子系统和gpio的子系统之间的联系是比较紧密的,而且内容也是比较复杂的;

  而且对于引脚控制而言,复用成什么模式是固定的,数据手册已经清楚的列写出来了,也就是我们可以提前把一个引脚的所有的复用模式给列选出来只能进行固定选择,只是把引脚的电气属性的配置权力下放到了开发人员,其他的就是固定模式的选择,基本没啥变化,而且不容易出错,因为这些子系统是芯片厂商BSP工程师都封装好了。

1.2 pinctrl子系统使用

  传统的配置 pin 的方式就是直接操作相应的寄存器,但是这种配置方式比较繁琐、而且容易出问题(比如 pin 功能冲突)。pinctrl 子系统就是为了解决这个问题而引入的,pinctrl 子系统主要工作内容如下:其中使用pinctrl子系统主要是在设备树中进行配置:

  1. 获取设备树中 pin 信息
  2. 根据获取到的 pin 信息来设置 pin 的复用功能
  3. 根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等

  对于我们使用者来讲,只需要在设备树里面设置好某个 pin 的相关属性即可,其他的初始化工作均由 pinctrl 子系统来完成,pinctrl 子系统源码目drivers/pinctrl。

1.2.1 追加pin节点

&esmp; 我们这里控制LED的是引IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03,这里简写成IO3,我们要添加这个IO3的的pin信息,那么如下面代码所示,我们为什么要向iomuxc 中追加fsl,pins信息,而不是在其他的父节点进行追加呢?

//imx6ull.dtsi
iomuxc: iomuxc@020e0000 {
				compatible = "fsl,imx6ul-iomuxc";
				reg = <0x020e0000 0x4000>;
			};
...........................(省略)
//imx6ull-14x14-evk.dts
&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog_1>;
	imx6ul-evk {
		pinctrl_gpioled: ledgrp{
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO03__GPIO1_IO03		0x10B0 /* LED-CTRL */
			>;
		};

  这里我们看一下GPIO1_IO03的数据手册:可以看到对于IO3的基地址是0x0x020E0000 ,我们再看一下对于追加的父节点:iomuxc中的reg描述信息:reg = <0x020e0000 0x4000>;其中第一个是不是也有一个0x020e0000,这就是我们为什么要向iomuxc 父节点追加pin节点,对于fsl,pins中的引脚信息,每个引脚都有唯一的偏移量而且已经宏定义好了,当我们使用这个节点时,系统会自动进行基地址+偏移地址然后计算出来IO03的实际地址,然后把后面的0x10B电气属性值赋值给这个寄存器的地址,然后进行一系列的配置

1.2.2 配置引脚信息节点

  当我们追加好了pin节点信息,且配置好了电气属性,接下来就是在设备树中再加上引脚的节点信息,添加引脚节点的信息是为了方便再驱动中进行信息的获取:添加的信息如下,这里添加的主要就是多了一条非常重要的gpio的信息:
led-gpios=<&gpio1 3 GPIO_ACTIVE_LOW>;

	pinctrl-names = "default";
		pinctrl-0 =  <&pinctrl_gpioled>;
		status = "okay";
		led-gpios=<&gpio1 3 GPIO_ACTIVE_LOW>;
	};

  我们上一步已经添加好了pin配置节点,主要目的就是把MX6UL_PAD_GPIO1_IO03引脚复用为:GPIO1_IO03模式,但是我们如何在驱动中把这些配置信息触发生效呢?于是我们就是进行了节点配置,并把所有的配置信息返回映射成一个GPIO号led-gpios,我们在驱动中获取这个gpio号,拿到这个gpio号我们就可以把上面的所有配置信息给正式生效,也就是通过下面的gpio子系统对gpio号进行申请,看看有没有其他设备占用这个gpio,如果没有其他设备占用这个gpio,就可以通过映射的gpio号进行pinctrcl的控制;

2. GPIO子系统

2.1 GPIO子系统简介

  pinctrl子系统的主要功能是设置pin(或PAD)的复用和电气属性,当复用为GPIO的模式时,就要选用GPIO子系统进行调用。gpio 子系统顾名思义,就是用于初始化 GPIO 并且提供相应的 API 函数,比如设置 GPIO为输入输出,读取 GPIO 的值等。gpio 子系统的主要目的就是方便驱动开发者使用 gpio,驱动开发者在设备树中添加 gpio 相关信息,然后就可以在驱动程序中使用 gpio 子系统提供的 API函数来操作 GPIO,Linux 内核向驱动开发者屏蔽掉了 GPIO 的设置过程,极大的方便了驱动开发者使用 GPIO;

2.1 gpio子系统API函数

  对于GPIO子系统的主要作用是通过API函数进行,相关功能的设置和读取,比较重要的API函数如下:

  • int gpio_request(unsigned gpio, const char *label)
  • void gpio_free(unsigned gpio)
  • int gpio_direction_input(unsigned gpio)
  • int gpio_direction_output(unsigned gpio, int value)
  • #define gpio_get_value __gpio_get_value
  • int __gpio_get_value(unsigned gpio)
  • #define gpio_set_value __gpio_set_value
  • void __gpio_set_value(unsigned gpio, int value)

  与gpio相关的of函数如下:

  • int of_gpio_named_count(struct device_node *np, const char *propname)
  • int of_gpio_count(struct device_node *np)
  • int of_get_named_gpio(struct device_node *np,const char *propname,int index)

3. 检查 PIN 是否被其他外设使用

  这一点非常重要,要检测很多初次接触设备树的驱动开发人员很容易因为这个小问题栽了大跟头!因为我们所使用的设备树基本都是在半导体厂商提供的设备树文件基础上修改而来的,而半导体厂商提供的设备树是根据自己官方开发板编写的,很多 PIN 的配置和我们所使用的开发板不一样。比如 A 这个引脚在官方开发板接的是 I2C 的 SDA,而我们所使用的硬件可能将 A 这个引脚接到了其他的外设,比如 LED 灯上,接不同的外设,A 这个引脚的配置就不同。一个引脚一次只能实现一个功能,如果 A 引脚在设备树中配置为了 I2C 的 SDA 信号,那么 A 引脚就不能再配置为 GPIO,否则的话驱动程序在申请 GPIO 的时候就会失败

标签:pin,引脚,pinctrl,GPIO,gpio,IMX6ULL,子系统
From: https://blog.csdn.net/w384829981/article/details/139459078

相关文章

  • STM32使用定时器在普通gpio上模拟pwm-红牛开发板LED1的亮度调节
    stm32F103zet只有固定的几个针脚可以输出tim定时器信号,在不支持tim输出的口上就没法输出pwm,在红牛开发版上的表现就是控制lcd屏幕亮度的a1针脚,可以输出pwm,屏幕亮度可以无极调节,但是4个led灯就只能控制开关。使用arduino的analogWrite函数,只能调节开关。可以用定时器的中断来控制......
  • 【STM32基础学习】--GPIO原理
    一.GPIO入门知识全称: generalpurposeintputoutpot(通用输入输出端口)。可以做输入也可以做输出。STM32芯片的GPIO引脚与外部设备连接起来,从而实现与外部通讯,控制以及数据采集的功能。二.GPIO的八种工作模式1.4种输入模式(可以读取端口的高低电平或者电压,用于读取按键......
  • 【GD32F303红枫派使用手册】第二节 GPIO-流水灯实验
    2.1实验内容通过本实验主要学习以下内容:GPIO结构及原理;GPIO输出功能实现;LED驱动原理。2.2实验原理2.2.1GPIO外设原理GD32F303系列MCU最多可支持112个通用I/O引脚(GPIO),分别为PA0~PA15,PB0~PB15,PC0~PC15,PD0~PD15,PE0~PE15,PF0~PF15和PG0~PG15,各......
  • [IMX6ULL驱动开发]-Linux对中断的处理(二)
    上一篇文章中,引入了Linux对于中断的一些简略流程以及中断抽象为具体实际形象。此文章主要是继续加深对Linux对中断的处理流程以及一些相应的数据结构。目录Linux对中断的扩展:硬件中断、软件中断多中断处理中断上下部处理流程发生中断A,并被中断A打断发生中断A,并被中断B打......
  • Linux下用户空间控制GPIO
    文章目录参考文章一、简介二、GPIO接口原理图三、在用户空间控制GPIO步骤参考文章https://blog.csdn.net/qq_41483419/article/details/134015533https://blog.csdn.net/baidu_38661691/article/details/97147652一、简介在用户空间中控制GPIO:​/sys/class/gpio......
  • STM32读取GPIO状态的代码优化
    最近看到新的读取GPIO状态引脚状态的代码伪代码如图:优势:读取消抖前第一次的GPIO状态,与引脚先前状态进行对比;如果电平状态一致则跳过延时消抖的流程,可以节约时间,减少裸机工作循环一轮所用时间​staticu8ReadIOPort(GPIO_TypeDef*GPIOx,u16PortNum,u8prePortStatus){......
  • [IMX6ULL驱动开发]-Linux对中断的处理(一)
    目录中断概念的引入ARM架构中断的流程异常向量表Linux系统对中断的处理ARM对程序和中断的处理Linux进程中断处理中断概念的引入如何理解中断,我们可以进行如下抽象。把CPU看做一个母亲,当它正在执行任务的时候,可以看为是一个母亲在看书。此时可能发生许多不同的情况,比......
  • IMX6ULL Linux内核网络驱动修改
    IMX6ULL网络驱动修改主要修改arch/arm/boot/dts/imx6ul-14x14-evk.dtsi设备树文件即可,修改方式和u-boot的设备树修改一致。硬件电路设备树修改需要修改的设备树位置:arch/arm/boot/dts/imx6ul-14x14-evk.dtsi增加复位引脚信息从上面的原理图可知网口1使用的复位引脚是GPIO......
  • LuckFox-pico 入门记录一:编译环境与GPIO
    LuckFoxRV1106点灯本文使用VMwave+ubuntu20.04虚拟机,并用CLion开发linux,简单记录一下配置过程;1虚拟机安装拿到板子,首先是配置环境,虚拟机选择ubuntu20.04,安装教程随便搜一下就行,网络配置选择NAT就行,可以不选择桥接模式,其他没有什么注意事项。比较难的一点是samba共享文件夹......
  • GPIO三种输出状态:推挽输出 / 开漏输出 / 高阻态
    一、GPIO基本的输出方式:  GPIO有三种状态:高电平,低电平,浮空/高阻态  设计时发现芯片的管脚描述中:有的支持推挽输出,有的支持开漏输出。就是GPIO的三种状态的组合 二、推挽输出(push-pull):描述GPIO输出高低电平时,电流的一个动作。要么推出去,要么挽回来。(1)推出去:上端的MOS管......