痞子衡嵌入式:聊聊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主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。
最后欢迎关注痞子衡个人微信公众号【痞子衡嵌入式】,一个专注嵌入式技术的公众号,跟着痞子衡一起玩转嵌入式。
衡杰(痞子衡),目前就职于某全球顶级半导体原厂MCU系统部门,担任高级嵌入式系统应用工程师。
专栏内所有文章的转载请注明出处:http://www.cnblogs.com/henjay724/
与痞子衡进一步交流或咨询业务合作请发邮件至 hengjie1989@foxmail.com
可以关注痞子衡的Github主页 https://github.com/JayHeng,有很多好玩的嵌入式项目。
关于专栏文章有任何疑问请直接在博客下面留言,痞子衡会及时回复免费(划重点)答疑。
痞子衡邮箱已被私信挤爆,技术问题不推荐私信,坚持私信请先扫码付款(5元起步)再发。