设为首页 加入收藏

TOP

痞子衡嵌入式:对比恩智浦全系列MCU(包含Kinetis/LPC/i.MXRT/MCX)的GPIO电平中断设计差异(一)
2023-07-23 13:31:12 】 浏览:78
Tags:衡嵌入 浦全系 MCU 包含 Kinetis/LPC/i.MXRT/MCX GPIO 平中断 计差异

  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦全系列MCU(包含Kinetis, LPC, i.MXRT, MCX)的GPIO电平中断设计差异

  在痞子衡旧文 《以i.MXRT1xxx的GPIO模块为例谈谈中断处理函数(IRQHandler)的标准流程》里,痞子衡主要介绍得是 GPIO 一般控制以及最常用的输入边沿中断相关知识。最近恩智浦官方社区有用户反映 i.MXRT1060 上 GPIO 中断状态寄存器(GPIO->ISR)在发生有效电平中断后的置位并不需要手动清零(W1C),其会在 I/O 输入电平状态切换后自动清零,这和手册里描述不一致。

  首先在痞子衡的认知里 GPIO 输入电平中断没有什么具体应用场景,想象一下,如果 GPIO 中断事件由输入电平值来触发,如果发生了有效输入电平且其状态不改变,那么 GPIO 中断响应函数就会被不断重复执行(此时 CPU 时间片无法再分给主函数),什么样的任务需要这样的处理呢?暂且不论应用场景,痞子衡今天就从恩智浦全系列 MCU 这方面的行为角度来做一下对比吧。

一、I/O中断控制模块差异

  恩智浦现有的经典 Arm Cortex-M MCU 产品线共有如下五大类,它们在 GPIO 一般控制和中断控制外设上是有差异的。首先 i.MXRT四位数/Kinetis/LPC 这三条线各自是完全不同的外设,然后 i.MXRT三位数是在 LPC 外设基础上做了增强,而最新的 MCX 系列则是组合了 Kinetis 和 LPC 外设。

芯片系列 I/O一般控制 I/O中断控制
Kinetis GPIO type1 PORT
LPC GPIO type2 PINT
i.MXRT四位数 GPIO type3 GPIO type3
i.MXRT三位数 GPIO type2 GPIO type2(增加interrupt A/B)
PINT
MCX GPIO type1 GPIO type1(集成Kinetis PORT)
PINT

二、不同系列MCU下测试结果

  根据上一节外设情况我们知道,只要测试了 i.MXRT四位数/Kinetis/LPC 这三个系列的情况,剩下两个系列自然也就不用测试了。

2.1 Kinetis

  Kinetis 系列分为 K/KL/KE/KS/KW/KV/KM/K32L 等若干子系列,但是它们关于 GPIO 中断设计这一块是一样的。痞子衡选取了 MKL03Z 这颗芯片来做的测试,查看其手册 PORTx->PCRn[ISF] 位或者 PORTx->ISFR 寄存器均标记了中断状态,并且标明了需要做 W1C 操作。

  我们可以直接在 \SDK_2.3.1_FRDM-KL03Z\boards\frdmkl03z\driver_examples\gpio\input_interrupt 例程上做测试,只需要做简单修改,痞子衡摘取了主要代码如下。FRDM-KL03Z 板上 SW3 按键对应 PTB5 引脚(按下为低电平,松开为高电平),代码设计里按一次 SW3 便打印一次。测试结果来看,在 Kinetis 上即使是电平中断,PORTx->ISFR 寄存器也是必须要手动清零的,与手册描述一致。

IRQ函数中是否清零Flag SW3动作 IRQ执行情况 打印输出结果
上电默认松开(高电平) IRQ函数未触发
SW3按下(低电平) IRQ函数重复执行
SW3松开(高电平) IRQ函数不再触发 出现一次打印
上电默认松开(高电平) IRQ函数未触发
SW3按下(低电平) IRQ函数重复执行
SW3松开(高电平) IRQ函数重复执行
volatile bool g_ButtonPress = false;
void PORTB_IRQHandler(void)
{
    // 清除中断标志
    PORTB->ISFR = 1U << 5U;
    g_ButtonPress = true;
}
int main(void)
{
    // 省略 PTB5 引脚的 PINMUX 配置
    gpio_pin_config_t sw_config = {
        kGPIO_DigitalInput, 0,
    };
    // 仅需此处修改:将 GPIO 中断模式改为低电平触发
    PORT_SetPinInterruptConfig(PORTB, 5U, kPORT_InterruptLogicZero);
    NVIC_EnableIRQ(PORTB_IRQn);
    GPIO_PinInit(GPIOB, 5U, &sw_config);
    while (1)
    {
        if (g_ButtonPress)
        {
            delay();
            PRINTF(" %s is pressed \r\n", "SW3");
            g_ButtonPress = false;
        }
    }
}

2.2 i.MXRT四位数

  i.MXRT四位数系列分为 RT1010/1015/1020/1040/1050/1060/1160/1170/1180 等若干子型号,但是它们关于 GPIO 中断设计是一样的。痞子衡选取了 i.MXRT1062 这颗芯片来做的测试,查看其手册 GPIOx->ISR 寄存器标记了中断状态,同样标明了需要做 W1C 操作。

  我们可以直接在 \SDK_2_12_1_EVK-MIMXRT1060\boards\evkmimxrt1060\driver_examples\gpio\input_interrupt 例程上做测试,只需要做简单修改,主要代码如下。MIMXRT1060-EVK 板上 SW8 按键对应 WAKEUP_GPIO5[0] 引脚(按下为低电平,松开为高电平),代码设计里按一次 SW8 便打印一次。测试结果来看,在 i.MXRT 四位数上如果是电平中断,GPIOx->ISR 寄存器会在电平状态切换时自动清零,跟手册描述有点差异,不过这样的设计比 Kinetis 上看起来更合理。

IRQ函数中是否清零Flag SW8动作 IRQ执行情况 打印输出结果
是/否 上电默认松开(高电平) IRQ函数未触发
SW8按下(低电平) IRQ函数重复执行
SW8松开(高电平) IRQ函数不再触发 出现一次打印
volatile bool g_InputSignal = false;
void GPIO5_Combined_0_15_IRQHandler(void)
{
    // 清除中断标志
    GPIO5->ISR = 1U << 0U;
    g_InputSignal = true;
    __DSB();
}
int main(void)
{
    // 省略 WAKEUP 引脚的 PINMUX 配置
    gpio_pin_config_t sw_config = {
        kGPIO_DigitalInput,
        0,
        kGPIO_IntLowLevel,  // 仅需此处修改:将 GPIO 中断模式改为低电平触发
    };
    GPIO_PortEnableInterrupts(GPIO5, 1U << 0U);
    NVIC_EnableIRQ(GPIO5_Combined_0_15_IRQn);
    GPIO_PinInit(GPIO5, 0U, &sw_config);
    while (1)
    {
        if (g_InputSignal)
        {
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇关于共享资源保护的思考 下一篇UBOOT编译--- UBOOT的编译和链接..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目