查看: 1288|回复: 2

[分享] i.MX RT1050学习笔记5-中断NVIC

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32003
    最后登录
    2024-4-9
    发表于 2021-3-31 14:53:30 | 显示全部楼层 |阅读模式
    i.MX RT1050学习笔记5-中断NVIC

    1 前言
    中断是一款MCU不可或缺的一部分,而RT1050则是搭载了非常强的中断系统。在这里不得不提一下NVIC(嵌套向量中断控制器),它是内核里面的一个模块,属于Cortex-M7内核,但是RT1050的NVIC其实是Cortex-M7里标准NVIC的阉割版,是一个子集。虽然是阉割版,但是也是非常强大了,其中系统异常有10 个,外部中断有160 个。下面让我们具体介绍一下。

    2 中断号
    CPU 通过中断号来区分不同的中断,每个中断请求拥有一个固定的标号,这个标号就是中断号。RT1050的中断号定义在MIMXRT1052.h文件中,在这里我截取一部分:
    1. typedef enum IRQn {
    2.   /* Auxiliary constants */
    3.   NotAvail_IRQn                = -128,             /**< Not available device specific interrupt */
    4.   /* Core interrupts */
    5.   NonMaskableInt_IRQn          = -14,              /**< Non Maskable Interrupt */
    6.   HardFault_IRQn               = -13,              /**< Cortex-M7 SV Hard Fault Interrupt */
    7.   MemoryManagement_IRQn        = -12,              /**< Cortex-M7 Memory Management Interrupt */
    8.   BusFault_IRQn                = -11,              /**< Cortex-M7 Bus Fault Interrupt */
    9.   UsageFault_IRQn              = -10,              /**< Cortex-M7 Usage Fault Interrupt */
    10.   SVCall_IRQn                  = -5,               /**< Cortex-M7 SV Call Interrupt */
    11.   DebugMonitor_IRQn            = -4,               /**< Cortex-M7 Debug Monitor Interrupt */
    12.   PendSV_IRQn                  = -2,               /**< Cortex-M7 Pend SV Interrupt */
    13.   SysTick_IRQn                 = -1,               /**< Cortex-M7 System Tick Interrupt */
    14.   /* Device specific interrupts */
    15.   DMA0_DMA16_IRQn              = 0,                /**< DMA channel 0/16 transfer complete */
    16.   DMA1_DMA17_IRQn              = 1,                /**< DMA channel 1/17 transfer complete */
    17.   DMA2_DMA18_IRQn              = 2,                /**< DMA channel 2/18 transfer complete */
    18.   DMA3_DMA19_IRQn              = 3,                /**< DMA channel 3/19 transfer complete */
    19. .. .. ..
    20. .. .. ..
    21. .. .. ..
    22.   PWM3_0_IRQn                  = 142,              /**< PWM3 capture 0, compare 0, or reload 0 interrupt */
    23.   PWM3_1_IRQn                  = 143,              /**< PWM3 capture 1, compare 1, or reload 0 interrupt */
    24.   PWM3_2_IRQn                  = 144,              /**< PWM3 capture 2, compare 2, or reload 0 interrupt */
    25.   PWM3_3_IRQn                  = 145,              /**< PWM3 capture 3, compare 3, or reload 0 interrupt */
    26.   PWM3_FAULT_IRQn              = 146,              /**< PWM3 fault or reload error interrupt */
    27.   PWM4_0_IRQn                  = 147,              /**< PWM4 capture 0, compare 0, or reload 0 interrupt */
    28.   PWM4_1_IRQn                  = 148,              /**< PWM4 capture 1, compare 1, or reload 0 interrupt */
    29.   PWM4_2_IRQn                  = 149,              /**< PWM4 capture 2, compare 2, or reload 0 interrupt */
    30.   PWM4_3_IRQn                  = 150,              /**< PWM4 capture 3, compare 3, or reload 0 interrupt */
    31.   PWM4_FAULT_IRQn              = 151               /**< PWM4 fault or reload error interrupt */
    32. } IRQn_Type;
    33. ————————————————
    34. 版权声明:本文为CSDN博主「小猫爪」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    35. 原文链接:https://blog.csdn.net/Oushuwen/article/details/108871928
    复制代码

    从代码中我们可以看到,中断号并不是从0开始,而是还存在小于0的中断号,在这里需要说一下,小于零的中断号属于内核中断,大家更容易称其为异常,一般应用我们是接触不到的,异常一般会被用在实时操作系统中,freeRTOS的任务切换就是通过出发pendSV异常实现的。而大于零的部分则是外部中断(这里的外部是相对于内核来说的,并不是相对于chip而言),我们通常所说的中断则是指的这部分,包括所有外设中断(如串口接收中断、GPIOEXT中断等)。我们在C代码中基本上就是对中单号进行操作,这是非常重要的索引符号。

    3 中断优先级分组和中断优先级
    对于这个部分,则是跟STM32(Cortex-M4)差不多了,也是可以进行中断优先级分组,分别设置主优先级(抢占优先级)和子优先级,在这里就不多介绍了,大家可以参考别人的文章进行详细的了解。下表描述了RT1050的中断优先级分组情况。

    3.1.png

    优先级的分组由内核外设SCB 的应用程序中断及复位控制寄存器AIRCR 的PRIGROUP[10:8]位决定,RT1050 分为了4 组。

    4 相关操作函数
    ARM给用户提供了非常方便的NVIC操作接口函数,如下所示:

    3.2.png

    5 应用实例
    下面我们以GPIO中断为例来介绍一下中断使用。之前先了解一下RT1050 GPIO中断的相关介绍。

    5.1 RT1050 GPIO中断
    RT1052 拥有5 组GPIO,每组GPIO 拥有32 个GPIO 输入输出引脚,每个输入输出引脚都能够触发中断。每组GPIO 拥有各自的中断相关寄存器,包括一个中断屏蔽寄存器(GPIOx_IMR),一个中断状态寄存(GPIOx_ISR),两个中断配置寄存器(GPIOx_ICR1、GPIOx_ICR2)。通过配置这些寄存器我们可以灵活的设置每一个输入输出引脚是否使用中断、中断触发条件、以及当前中断状态。

    ①中断屏蔽寄存器(GPIOx_IMR),中断屏蔽寄存用于配置输入输出引脚是否使用中断,该寄存器是32 位寄存,0 到31 位依次控制输入输出引脚0 到31。系统复位后GPIOx_IMR= 0,表示禁止所有中断,如果要使用中断必须设置相应位为1。

    ②中断状态寄存器(GPIOx_ISR),该寄存器是32 位寄存器,0 到31 位依次标记0 到31 个输入输出引脚的中断状态。如果发生了中断则相应的中断标志位被硬件自动置1,软件写入1 清除中断标志位。

    ③中断配置寄存器(GPIOx_ICR),每组GPIO 拥有两个中断配置寄存器(32 位),低16 个引脚使用GPIOx_ICR1,高16个引脚使用GPIOx_ICR2。每个输入/输出引脚占用两位,可配置为低电平触发中断、高电平触发中断、上升沿触发中断、下降沿触发中断。我们根据外部电路和实际需要配置为不同的触发模式。

    5.2 中断配置过程
    我们在实现一个中断配置过程中,需要考虑以下几个点:
    ①配置中断优先级分组
    ②配置中断主、子优先级
    ③使能对应的中断号的中断请求,
    ④使能具体中断(如GPIO中断使能)
    ⑤声明中断服务函数

    我们联系NXP官网DEMO来说一下(官方怎么中断优先级设置则是采取默认配置,在我们需要进行具有多个中断的系统设计中,则是需要进行细致的中断优先级配置):
    1. void EXAMPLE_GPIO_IRQHandler(void)//对应步骤五
    2. {
    3.     /* clear the interrupt status */
    4.     GPIO_PortClearInterruptFlags(EXAMPLE_SW_GPIO, 1U << EXAMPLE_SW_GPIO_PIN);
    5.     /* Change state of switch. */
    6.     g_InputSignal = true;
    7.     SDK_ISR_EXIT_BARRIER;
    8. }

    9. /*!
    10. * @brief Main function
    11. */
    12. int main(void)
    13. {
    14.     /* Define the init structure for the input switch pin */
    15.     gpio_pin_config_t sw_config = {
    16.         kGPIO_DigitalInput,
    17.         0,
    18.         kGPIO_IntRisingEdge,
    19.     };

    20.     /* hardware initialiize, include IOMUX, Uart debug initialize */
    21.     BOARD_ConfigMPU();
    22.     BOARD_InitPins();
    23.     BOARD_BootClockRUN();
    24.     BOARD_InitDebugConsole();
    25.     PRINTF("GPIO Driver example.\r\n");
    26.     GPIO_PinInit(EXAMPLE_SW_GPIO, EXAMPLE_SW_GPIO_PIN, &sw_config);
    27.     /* Init input switch GPIO. */
    28.     EnableIRQ(EXAMPLE_SW_IRQ);  //对应步骤三
    29.     /* Enable GPIO pin interrupt */
    30.     GPIO_PortEnableInterrupts(EXAMPLE_SW_GPIO, 1U << EXAMPLE_SW_GPIO_PIN);//对应步骤四

    31.     while (1)
    32.     {
    33.         if (g_InputSignal)
    34.         {
    35.             delay();
    36.             if (1 == GPIO_PinRead(EXAMPLE_SW_GPIO, EXAMPLE_SW_GPIO_PIN))
    37.             {
    38.                 PRINTF("%s is turned on.\r\n", EXAMPLE_SW_NAME);
    39.             }
    40.             /* Reset state of switch. */
    41.             g_InputSignal = false;
    42.         }
    43.     }
    44. }
    复制代码
    版权声明:本文为「小猫爪」的原创文章

    签到签到
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-4-10 22:38
  • 签到天数: 1335 天

    [LV.10]以坛为家III

    88

    主题

    4292

    帖子

    12

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    9049
    最后登录
    2024-4-13
    发表于 2021-3-31 14:59:40 | 显示全部楼层
    我也好久没有写相关的文章了
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32003
    最后登录
    2024-4-9
     楼主| 发表于 2021-3-31 18:28:48 | 显示全部楼层
    jobszheng5 发表于 2021-3-31 14:59
    我也好久没有写相关的文章了

    快来几篇
    签到签到
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-20 11:17 , Processed in 0.112527 second(s), 21 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表