• 痞子衡嵌入式:聊聊i.MXRT1xxx上的普通GPIO与高速GPIO差异及其用法



      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT上的普通GPIO与高速GPIO差异

      GPIO 可以说是 MCU 上最简单最常用的外设模块了,当一些原生功能外设接口模块不能满足项目设计要求时,我们常常会考虑使用 GPIO 来软件模拟实现相应功能,这时候 GPIO 本身性能就显得至关重要了。

      在早期的 i.MXRT1015/1020/1024/1050 型号上,GPIO 都是普通性能(注意这里的普通其实相比一般低端 MCU 来说已经够性能优越了),考虑到 i.MXRT 是性能怪兽,需要配置更强的 GPIO,因此在后续的 i.MXRT1010/1060/1064/1160/1170 型号上,出现了 HSGPIO,今天痞子衡就跟大家聊一聊 GPIO 和 HSGPIO差异:

    一、HSGPIO是什么?

      HSGPIO 是 High-Speed GPIO 缩写,有时候也叫紧耦合 GPIO 或者单时钟周期 GPIO,简单说就是其模块(IP)时钟源速度高于普通 GPIO 时钟源,因此我们可以以更高频率访问其模块寄存器。下表列出了 i.MXRT 各型号上 HSGPIO 分布:

    型号 普通GPIO 高速GPIO
    i.MXRT1010 GPIO1、GPIO5 GPIO2
    i.MXRT1060/1064 GPIO1 - GPIO5 GPIO6 - GPIO9
    i.MXRT1160/1170 GPIO1 - GPIO13 CM7_GPIO2、CM7_GPIO3

      我们以 i.MXRT1060 为例,翻看其参考手册 CCM 时钟模块章节,可以看到普通 GPIO1-5 的时钟源是 IPG_CLK_ROOT、而高速 GPIO6-9 的时钟源则是 AHB_CLK_ROOT:

      在 i.MXRT1060 上 IPG_CLK_ROOT 最高频率是 150MHz、而 AHB_CLK_ROOT 即内核频率,可到 600MHz,所以单从时钟源角度来看,HSGPIO 访问性能应是 GPIO 的 "四倍"(这里打了个引号,实际芯片设计时,HSGPIO 总线访问有延迟,做不到跟 AHB 总线同频):

      下图是 i.MXRT1060 内核结构框图,可以看到其实 HSGPIO 与 AHBP 总线之间经过了 Split 和 AIPS-Lite 两级处理,所以 HSGPIO 最终访问频率并不等于 AHBP 总线频率,只是时钟源来自于 AHBP 总线。

    • Note1: i.MXRT1170 内核结构里 HSGPIO 也是一样会经过 Split 和 AIPS-Lite 两级处理。
    • Note2: i.MXRT1010 内核结构里 HSGPIO 做过了优化,仅 Split 一级处理。

    二、共享 PAD 设计

      从芯片内部来说,GPIO 与 HSGPIO 模块是独立的,但是因为芯片外部引脚(PAD)资源有限,因此部分 HSGPIO 是与 GPIO 模块共享 PAD 的,最终 I/O 实际性能其实受限于同一个物理 PAD 特性。

      我们以封装最简单的 i.MXRT1010 为例,下图最左侧列出了全部的 PAD,其中 GPIO_SD[13:0] 是 HSGPIO 专用引脚,而 GPIO[13:0]、GPIO_AD[14:0] 则是 GPIO 与 HSGPIO 复用引脚,当这些 GPIO/HSGPIO 复用引脚被配置为 GPIO 功能时,它们既可以映射到 GPIO1(普通GPIO),也可以映射到 GPIO2(HSGPIO):

    • Note:如果已经将 GPIO_SD[13:0] 配置为了 GPIO2,则不要再将 GPIO[13:0] 配置为 HSGPIO,会发生冲突。

      具体 GPIO 映射功能是由 IOMUXC_GPR26 寄存器来控制的(注意这是个软复位不置位的寄存器)。比如当 GPIO_11 被配置为了 GPIOMUX_IO11 功能时,那么 IOMUXC_GPR26[11] 决定了其映射关系:

    IOMUXC_GPR26[11] = 0,则 GPIO_11 对应 GPIO1[11],为普通 GPIO  
    IOMUXC_GPR26[11] = 1,则 GPIO_11 对应 GPIO2[11],为 HSGPIO  
    

      下表列出了 i.MXRT 各型号上 GPIO/HSGPIO 切换控制关系:

    型号 PAD切换控制寄存器 ALT功能名 对应切换GPIO
    i.MXRT1010 IOMUXC_GPR->GPR26 GPIO_MUX GPIO1与GPIO2
    i.MXRT1060/1064 IOMUXC_GPR->GPR26
    IOMUXC_GPR->GPR27
    IOMUXC_GPR->GPR28
    IOMUXC_GPR->GPR29
    GPIO_MUX1
    GPIO_MUX2
    GPIO_MUX3
    GPIO_MUX4
    GPIO1与GPIO6
    GPIO2与GPIO7
    GPIO3与GPIO8
    GPIO4与GPIO9
    i.MXRT1160/1170 IOMUXC_GPR->GPR40、41
    IOMUXC_GPR->GPR42、43
    GPIO_MUX2
    GPIO_MUX3
    GPIO2与CM7_GPIO2
    GPIO3与CM7_GPIO3

    三、PAD 运行速度

      前面讲了,不管是使能了普通 GPIO 还是 HSGPIO,最终都是由同一个物理 PAD 来输出信号,因此 I/O 实际性能最终受限于这个 PAD 最大运行速度。

      继续以 i.MXRT1010 为例,每个 PAD 在 IOMUXC 模块里都有一个专门配置电气属性的寄存器 IOMUXC_SW_PAD_CTL_PAD_xxIO,选取 GPIO_11 的相应配置寄存器为例,组合其中 SRE、DSE、SPEED 位可以得到不同运行速度(具体组合值可在参考手册 GPIO 章节搜索 Operating Frequency 小节查看),不过我们能看到 PAD 最大运行速度是 200MHz:

      在 i.MXRT1010 数据手册里,我们还可以看到更具体的 I/O 翻转时间测试:

    四、HSGPIO 示例代码

      基于上面的理论知识,我们改造一下 i.MXRT1010 SDK 里的 \driver_examples\gpio\led_output 例程,加入如下 HSGPIO 相关代码,同样可以达到闪烁 LED 灯的功能。

      介绍了这么多,如果只是用 HSGPIO 控制小灯闪烁,似乎看不出性能差异,下一篇文章,痞子衡将用示波器为大家实测 GPIO 与 HSGPIO 极限翻转频率,再提前剧透一下,GPIO->DR_TOGGLE 和 GPIO->DR 寄存器实现 I/O 翻转效率还不一样哦。

    bool is_normal_gpio = false;
    
    int main(void)
    {
        BOARD_ConfigMPU();
        BOARD_InitBootClocks();
    
        /* Define the init structure for the output LED pin*/
        gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
    
        CLOCK_EnableClock(kCLOCK_Iomuxc);      
        IOMUXC_SetPinMux(IOMUXC_GPIO_11_GPIOMUX_IO11, 0U); 
        if (is_normal_gpio)
        {
            // GPIO1
            IOMUXC_GPR->GPR26 &= ~(1u << 11);
            // Slow Slew Rate, 100MHz
            IOMUXC_SetPinConfig(IOMUXC_GPIO_11_GPIOMUX_IO11, 0x70A0U);
            GPIO_PinInit(GPIO1, 11, &led_config);
        }
        else
        {
            // GPIO2
            IOMUXC_GPR->GPR26 |= (1u << 11);
            // Fast Slew Rate, 200MHz
            IOMUXC_SetPinConfig(IOMUXC_GPIO_11_GPIOMUX_IO11, 0x70F9U);
            GPIO_PinInit(GPIO2, 11, &led_config);
        }
    
        while (1)
        {
            SDK_DelayAtLeastUs(100000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
    
            if (is_normal_gpio)
            {
                //GPIO1->DR_TOGGLE = (1u << 11);
                GPIO1->DR ^= (1u << 11);
                __DSB();
            }
            else
            {
                //GPIO2->DR_TOGGLE = (1u << 11);
                GPIO2->DR ^= (1u << 11);
                __DSB();
            }
        }
    }
    

      至此,i.MXRT上的普通GPIO与高速GPIO差异痞子衡便介绍完毕了,掌声在哪里~~~

    欢迎订阅

    文章会同时发布到我的 博客园主页CSDN主页知乎主页微信公众号 平台上。

    微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

      最后欢迎关注痞子衡个人微信公众号【痞子衡嵌入式】,一个专注嵌入式技术的公众号,跟着痞子衡一起玩转嵌入式。

    痞子衡嵌入式-微信二维码 痞子衡嵌入式-微信收款二维码 痞子衡嵌入式-支付宝收款二维码

      衡杰(痞子衡),目前就职于恩智浦MCU系统部门,担任嵌入式系统应用工程师。

      专栏内所有文章的转载请注明出处:http://www.cnblogs.com/henjay724/

      与痞子衡进一步交流或咨询业务合作请发邮件至 hengjie1989@foxmail.com

      可以关注痞子衡的Github主页 https://github.com/JayHeng,有很多好玩的嵌入式项目。

      关于专栏文章有任何疑问请直接在博客下面留言,痞子衡会及时回复免费(划重点)答疑。

      痞子衡邮箱已被私信挤爆,技术问题不推荐私信,坚持私信请先扫码付款(5元起步)再发。


  • 相关阅读:
    Iptables 之二扩展模块 nat
    sudo 命令
    7、CentOS6 编译安装
    MySQL5.7 基础之二 DCL DML
    SQL Server 2008R2安装
    6、httpd2.4 编译安装LAMP
    MySQL 基础之一
    gulp
    msbuild
    inno setup
  • 原文地址:https://www.cnblogs.com/henjay724/p/15518705.html
Copyright © 2020-2023  润新知