i.MX6ULL(十八) linux pinctrl 子系统

IMX6UL串口RS485半双工模式设置调试过程 前言:RS485驱动有两种模式,一种是硬件的(也就是通过TXD信号控制485芯片的使能),这种模式简单实用,但是也有弊端。另外一种是软件的方式,发送数据前,通过软件控制GPIO使能外部485芯片,发送完毕后,再去禁用外部RS485芯片。 1. IMXUL的驱动中是支持RS485模式的,通过修改设备树文件即可实现。 2. 但是由于电路的问题,导致在发送数据的同时,也收到了自己发送出去的数据... 阅读详情

一 简介

上一章我们编写了基于设备树的 LED 驱动,但是驱动的本质还是没变,都是配置 LED 灯
所使用的 GPIO 寄存器,驱动开发方式和裸机基本没啥区别。Linux 是一个庞大而完善的系统,
尤其是驱动框架,像 GPIO 这种最基本的驱动不可能采用“原始”的裸机驱动开发方式,否则
就相当于你买了一辆车,结果每天推着车去上班。Linux 内核提供了 pinctrl 和 gpio 子系统用于
GPIO 驱动,本章我们就来学习一下如何借助 pinctrl 和 gpio 子系统来简化 GPIO 驱动开发。
没什么特别注意的 记忆就行了

二 pinctrl 子系统

2.1 pinctrl 子系统简介

Linux 驱动讲究驱动分离与分层,pinctrl 和 gpio 子系统就是驱动分离与分层思想下的产物,
驱动分离与分层其实就是按照面向对象编程的设计思想而设计的设备驱动框架,关于驱动的分
离与分层我们后面会讲。本来 pinctrl 和 gpio 子系统应该放到驱动分离与分层章节后面讲解,但
是不管什么外设驱动,GPIO 驱动基本都是必须的,而 pinctrl 和 gpio 子系统又是 GPIO 驱动必
须使用的,所以就将 pintrcl 和 gpio 子系统这一章节提前了。
我们先来回顾一下上一章是怎么初始化 LED 灯所使用的 GPIO,步骤如下:
①、修改设备树,添加相应的节点,节点里面重点是设置 reg 属性,reg 属性包括了 GPIO
相关寄存器。
②、获取 reg 属性中 IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 这两个寄存器地址,并且初始化这两个寄存器,这
两个寄存器用于设置 GPIO1_IO03 这个 PIN 的复用功能、上下拉、速度等。
③、在②里面将 GPIO1_IO03 这个 PIN 复用为了 GPIO 功能,因此需要设置 GPIO1_IO03
这个 GPIO 相关的寄存器,也就是 GPIO1_DR 和 GPIO1_GDIR 这两个寄存器。
总结一下,②中完成对 GPIO1_IO03 这个 PIN 的初始化,设置这个 PIN 的复用功能、上下
拉等,比如将 GPIO_IO03 这个 PIN 设置为 GPIO 功能。③中完成对 GPIO 的初始化,设置 GPIO
为输入/输出等。如果使用过 STM32 的话应该都记得,STM32 也是要先设置某个 PIN 的复用功
能、速度、上下拉等,然后再设置 PIN 所对应的 GPIO。其实对于大多数的 32 位 SOC 而言,引
脚的设置基本都是这两方面,因此 Linux 内核针对 PIN 的配置推出了 pinctrl 子系统,对于 GPIO
的配置推出了 gpio 子系统。本节我们来学习 pinctrl 子系统,下一节再学习 gpio 子系统。
大多数 SOC 的 pin 都是支持复用的,比如 I.MX6ULL 的 GPIO1_IO03 既可以作为普通的
GPIO 使用,也可以作为 I2C1 的 SDA 等等。此外我们还需要配置 pin 的电气特性,比如上/下
拉、速度、驱动能力等等。传统的配置 pin 的方式就是直接操作相应的寄存器,但是这种配置
方式比较繁琐、而且容易出问题(比如 pin 功能冲突)。pinctrl 子系统就是为了解决这个问题而引
入的,pinctrl 子系统主要工作内容如下:
①、获取设备树中 pin 信息。
②、根据获取到的 pin 信息来设置 pin 的复用功能
③、根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等。
对于我们使用者来讲,只需要在设备树里面设置好某个 pin 的相关属性即可,其他的初始
化工作均由 pinctrl 子系统来完成,pinctrl 子系统源码目录为 drivers/pinctrl。

2.2  I.MX6ULL 的 pinctrl 子系统驱动

2.2.1、PIN 配置信息详解
要使用 pinctrl 子系统,我们需要在设备树里面设置 PIN 的配置信息,毕竟 pinctrl 子系统要
根据你提供的信息来配置 PIN 功能,一般会在设备树里面创建一个节点来描述 PIN 的配置信
息。打开 imx6ull.dtsi 文件,找到一个叫做 iomuxc 的节点,如下所示:
示例代码 45.1.2.1 iomuxc 节点内容 1
 iomuxc: iomuxc@020e0000 {
 compatible = "fsl,imx6ul-iomuxc";
 reg = <0x020e0000 0x4000>;
};
iomuxc 节点就是 I.MX6ULL 的 IOMUXC 外设对应的节点,看起来内容很少,没看出什么
跟 PIN 的配置有关的内容啊,别急! imx6ull-14x14-evk-emmc.dts也很少 ,打开 imx6ull-14x14-evk-emmc.dts,找到如下所示内容:主要pin内容和板子相关 imx6ull很多系列 通用部分被放入更高级别dts内
&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog_1>;
	imx6ul-evk {
		pinctrl_hog_1: hoggrp-1 {
			fsl,pins = <
				MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */
				MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 /* SD1 VSELECT */
				MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
			>;
		};

		pinctrl_csi1: csi1grp {
			fsl,pins = <
				MX6UL_PAD_CSI_MCLK__CSI_MCLK		0x1b088
				MX6UL_PAD_CSI_PIXCLK__CSI_PIXCLK	0x1b088
				MX6UL_PAD_CSI_VSYNC__CSI_VSYNC		0x1b088
				MX6UL_PAD_CSI_HSYNC__CSI_HSYNC		0x1b088
				MX6UL_PAD_CSI_DATA00__CSI_DATA02	0x1b088
				MX6UL_PAD_CSI_DATA01__CSI_DATA03	0x1b088
				MX6UL_PAD_CSI_DATA02__CSI_DATA04	0x1b088
				MX6UL_PAD_CSI_DATA03__CSI_DATA05	0x1b088
				MX6UL_PAD_CSI_DATA04__CSI_DATA06	0x1b088
				MX6UL_PAD_CSI_DATA05__CSI_DATA07	0x1b088
				MX6UL_PAD_CSI_DATA06__CSI_DATA08	0x1b088
				MX6UL_PAD_CSI_DATA07__CSI_DATA09	0x1b088
			>;
		};

		pinctrl_enet1: enet1grp {
			fsl,pins = <
				MX6UL_PAD_ENET1_RX_EN__ENET1_RX_EN	0x1b0b0
				MX6UL_PAD_ENET1_RX_ER__ENET1_RX_ER	0x1b0b0
				MX6UL_PAD_ENET1_RX_DATA0__ENET1_RDATA00	0x1b0b0
				MX6UL_PAD_ENET1_RX_DATA1__ENET1_RDATA01	0x1b0b0
				MX6UL_PAD_ENET1_TX_EN__ENET1_TX_EN	0x1b0b0
				MX6UL_PAD_ENET1_TX_DATA0__ENET1_TDATA00	0x1b0b0
				MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01	0x1b0b0
				MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1	0x4001b031
			>;
		};

		pinctrl_enet2: enet2grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO07__ENET2_MDC		0x1b0b0
				MX6UL_PAD_GPIO1_IO06__ENET2_MDIO	0x1b0b0
				MX6UL_PAD_ENET2_RX_EN__ENET2_RX_EN	0x1b0b0
				MX6UL_PAD_ENET2_RX_ER__ENET2_RX_ER	0x1b0b0
				MX6UL_PAD_ENET2_RX_DATA0__ENET2_RDATA00	0x1b0b0
				MX6UL_PAD_ENET2_RX_DATA1__ENET2_RDATA01	0x1b0b0
				MX6UL_PAD_ENET2_TX_EN__ENET2_TX_EN	0x1b0b0
				MX6UL_PAD_ENET2_TX_DATA0__ENET2_TDATA00	0x1b0b0
				MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01	0x1b0b0
				MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2	0x4001b031
			>;
		};

		pinctrl_flexcan1: flexcan1grp{
			fsl,pins = <
				MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX	0x1b020
				MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX	0x1b020
			>;
		};

		pinctrl_flexcan2: flexcan2grp{
			fsl,pins = <
				MX6UL_PAD_UART2_RTS_B__FLEXCAN2_RX	0x1b020
				MX6UL_PAD_UART2_CTS_B__FLEXCAN2_TX	0x1b020
			>;
		};

		pinctrl_i2c1: i2c1grp {
			fsl,pins = <
				MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
				MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
			>;
		};

		pinctrl_i2c2: i2c2grp {
			fsl,pins = <
				MX6UL_PAD_UART5_TX_DATA__I2C2_SCL 0x4001b8b0
				MX6UL_PAD_UART5_RX_DATA__I2C2_SDA 0x4001b8b0
			>;
		};

		pinctrl_lcdif_dat: lcdifdatgrp {
			fsl,pins = <
				MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x79
				MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x79
				MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x79
				MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x79
				MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x79
				MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x79
				MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x79
				MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x79
				MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x79
				MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x79
				MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x79
				MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x79
				MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x79
				MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x79
				MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x79
				MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x79
				MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x79
				MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x79
				MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x79
				MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x79
				MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x79
				MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x79
				MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x79
				MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x79
			>;
		};

		pinctrl_lcdif_ctrl: lcdifctrlgrp {
			fsl,pins = <
				MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x79
				MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x79
				MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x79
				MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x79
			>;
		};

		pinctrl_pwm1: pwm1grp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
			>;
		};

		pinctrl_qspi: qspigrp {
			fsl,pins = <
				MX6UL_PAD_NAND_WP_B__QSPI_A_SCLK      0x70a1
				MX6UL_PAD_NAND_READY_B__QSPI_A_DATA00 0x70a1
				MX6UL_PAD_NAND_CE0_B__QSPI_A_DATA01   0x70a1
				MX6UL_PAD_NAND_CE1_B__QSPI_A_DATA02   0x70a1
				MX6UL_PAD_NAND_CLE__QSPI_A_DATA03     0x70a1
				MX6UL_PAD_NAND_DQS__QSPI_A_SS0_B      0x70a1
			>;
		};

		pinctrl_sai2: sai2grp {
			fsl,pins = <
				MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK	0x17088
				MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC	0x17088
				MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA	0x11088
				MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA	0x11088
				MX6UL_PAD_JTAG_TMS__SAI2_MCLK		0x17088
			>;
		};

		pinctrl_tsc: tscgrp {
			fsl,pins = <
				MX6UL_PAD_GPIO1_IO01__GPIO1_IO01	0xb0
				MX6UL_PAD_GPIO1_IO02__GPIO1_IO02	0xb0
				MX6UL_PAD_GPIO1_IO03__GPIO1_IO03	0xb0
				MX6UL_PAD_GPIO1_IO04__GPIO1_IO04	0xb0
			>;
		};

		pinctrl_uart1: uart1grp {
			fsl,pins = <
				MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
				MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX 0x1b0b1
			>;
		};

		pinctrl_uart2: uart2grp {
			fsl,pins = <
				MX6UL_PAD_UART2_TX_DATA__UART2_DCE_TX	0x1b0b1
				MX6UL_PAD_UART2_RX_DATA__UART2_DCE_RX	0x1b0b1
				MX6UL_PAD_UART3_RX_DATA__UART2_DCE_RTS	0x1b0b1
				MX6UL_PAD_UART3_TX_DATA__UART2_DCE_CTS	0x1b0b1
			>;
		};

		pinctrl_uart2dte: uart2dtegrp {
			fsl,pins = <
				MX6UL_PAD_UART2_TX_DATA__UART2_DTE_RX	0x1b0b1
				MX6UL_PAD_UART2_RX_DATA__UART2_DTE_TX	0x1b0b1
				MX6UL_PAD_UART3_RX_DATA__UART2_DTE_CTS	0x1b0b1
				MX6UL_PAD_UART3_TX_DATA__UART2_DTE_RTS	0x1b0b1
			>;
		};

		pinctrl_usdhc1: usdhc1grp {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x17059
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x10071
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x17059
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x17059
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x17059
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x17059
			>;
		};

		pinctrl_usdhc1_100mhz: usdhc1grp100mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170b9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100b9
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170b9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170b9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170b9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170b9
			>;
		};

		pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
			fsl,pins = <
				MX6UL_PAD_SD1_CMD__USDHC1_CMD     0x170f9
				MX6UL_PAD_SD1_CLK__USDHC1_CLK     0x100f9
				MX6UL_PAD_SD1_DATA0__USDHC1_DATA0 0x170f9
				MX6UL_PAD_SD1_DATA1__USDHC1_DATA1 0x170f9
				MX6UL_PAD_SD1_DATA2__USDHC1_DATA2 0x170f9
				MX6UL_PAD_SD1_DATA3__USDHC1_DATA3 0x170f9
			>;
		};

		pinctrl_usdhc2: usdhc2grp {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
			>;
		};

		pinctrl_usdhc2_8bit: usdhc2grp_8bit {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x10069
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x17059
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x17059
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x17059
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x17059
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x17059
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x17059
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x17059
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x17059
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x17059
			>;
		};

		pinctrl_usdhc2_8bit_100mhz: usdhc2grp_8bit_100mhz {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100b9
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170b9
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170b9
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170b9
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170b9
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170b9
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170b9
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170b9
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170b9
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170b9
			>;
		};

		pinctrl_usdhc2_8bit_200mhz: usdhc2grp_8bit_200mhz {
			fsl,pins = <
				MX6UL_PAD_NAND_RE_B__USDHC2_CLK     0x100f9
				MX6UL_PAD_NAND_WE_B__USDHC2_CMD     0x170f9
				MX6UL_PAD_NAND_DATA00__USDHC2_DATA0 0x170f9
				MX6UL_PAD_NAND_DATA01__USDHC2_DATA1 0x170f9
				MX6UL_PAD_NAND_DATA02__USDHC2_DATA2 0x170f9
				MX6UL_PAD_NAND_DATA03__USDHC2_DATA3 0x170f9
				MX6UL_PAD_NAND_DATA04__USDHC2_DATA4 0x170f9
				MX6UL_PAD_NAND_DATA05__USDHC2_DATA5 0x170f9
				MX6UL_PAD_NAND_DATA06__USDHC2_DATA6 0x170f9
				MX6UL_PAD_NAND_DATA07__USDHC2_DATA7 0x170f9
			>;
		};

		pinctrl_wdog: wdoggrp {
			fsl,pins = <
				MX6UL_PAD_LCD_RESET__WDOG1_WDOG_ANY    0x30b0
			>;
		};
	};
};
就是向 iomuxc 节点追加数据,不同的外设使用的 PIN 不同、其配置也不 同,因此一个萝卜一个坑,将某个外设所使用的所有 PIN 都组织在一个子节点里面。示例代码
45.1.2.2 中 pinctrl_hog_1 子节点就是和热插拔有关的 PIN 集合,比如 USB OTG 的 ID 引脚。
pinctrl_flexcan1 子节点是 flexcan1 这个外设所使用的 PIN,pinctrl_wdog 子节点是 wdog 外设所
使用的 PIN。如果需要在 iomuxc 中添加我们自定义外设的 PIN,那么需要新建一个子节点,然
后将这个自定义外设的所有 PIN 配置信息都放到这个子节点中。这点imx6ull参考文档中寄存器组结构也是这么设计的。
pinctrl/gpio子系统由半导体厂商实现 定义了所有 gpio引脚 复用控制对应寄存器 
设备树-->pin寄存器组---->设备功能--->对应N寄存器---->寄存器(gpio引脚1:1)---->&gpio/pinctrl -->复用(控制寄存器)

将其与示例代码 45.1.2.1 结合起来就可以得到完成的 iomuxc 节点,如下所示:
 iomuxc: iomuxc@020e0000 {
 compatible = "fsl,imx6ul-iomuxc";
 reg = <0x020e0000 0x4000>;

   pinctrl-names = "default";
	 pinctrl-0 = <&pinctrl_hog_1>;
	    imx6ul-evk {
		  pinctrl_hog_1: hoggrp-1 {
			  fsl,pins = <
			    	MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */
			    	MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 /* SD1 VSELECT */
			    	MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */
			    >;
		    };

......

};
第 2 行,compatible 属性值为“fsl,imx6ul-iomuxc”,前面讲解设备树的时候说过,Linux 内
核会根据 compatbile 属性值来查找对应的驱动文件,所以我们在 Linux 内核源码中全局搜索字
符串“fsl,imx6ul-iomuxc”就会找到 I.MX6ULL 这颗 SOC 的 pinctrl 驱动文件。
第 9~12 行,pinctrl_hog_1 子节点所使用的 PIN 配置信息,我们就以第 9 行的 UART1_RTS_B
这个 PIN 为例,讲解一下如何添加 PIN 的配置信息,UART1_RTS_B 的配置信息如下:
MX6UL_PAD_UART1_RTS_B__GPIO1_IO19  0x17059   
首先说明一下,UART1_RTS_B 这个 PIN 是作为 SD 卡的检测引脚,也就是通过此 PIN 就
可 以 检 测 到 SD 卡 是 否 有 插 入 。
UART1_RTS_B 的 配 置 信 息 分 为 两 部 分 :引脚__IO复用
对于一个 PIN 的配置主要包括两方面, 一个是设置这个 PIN 的复用功能,另一个就是设置这个 PIN 的电气特性。
首先来看一下 MX6UL_PAD_UART1_RTS_B__GPIO1_IO19,这是一个宏定义,定义在文件
arch/arm/boot/dts/imx6ul-pinfunc.h 中,imx6ull.dtsi 会引用 imx6ull-pinfunc.h 这个头文件,而
imx6ull-pinfunc.h 又会引用 imx6ul-pinfunc.h 这个头文件
示例代码 45.1.2.4 中一共有 8 个以“MX6UL_PAD_UART1_RTS_B”开头的宏定义,大家
仔细观察应该就能发现,这 8 个宏定义分别对应 UART1_RTS_B 这个 PIN 的 8 个复用 IO。查
阅《I.MX6ULL 参考手册》可以知 UART1_RTS_B 的可选复用 IO 如图 45.1.2.1 所示:
IOMUXC_SW_MUX_CTL_PAD_UART1_RTS_B 控制寄存器_引脚
示例代码 196 行的宏定义 MX6UL_PAD_UART1_RTS_B__GPIO1_IO19 表示将
UART1_RTS_B 这个 IO 复用为 GPIO1_IO19。此宏定义后面跟着 5 个数字,也就是这个宏定义
的具体值,如下所示:
0x0090                 0x031C                  0x0000                 0x5 (复用模式)                0x0
<mux_reg           conf_reg              input_reg               mux_mode                    input_val>

寄存器偏移地址   conf_reg 寄偏      input_reg 寄偏        mux_reg寄值       input_reg 寄值,在这里无效

0x0090:mux_reg 寄存器偏移地址,设备树中的 iomuxc 节点就是 IOMUXC 外设对应的节
点 , 根 据 其 reg 属 性 可 知 IOMUXC 外 设 寄 存 器 起 始 地 址 为 0x020e0000 。
0x020e0000+0x0090=0x020e0090,IOMUXC_SW_MUX_CTL_PAD_UART1_RTS_B 寄存器地址 正好是 0x020e0090

0x17059,
反应快的同学应该已经猜出来了,0x17059 就是 conf_reg 寄存器值!此值由用户自行设置,通
过此值来设置一个 IO 的上/下拉、驱动能力和速度等。在这里就相当于设置寄存器
IOMUXC_SW_PAD_CTL_PAD_UART1_RTS_B 的值为 0x17059
2.2.2 、PIN 驱动程序讲解

略....

2.3 设备树中添加 pinctrl 节点模板

我们已经对 pinctrl 有了比较深入的了解,接下来我们学习一下如何在设备树中添加某个外
设 的 PIN 信 息 。 关 于 I.MX 系 列 SOC 的 pinctrl 设 备 树 绑 定 信 息 可 以 参 考 文 档
Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt。这里我们虚拟一个名为“test”的设
备,test 使用了 GPIO1_IO00 这个 PIN 的 GPIO 功能,pinctrl 节点添加过程如下:
1、创建对应的节点
同一个外设的 PIN 都放到一个节点里面,打开 imx6ull-alientek-emmc.dts,在 iomuxc 节点
中的“imx6ul-evk”子节点下添加“pinctrl_test”节点。添加完成以后如下所示:
示例代码 45.1.2.10 test 设备 pinctrl 节点
1 pinctrl_test: testgrp {
2 /* 具体的 PIN 信息 */
3 };
2、添加“fsl,pins”属性
设备树是通过属性来保存信息的,因此我们需要添加一个属性,属性名字一定要为“fsl,pins”,
因为对于 I.MX 系列 SOC 而言,pinctrl 驱动程序是通过读取“fsl,pins”属性值来获取 PIN 的配
置信息,完成以后如下所示:
示例代码 45.1.2.11 添加"fsl,pins"属性
1 pinctrl_test: testgrp {
2
fsl,pins = <
3 /* 设备所使用的 PIN 配置信息 */
4 >;
5 };
3、在“fsl,pins”属性中添加 PIN 配置信息
最后在“fsl,pins”属性中添加具体的 PIN 配置信息,完成以后如下所示:
示例代码 45.1.2.13 完整的 test 设备 pinctrl 子节点
1 pinctrl_test: testgrp {
2
fsl,pins = <
3 MX6UL_PAD_GPIO1_IO00__GPIO1_IO00 config /*config 是具体设置值*/
4 >;
5 };

IMX6ULL GPIO PAD引脚配置解析 IMX6ULL GPIO 电器属性寄存器 阅读详情

相关推荐

华为昇腾Atlas200DK. CANN模型推理——目标检测结果不对(无检测结果)的问题解决

目录前言问题描述问题排查1.后处理模块问题排查2.预处理模块问题排查3.模型问题排查4.算法bug问题排查5.AI板卡问题排查6.模型精度问题排查6.模型推理问题解决:模型输入数据与预处理不同后记 前言 上周我在华为昇腾Atlas200DK中部署nanodet和yolov5时,出现了目标检测结果不对(没有检测到任何物体),困扰了整整三天,最后找到原因并圆满解决,在这里记录一下debug过程。 以上测试均在python中完成。 问题描述 第一天上午,我首先将nanodet由pytorch的.pth模型转换为.

qq_41035283的博客 5604

Linux LCD 驱动实验

I.MX6ULL 的 eLCDIF 接口驱动程序 NXP 已经编写好了,因此 LCD 驱动部分我们不需要去修改。我们需要做的就是按照所使用的 LCD 来修改设备树。

m0_51144400的博客 301

浅析MOS管导通过程及RC吸收电路设计要点

RC吸收电路 米勒电容 MOS导通过程

liangbo1999的博客 2万+

imx6ul 设备树文件

这个设备树文件的路径名字为:linux-4.1.15\arch\arm\boot\dts\imx6ul-14x14-evk.dts 然后修改里面的管脚要参照的文件是:linux-4.1.15\arch\arm\boot\dts\imx6ul-pinfunc.h 这个h文件中的内容标识了各个引脚可以配置成什么功能比如: MX6UL_PAD_UART4_TX_DATA__GPIO1_IO28 MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 这两个,在下划线前面的内容是相同的,也就.

cao849861802的博客 2741

S7-1200 Modbus TCP客户端配置实战:从基础设置到数据交互详解

本文详细介绍了S7-1200 Modbus TCP客户端的配置方法,从基础设置到数据交互的完整流程。涵盖硬件准备、TIA Portal配置、MB_CLIENT指令参数详解、数据缓冲区管理及实战测试,帮助工程师快速掌握西门子PLC与Modbus TCP通信的关键技术。

fire9的博客 311

2026 蓝牙技术趋势展望:信道探测、Auracast、高吞吐 HID 与 AI 融合引领行业变革

蓝牙技术2026年展望:信道探测、Auracast广播音频和AI融合将引领创新。蓝牙信道探测技术将实现亚米级精确定位,在工业资产追踪和汽车数字钥匙领域大显身手。Auracast广播音频将持续拓展公共场所应用,提升音频包容性体验。高数据吞吐量和超低延迟功能将支持AR/VR等新兴场景。AI与蓝牙的深度融合将推动可穿戴设备智能化发展,实现实时健康监测和个性化音频服务。蓝牙技术凭借其多功能性和创新力,正成为连接万物的关键技术,持续推动行业变革和生活品质提升。

专业开发者的博客,一个从事Android WiFi和蓝牙的工程师 113

imx6ull lcd驱动编写

一、LCD驱动框架编写 二、LCD引脚配置 使用pinctrl配置LCD引脚 使用GPIO子系统控制背光 i.MX Pins Tool 下载并安装i.MX Pins Tool v6工具,打开配置文件。 该软件可以点击某个引脚,配置对应的功能,就可以生成设备树代码 。 如何配置LCD引脚的功能 需要知道哪些引脚需要配置(看原理图) 需要知道这些引脚应该配置成什么 B_LCD_DATAXXX:这24位的数据引脚肯定需要配置成LCD的功能 B_LCD_VSYNC:列同步信号 B_LCD_HSYNC:水平同步

习惯就好zz的专栏 1311

【AI面试】 Python 的装饰器

Python装饰器是一种高阶函数,用于在不修改原函数代码的情况下增强其功能。它通过@语法糖接收目标函数作为参数,并返回一个包含额外逻辑(如日志、缓存、权限验证等)的新函数。装饰器的核心价值在于代码复用和解耦,符合开闭原则,典型应用包括性能分析、权限控制等场景。例如,@timer_decorator可自动为函数添加耗时统计功能。本质上,@decorator等价于func = decorator(func),实际调用的是装饰器返回的包装函数。进阶技巧包括使用@functools.wraps保留原函数元信息。装饰

钱多多先森 184

【NXP IMX系列】UBOOT 板载IO时钟移植配置

i.MX BSP Porting Guide Chapter 2 Configuring the IOMUX Controller 板载IO 配置与CCM初始化

wanggeege的博客 1838

KNN算法实现数据分类及matlab完整代码

其基本思想是:对于一个未知样本,找出与该样本距离最近的k个已知样本,然后根据这k个样本的类别来确定该未知样本的类别。在本文中,我们采用iris数据集,该数据集包含四个属性:花萼长度、花萼宽度、花瓣长度、花瓣宽度,以及三个类别:山鸢尾、变色鸢尾、维吉尼亚鸢尾。KNN算法具有简单、直观、易于理解等特点,适用于多分类和二分类问题,但其计算复杂度随着样本数量的增加而增加,也容易受异常值影响。在KNN算法中,常用的距离函数有欧氏距离、曼哈顿距离等。(2)选择距离最近的k个样本,并根据它们的类别来确定未知样本的类别。

qq_39605374的博客 1516

YOLOv8改进策略【卷积层】| GnConv:一种通过门控卷积和递归设计来实现高效、可扩展、平移等变的高阶空间交互操作

HorNet: 利用递归门控卷积实现高效高阶空间交互GnConv(Recursive Gated Convolution,递归门控卷积)

Limiiiing的博客 324

i.MX 6ULL 驱动开发 五:LED 驱动

内核中描述以及NXP提供设备配置添加。内核中描述以及NXP提供设备配置添加。2、拷贝编译成功的设备树文件。文件被设备源码文件引用。灯可以正常被点亮和关闭。查看设备树解析是否成功。子系统设置为低电平。

OnlyLove_的博客 935

SQL注入详解

SQL注入(SQL Injection)是一种常见的Web安全漏洞,主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱库、被删除、甚至整个服务器权限陷)。 即:注入产生的原因是后台服务器接收相关参数未经过滤直接带入数据库查询...

渗透之路,攻防之间皆学问 26万+

pinctrl 配置信息详解

这就是宏 MX6UL_PAD_UART1_RTS_B GPIO1_IO19 的含义,看的比较仔细的同学应该会发现并没有 conf_reg 寄存器的值,config_reg 寄存器是设置一个 PIN 的电气特性的,这么重要的寄存器怎么没有值呢?, 在 这 里 就 相 当 于 设 置IOMUXC_SW_MUX_CTL_PAD_UART1_RTS_B 寄存器为 0x5,也即是设置 UART1_RTS_B 这个 PIN 复用为GPIO1_IO19。

weixin_52849254的博客 892

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

linux的LCD的驱动编写

IMX6U系列芯片内部自带一个增强型液晶接口外设eLCDIF(Enhanced LCD Interface),配合使用DDR作为显存, 可直接控制液晶面板,无需额外增加液晶控制器芯片。

qq_24093081的博客 1301

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

IMX6ULL PHY 芯片驱动

该 of 函数想要从设备树中获取 "phy-reset-gpios" 引脚,很显然这里是获取不到的,因为设备树中没有配置。

lyndon 3089

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

IMX6ULL学习笔记(20)——UART串口使用

在目录下添加官方SDK寄存器定义文件MCIMX6Y2.h,位于目录下。在官方SDK的头文件MCIMX6Y2.h文件多达4万多行,包含了i.MX6U芯片几乎所有的寄存器定义以及中断编号的定义。这里只列GPIO1相关寄存器的部分代码。其他寄存器定义与此类似。添加这些定义之后我们就可以直接使用语句操作GPIO1的DR寄存器。操作方法与STM32非常相似。

Leung的博客 5494

I.MX6UL主板TF卡启动Linux的实现(三)-LINUX的软件修改(DTS)

软件支持: 要把板子跑起来,无非就是包括U-boot、dtb、Kernel和跟文件系统均写入正确,此次TF启动只修改U-boot和dtb的部分代码。 3.1 U-boot u-boot如果要支持TF卡启动,则启用USDHC1,注释USDHC2。修改uboot-imx/include/configs/mx6ul_arm2.h,修改后如下图3-1。 图3-1 然后,修改uboot-imx/board/freescale/mx6ul_14x14_ddr3_arm2/mx6ul_14x14_ddr3_arm2.c

szembed的博客 533

(三)正点原子I.MX6ULL kernel6.1挂根文件系统

移植NXP官方最新的linux kernel(linux-imx-lf-6.1.y) 移植方法基本参照正点原子教程 移植开发板:正点原子阿尔法2.1

qq_42697289的博客 1124

开发板 集成下载器 jtag_迅为i.MX6ULL开发板原理图分析介,重点是 LVDS 接口是 RGB 信号通过芯片 GM8285C转换, HDMI 接口是 RGB 接口通过 Sil9022A 转换

https://blog.csdn.net/weixin_40002846/article/details/110261490

二进制模----细微行动改变影响世界 2210

imx6ul——uboot添加RTC,pcf8563驱动

博主使用的是天嵌的imx6ul_coreB 一般来说uboot一开始是不支持RTC,可是有时需要在uboot上使用RTC,那么就记录一下如何添加RTC   1.添加RTC芯片配置相关 要添加RTC,首先在配置文件中添加宏开启pcf8563芯片的支持,以及RTC的设备地址等,使能date命令并设置RTC设备使用总线号。由于date命令是读取RTC内的时间,所以必须使用相关SOC自带rtc的驱...

a617996505的博客 2457

imx6ull EMMC和NABD 的移植注意事项,差别

移植时使用emmc的dtb设备树文件使用网络文件系统、tftp方式加载内核文件和设备树文件没有问题,这时候在网络文件系统内使用 cat /proc/mtd 不可以查看分区情况 , 下载到nand后,系统不可以启动,显示读取内核文件失败和读取设树文件失败; 问题原因时,nand 的驱动没有开启,需要新建一个nand的设备dts文件 文件内容如下: /* * Copyright (C) 2016 Freescale Semiconductor, Inc. * * This prog...

Car12 1385

常用linux驱动函数以及例子

1 常用linux驱动函数 ​ //网络 // dma传输 //1申请一个DMA channel dma_request_channel(mask, sata_dwc_dma_filter, hsdevp); //2根据设备(slave)的特性,配置DMA channel的参数 int dmaengine_slave_config(struct dma_chan *chan, struct dma_slave_config *config) //3 初始化一个DMA传输描述符 desc=dmaen.

w356877795的专栏 4228

迅为IMX6ULL开发板Linux下电容触摸屏实验-实验程序编写

54.2硬件原理图 在本实验中使用迅为的 7 寸屏为例,使用的是 FT5426 触摸芯片。 从原理图中得知,7 寸屏使用 I2C2,触摸屏复位引脚为 SNVS_TAMPER9,中断引脚为 GPIO_9。54.3实验程序编写54.3.1 修改设备树文件 1 、添加 FT5426 的 的 pinctrl信息 FT5426 触摸芯片用到了 4 个 IO,一个复位 IO、一个中断 IO、I2C2 的 SCL 和 SDA,所以我们需要先在设备树中添加 IO 相关的信息。复位 IO 和中断 IO 是普通的 ...

mucheni的博客 984

【2020/11/3学习笔记】GPRS模块接入OneNet接受数据与下发命令(基于TCP透传)

OneNet配置 登陆OneNet,选择添加产品,添加多协议接入 然后在多协议接入页面,选择TCP透传添加设备 最后在设备详情栏中,添加Apikey 上传lua脚本 我使用的lua脚本如下 ----------------------------------------------------------------------- -- 使用说明: -- -- V1.3

qq_37704442的博客 1694

[imx6ul开发常见问题]如何调试出I2C?

4.2如何调试出I2C? 答:客户可以根据实际硬件电路,确定硬件管脚具体用哪一个,打开内核源代码/arch/arm/boot/dts/myb-y6ull-14x14.dts。 myb-y6ull-14x14.dts已经制作了I2C1,I2C2. 此处以I2C3为例。由于I2c3使用了fec2的管脚, 故fec2需要disable。 &i2c3 { clock-frequ...

u011837423的专栏 908
上一篇: i.MX6ULL(十七) linux LED驱动
下一篇: i.MX6ULL(十九) linux gpio子系统
江太翁
博客等级 码龄15年 271粉丝 141原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值