大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是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 分组,目前 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 分组以及 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 中断方面是不是在 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主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
作为新的阿里云用户,您可以50免费试用多种优惠,价值高达1,700美元(或8,500美元)。这将让您了解和体验阿里云平台上提供的一系列产品和服务。如果您以个人身份注册免费试用,您将获得价值1,700美元的优惠。但是,如果您是注册公司,您可以选择企业免费试用,提交基本信息通过企业实名注册验证,即可开始价值$8,500的免费试用!本教程介绍了如何设置您的帐户并使用您的免费试用版。关于免费试用在我们开始此试用之前,您还必须遵守以下条款和条件才能访问您的免费试用:只有在一年内创建的账户才有资格获得阿里云免费试用。通过此免费试用优惠,用户可以免费试用免费试用活动页面上列出的每种产品一次。如果您有多个帐
我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.
RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)
A/ctohttp://wiki.nginx.org/CoreModule#usermaster进程曾经以root用户运行,是否可以以不同的用户运行nginxmaster进程? 最佳答案 只需以非root身份运行init脚本(即/etc/init.d/nginxstart),就可以用不同的用户运行nginxmaster进程。如果这真的是你想要做的,你将需要确保日志和pid目录(通常是/var/log/nginx&/var/run/nginx.pid)对该用户是可写的,并且您所有的listen调用都是针对大于1024的端口(因为绑定(
有没有办法在sinatra的beforedoblock中停止执行并返回不同的值?beforedo#codeishere#Iwouldliketo'return"Message"'#Iwouldlike"/home"tonotgetcalled.end//restofthecodeget'/home'doend 最佳答案 beforedohalt401,{'Content-Type'=>'text/plain'},'Message!'end如果你愿意,你可以只指定状态,这里有状态、标题和正文的例子
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使
我的ruby脚本从命令行参数获取某些输入。它检查是否缺少任何命令行参数,然后提示用户输入。但是我无法使用gets从用户那里获得输入。示例代码:test.rbname=""ARGV.eachdo|a|ifa.include?('-n')name=aputs"Argument:#{a}"endendifname==""puts"entername:"name=getsputsnameend运行脚本:rubytest.rbraghav-k错误结果:test.rb:6:in`gets':Nosuchfileordirectory-raghav-k(Errno::ENOENT)fromtes
我从ui中得到日期范围为-approved_between"=>"2013-03-17-2013-03-18"我需要拆分此approved_start_date="2013-03-17"和approved_end_date="2013-03-18"...我希望使用它在mysql中查询,因为mysql中的日期格式是created_at:2012-07-2810:35:01.我正在做的是:approved=approved_between.split("")approved_start_date=approved[0]approved_end_date=approved[2]很确定这不是处