痞子衡嵌入式:聊聊i.MXRT1170双核下不同GPIO组的访问以及中断设计


  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是i.MXRT1170双核下不同GPIO组的访问以及中断设计

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

  今天痞子衡和大家聊一聊 i.MXRT1170 的 GPIO 外设使用在两个核下有什么异同以及注意点,在正文开始之前,建议大家先浏览一下痞子衡之前写的关于 GPIO 的两篇文章:《以i.MXRT1xxx的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程》《聊聊i.MXRT1xxx上的普通GPIO与高速GPIO差异及其用法》

  • Note:本文内容虽以 i.MXRT1170 为例,但同样适用 i.MXRT1160。

一、从引脚看GPIO分组

  先聊聊 GPIO 分组,目前 i.MXRT1170 芯片封装主要是 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.MXRT1170 GPIO 相关的 Pinmux 表,其中 GPIO1-6、GPIO13 主要在 Alt5 选项里,GPIO7-12 主要在 Alt10 选项里,并且大部分 I/O 引脚默认功能就是 GPIO(见表中 DEF 一栏)。此外表中并未看到 CM7_GPIO2-3 选项,这是因为其和 GPIO2-3 共用了 Alt5 选项(需进一步通过 IOMUXC_GPR->GPR40-43 寄存器设置)。

二、关于GPIO外设访问

  知道了 GPIO 分组以及 I/O 引脚复用情况,那么这些 GPIO 模块是否可以被 i.MXRT1170 两个核(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 在两个核下都能被正常访问。

  • Note:在 CM4 系统地址映射里,CM7_GPIO2_BASE 0x42008000u、CM7_GPIO3_BASE 0x4200C000u 地址都是不可访问状态。
测试函数 cm7下 cm4下
toggle_gpio3_3 正常工作,LED闪烁 正常工作,LED闪烁
toggle_cm7_gpio3_3 正常工作,LED闪烁 异常跑飞
toggle_gpio9_3 正常工作,LED闪烁 正常工作,LED闪烁

三、关于GPIO中断设计

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

  大部分外设中断号定义在两个核下都是一致的,这意味着 i.MXRT1170 两个核设计上其实是对等关系。但是 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。

测试函数 cm7下 cm4下
config_irq_gpio3_3 中断正常触发 中断正常触发
config_irq_cm7_gpio3_3 中断正常触发 /
config_irq_gpio9_3 / 中断正常触发

  至此,i.MXRT1170双核下不同GPIO组的访问以及中断设计痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

posted @ 2022-08-12 15:37  痞子衡  阅读(709)  评论(0编辑  收藏  举报