i.MX RT1170双核下不同GPIO组的访问以及中断设计

cathy的头像

在双核的i.MX RT1170下设计应用程序,有一个比较重要的考虑点是片内外设资源共享以及任务分配问题,同样一个任务既可以放在默认主核CM7下做,也可以放在默认从核 CM4下去完成。如果这个任务跟片内外设有关,那就得考虑该外设是否在两个核下设计与使用一致,这在项目开始前必须要调研清楚。

今天就和大家聊一聊i.MX RT1170的GPIO外设的使用,在两个核下有什么异同以及注意点。

在正文开始之前,建议大家先浏览一下我之前写的关于GPIO的两篇文章:《以i.MX RT1xxx的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程》《聊聊i.MX RT1xxx上的普通GPIO与高速GPIO差异及其用法》

注:本文内容虽以i.MX RT1170为例,但同样适用i.MX RT1160。

一、从引脚看GPIO分组

先聊聊GPIO分组,目前 i.MX RT1170 芯片封装主要是BGA289,除去电源、地、时钟、专用外设引脚外,可用作通用I/O的引脚剩下174个,而芯片内部GPIO模块多达 16个(GPIO1-13、CM7_GPIO2-3),显然GPIO模块太富裕了,显得硬件I/O引脚资源有点紧张,所以不可避免地多个GPIO 模块要复用硬件 I/O引脚,复用关系如下:

  • GPIO1与GPIO7复用同一组I/O引脚,共32个pin。
  • GPIO2与GPIO8以及CM7_GPIO2复用同一组I/O引脚,共32个pin。
  • GPIO3与GPIO9以及CM7_GPIO3复用同一组I/O引脚,共32个pin。
  • GPIO4与GPIO10复用同一组I/O引脚,共32个pin。
  • GPIO5与GPIO11复用同一组I/O引脚,共17个pin。
  • GPIO6与GPIO12复用同一组I/O引脚,共16 个pin。
  • GPIO13独享一组I/O引脚,共13个pin。

下图是i.MX RT1170 GPIO相关的Pinmux表,其中GPIO1-6、GPIO13主要在Alt5选项里,GPIO7-12主要在 Alt10 选项里,并且大部分I/O引脚默认功能就是GPIO(见表中 DEF 一栏)。此外表中并未看到CM7_GPIO2-3选项,这是因为其和GPIO2-3共用了 Alt5选项(需进一步通过IOMUXC_GPR->GPR40-43寄存器设置)。

“i.MX

二、关于GPIO外设访问

知道了GPIO分组以及I/O引脚复用情况,那么这些GPIO模块是否可以被i.MX RT1170 两个核(CM7/CM4)对等访问呢?我们用官方例程 \SDK_2.11.1_MIMXRT1170-EVK\boards\evkmimxrt1170\driver_examples\gpio\led_output 来做测试,这个例程操作的是 MIMXRT1170-EVK 板卡上用于连接 LED 灯的引脚 GPIO_AD_04,从上一节里我们得知这个 I/O 引脚可被用作 GPIO3[3]、CM7_GPIO3[3]、GPIO9[3],因此我们编写了如下三个相应的 gpio 翻转测试函数:)。

gpio_pin_config_t s_ledConfig = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};

void toggle_gpio3_3(void)
{
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_04_GPIO_MUX3_IO03, 0U);
    IOMUXC_GPR->GPR42 &= ~(1u << 3);
    GPIO_PinInit(GPIO3, 3, &s_ledConfig);
    while(1)
    {
        SDK_DelayAtLeastUs(100000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
        GPIO_PortToggle(GPIO3, 1u << 3);
    }
}

void toggle_cm7_gpio3_3(void)
{
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_04_GPIO_MUX3_IO03, 0U);
    IOMUXC_GPR->GPR42 |= (1u << 3);
    GPIO_PinInit(CM7_GPIO3, 3, &s_ledConfig);
    while(1)
    {
        SDK_DelayAtLeastUs(100000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
        GPIO_PortToggle(CM7_GPIO3, 1u << 3);
    }
}

void toggle_gpio9_3(void)
{
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_04_GPIO9_IO03, 0U);
    GPIO_PinInit(GPIO9, 3, &s_ledConfig);
    while(1)
    {
        SDK_DelayAtLeastUs(100000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
        GPIO_PortToggle(GPIO9, 1u << 3);
    }
}

我们把上面三个函数分别加到两个核下的 led_output 工程主函数里,并且在板卡上实测,结果如下表。

据此进一步扩展结论,除了 CM7_GPIO2-3 无法在 CM4 内核下被访问外,其余 GPIO1-13 在两个核下都能被正常访问。

注:在 CM4 系统地址映射里,CM7_GPIO2_BASE 0x42008000u、CM7_GPIO3_BASE 0x4200C000u 地址都是不可访问状态。

“i.MX

三、关于GPIO中断设计

除了 GPIO 外设一般寄存器访问之外,GPIO 中断方面是不是在 i.MX RT1170 两个核(CM7/CM4)下设计也一致呢?这得对比 MIMXRT1176_cm7.h 和 MIMXRT1176_cm4.h 头文件里关于 IRQn_Type 的定义,我将相同项去掉了,只保留差异项的定义对比如下(GPIO 相关的全部保留了):

“i.MX

大部分外设中断号定义在两个核下都是一致的,这意味着 i.MX RT1170 两个核设计上其实是对等关系。但是 GPIO 中断这里确实是有不小的区别的:

  • GPIO1-5、GPIO13 中断在两个核下定义一致
  • GPIO6、CM7_GPIO2-3 中断仅在 CM7 核下有定义
  • GPIO7-12 中断仅在 CM4 核下有定义

继续以上一节操作的 MIMXRT1170-EVK 板卡上用于连接 LED 灯的引脚 GPIO_AD_04 为例测试其中断情况,编写了相关中断配置使能函数如下:

gpio_pin_config_t s_ledConfig = {kGPIO_DigitalInput, 0, kGPIO_IntRisingEdge};

void GPIO3_Combined_0_15_IRQHandler(void)
{
    GPIO_PortClearInterruptFlags(GPIO3, 1U << 3);
    SDK_ISR_EXIT_BARRIER;
}

void config_irq_gpio3_3(void)
{
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_04_GPIO_MUX3_IO03, 0U);
    IOMUXC_GPR->GPR42 &= ~(1u << 3);
    NVIC_EnableIRQ(GPIO3_Combined_0_15_IRQn);
    GPIO_PinInit(GPIO3, 3, &s_ledConfig);
    GPIO_PortEnableInterrupts(GPIO3, 1U << 3);
}

void CM7_GPIO2_3_IRQHandler(void)
{
    GPIO_PortClearInterruptFlags(CM7_GPIO3, 1U << 3);
    SDK_ISR_EXIT_BARRIER;
}

void config_irq_cm7_gpio3_3(void)
{
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_04_GPIO_MUX3_IO03, 0U);
    IOMUXC_GPR->GPR42 |= (1u << 3);
    NVIC_EnableIRQ(CM7_GPIO2_3_IRQn);
    GPIO_PinInit(CM7_GPIO3, 3, &s_ledConfig);
    GPIO_PortEnableInterrupts(CM7_GPIO3, 1U << 3);
}

void GPIO7_8_9_10_11_IRQHandler(void)
{
    GPIO_PortClearInterruptFlags(GPIO9, 1U << 3);
    SDK_ISR_EXIT_BARRIER;
}

void config_irq_gpio9_3(void)
{
    CLOCK_EnableClock(kCLOCK_Iomuxc);
    IOMUXC_SetPinMux(IOMUXC_GPIO_AD_04_GPIO9_IO03, 0U);
    NVIC_EnableIRQ(GPIO7_8_9_10_11_IRQn);
    GPIO_PinInit(GPIO9, 3, &s_ledConfig);
    GPIO_PortEnableInterrupts(GPIO9, 1U << 3);
}

我们把上面三个 config 函数分别加到两个核下的 led_output 工程主函数里,并且在板卡上实测,可以使用外部高电平强加到 GPIO_AD_04 引脚(R1855 电阻一端),然后再移除高电平以造出输入电平翻转,测试结果如下表。据此进一步扩展结论,如果希望双核下得到一致的 GPIO 使用体验,建议选择 GPIO1-5、GPIO13。

“i.MX

来源:恩智浦MCU加油站
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理(联系邮箱:cathy@eetrend.com)。