精华内容
下载资源
问答
  • STM32中断控制的流程
    2020-07-08 15:29:45

    *对于 STM32 讲(还是以Timer2例),外部中断通道位置 28(35 号优先级)是给外部设备 TIME2 的,但 TIME2本身能够引起中断的中断源或事件有好多个,比如更新事件(上溢/下溢) 、输入捕获、输出匹配、DMA 申请等。所有TIME2 的中断事件都是通过一个 TIME2 的中断通道向 STM32 内核提出中断申请,那么 STM32 中如何处理和控制 TIME2 和它众多的、不同的、中断申请呢?

    1.因为cortex_m3 内核对于每一个外部中断通道都有相应的控制字和控制位,用于单独的和总的控制该中断通道。它们包括有:

    中断优先级控制字:PRI_n(前面有提到过)
    中断允许设置位:在 ISER 寄存器中
    中断允许清除位:在 ICER 寄存器中
    中断悬挂 Pending(排队等待)位置位:在 ISPR 寄存器中(类似于置中断通道标志位)
    中断悬挂 Pending(排队等待)位清除:在 ICPR 寄存器中(用于清除中断通道标志位)
    正在被服务(活动)的中断(Active)标志位:在 IABR 寄存器中, (只读,可以知道当前内核正在处理哪个中断通道)
    2.作为外围设备 TIME2 本身也包括更具体的,管理自己不同中断的中断控制器(位) ,它们主要是自身各个不同类型中断的允许控制位, 和各自相应的中断标志位 (STM32 的手册中有详细的说明) 。

    理解上面两点之后,我们可以全程、全面和综合的来了解 TIME2 的中断过程,以及如何控制的。

    ①初始化过程

    首先要设置寄存器 AIRC 中 PRIGROUP 的值, 规定系统中的抢先优先级和子优先级的个数(在 4 个 bits 中占用的位数) ;
    设置 TIME2 本身的寄存器,允许相应的中断,如允许 UIE(TIME2_DIER 的第[0]位)
    设置 TIME2 中断通道的抢先优先级和子优先级(IP[28],在 NVIC 寄存器组中)
    设置允许 TIME2 中断通道。在 NVIC 寄存器组的 ISER 寄存器中的一位。

    ②中断响应过程

    当 TIME2 的 UIE 条件成立(更新,上溢或下溢) ,硬件将 TIME2 本身寄存器中 UIE 中断标志置位,然后通过 TIME2 中断通道向内核申请中断服务。
    此时内核硬件将 TIME2 中断通道的 Pending 标志置位(相当与中断通道标志置位) ,表示 TIME2 有中断申请。
    如果当前有中断在处理,TIME2 的中断级别不够高,那么就保持 Pending 标志,当然用户可以在软件中通过写 ICPR 寄存器中相应的位把本次中断清除掉。
    当内核有空,开始响应 TIME2 的中断,进入 TIME2 的中断服务。此时硬件将 IABR 寄存器中相应的标志位置位, 表示 TIME2 中断正在被处理。 同时硬件清除 TIME2 的 Pending 标志位。

    ③ 执行 TIME2 的中断服务程序
    所有 TIME2 的中断事件, 都是在一个 TIME2 中断服务程序中完成的, 所以进入中断程序后, 中断程序需要首先判断是哪个 TIME2 的具体事件的中断, 然后转移到相应的服务代码段去。
    注意不要忘了把该具体中断事件的中断标志位清除掉, 硬件是不会自动清除 TIME2 寄存器中具体的中断标志位的。
    如果 TIME2 本身的中断事件多于 2 个, 那么它们服务的先后次序就由用户编写的中断服务决定了。换句话说,对于 TIME2 本身的多个中断的优先级,系统是不能设置的。所以用户在编写服务程序时,应该根据实际的情况和要求,通过软件的方式,将重要的中断优先处理掉。
    当然你也可以每次中断服务只处理其中的一个,然后再次进入中断,处理下一个。

    ④中断返回
    内核执行完中断服务后,便进入中断返回过程,在这个过程中需要:

    硬件将 IABR 寄存器中相应的标志位清另,表示该中断处理完成如果 TIME2 本身还有中断标志位置位,表示 TIME2 还有中断在申请,则重新将 TIME2的 Pending 标志置为 1,等待再次进入 TIME2 的中断服务。
    以上中断过程在《ARM Cortex-M3 权威指南》中有详细描述,并配合时序图说明,可以参考。
    然后,就可以在 ST 提供的函数库的帮助下,正确的设置和使用 STM32 的中断系统了。

    Linux-C语言学习交流【721709245】在学的进群一起交流,资料自己群文件下载。

    相关资料:
    (stm32 USART串口应用)

    PWM脉宽调制技术

    更多相关内容
  • STM32中断流程处理

    2018-04-30 14:58:33
    中断的定义:指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即在程序运行过程中,中断的定义:指当出现需要时,CPU暂时停止当前程序的执行转而执行处理新情况的程序和执行过程。即...
  • STM32外部中断处理流程pdf,STM32外部中断处理流程
  • STM32异常及中断处理流程学习笔记

    千次阅读 2020-06-16 16:59:11
    处理器在运行一个中断处理时能否在响应另外一个中断,是由该中断的抢占优先级决定的,子优先级只会用在具有两个相同抢占优先级的异常同时产生的情形,同时产生时,具有更高子优先级(数值更小)的异常会被优先处理。...

    在这里插入图片描述
    在这里插入图片描述
    前三个系统异常具有固定的优先级,由负数表示,比其它的优先级都高,其余的异常具有可编程的优先级,范围为0~255.
    在这里插入图片描述
    STM32采用了4位,由中断优先级分组寄存器决定抢占优先级和子优先级的位数。
    在这里插入图片描述
    在这里插入图片描述
    处理器在运行一个中断处理时能否在响应另外一个中断,是由该中断的抢占优先级决定的,子优先级只会用在具有两个相同抢占优先级的异常同时产生的情形,同时产生时,具有更高子优先级(数值更小)的异常会被优先处理。
    在这里插入图片描述
    在这里插入图片描述
    深入了解异常
    对于Cortex-M处理器,可以将异常处理或中断复位程序实现为普通的C程序/函数,为了详细了解这种机制,我们先来看一下C函数在ARM架构上是如何工作的。
    用于ARM架构的C编译器遵循ARM的一个名为AAPCS(ARM架构过程调用标准)。根据这个标准,C函数可以修改R0~R3、R12、R14(LR)以及PSR。若C函数需要使用R 4 ~R11,就应该将这些寄存器保存到栈空间中,并且在函数结束前将它们恢复。
    R0~R3、R12、LR以及PSR被称作“调用者保存寄存器”,若在函数调用后还需要使用这些寄存器的值,在进行调用前,调用子程序的程序代码需要将这些寄存器的内容保存到内存中(如栈)。函数调用后不需要使用的寄存器数值则不用保存。
    R4~R11为“被调用者保护寄存器”,被调用的子程序或函数需要确保这些寄存器在函数结束时不会发生变化(与进入函数时的数值一样)。这些寄存器的数值可能会在函数执行过程中变化,不过需要在函数退出前将它们恢复为初始值。
    在这里插入图片描述

    展开全文
  • STM32异常与中断过程详解

    千次阅读 多人点赞 2021-06-14 15:14:52
    1. 异常与中断概念引入 ...但无论是异常还是中断,都会引起程序执行偏离正常的流程,转而去执行异常/中断处理函数。 下面对异常和中断的介绍,如果中断信号的产生原因来自CPU内部,则称之为异常;如果中断信号来

    1. 异常与中断概念引入

    异常主要是指来自CPU内部的意外事件,比如执行了未定义指令、算术溢出、除零运算等发生在CPU内部的意外事件,这些异常的发生,会引起CPU运行相应的异常处理程序;中断一般来自硬件(如片上外设、外部I/O输入等)发生的事件,当这些硬件产生中断信号时,CPU会暂停当前运行的程序,转而去处理相关硬件的中断服务程序。但无论是异常还是中断,都会引起程序执行偏离正常的流程,转而去执行异常/中断的处理函数。

    下面对异常和中断的介绍,如果中断信号的产生原因来自CPU内部,则称之为异常;如果中断信号来自CPU外部,则称之为中断。有些场合如果没有明确指出是异常还是中断,就统称为中断。

    1.1 为什么需要中断

    在网上看到一个非常有意思的例子,这里引用下类似的例子来说明为什么需要中断。当你正在看一部很喜欢的电影时,这个时候你觉得有点口渴了,需要去烧一壶开水,假设水烧开需要10分钟。那么请问你如何知道水烧开了呢?也许你会有这两种选择:

    1. 每隔一小会你就跑去看一下这壶水有没有被烧开,然后回来接着看电影;
    2. 你可以等到水壶发出水被烧开的声音才去看一下,这期间你一直在看电影。

    第一种情况的处理方式,实际上就是不断的查询水是否被烧开了,如果烧开了就关火,没烧开就接着继续看电影,这种处理方式可能会累死你,而且你也会觉得自己有点笨。写程序描述如下:

    while (1)
    {
    	see a film(看电影)
        check water boiling(查看水是否烧开)
        if (水还没开)
            return(继续看电影)
        else
            关火    
    }
    

    第二种方式可以看作是烧开水的声音发出了一个信号给你,你接收到这个信号,然后就知道了我该去关火了,也就是说这个信号中断了你看电影的过程,而在这之前你可以一直享受看电影的过程。写程序描述如下:

    while (1)
    {
    	see a film(看电影)   
    }
    
    中断服务程序()
    {
        关火
    }
    

    这个例子类比于CPU的话,CPU也是可以选择这两种方式去处理意外事件的,查询方式或者中断方式。对于查询方式很明显会使得CPU的资源无法得到充分的利用,因为CPU的速度是远远大于外设的速度的,CPU在查询外设的状态时就需要等待外设的响应,使得CPU做了很多无用功。而对于中断方式,当外部事件还没达到就绪状态时(类比就是水还没烧开这件事),CPU可以专心的做其他任务,一旦CPU接收到中断信号时,转而去处理中断请求,CPU处理完毕之后再接着执行原来的任务。

    从这个类比的例子可以看出,中断机制使得CPU具有了异步处理能力。有了中断机制之后,CPU可以一直专心的执行它的主任务,不用一直去查询设备的状态。设备本身如果达到了就绪状态,需要CPU去处理的时候,此时设备发出一个中断信号给CPU,通知CPU说:“我要你来处理一下了,赶紧来吧”!CPU收到通知之后,先把主任务暂停一会,然后跳转到相应外设的中断服务函数处理该外设的中断请求,处理完之后CPU再继续回去执行主任务。

    1.2 ARM体系如何使用中断

    在ARM体系中,使用中断的过程一般有如下步骤:

    1. 中断初始化

      1.1 设置中断源,让某个外设可以产生中断;

      1.2 设置中断控制器,使能/屏蔽某个外设的中断通道,设置中断优先级等;

      1.3 使能CPU中断总开关

    2. CPU在运行正常的程序

    3. 产生中断,比如用户按下了按键 —> 中断控制器 —> CPU

    4. CPU每执行完一条指令都会检查是否有异常/中断产生

    5. 发现有异常/中断产生,开始处理:

      5.1 保存现场

      5.2 分辨异常/中断,调用对应的异常/中断处理函数

      5.3 恢复现场

    2. STM32异常与中断处理流程

    2.1 概述

    上面讲到当CPU产生异常/中断时,CPU会暂停当前程序的运行,转而去处理异常/中断的处理函数。但是这里有一些疑问:CPU如何调用异常/中断的处理函数?调用完之后如何返回?在运行中断处理函数之后,如何保证原来被打断的运行环境不被中断处理函数所改变?这几个问题是异常与中断处理流程中非常关键的问题,这些问题会在下面进行讨论,并给出解答。

    当异常/中断发生时,ARM架构对于异常/中断的处理流程基本都是:

    1. 保存现场
    2. 分辨异常/中断,调用对应的异常/中断处理函数
    3. 恢复现场

    但是细分到不同的架构(比如M3和A7架构)时,具体的处理流程还是有一些差异的,而对于STM32来说,中断的整个处理流程硬件帮我们做了大部分的工作,比如保存现场、分别异常/中断,跳转执行、恢复现场等工作,都是硬件帮我们实现了的。那么我们要做的事情是什么?我们只需要编写中断服务函数中具体想要实现的逻辑代码即可,发生异常/中断后,CPU跳转执行的就是我们实现的这部分代码。

    2.2 异常向量表

    对于STM32,当某一个外设的中断发生时,CPU如何去调用相应外设的中断服务函数?这就需要引入异常向量表的概念了。STM32的中断向量表可以看成是一个指针数组,这个数组里面存放的就是一个个的中断服务函数的入口地址(向量表首地址规定是栈顶指针)。当CPU检查到某个中断产生时,硬件会根据我们提供的中断号自动跳转到向量表中与这个中断号对应的这个中断服务函数的入口地址,从而执行相应的中断服务函数。

    比如发生了Reset异常,那么CPU会从异常向量表的第1项找到Reset_Handler函数的地址,然后跳转到该函数执行;如果发生其他中断,CPU同样可以从表格里面找到对应的中断服务函数的地址,然后跳转到该函数执行。

    STM32F103的中断向量表如下所示:

    __Vectors       DCD     __initial_sp               ; Top of Stack
                    DCD     Reset_Handler              ; Reset Handler
                    DCD     NMI_Handler                ; NMI Handler
                    DCD     HardFault_Handler          ; Hard Fault Handler
                    DCD     MemManage_Handler          ; MPU Fault Handler
                    DCD     BusFault_Handler           ; Bus Fault Handler
                    DCD     UsageFault_Handler         ; Usage Fault Handler
                    DCD     0                          ; Reserved
                    DCD     0                          ; Reserved
                    DCD     0                          ; Reserved
                    DCD     0                          ; Reserved
                    DCD     SVC_Handler                ; SVCall Handler
                    DCD     DebugMon_Handler           ; Debug Monitor Handler
                    DCD     0                          ; Reserved
                    DCD     PendSV_Handler             ; PendSV Handler
                    DCD     SysTick_Handler            ; SysTick Handler
    
                    ; External Interrupts
                    DCD     WWDG_IRQHandler            ; Window Watchdog
                    DCD     PVD_IRQHandler             ; PVD through EXTI Line detect
                    DCD     TAMPER_IRQHandler          ; Tamper
                    DCD     RTC_IRQHandler             ; RTC
                    DCD     FLASH_IRQHandler           ; Flash
                    DCD     RCC_IRQHandler             ; RCC
                    DCD     EXTI0_IRQHandler           ; EXTI Line 0
                    DCD     EXTI1_IRQHandler           ; EXTI Line 1
                    DCD     EXTI2_IRQHandler           ; EXTI Line 2
                    DCD     EXTI3_IRQHandler           ; EXTI Line 3
                    DCD     EXTI4_IRQHandler           ; EXTI Line 4
                    DCD     DMA1_Channel1_IRQHandler   ; DMA1 Channel 1
                    DCD     DMA1_Channel2_IRQHandler   ; DMA1 Channel 2
                    DCD     DMA1_Channel3_IRQHandler   ; DMA1 Channel 3
                    DCD     DMA1_Channel4_IRQHandler   ; DMA1 Channel 4
                    DCD     DMA1_Channel5_IRQHandler   ; DMA1 Channel 5
                    DCD     DMA1_Channel6_IRQHandler   ; DMA1 Channel 6
                    DCD     DMA1_Channel7_IRQHandler   ; DMA1 Channel 7
                    DCD     ADC1_2_IRQHandler          ; ADC1 & ADC2
                    DCD     USB_HP_CAN1_TX_IRQHandler  ; USB High Priority or CAN1 TX
                    DCD     USB_LP_CAN1_RX0_IRQHandler ; USB Low  Priority or CAN1 RX0
                    DCD     CAN1_RX1_IRQHandler        ; CAN1 RX1
                    DCD     CAN1_SCE_IRQHandler        ; CAN1 SCE
                    DCD     EXTI9_5_IRQHandler         ; EXTI Line 9..5
                    DCD     TIM1_BRK_IRQHandler        ; TIM1 Break
                    DCD     TIM1_UP_IRQHandler         ; TIM1 Update
                    DCD     TIM1_TRG_COM_IRQHandler    ; TIM1 Trigger and Commutation
                    DCD     TIM1_CC_IRQHandler         ; TIM1 Capture Compare
                    DCD     TIM2_IRQHandler            ; TIM2
                    DCD     TIM3_IRQHandler            ; TIM3
                    DCD     TIM4_IRQHandler            ; TIM4
                    DCD     I2C1_EV_IRQHandler         ; I2C1 Event
                    DCD     I2C1_ER_IRQHandler         ; I2C1 Error
                    DCD     I2C2_EV_IRQHandler         ; I2C2 Event
                    DCD     I2C2_ER_IRQHandler         ; I2C2 Error
                    DCD     SPI1_IRQHandler            ; SPI1
                    DCD     SPI2_IRQHandler            ; SPI2
                    DCD     USART1_IRQHandler          ; USART1
                    DCD     USART2_IRQHandler          ; USART2
                    DCD     USART3_IRQHandler          ; USART3
                    DCD     EXTI15_10_IRQHandler       ; EXTI Line 15..10
                    DCD     RTCAlarm_IRQHandler        ; RTC Alarm through EXTI Line
                    DCD     USBWakeUp_IRQHandler       ; USB Wakeup from suspend
                    DCD     TIM8_BRK_IRQHandler        ; TIM8 Break
                    DCD     TIM8_UP_IRQHandler         ; TIM8 Update
                    DCD     TIM8_TRG_COM_IRQHandler    ; TIM8 Trigger and Commutation
                    DCD     TIM8_CC_IRQHandler         ; TIM8 Capture Compare
                    DCD     ADC3_IRQHandler            ; ADC3
                    DCD     FSMC_IRQHandler            ; FSMC
                    DCD     SDIO_IRQHandler            ; SDIO
                    DCD     TIM5_IRQHandler            ; TIM5
                    DCD     SPI3_IRQHandler            ; SPI3
                    DCD     UART4_IRQHandler           ; UART4
                    DCD     UART5_IRQHandler           ; UART5
                    DCD     TIM6_IRQHandler            ; TIM6
                    DCD     TIM7_IRQHandler            ; TIM7
                    DCD     DMA2_Channel1_IRQHandler   ; DMA2 Channel1
                    DCD     DMA2_Channel2_IRQHandler   ; DMA2 Channel2
                    DCD     DMA2_Channel3_IRQHandler   ; DMA2 Channel3
                    DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
    __Vectors_End
    

    一般来说向量表都会被链接到一个程序存储的最前面的位置的,对于STM32F103来说,程序运行和加载的起始地址都是0x08000000,所以STM32的异常向量表也会会被加载到0x08000000地址处的。

    对于ARM架构,规定向量表的基地址默认是0x00000000或0xFFFF0000位置的(对于STM32向量表的默认基地址就是0地址),而STM32向量表的基地址是被链接在了0x08000000的地址处,这样当中断发生时,不就跳转到了错误的函数入口地址了吗?为了解决这个问题,ARM允许可以修改异常向量表的基地址,这样就可以把异常向量表的基地址重新修改在内部Flash的起始地址0x08000000位置了。完成这一工作的是官方固件库的SystemInit函数,相关代码如下:

    #define FLASH_BASE       ((uint32_t)0x08000000) /*!< FLASH base address in the alias region */
    #define VECT_TAB_OFFSET  0x0 /*!< Vector Table base offset field. This value must be a multiple of 0x200. */
    #define SCB              ((SCB_Type *)           SCB_BASE)         /* !< SCB configuration struct         */
    
    void SystemInit (void)
    {
        /****************此处省略部分代码****************/
    #ifdef VECT_TAB_SRAM
      SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET;  /* Vector Table Relocation in Internal SRAM.  */
    #else
      SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
    #endif 
    }
    

    其中 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; 这一行代码就是把异常向量表基地址更改到了0x08000000的地址中去了。

    补充:我曾自己写过简单的启动文件测试,并没有去调用SystemInit函数,自己也没有在其他地方对向量表的基地址更改到0x08000000的地址中去,但是当CPU检查到有中断发生时,还是可以跳转到正确的中断服务函数的入口地址处。为什么会这样?我查阅了下相关的资料,了解到当STM32从Flash启动时,实际上会把Flash的那段存储空间0x08000000 ~ 0x0807FFFF映射到0x00000000 ~ 0x0007FFFF这一段地址的存储空间,也就是说当CPU从Flash启动时,CPU从0地址处开始执行指令和从0x08000000地址处开始执行指令是一样的。所以,这个时候我没有去更改异常向量表的基地址,CPU仍然可以跳转到正确的中断服务程序。

    2.3 保存现场

    2.3.1 概念引入

    我们在Keil里面写一段非常简单的代码,实现 a = a + b; 这个式子。当然我们并不是要去关心这个式子本身,而是利用Keil的仿真功能,去查看一下CPU执行这个式子后,其内部寄存器的变化。仿真截图如下:
    在这里插入图片描述
    从上面这个仿真的汇编代码可以看出,CPU要完成 a = a + b; 的运算,实际上是先去读取a, b的内存所保存的数据到内部寄存器r0, r1中,然后再执行r0 = r0 + r1的运算,最后把r0的值写回到内存a中,这样才完成了一次a = a + b; 的运算。另外,可以观察到CPU在运行程序的过程中,它内部的r0 - r15,还有程序状态寄存器xPSR的值,都是在不断的变化中的。

    那么问题来了,假设CPU在运行 a = a + b; 这个式子的中途,程序运行过程被中断信号打断了。要想这个式子可以得到正确的结果,那么就要确保中断前CPU的这几个寄存器的值以及中断返回后这些寄存器的值都要保持不变,还有保存在内存空间a, b的值也不会被改变。这样运行这个式子得到的最终结果才是正确的。

    对于保持a, b内存的值不变,这个好办,中断程序中不要去改写a, b的值即可。但是我们如何保持中断前后CPU内部寄存器的值不被改变呢?因为中断程序的运行肯定也是需要用到CPU内部的寄存器的,所以必须得有一种机制去保持中断前后CPU内部寄存器的值不被改变。也就是说,所谓的现场,实际上就是CPU运行到某一时刻时,CPU内部寄存器的值

    那么如何保存现场和恢复现场呢?这就需要用到栈。CPU在跳转到异常/中断程序前,就需要把这些不希望被中断程序所改变的寄存器的值保存到栈中,这就是保存现场。在异常/中断处理完之后,从栈中恢复这些寄存器的值,这就是恢复现场

    2.3.2 保存哪些寄存器的值

    上面说了,所谓保存现场就是保存CPU内部一些寄存器的值到栈中。CPU内部常用的寄存器有 r0 ~ r15,再加上程序状态寄存器,一共16个(当然其他模式下可能还有对应的其他寄存器)。下图就是STM32F103内部寄存器示例(M3内核不具有浮点运算单元,这里不讨论浮点运算单元的寄存器了):
    在这里插入图片描述
    当发生异常/中断时,CPU跳转之前,就需要把这些寄存器的值保存到栈中,那么我们需要把CPU的这16个寄存器都保存到栈中吗?很显然是不需要的。

    ARM公司推出了一个ATPCS标准,即ARM-THUMB procedure call standard(ARM-Thumb过程调用标准)。在这份标准里面,都规定了这16个寄存器的使用规则,如下表所示:

    寄存器别名使用规则
    r15pc程序计数器
    r14lr连接寄存器
    r13sp数据栈指针
    r12ip子程序内部调用的scratch寄存器
    r11v8ARM状态局部变量寄存器8
    r10v7、s1ARM状态局部变量寄存器7、在支持数据栈检查的ATPCS中为数据栈限制指针
    r9v6、sbARM状态局部变量寄存器6、在支持RWPI的ATPCS中为静态基址寄存器
    r8v5ARM状态局部变量寄存器5
    r7v4、wrARM状态局部变量寄存器4、Thumb状态工作寄存器
    r6v3ARM状态局部变量寄存器3
    r5v2ARM状态局部变量寄存器2
    r4v1ARM状态局部变量寄存器1
    r3a4参数/结果/scratch 寄存器4
    r2a3参数/结果/scratch 寄存器3
    r1a2参数/结果/scratch 寄存器2
    r0a1参数/结果/scratch 寄存器1

    其中,r0 ~ r3是函数调用时用来传递参数或者保存函数返回值的,r4 ~ r11是用来保存局部变量的,r12 ~ r15是特殊功能寄存器。这些寄存器一般会被拆分成2部分:调用者保存的寄存器(r0-r3, r12, lr, psr)被调用者保存的寄存器(r4-r11)

    比如函数A调用函数B,那么函数A就是调用者,函数B就是被调用者。那么根据这份ATPCS规则,函数A在调用函数B之前,函数A就应该要保存r0-r3, r12, lr, psr这几个调用者要保存的寄存器;而对于r4-r11这几个寄存器,调用函数B的前后,函数B本身会保证调用前后这些寄存器的值保持不变。

    那么,如果函数B是中断服务函数,因为函数B本身会保证r4-r11的值不会被改变,所以保存现场也就是保存r0-r3, r12, lr, psr这几个寄存器的值即可。

    2.3.3 STM32如何保存现场

    我们已经知道了什么是现场,保存现场要保存哪些寄存器的值了。那么对于STM32来说,是如何保存这些寄存器的值到栈中的呢?

    非常幸运的是,STM32保存现场的工作是CPU的硬件自动帮我们完成的(我们不要想当然的认为所有架构的硬件都会帮我们完成这部分工作,对于Cortex-A7架构来说就不是硬件帮我们完成的),我们不需要自己写代码去把中断前需要保存的寄存器的值存放到栈中。具体过程如下图所示:
    在这里插入图片描述

    2.4 恢复现场

    恢复现场就是指CPU执行完异常/中断服务函数后,返回到LR寄存器所指示的地址处(就是中断前的下一条指令的地址),并且把保存在栈中寄存器的值恢复到寄存器中去。

    对于如何返回到中断前下一条指令的地址,其实很容易就可以实现,只要我们把下一条指令的地址存放到LR寄存器即可,CPU返回的话就是把LR寄存器的值赋值给PC程序计数器,这样就可以返回到了中断前下一条指令中继续运行程序了。但是如果这样做的话,硬件帮我们保存在栈中的寄存器的值,返回去是怎么恢复那些寄存器的值?

    对于这个问题,STM32帮我们实现了一套机制。CPU进入异常/中断服务程序时,LR寄存器保存的并不是中断前下一条指令的地址,而是会保存一个特殊的数值,被称为EXC_RETURN。对于EXC_RETURN位域的定义和具体的数值含义,可以查看《ARM Crotex-M3与Cortex-M4权威指南》一书中第八章的描述。这里截图如下作为参考:
    在这里插入图片描述
    所以,当异常/中断返回时,LR寄存器赋值给PC的值是一个被称为EXC_RETURN的值,而一旦CPU识别到PC的值等于EXC_RETURN的话,那么就会触发异常/中断返回机制,这个机制会帮我们把保存在栈中r0-r3, r12, lr, psr的寄存器的值恢复回去。

    展开全文
  • STM32中断原理

    2021-11-05 12:30:29
    二、STM32CubeMX中断方式点灯 2.1 项目内容 2.2 工程设置 2.3 代码实操 2.4 硬件连接 2.5 运行效果 三、STM32CubeMX中断串口通信 3.1 项目内容 3.2 工程设置 3.3 代码实操 3.4 效果展示 四、参考文献 ...

    目录

    一、中断介绍

    1.1 什么是中断

    1.2 中断的作用

    1.3 中断的约束

    二、STM32CubeMX中断方式点灯

    2.1 项目内容

    2.2 工程设置

    2.3 代码实操

    2.4 硬件连接

    2.5 运行效果

    三、STM32CubeMX中断串口通信

    3.1 项目内容

    3.2 工程设置 

    3.3 代码实操

    3.4 效果展示

     四、参考文献


     

    本篇博客内容包括 :

    1.介绍STM32中的中断系统。

    2.采用中断进行点灯实验。

    3.采用串口中断方式实现串口通信。

    一、中断介绍

    1.1 什么是中断

    中断通常被定义为一个事件,该事件能够改变处理器执行指令的顺序。这样的事件与 CPU 芯片内外部硬件电路产生的电信号相对应。

    中断分为同步中断异步中断

    同步中断——同步中断是当指令执行时由 控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后 CPU 才会发出中断。

    异步中断——异步中断是由其他硬件设备依照 CPU 时钟信号随机产生的。

    通常我们所说的中断指的是异步中断,我们将同步中断称为异常。(异常是由程序的错误产生的,或者是由内核必须处理的异常条件产生的)

    1.2 中断的作用

    跟据中断的定义,我们可以通过中断使处理器转而去优先运行正常控制流之外的代码

    当一个中断信号达到时,CPU 必须停止它当前正在做的事情,并且切换到一个另一个活动。为了做到这就要在内核态堆钱保存程序计数器的当前值,并把与中断类型相关的地址放进程序计数量。

    1.3 中断的约束

    中断处理是由内核执行的最敏感的任务之一,因为它必须满足下列约束:

    1)中断应该被尽可能快地处理完
    2)中断处理程序必须编成使相应的内核控制路径能以嵌套的方式执行
    3)内核在处理一个中断时,可接受新的中断。但存在一个临界区,中断必须被禁止

    出于1)和3)的约束,中断的设计一般将中断处理程序分为两部分执行(即上半部和下半部函数)。上半部为中断被禁止的临界区,执行关键而紧急的任务,如把接收到的帧拷贝到输入队列,以便下半部函数执行时能进行处理。

    二、STM32CubeMX中断方式点灯

    2.1 项目内容

    用stm32F103芯片的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。

    这里我选用的芯片为正点原子的STM32F103RC迷你板。

    设置PA1端接开关,PB5接LED。

    对于按键电路,设置上拉式按键

    • 按键按下,引脚PA1读到低电平
    • 按键释放,引脚PA1读到高电平

    LED灯的触发方式

    • 按键按下瞬间,形成下降沿
    • 按键释放瞬间,形成上升沿

    在这里插入图片描述

     因此这里设置上升沿触发,即松开按键时灯亮,因为题目要求为开关接高高电平亮灯。

    2.2 工程设置

    • 新建工程

    新建工程的过程在这我就不赘述了,需要的朋友可以看看我的另一篇博客

    基于STM32 CubeMX+MDK5使用HAL库点亮流水灯,并使用逻辑分析仪观察管脚时序波形_歪比巴不的博客-CSDN博客

    • 时钟设置

    配置RCC使用外部时钟

    然后再来配置stm32的时钟树框图,将8改为72,回车确认 

    再按着顺序继续配置

    •  外设配置

     点击GPIO,选择自己用到的管脚,这里我的LED是连在PA8管脚,按键是连在PB8

    连接LED的管脚选择GPIO_Output

     对于LED对应的PA8管脚,默认设置即可,名字设为LED

    按键所连的管脚选择GPIO_EXIT

     

     对于按键对应的管脚,我这里让默认输入为0,选择pull down,选择上升沿触发

     使能对应的外部中断

     

    2.3 代码实操

    代码如下: 

    void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
    {
    		for(long i = 1;i<72000;i++){}; //消除抖动
    		if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==1)
    		{
    			HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
    		}
    	__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    }
    

    在如图位置粘贴代码

    2.4 硬件连接

    LED短脚接地,长脚接PB8,按键一端接3.3V,一端接PB8

    LED短脚——GND

    LED长脚——PA8

    按键一端——3.3V

    按键另一端——PB8

    2.5 运行效果

     

    三、STM32CubeMX中断串口通信

    3.1 项目内容

    完成一个STM32的USART串口通讯程序,要求:
    1)设置波特率为115200,1位停止位,无校验位;
    2)STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收。

    3.2 工程设置 

    由于新工程配置大多如上方led灯示例,所以以下只讲述不同之处

    USART1中的Mode选择Asynchronous

     使能中断

    3.3 代码实操

    添加存放数据的数组 

    uint8_t a[]="Hello windows!\n";
    

     添加回转函数

    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
    {
    		HAL_UART_Transmit_IT(&huart1, a, sizeof(a));
    }
    
    

    在主函数中添加中断调用 

    HAL_UART_Transmit_IT(&huart1, a, sizeof(a));
    

    3.4 效果展示

     

     四、参考文献

    中断详解(一)——基本概念_Windeal-CSDN博客_中断概述什么是中断    中断通常被定义为一个事件,该事件能够改变处理器执行指令的顺序。这样的事件与 CPU 芯片内外部硬件电路产生的电信号相对应。    中断分为同步中断和异步中断。    同步中断——同步中断是当指令执行时由 控制单元产生的,之所以称为同步,是因为只有在一条指令终止执行后 CPU 才会发出中断    异步中断——异步中 断是由其他硬件设备依照https://blog.csdn.net/windeal3203/article/details/44588205?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163608715316780262593935%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163608715316780262593935&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-8-44588205.pc_search_result_cache&utm_term=%E4%B8%AD%E6%96%AD%E5%9F%BA%E7%A1%80%E4%BB%8B%E7%BB%8D&spm=1018.2226.3001.4187


    【STM32】HAL库 STM32CubeMX教程四---UART串口通信详解_Z小旋-CSDN博客_hal_uart_transmit前言:今天我们学习STM32CubeMX串口的操作,以及HAL库串口的配置,我们会详细的讲解各个模块的使用和具体功能,并且基于HAL库实现Printf函数功能重定向,UART中断接收,本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用所用工具:1、芯片:STM32F407ZET62、STM32CubeMx软件3、IDE: M...https://blog.csdn.net/as480133937/article/details/99073783

    展开全文
  • STM32中断处理

    2020-08-02 18:25:37
    STM32最多有32中断源,大体上可分为两类,外部中断源与内部中断源(引起ARM芯片执行指令/内部功能模块),其中断优先级别可分为FIQ(快速中断请求)、向量IRQ、非向量IRQ,其级别依次递减. Cortex内核具有强大的异常...
  • STM32中断

    千次阅读 2021-11-02 09:31:31
    STM32中断控制LED灯一、STM32中断1. 概念2. 中断响应过程3. 中断优先级二、仿中断高低电平控制LED灯1. CubeMx2. 控制代码编写三、总结四、参考 一、STM32中断 1. 概念 中断是由内核外部产生的,一般由硬件引起,...
  • STM32 中断

    2022-02-16 18:56:53
    STM32 中断 1. 基础知识 1. Cortex-M3支持 256 个中断,其中包含了 16 个内核中断,240个外部中断。 2. STM32只有 84 个中断,包括 16 个内核中断和 68 个可屏蔽中断。 3. STM32F103上只有 60 个可屏蔽中断,F107上才有 ...
  • STM32中断的详细介绍及使用流程

    千次阅读 2022-01-24 08:59:39
    》》CPU执行程序时,由于发生了某种随机的事件(外部或内部),引起CPU暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序中断处理程序),以处理该事件,该事件处理完后又返回被中断的程序继续...
  • STM32 中断系统概述

    2021-10-18 12:33:03
    STM32 中断系统概述笔记(一)中断概述中断相关的基本概念STM32的中断系统基本概念:NVIC 嵌套向量中断控制器中断通道中断优先级优先级分组EXTI 外部中断控制器三种外部中断触发方式引脚分组 / 中断通道HAL库的中断...
  • stm32的架构图可以看到,挂载在APB2上的外设有GPIO、EXTI、AFIO GPIO的所有引脚默认是与输入输出寄存器相连映射的 AFIO算是一个不是外设的外设,因为它主要是用来将引脚重映射到其它外设寄存器的,但是对它操作也...
  • STM32中断控制LED灯

    2021-11-06 09:41:24
    目录STM32中断简介对LED进行中断处理中断实现串口通信总结参考 STM32中断简介 中断是由内核外部产生的,一般由硬件引起,比如外设中断和外部中断等。过程大致包含中断发生,中断处理和中断返回。中断可以做到实施...
  • 手把手之STM32中断

    2021-01-17 13:59:06
    而在单片机执行代码的过程中,难免会有一些突发的情况需要处理,这样就会打断当前的代码,待处理完突发情况之后,程序会回到被打断的地方继续执行。●关于STM32中断几乎任何一款单片机都会有中断。以STM32F407VE来...
  • STM32中断编程步骤

    千次阅读 2020-07-01 19:36:45
    介绍stm32f10x中断的概念,已经中断向量表,还有中断编程的一下要点,涉及的一下寄存器
  • STM32 中断原理及外部中断的实现

    千次阅读 2021-01-18 15:39:09
    STM32使用了其中一部分,16个内核中断,107系列有68个可屏蔽中断(103系列只有60个),16级可编程的中断优先级。 中断寄存器: ISER[8],Interrupt Set-Enable Registers,中断使能寄存器组,用8个32位寄存器控制...
  • 1,意思是APB2接高速设备2、Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为stm32f10x_conf.h专门控制外围器件的配置,也就是开关头文件的作用3、HSE Osc(High Speed External Oscillator)高速外部晶振...
  • STM32中断控制led灯

    2021-10-31 09:41:32
    这里写自定义目录标题功能快捷键合理的创建标题,有助...中断是指计算机运行过程中,出现某些意外情况需要主机干预的时候,机器能自动停止正在运行的程序处理新情况的程序处理完毕后又返回原被暂停的程序继续运行 1
  • stm32 中断(f4)

    2022-02-28 22:25:19
    在学习 51 单片机时,我们就接触过中断,中断其实就是当 CPU 执行程序时,由于发生了某种随机的事件(外部或内部),引起 CPU 暂时中断正在运行的程序,转去执行一段特殊的服务程序(中断服务子程序中断处理程序),以...
  • STM32中断相关知识总结

    千次阅读 2020-10-07 21:58:00
    中断是指处理器运行过程中,出现某些意外情况,CPU能自动停止正在运行的程序并转入处理新情况的程序中断服务函数),处理完毕后又返回原被暂停的程序继续运行。 CM3和CM7 内核支持 256 个中断,其中包含了 16 个...
  • 中断,即机器运行过程中出现某些意外情况,需要机器停止正在运行的程序并转入处理新情况的程序处理完毕之后又返回原来被暂停的程序继续运行。 理解中断 想象一个这样的场景: 你在认真的敲代码,你妈喊你出...
  • stm32外部中断实验

    2022-03-09 17:01:23
    2.STM32 的每个 IO 都可以作为外部中断中断输入口,STM32F103 的中断控制器支持 19 个外部中 断/事件请求。每个中断设有状态位,每个中断/事件都有独立的触发和屏蔽设置。 STM32F103 的 19 个外部中断为: 线 0~...
  • 中断是指计算机运行过程中,出现某些意外情况需要计算机处理时,技能能自动暂停正在运行的程序并转入处理新情况的程序处理完毕后又返回原先被暂停的程序继续运行的功能。 举一个生活例子来说明:小明在厨房干活,...
  • STM32中断系统

    千次阅读 多人点赞 2021-04-19 15:04:39
    10.1 Cortex-M3 的中断和优先级 正常情况下,微处理器根据代码内容,按顺序执行指令。执行过程中,如果遇到其它紧急的事件需要处理,则先暂停当前任务,执行紧急事件,待紧急事件处理完后,再恢复到刚才暂停的地方...
  • 中断系统
  • STM32的这些经典功能,你真的掌握了吗?首先,在学习Cortex-M3时,我们必须要知道必要的缩略语。创客学院整理如下:AMBA:先进单片机总线架构 ADK:AMBA设计c9200446619921FFCa4b252220c1fe2aAHB:先进高性能总线 AHB-...
  • 中断编程的顺序: 1.选择中断分组: NVIC_PriorityGroupConfig() 2.初始化结构体: NVIC_InitTypeDef() 3.配置NVIC寄存器: NVIC_Init(NVIC_InitTypeDef) 4编写中断服务函数. 外部中断: EXTI_InitTypeDef ...
  • stm32 hal串口中断分析

    2022-04-08 17:24:17
    HAL_UART_IRQHandler //调用HAL库中断处理公用函数。 功能:对接收到的数据进行判断和处理 判断是发送中断还是接收中断,然后进行数据的发送和接收,在中断服务函数中使用 /* UART in mode Receiver --------...
  • 1,意思是APB2接高速设备2、Stm32f10x.h相当于reg52.h(里面有基本的位操作定义),另一个为stm32f10x_conf.h专门控制外围器件的配置,也就是开关头文件的作用3、HSE Osc(High Speed External Oscillator)高速外部晶振...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,284
精华内容 2,513
关键字:

stm32中断处理流程