当前位置:   article > 正文

NXP i.MX6 GPIO原理解析及引脚复用_nxp芯片引脚如何配置

nxp芯片引脚如何配置

项目场景:

在眺望电子TW-IMX6DL-EVM开发板上复用GPIO引脚,并分享其原理。

编译环境及开发包: 主机:ubuntu18.04
交叉编译器:arm-linux-gnueabihf-gcc
开发板:TW-IMX6DL-EVM
Linux:Linux-4.1.15

注意:本文章的所有命令涉及到的路径均为眺望电子官方环境路径,需根据自身实际环境改变。本文所演示的平台来自于眺望电子 iMX6 ARM嵌入式平台,这是一个基于NXP iMX6 ARM处理器,支持单核/双核Cortex-A9的核心板。


解决方案:

1、GPIO操作原理

1.1 GPIO寄存器

每一个GPIO有8个寄存器需要配置,每一个GPIO寄存器功能如下:
GPIO_DR(Data Register)数据寄存器
  当GDIR设置为输出时,写DR的内容用来驱动GPIO的引脚,读DR的内容则返回存储在DR中的值。
  当GDIR设置为输入时,读DR返回给定IO 引脚的状态(PSR data),而不是DR data。
  
GPIO_GDIR(Data Direction Register)方向控制寄存器
  控制GPIO引脚的方向,1作为输出,0作为输入,寄存器中的每一位标识一个特定pad的方向。
  仅当相应的引脚被设置为GPIO,GDIR才起作用。
  
GPIO_PSR(pad status register)状态寄存器
  32-bit的只读寄存器。寄存器中的每一位都存储相应pad的值。
  
GPIO_ICR1,ICR2中断控制寄存器
   两个32-bit寄存器,寄存器中每两位控制一条中断线,ICR1控制中断0~15,ICR2控制中断16~31。其可设置的值为:

  • 00中断是低电平触发触发
  • 01中断是高电平触发
  • 10中断是上升沿触发
  • 11中断时下降沿触发

IMR(Interrupt Mask Register)中断屏蔽寄存器
  32-bit寄存器,每一位是相应中断线的屏蔽位, 0中断被屏蔽,1中断被使能。
  
GPIO_ ISR(Interrupt Status Register)中断状态寄存器
  32bit register,每一位用于指定对应的中断线是否有中断发生,当一个中断发生,这个寄存器中的相应位被设置为1。
  
GPIO_EDGE_SEL(Edge Select Register)
  32bit 寄存器,覆盖ICR寄存器的配置,选择edge 作为中断触发的条件。

1.2 IO功能操作

从引脚读取数据:
配置IOMUX选择GPIO模式;
配置GPIO的GPDR为输入;
从PSR寄存器读取数据(也可以从DR读取,此时会返回PSR内的值);

写数据到引脚:
配置IOMUX选择GPIO模式;
配置GPIO的GPDR为输出;
写值到Data Register(DR);

中断控制:
  除了通用的input/output功能外,GPIO内部的edge-detect逻辑反映一个被配置为input的pad是否发生了状态转换。

2.内核GPIO操作

设备树imx6qdl-sabresd.dtsi是TW-AC6-EVM设备的配置文件。其中GPIO的配置在pinctrl_hog:hoggrp标签下。
程序清单1 引脚复用为gpio功能
目录:arch/arm/boot/dts/imx6qdl-sabresd.dtsi

&iomuxc {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_hog>;

	imx6qdl-sabresd {
		pinctrl_hog: hoggrp {
			fsl,pins = <
			
				MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
				MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
				MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
				MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
				MX6QDL_PAD_GPIO_0__CCM_CLKO1    0x130b0
				MX6QDL_PAD_EIM_D22__GPIO3_IO22  0x80000000
				MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x80000000
				MX6QDL_PAD_EIM_CS1__GPIO2_IO24 0x80000000
				MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000
				MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
				MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x80000000
				MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x80000000
				MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x80000000
				MX6QDL_PAD_SD3_RST__GPIO7_IO08	0x80000000
				MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000
				MX6QDL_PAD_NANDF_CS0__GPIO6_IO11 0x80000000
				MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x80000000
				MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x80000000
				MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000
				
				MX6QDL_PAD_GPIO_4__GPIO1_IO04  0x80000000 
			>;
		};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

程序清单1中的MX6QDL_PAD类型宏定义在arch/arm/boot/dts/imx6q-pinfunc.h文件中。

#define MX6QDL_PAD_EIM_D16__GPIO3_IO16              0x090 0x3a4 0x000 0x5 0x0
  • 1

宏的各项含义为:

0x090        IOMUXC_SW_MUX_CTL_PAD_EIM_DATA16    mux寄存器偏移地址
0x3a4         IOMUXC_SW_PAD_CTL_PAD_EIM_DATA16    pad寄存器偏移地址
0x000                                            input寄存器偏移地址
0x5          ALT5 — Select signal GPIO3_IO16.    mux的模式
0x0                                              input类型
0x80000000   IOMUXC_SW_MUX_CTL_PAD_EIM_DATA16的值 设置为芯片默认
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

之后会在内核初始化时调用drivers/pinctrl/pinctrl-imx.c中imx_pinctrl_parse_groups函数读取fsl.pin属性值,并保存在lisk指针变量中,紧接着,分别读取list中的值mux_reg、conf_reg、input_reg的值并设置为mux_mode、config、input_val。更多关于设备树gpio的配置资料,请阅读Documentation/devicetree/bindings/pinctrl/fsl,imx-pinctrl.txt。

若是在文件系统中GPIO的value一直为0,则需要在arch/arm/boot/dts/imx6q-pinfunc.h文件中修改MX6QDL_PAD_EIM_D16__GPIO3_IO16的值,在上一节可知可以通过修改引脚功能寄存器IOMUXC_SW_MUX的SION位为1设置为软件强行配置模式。修改结果如下:

#define MX6QDL_PAD_EIM_D16__GPIO3_IO16 0x144 0x514 0x000 0x15 0x0
  • 1

3.示例

3.1CAN1总线引脚复用为GPIO

打开“IMX6DQRM.pdf”数据手册的“26.2 External Signals”章节可以看到CAN总线I/O信号.

打开imx6qdl-sabresd.dtsi内核设备树文件,搜索can1可以得到如程序清单2的内容:
程序清单2 can1相关代码
目录:arch/arm/boot/dts/imx6qdl-sabresd.dtsi

&can1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_flexcan1>;
	status = "okay"; 
};
		pinctrl_flexcan1: flexcan1grp {
			fsl,pins = <
				MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX        0x17059
				MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX		0x17059
			>;
		};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

把程序清单2的内容中的两个引脚(即fsl,pins下的两个引脚)删除掉或者注释,以防重复使用该引脚。
注:引脚复用的原则是:在设备树中添加想要实现的该引脚的功能,需要把以前的复用功能去掉,无复用功能直接添加即可。

从程序清单2中可以得到can1读引脚使用图1的I/O信号是KEY_ROW2。KEY_ROW2是一个引脚独一无二的标志,由此判断设备树中的引脚是否为同一引脚。
  在imx6q-pinfunc.h头文件中搜索KEY_ROW2,可以得到如程序清单3内容:

程序清单3 KEY_ROW2引脚复用
目录:arch/arm/boot/dts/imx6q-pinfunc.h

#define MX6QDL_PAD_KEY_ROW2__ECSPI1_SS2             0x20c 0x5dc 0x808 0x0 0x1
#define MX6QDL_PAD_KEY_ROW2__ENET_TX_DATA2          0x20c 0x5dc 0x000 0x1 0x0
#define MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX            0x20c 0x5dc 0x7e4 0x2 0x0
#define MX6QDL_PAD_KEY_ROW2__KEY_ROW2               0x20c 0x5dc 0x000 0x3 0x0
#define MX6QDL_PAD_KEY_ROW2__SD2_VSELECT            0x20c 0x5dc 0x000 0x4 0x0
#define MX6QDL_PAD_KEY_ROW2__GPIO4_IO11             0x20c 0x5dc 0x000 0x5 0x0
#define MX6QDL_PAD_KEY_ROW2__HDMI_TX_CEC_LINE       0x20c 0x5dc 0x88c 0x6 0x1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

可以看到引脚KEY_ROW2除了可以复用FLEXCAN1_RX还可以复用为GPIO4_IO11功能。一般可以从引脚的命名后缀可以看出该引脚的作用,如MX6QDL_PAD_KEY_ROW2__FLEXCAN1_RX该引脚复用为can读引脚,MX6QDL_PAD_KEY_ROW2__GPIO4_IO11该引脚复用为GPIO。
  在imx6qdl-sabresd.dtsi设备树文件的pinctrl_hog: hoggrp标签下添加GPIO引脚复用:
程序清单4 KEY_ROW2引脚复用成GPIO
目录:arch/arm/boot/dts/imx6qdl-sabresd.dtsi

&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;

imx6qdl-sabresd {	
pinctrl_hog: hoggrp {
fsl,pins = <
...
MX6QDL_PAD_KEY_ROW2__GPIO4_IO11 0x80000000 /* 引脚KEY_ROW2复用为GPIO4_IO11 */
>;
}; 
...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

复用成gpio,后面的config值默认是0x80000000,为快速配置,如果复用成其它功能相关的值可以参考设备树中默认配置的值,如串口uart配置的值为0x1b0b1

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/744510
推荐阅读
相关标签
  

闽ICP备14008679号