signed

QiShunwang

“诚信为本、客户至上”

正点原子-Linux资料学习笔记-裸机开发-3

2021/5/14 22:13:50   来源:

1.汇编LED灯实验

   1)I.MX6U GPIO详解

        1、I.MX6U IO命名

              参考手册中的形如“IOMUXC_SW_MUC_CTL_PAD_GPIO1_IO00”的就是 GPIO 命名,命

              名形式就是“IOMUXC_SW_MUC_CTL_PAD_XX_XX”,后面的“XX_XX”就是 GPIO 命名,

              比如:GPIO1_IO01、UART1_TX_DATA、JTAG_MOD、SNVS_TAMPER1 等等。

              I.MX6U 的 GPIO并不像 STM32 一样以 PA0~15 这样命名,他是根据某个 IO 所拥有的功能来命名的

              比如我们一看到 GPIO1_IO01 就知道这个肯定能做 GPIO,看到 UART1_TX_DATA 肯定就知道这个 IO

              肯定能做为 UART1 的发送引脚。

             “Chapter 30: IOMUX Controller(IOMUXC)”这一章列出了I.MX6U 的 所 有 IO , 如果你找遍第30章的书 签 ,

              你会发现貌似GPIO只有GPIO1_IO00~GPIO1_IO09,难道 I.MX6U的GPIO 只有这10个?显然不是的,

             我们知道STM32的很多 IO 是可以复用为其它功能的,那么 I.MX6U 的其它 IO 也是可以复用为 GPIO 功能。

             同样的,GPIO1_IO00~GPIO_IO09也是可以复用为其它外设引脚的。

        2、I.MX6U IO复用

              以 IO“IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00”为例,打开参考手册的 1329 页,如图1所示:

                                                                              图1  GPIO1_IO00 复用

            从图 8.1.3.1 可以看到有个名为:IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00 的寄存器,寄存器地址为 0X020E005C,

           这个寄存器是 32 位的,但是只用到了最低 5 位,其中bit0~bit3(MUX_MODE)就是设置 GPIO1_IO00 的复用功能的。

           GPIO1_IO00 一共可以复用为9种功能 IO,分别对应 ALT0~ALT8,其中 ALT5 就是作为 GPIO1_IO00。GPIO1_IO00 还可以作

           为 I2C2_SCL、GPT1_CAPTURE1、ANATOP_OTG1_ID 等。这个就是 I.MX6U 的 IO 复用。

           再来看一个“IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA”这个 IO,这个 IO 对应的复用如图2所示:

                                                           图2 UART1_TX_DATA IO 复用 

              同样的,从图 8.1.3.2 可以看出,UART1_TX_DATA 可以复用为 8 种不同功能的 IO,分为ALT0~ALT5 和 ALT8、ATL9,

              其中 ALT5 表示 UART1_TX_DATA 可以复用为 GPIO1_IO16。

              由此可见,I.MX6U 的 GPIO 不止 GPIO1_IO00~GPIO1_IO09 这 10 个,其它的 IO 都可以复用为 GPIO 来使用。

              I.MX6U 的 GPIO 一共有 5 组GPIO1、GPIO2、GPIO3、GPIO4 和 GPIO5其中 GPIO1 有 32 个 IO,GPIO2 有 22 个 IO,

              GPIO3 有 29 个 IO、GPIO4 有 29 个 IO,GPIO5最少,只有 12 个 IO,这样一共有 124 个 GPIO。

          3、I.MX6U IO 配置

                细心的读者应该会发现在《I.MX6UL 参考手册》第 30 章“Chapter 30: IOMUXController(IOMUXC)”的书签中,每一个 IO 会出现两次,

                它们的名字差别很小,不仔细看就看不出来,比如 GPIO1_IO00 有如下两个书签,如图3所示:

                                                                                        图3 2个不同的定义

               上面两个都是跟 GPIO_IO00 有关的寄存器,名字上的区别就是红色部分,一个是“MUX”,一个是“PAD”。

                IOMUX_SW_MUX_CTL_PAD_GPIO1_IO00 我们前面已经说了,是用来配置GPIO1_IO00 复用功能的,

                那么 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 是做什么的呢?找到这个书签对应的 1582 页,如图4 所示:

                                                                              图4 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 寄存器 

                  从图4中可以看出,IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 也是个寄存器,寄存器地址为 0X020E02E8。

                 这也是个 32 位寄存器,但是只用到了其中的低 17 位,在看这写位的具体含义之前,先来看一下图5所示的 GPIO 功能图:

                                                                                  图5 GPIO 功能图

                   我们对照着图4来详细看一下寄存器 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO00 的各个位的含义:

                   HYS(bit16):对应图4中 HYS,用来使能迟滞比较器,当 IO 作为输入功能的时候有效,用于设置输入接收器的施密特触发器是否使能。

                                        如果需要对输入波形进行整形的话可以使能此位。此位为0的时候禁止迟滞比较器为1的时候使能迟滞比较器

                  PUS(bit15:14) :对应图4中的PUS,用来设置上下拉电阻的,一共有四种选项可以选择,如图6所示:

                                                                 图6 上下拉设置

                PUE(bit13) :图4没有给出来,当 IO 作为输入的时候,这个位用来设置 IO 使用上下拉还是状态保持器。

                                      当为0的时候使用状态保持器,当为1的时候使用上下拉。状态保持器在IO 作为输入的时候才有用,顾名思义,

                                      就是当外部电路断电以后此 IO 口可以保持住以前的状态。

                PKE(bit12) :对应图5中的 PKE,此为用来使能或者禁止上下拉/状态保持器功能,为0时禁止上下拉/状态保持器为 1 时使能上下拉和状态保持器

                ODE(bit11):对应图5中的ODE,当 IO 作为输出的时候,此位用来禁止或者使能开路输出,此位为0的时候禁止开路输出,当此位为1的时候就使能开路输出功能

                       SPEED(bit7:6) :对应图5中的SPEED,当 IO 用作输出的时候,此位用来设置 IO 速度,设置如图7所示:

                                                                  图7 速度配置 

                DSE(bit5:3):对应图5中的 DSE,当 IO 用作输出的时候用来设置 IO 的驱动能力,总共有 8 个可选选项,如图8所示:

                                                              图8 驱动能力设置

               SRE(bit0) :对应图5中的 SRE,设置压摆率,当此位为0的时候是低压摆率,当为1的时候是高压摆率

                                   这里的压摆率就是 IO 电平跳变所需要的时间,比如从 0 到 1 需要多少时间,时间越小波形就越陡,

                                   说明压摆率越高;反之,时间越多波形就越缓,压摆率就越低。如果你的产品要过 EMC 的话那就可以使用小的压摆率,

                                   因为波形缓和,如果你当前所使用的 IO做高速通信的话就可以使用高压摆率。

         4、I.MX6U GPIO 配置

                     将其复用为 GPIO 以后还需要对其 GPIO 的功能进行配置,关于 I.MX6U 的 GPIO 请参考《IMX6UL 参考手册》

                     的第26章“Chapter 26 General Purpose Input/Ouput(GPIO)”,GPIO 结构如图9所示:

                                                             图9 GPIO 结构图

                在图9的 左 下 角 的 IOMUXC 框 图 里 面 就 有 SW_MUX_CTL_PAD_* 和SW_PAD_CTL_PAD_*两种寄存器。

               这两种寄存器前面说了用来设置 IO 的复用功能和 IO 属性配置。左上角部分的 GPIO 框图就是,当 IO 用作 GPIO 的时候需要设置的寄存器,

                一共有八个:DR、GDIR、PSR、ICR1、ICR2、EDGE_SEL、IMR 和 ISR。

               前面我们说了 I.MX6U 一共有GPIO1~GPIO5 共五组 GPIO,每组 GPIO 都有这 8 个寄存器。我们来看一下这 8 个寄存器都是什么含义。

               1.DR寄存器

                   首先来看一下 DR 寄存器,此寄存器是数据寄存器,结构图如图10所示:

                                                                                      图10 DR 寄存器结构图 

                    此寄存器是 32 位的,一个 GPIO组最大只有 32 个 IO,因此 DR 寄存器中的每个位都对应一个GPIO

                    当 GPIO 被配置为输出功能以后,向指定的位写入数据那么相应的 IO 就会输出相应的高低电平,

                    比如要设置 GPIO1_IO00 输出高电平,那么就应该设置 GPIO1.DR=1。当 GPIO被配置为输入模式以后,

                    此寄存器就保存着对应IO的电平值,每个位对对应一个 GPIO,例如,当 GPIO1_IO00 这个引脚接地的话,那么 GPIO1.DR 的 bit0 就是 0。

                2.GDIR 寄存器

                    看完 DR 寄存器,接着看 GDIR 寄存器,这是方向寄存器,用来设置某个 GPIO 的工作方向的,即输入/输出,GDIR 寄存器结构如图11所示:

                                                                                图11 GDIR 寄存器

                     GDIR 寄存器也是 32 位的,此寄存器用来设置某个 IO 的工作方向,是输入还是输出。同样的,每个 IO 对应一个位,

                     如果要设置 GPIO 为输入的话就设置相应的位为 0,如果要设置为输出的话就设置为 1。比如要设置 GPIO1_IO00 为输入,

                     那么 GPIO1.GDIR=0;

                  3.PSR 寄存器

                     接下来看 PSR 寄存器,这是 GPIO 状态寄存器,如图12所示:

                                                                                   图12 PSR 状态寄存器 

                    同样的 PSR 寄存器也是一个 GPIO 对应一个位,读取相应的位即可获取对应的 GPIO 的状态,也就是 GPIO 的高低电平值。

                    功能和输入状态下的 DR 寄存器一样

                4.ICR1和ICR2 寄存器

                    接下来看ICR1和ICR2这两个寄存器,都是中断控制寄存器ICR1用于配置低16个GPIO,ICR2 用于配置高 16 个 GPIO,ICR1 寄存器如图13所示:

                                                                                   图13 ICR1 寄存器

                     ICR1 用于 IO0~15 的配置, ICR2 用于 IO16~31 的配置。ICR1 寄存器中一个 GPIO 用两个位,这两个位用来配置中断的触发方式,

                     和 STM32 的中断很类似,可配置的选项如图14所示:

                                                                        图14 中断触发配置

                    以GPIO1_IO15为例,如果要设置GPIO1_IO15为上升沿触发中断,那么GPIO1.ICR1=2<<30,如果要设置 GPIO1 的 IO16~31 的话

                   就需要设置 ICR2 寄存器了。

               5. IMR 寄存器

                   接下来看 IMR 寄存器,这是中断屏蔽寄存器,如图15所示:

                                                                          图15 IMR 寄存器

                    IMR 寄存器也是一个 GPIO 对应一个位,IMR 寄存器用来控制 GPIO 的中断禁止和使能,如果使能某个 GPIO 的中断,

                   那么设置相应的位为 1 即可,反之,如果要禁止中断,那么就设置相应的位为 0 即可。例如,要使能 GPIO1_IO00 的中断,

                   那么就可以设置 GPIO1.MIR=1 即可。

               6. ISR 寄存器

                   接下来看寄存器 ISR,ISR 是中断状态寄存器,寄存器如图16所示:

                                                                                 图16 ISR 寄存器

                     ISR 寄存器也是 32 位寄存器,一个 GPIO 对应一个位,只要某个 GPIO 的中断发生,那么ISR 中相应的位就会被置 1

                    所以,我们可以通过读取 ISR 寄存器来判断 GPIO 中断是否发生,相当于 ISR 中的这些位就是中断标志位。

                    当我们处理完中断以后,必须清除中断标志位清除方法就是向 ISR 中相应的位写 1,也就是写1清零

                7.  EDGE_SEL 寄存器

                     最后来看一下 EDGE_SEL 寄存器,这是边沿选择寄存器,寄存器如图17所示:

                                                            图17 EDGE_SEL 寄存器

                       EDGE_SEL 寄存器用来设置边沿中断,这个寄存器会覆盖 ICR1 和 ICR2 的设置,同样是一个 GPIO 对应一个位。

                      如果相应的位被置 1,那么就相当于设置了对应的 GPIO 是上升沿和下降沿(双边沿)触发。例如,我们设置 GPIO1.EDGE_SEL=1,

                      那么就表示 GPIO1_IO01 是双边沿触发中断,无论 GFPIO1_CR1 的设置为多少,都是双边沿触发。

          4、I.MX6U GPIO 时钟使能