1.前言

单片机的复位功能,重要性毋庸置疑。今天,我们根据芯片datasheet和用户手册来梳理下单片机的复位功能。

芯片有三种类型的复位,分别是系统复位、电源复位和备份域复位。
下面详细讲解一下这三种复位。

2.系统复位

只要发生以下五种实践,就会产生系统复位:
1.NRST 引脚低电平(外部复位)
2. 窗口看门狗计数结束(WWDG 复位)
3. 独立看门狗计数结束(IWDG 复位)
4. 软件复位(SW 复位)
5. 低功耗管理复位

而系统复位发生时,除了时钟控制寄存器 CSR 中的复位标志和备份域中的寄存器外,系统复位会将其它全部寄存器都复位为复位值。

在这里插入图片描述

2.1 NRST 引脚低电平(外部复位)

NRST在芯片上是一个复位引脚,当该引脚接受到低电平信号时,就会产生系统复位。
这个低电平信号是有电压以及持续时间的要求的。
电压得不高于0.8V,持续时间最好能大于100ns。
在这里插入图片描述
在外围电路设计上,推荐的设计如下图所示。
在这里插入图片描述
我们看下面A和B两个复位电路图设计,我们只讲解A,B不进行讲解,读者自行分析B电路图是否能用。
A:
电源VCC和GND之间,串联了电路R和电容C。刚开始供电时,电容C正极还没有电压,NRST与GND连通,低电平。当过了1个时间常数后,电容C充电完成,C正极电压大于0.8V后,NRST退出复位状态。

在这里插入图片描述
实际设计中,常常会增加一个手动复位的按钮。只需要在AB电路的电容两端并联一个按键,当按键按下时,NRST为低电平,MCU复位。

当复位按钮被按下时,U11开关闭合,NRST和GND连通,感受到低电平信号。

1.上电的瞬间,电容C48两端电压为0V,NRST为低电平,stm32处于复位状态,VCC3.3通过电阻R50给电容充电,当电容C48的电压升高到0.8V以上,stm32退出复位状态进入运行状态。

2.当上电持续一段时间后,C48完成了充电。当我们需要手动复位的时候只需要按下按钮,此时U11开关闭合,C48与GND连通,电容迅速放电,NRST为低电平。松手后,U11开关断开,电容C48会继续充电,当电容C48的电压升高到0.8V以上,STM32退出复位状态进入运行状态。

在这里插入图片描述

2.2 窗口看门狗计数结束(WWDG 复位)

本章节后续补充。

2.3 独立看门狗计数结束(IWDG 复位)

本章节后续补充。

2.4 软件复位(SW 复位)

当软件复位发生时,RCC 时钟控制和状态寄存器 (RCC_CSR) 中的复位标志位SFTRSTF会由硬件置1。当我们获知SFTRSTF位置1是,即确定发生软件复位。

要对器件进行软件复位,必须将 NVIC(嵌套向量中断控制器) 的 AIRCR(Application Interrupt and Reset Control Register) 寄存器SYSRESETREQ 位置 1
在这里插入图片描述

RCC 时钟控制和状态寄存器 (RCC_CSR)

上文讲到的所有类型的复位,我们都可以通过RCC 时钟控制和状态寄存器中的相应位获知,是否有相应类型的复位发生。

在这里插入图片描述

2.5 低功耗管理复位

本章节后续补充。

3.复位后的行为

当发生复位后,系统会做哪些工作?

以NRST 引脚低电平(外部复位)为例,当STM32的NRST引脚被拉低触发外部复位时,系统会执行以下关键操作,并最终调用SystemInit函数完成初始化:

3.1.外部复位时的系统行为

(1) 硬件复位序列

1.寄存器清零:CPU核心寄存器(如PC、SP)和外设寄存器被重置为默认值。 时钟关闭:大部分外设时钟被禁用,仅保留必要的基础时钟。
2. BOOT引脚配置:读取BOOT0和BOOT1引脚电平,确定启动介质(如Flash、SRAM或系统存储器)。
3.向量表定位:根据启动方式,从对应存储介质(如Flash起始地址0x08000000)读取中断向量表。

(2) 复位向量执行

堆栈指针初始化:从向量表的第0个位置(0x08000000)获取初始堆栈指针(MSP)。
复位处理函数跳转:从向量表的第1个位置(0x08000004)获取复位向量,跳转到Reset_Handler函数。
Reset_Handler 是硬件复位后的入口函数,负责初始化堆栈、数据段,并调用 main()。

1.硬件自动加载__initial_sp: __initial_sp的执行是硬件自动完成的,无需软件干预。复位后,Cortex-M内核直接加载__initial_sp到MSP,确保堆栈可用

复位后,内核从中断向量表起始地址0x08000000加载初始堆栈指针到MSP,确保堆栈可用。
2. 硬件自动跳转到Reset_Handler: 内核从向量表的第1个位置(0x08000004)获取复位向量,跳转到Reset_Handler函数。
3. Reset_Handler调用SystemInit: 在Reset_Handler中,通过BLX指令调用SystemInit函数,配置系统时钟和其他硬件资源。
4. 跳转到main函数: Reset_Handler最终通过__main函数跳转到用户编写的main()函数。

下面是中断向量表,

__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 handler */
                DCD     WWDGT_IRQHandler                  ; 16:Window Watchdog Timer
                DCD     LVD_IRQHandler                    ; 17:LVD through EXTI Line detect
                DCD     TAMPER_STAMP_IRQHandler           ; 18:Tamper and TimeStamp through EXTI Line detect
                DCD     RTC_WKUP_IRQHandler               ; 19:RTC Wakeup through EXTI Line
                DCD     FMC_IRQHandler                    ; 20:FMC
                DCD     RCU_CTC_IRQHandler                ; 21:RCU and CTC
                DCD     EXTI0_IRQHandler                  ; 22:EXTI Line 0
                DCD     EXTI1_IRQHandler                  ; 23:EXTI Line 1
                DCD     EXTI2_IRQHandler                  ; 24:EXTI Line 2
                DCD     EXTI3_IRQHandler                  ; 25:EXTI Line 3
                DCD     EXTI4_IRQHandler                  ; 26:EXTI Line 4
                DCD     DMA0_Channel0_IRQHandler          ; 27:DMA0 Channel0
                DCD     DMA0_Channel1_IRQHandler          ; 28:DMA0 Channel1
                DCD     DMA0_Channel2_IRQHandler          ; 29:DMA0 Channel2
                DCD     DMA0_Channel3_IRQHandler          ; 30:DMA0 Channel3
                DCD     DMA0_Channel4_IRQHandler          ; 31:DMA0 Channel4
                DCD     DMA0_Channel5_IRQHandler          ; 32:DMA0 Channel5
                DCD     DMA0_Channel6_IRQHandler          ; 33:DMA0 Channel6
                DCD     ADC_IRQHandler                    ; 34:ADC
                DCD     CAN0_TX_IRQHandler                ; 35:CAN0 TX
                DCD     CAN0_RX0_IRQHandler               ; 36:CAN0 RX0
                DCD     CAN0_RX1_IRQHandler               ; 37:CAN0 RX1
                DCD     CAN0_EWMC_IRQHandler              ; 38:CAN0 EWMC
                DCD     EXTI5_9_IRQHandler                ; 39:EXTI5 to EXTI9
                DCD     TIMER0_BRK_TIMER8_IRQHandler      ; 40:TIMER0 Break and TIMER8
                DCD     TIMER0_UP_TIMER9_IRQHandler       ; 41:TIMER0 Update and TIMER9
                DCD     TIMER0_TRG_CMT_TIMER10_IRQHandler ; 42:TIMER0 Trigger and Commutation and TIMER10
                DCD     TIMER0_Channel_IRQHandler         ; 43:TIMER0 Channel Capture Compare
                DCD     TIMER1_IRQHandler                 ; 44:TIMER1
                DCD     TIMER2_IRQHandler                 ; 45:TIMER2
                DCD     TIMER3_IRQHandler                 ; 46:TIMER3
                DCD     I2C0_EV_IRQHandler                ; 47:I2C0 Event
                DCD     I2C0_ER_IRQHandler                ; 48:I2C0 Error
                DCD     I2C1_EV_IRQHandler                ; 49:I2C1 Event
                DCD     I2C1_ER_IRQHandler                ; 50:I2C1 Error
                DCD     SPI0_IRQHandler                   ; 51:SPI0
                DCD     SPI1_IRQHandler                   ; 52:SPI1
                DCD     USART0_IRQHandler                 ; 53:USART0
                DCD     USART1_IRQHandler                 ; 54:USART1
                DCD     USART2_IRQHandler                 ; 55:USART2
                DCD     EXTI10_15_IRQHandler              ; 56:EXTI10 to EXTI15
                DCD     RTC_Alarm_IRQHandler              ; 57:RTC Alarm
                DCD     USBFS_WKUP_IRQHandler             ; 58:USBFS Wakeup
                DCD     TIMER7_BRK_TIMER11_IRQHandler     ; 59:TIMER7 Break and TIMER11
                DCD     TIMER7_UP_TIMER12_IRQHandler      ; 60:TIMER7 Update and TIMER12
                DCD     TIMER7_TRG_CMT_TIMER13_IRQHandler ; 61:TIMER7 Trigger and Commutation and TIMER13
                DCD     TIMER7_Channel_IRQHandler         ; 62:TIMER7 Capture Compare
                DCD     DMA0_Channel7_IRQHandler          ; 63:DMA0 Channel7
                DCD     EXMC_IRQHandler                   ; 64:EXMC
                DCD     SDIO_IRQHandler                   ; 65:SDIO
                DCD     TIMER4_IRQHandler                 ; 66:TIMER4
                DCD     SPI2_IRQHandler                   ; 67:SPI2
                DCD     UART3_IRQHandler                  ; 68:UART3
                DCD     UART4_IRQHandler                  ; 69:UART4
                DCD     TIMER5_DAC_IRQHandler             ; 70:TIMER5 and DAC0 DAC1 Underrun error
                DCD     TIMER6_IRQHandler                 ; 71:TIMER6
                DCD     DMA1_Channel0_IRQHandler          ; 72:DMA1 Channel0
                DCD     DMA1_Channel1_IRQHandler          ; 73:DMA1 Channel1
                DCD     DMA1_Channel2_IRQHandler          ; 74:DMA1 Channel2
                DCD     DMA1_Channel3_IRQHandler          ; 75:DMA1 Channel3
                DCD     DMA1_Channel4_IRQHandler          ; 76:DMA1 Channel4
                DCD     ENET_IRQHandler                   ; 77:Ethernet
                DCD     ENET_WKUP_IRQHandler              ; 78:Ethernet Wakeup through EXTI Line
                DCD     CAN1_TX_IRQHandler                ; 79:CAN1 TX
                DCD     CAN1_RX0_IRQHandler               ; 80:CAN1 RX0
                DCD     CAN1_RX1_IRQHandler               ; 81:CAN1 RX1
                DCD     CAN1_EWMC_IRQHandler              ; 82:CAN1 EWMC
                DCD     USBFS_IRQHandler                  ; 83:USBFS
                DCD     DMA1_Channel5_IRQHandler          ; 84:DMA1 Channel5
                DCD     DMA1_Channel6_IRQHandler          ; 85:DMA1 Channel6
                DCD     DMA1_Channel7_IRQHandler          ; 86:DMA1 Channel7
                DCD     USART5_IRQHandler                 ; 87:USART5
                DCD     I2C2_EV_IRQHandler                ; 88:I2C2 Event
                DCD     I2C2_ER_IRQHandler                ; 89:I2C2 Error
                DCD     USBHS_EP1_Out_IRQHandler          ; 90:USBHS Endpoint 1 Out 
                DCD     USBHS_EP1_In_IRQHandler           ; 91:USBHS Endpoint 1 in
                DCD     USBHS_WKUP_IRQHandler             ; 92:USBHS Wakeup through EXTI Line
                DCD     USBHS_IRQHandler                  ; 93:USBHS
                DCD     DCI_IRQHandler                    ; 94:DCI
                DCD     0                                 ; 95:Reserved
                DCD     TRNG_IRQHandler                   ; 96:TRNG
                DCD     FPU_IRQHandler                    ; 97:FPU

__Vectors_End

3.2.复位是否触发中断?

复位与中断的区别:

复位不属于中断,而是一种系统重置。中断需要处理器在正常操作期间响应事件,而复位则是将系统恢复到初始状态。

复位标志:

复位后,可通过检查RCC->CSR寄存器中的SFTRSTF标志位确认是否发生了软件复位。外部复位(如NRST引脚低电平)不会触发中断服务函数,但会清除所有中断标志。

3.3. SystemInit函数的调用路径

(1) 启动文件中的调用
启动文件作用:

启动文件(如startup_stm32f103xb.s)是汇编编写的初始化代码,完成从硬件复位到C环境初始化的过渡。

Reset_Handler函数:
复位向量指向的Reset_Handler是启动流程的第一个执行函数,其核心步骤如下:

;/* reset Handler */
Reset_Handler   PROC
                EXPORT  Reset_Handler                     [WEAK]
                IMPORT  SystemInit
                IMPORT  __main
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP

(2) SystemInit的执行内容
系统时钟配置:
SystemInit函数(通常位于system_stm32fxxx.c)配置系统时钟(如将HCLK配置为72MHz),并初始化其他硬件资源(如Flash、外设时钟)。
用户覆盖机制:
允许用户通过重定义SystemInit函数来扩展或修改初始化逻辑。

3.4.验证与调试

复位状态寄存器:

通过检查RCC->CSR寄存器中的复位标志位(如PORRSTF、PINRSTF),可以确认复位的类型(如上电复位、外部复位等)。

中断服务函数:

如果复位是由看门狗超时引起的,则会在复位后执行相应的看门狗中断服务函数。但在外部复位的情况下,不会触发中断服务函数。

3.5总结

当NRST引脚低电平触发外部复位时,STM32会执行以下流程:

1.硬件复位:清零寄存器、关闭外设时钟、定位向量表。
2.跳转至Reset_Handler:从向量表获取复位向量,执行启动文件中的Reset_Handler。
3.调用SystemInit:配置系统时钟和其他硬件资源。
4.跳转至main函数:通过C库的__main函数初始化数据段和bss段,最终进入用户main()函数。
这一流程确保了系统在复位后能够稳定地初始化硬件环境,并正确执行用户程序。

本章节内容,读者可以进一步了解:STM32启动文件解析【建议收藏】

参考

1.单片机复位详解
2.STM32 复位电路设计
3.一、STM32F407ZGT6电路图设计(基础系统)
########################################################################

交流使人进步,碰撞产生火花! 欢迎 大家留言评论!
########################################################################
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐