目录
1.单片机启动流程
2.看门狗
3.最小系统
4.ROM、RAM、Flash
5.EPROM、EEPROM
6.Bootloader与OTA
7.NAND FLASH 和NOR FLASH
相同点
区别
适用场景
8.CPU、MPU、MCU、SOC、SOPC
9.交叉编译
10.寄存器
寄存器的作用
寄存器与内存的区别
11.Cortex-M3寄存器组
通用寄存器
特殊功能寄存器
12.保存、恢复现场的详细操作
13.ARM Cortex-M3和M4的区别
14.异常和中断
15.中断和DMA的区别
16.DMA
17.中断响应执行流程
1.单片机启动流程
单片机的启动流程是指从上电或复位开始到应用用户主程序执行的一系列自动操作过程,不同架构的单片机流程略有差异,但核心逻辑相似。
首先,当单片机接通电源或收到复位信号(如外部复位引脚触发、看门狗超时、软件复位指令等),硬件电路会先进行复位操作,让内部所有寄存器回到初始状态,确保系统从已知的初始条件开始运行。
接下来,单片机通常会执行一段固化在芯片内部的 “启动代码”(也叫引导程序或启动程序),这段代码由芯片厂商预先编写,存放在只读存储器(ROM 或 Flash 的特定区域)中,用户无法修改。启动代码的主要任务包括初始化关键硬件,比如配置系统时钟(从默认的低速内部时钟切换到高速外部时钟或 PLL 锁相环,以满足运行速度需求)、设置堆栈指针(为后续程序运行分配栈空间,用于函数调用和局部变量存储)、初始化数据段和 BSS 段(将程序中的全局变量和静态变量从 Flash 加载到 RAM 中,并对未初始化的变量清零)。
完成这些初始化后,启动代码会寻找用户程序的入口点(通常是 main 函数的地址),并跳转到该地址,此时单片机开始执行用户编写的主程序,启动流程结束。
对于一些支持程序下载或在线编程的单片机,启动流程中可能还会包含一段引导加载程序(Bootloader),用于检测是否需要从外部存储(如串口、SPI Flash)加载新的程序,如果不需要则继续执行上述常规启动步骤,这使得单片机可以方便地更新固件而无需专用编程器。
2.看门狗
在单片机系统中,看门狗(Watchdog Timer,简称 WDT)是一种用于监控程序运行状态、防止程序 “死机” 或进入无限循环的硬件定时器,本质上是一套保障系统可靠性的 “程序异常自救机制”。单片机在运行过程中,可能会因为电磁干扰、硬件临时故障、代码漏洞(比如数组越界导致的逻辑混乱、意外触发的死循环等),使得程序脱离预设的正常执行流程,陷入 “假死” 状态,无法完成原本的控制、采集等功能,而看门狗的核心作用就是在这种情况下,强制让失控的系统重启,恢复到初始运行状态,避免长时间 “死机” 带来的设备失效或功能异常。
看门狗的工作原理围绕 “定时器计时” 和 “超时触发复位” 展开,其中关键操作是 “喂狗”。具体来说,程序启动后首先需要初始化看门狗,设定一个合适的 “超时时间”(比如几十毫秒到几秒,根据单片机型号和实际需求确定),初始化完成后,看门狗定时器会开始从 0 向上计数(或从预设值向下递减)。如果程序正常运行,就需要在定时器计数达到设定的超时时间之前,通过代码向看门狗的特定寄存器写入预设的 “喂狗指令”(比如某些单片机要求连续写入 0x55 和 0xAA),写入指令后,定时器会立即清零并重新开始计时,从而避免触发复位;但如果程序因为故障陷入失控状态,就无法按时执行 “喂狗” 操作,此时看门狗定时器会一直计数直到达到超时时间,随后会自动触发单片机的系统复位信号,强制单片机重新上电启动,让程序从初始状态重新运行,脱离失控困境。
单片机的看门狗主要分为内置和外置两种类型,内置看门狗是集成在单片机芯片内部的硬件模块,像 51 单片机、STM32、AVR 等主流型号基本都自带,它无需额外添加硬件,成本较低,且能通过软件灵活调整超时时间,适合消费电子、智能家居等大多数常规场景;外置看门狗则是独立的外部芯片(如 MAX813L、X5045 等),需要通过单片机的 I/O 口或专用引脚进行 “喂狗”,虽然会额外占用 PCB 空间和增加成本,但独立性更强,即便单片机内部核心硬件(如时钟模块)出现故障,仍能正常触发复位,因此更适合工业控制、汽车电子、医疗设备等对可靠性要求极高的场景。
3.最小系统
STM32 的最小系统是指能让 STM32 单片机正常工作的最基础电路组成。它通常由 STM32 主芯片、电源电路、复位电路、时钟电路和下载调试接口这几部分构成。
电源电路负责提供稳定的工作电压(一般为 3.3V),通过稳压芯片将外部输入的电压(如 5V)转换为单片机所需的稳定电压,同时包含滤波电容以滤除电源噪声。
复位电路用于让单片机在需要时回到初始状态,通常由复位按键、电阻和电容组成,按下按键时产生复位信号,松开后单片机重新启动。
时钟电路为单片机提供工作时序,包括外部高速时钟(如 8MHz 晶振配合两个电容)和内部 RC 振荡器,外部晶振能提供更高精度的时钟信号,满足精确计时或高速外设的需求。
下载调试接口(如 SWD 接口,由 SWCLK 和 SWDIO 两根线组成)用于程序的下载和在线调试,方便开发者将编写好的程序烧录到单片机中,并进行运行状态的调试。
这些部分共同协作,确保 STM32 单片机能够正常上电、启动、运行程序并支持开发调试,是构建任何基于 STM32 的电子系统的基础。
4.ROM、RAM、Flash
在单片机(如 STM32)及各类电子系统中,ROM、RAM、Flash 都是核心存储部件,但它们的存储特性、用途和工作原理差异很大,分别对应不同的功能需求。
ROM(只读存储器,Read-Only Memory)是一种断电后数据不会丢失的 “非易失性存储”,早期的 ROM 数据由厂商在生产时固化,用户无法修改,主要用来存放单片机的启动代码、基础驱动程序等固定不变的内容,比如早期 51 单片机里的引导程序就存在 ROM 中。不过现在常见的是 “可擦写 ROM”(如 EPROM、EEPROM),用户可以通过专用工具修改数据,但擦写次数有限(通常上万次),且擦写速度较慢,所以更多用于存储少量需要长期保存、很少修改的信息,比如设备参数、校准数据等。
RAM(随机存取存储器,Random Access Memory)则是 “易失性存储”,断电后数据会立即丢失,它的特点是读写速度极快,能高效配合 CPU 进行数据交换,主要用途是临时存放程序运行时的动态数据 —— 比如程序中的局部变量、函数调用时的栈数据、实时采集的传感器数据等。CPU 在执行程序时,会把需要频繁操作的数据从 Flash 或 ROM 加载到 RAM 中,因为 RAM 的读写速度远快于非易失性存储,能大幅提升程序运行效率,但由于断电失数据的特性,它无法长期保存信息,每次上电后都需要重新从其他存储中加载数据。
Flash(闪存)是目前单片机中最常用的 “非易失性存储”,兼具了 ROM 的断电保数据特性和接近 RAM 的读写便捷性(但速度仍慢于 RAM),它的擦写次数比 EEPROM 更多(通常可达 10 万次以上),且存储容量更大,成本相对较低。在 STM32 等现代单片机中,Flash 主要用来存放用户编写的应用程序(比如控制逻辑、算法代码),单片机上电后会从 Flash 中读取程序指令并执行;同时,Flash 也能用来存储需要长期保存、偶尔修改的大量数据,比如日志信息、配置文件等。不过 Flash 的擦写有 “按块擦除” 的特点(不能像 RAM 那样单个字节随意修改),所以在写入数据时需要配合特定的驱动程序来管理擦写操作。
简单来说,三者的核心区别可以概括为:ROM(含 EEPROM)适合存少量、长期不变或极少修改的数据;RAM 适合存程序运行时临时用、高速读写的数据;Flash 则适合存大量的程序代码和需要长期保存、偶尔修改的数据,三者协同工作,共同支撑单片机的正常运行。
5.EPROM、EEPROM
EPROM(可擦除可编程只读存储器)和 EEPROM(电可擦除可编程只读存储器)都是可擦写的非易失性存储设备,断电后数据不会丢失,常用于存储需要长期保存且可能偶尔修改的信息,但两者在擦除方式、操作便捷性和应用场景上有明显区别。
EPROM 的擦除需要通过紫外线照射芯片表面的透明窗口来完成,整个过程通常需要几分钟,且擦除时必须将芯片从电路板上取下,操作繁琐,适合早期对存储修改需求较少的场景,比如早期单片机中的固定程序存储。
EEPROM 则改进了擦除方式,可通过电信号直接擦除和改写数据,无需物理拆卸芯片,甚至能在系统运行中在线修改(即 “在系统编程”),擦写速度也更快(毫秒级),虽然存储容量通常小于 EPROM,且擦写次数相对有限(一般几万到几十万次),但因其操作便捷性,在现代电子设备中应用更广泛,比如用于存储设备参数、校准数据、用户设置等需要灵活修改的少量信息,像智能仪表的配置参数、汽车电子中的故障码存储等场景常能见到它的身影。
6.Bootloader与OTA
Bootloader 是嵌入式系统中在应用程序运行之前执行的一段引导程序,相当于系统的 “启动管家”,主要负责初始化硬件、准备运行环境,并最终将控制权转交给用户应用程序。在 STM32 等单片机中,Bootloader 通常分为两种:一种是芯片出厂时固化在系统存储器中的 “内置 Bootloader”,由芯片厂商(如 ST 公司)编写,用户无法修改,它支持通过串口、SPI、I2C 等外设接口接收程序数据,实现对主 Flash 的编程(即 ISP 下载),方便用户在没有专用编程器的情况下更新固件;另一种是用户自定义的 Bootloader,由开发者根据需求编写并烧录到主 Flash 的特定区域,这类 Bootloader 可以实现更灵活的功能,比如从 SD 卡、以太网或无线模块读取程序镜像进行升级(即 OTA 升级),或者对应用程序进行校验、加密保护等。
Bootloader 的工作流程通常包括几个阶段:
- 首先进行最基础的硬件初始化,如配置时钟、初始化关键外设(如用于通信的串口)和设置堆栈;
- 然后根据预设的触发条件(如特定按键按下、收到升级指令)判断是否需要执行升级操作,若需要则通过相应接口接收新的程序数据并写入 Flash;
- 若无需升级,则跳转到用户应用程序的起始地址,将系统控制权移交,之后 Bootloader 的使命完成,应用程序开始运行。
这种分层启动的设计,既保证了系统能够可靠启动,又为程序更新和功能扩展提供了便利,是嵌入式系统中实现固件升级和系统管理的重要机制。
OTA 是一种具体的程序更新方式,指通过无线通信(如 Wi-Fi、蓝牙、蜂窝网络等)远程传输新的固件镜像,让设备无需物理连接(如用数据线接电脑)就能完成升级。
在实际应用中,OTA 的实现依赖于 Bootloader:设备运行时,应用程序若收到远程的 OTA 升级指令,会将新固件暂时存放在存储区(如 Flash 的特定分区),然后触发系统复位;复位后 Bootloader 启动,检测到存储区有新固件,便执行擦除旧程序、写入新程序的操作,完成后再跳转到新程序运行。这里的 Bootloader 需要被设计为支持从存储区读取新固件并处理升级逻辑,而 OTA 则解决了 “如何将新固件传到设备” 的问题,两者结合让嵌入式设备(如物联网传感器、智能家居设备)的远程升级成为可能,大幅降低了维护成本。
7.NAND FLASH 和NOR FLASH
Flash分为NAND flash和NOR flash两种。它们的核心功能都是断电后保留数据。NOR的特点是芯片内执行(XIP, eXecute In Place),这样应用程序可以直接在flash闪存内运行,不必再把代码读到系统RAM中。NOR的传输效率很高,但是很低的写入和擦除速度大大影响了它的性能。而NAND则是高数据存储密度的理想解决方案。NAND的写入和擦除速度更快,且存储容量更大,但是用户不能直接运行NAND Flash上的代码。
相同点
- 非易失性:两者均为非易失性存储,断电后数据不会丢失,这是相对于 RAM(随机存取存储器)的核心优势。
- 基于浮栅晶体管:存储原理均依赖 “浮栅晶体管”(Floating Gate Transistor),通过在浮栅中捕获电荷来表示数据(0/1)。
- 可擦除重写:支持数据的擦除和重写(需按块 / 扇区操作,不能直接修改单个字节)。
区别
对比维度 | NAND Flash | NOR Flash |
---|---|---|
存储结构 | 以 “块(Block)” 为单位组织,块内包含页(Page),类似硬盘结构 | 以 “扇区(Sector)” 为单位,支持随机地址访问,类似内存结构 |
读取方式 | 需通过页地址顺序读取,不支持随机地址直接访问(类似硬盘) | 支持随机地址读取(直接访问任意地址),速度快 |
写入 / 擦除特性 | 写入前需先擦除块(块级擦除),擦除速度快(毫秒级) | 写入前需先擦除扇区(扇区级擦除),擦除速度慢(秒级) |
容量与成本 | 容量大(可达 TB 级),单位存储成本低 | 容量小(通常几十 MB 到几百 MB),单位存储成本高 |
数据总线宽度 | 多为 8 位或 16 位总线,并行读取效率高 | 多为 1 位或 8 位总线,适合小数据量读取 |
坏块管理 | 存在天然坏块,需通过固件 / 软件进行坏块管理 | 几乎无坏块,无需复杂管理 |
可靠性与寿命 | 擦写次数相对较低(SLC 约 10 万次,MLC 约 1 万次) | 擦写次数较高(SLC 可达 10 万次以上) |
典型应用场景 | 大容量数据存储(U 盘、SSD、存储卡、嵌入式系统数据区) | 代码存储(嵌入式系统的程序区、BIOS、固件) |
适用场景
-
选 NOR Flash:
当需要存储程序代码并直接运行(如嵌入式系统的 Bootloader、BIOS、小型固件),或需要频繁随机读取小数据时(如配置信息),优先选择 NOR。例如:路由器的启动程序、汽车电子的控制固件。 -
选 NAND Flash:
当需要大容量数据存储(如文件、图像、日志),或需要高写入 / 擦除效率时,优先选择 NAND。例如:U 盘、SD 卡、固态硬盘(SSD)、智能手机的存储芯片。
8.CPU、MPU、MCU、SOC、SOPC
CPU(Central Processing Unit),是一台计算机的运算核心和控制核心。CPU由运算器、控制器和寄存器及实现它们之间联系的数据、控制及状态的总线构成。差不多所有的CPU的运作原理可分为四个阶 段:提取(Fetch)、解码(Decode)、执行(Execute)和写回(Writeback)。 CPU从存储器或高速缓冲存储器中取出指令,放入指令寄存器,并对指令译码,并执行指令。所谓的计算机的可编程性主要是指对CPU的编程。
MPU(Micro Processor Unit)微处理器(不是微控制器),通常代表一个功能强大的CPU(可理解为增强版的CPU),但不是为任何已有的特定计算目的而设计的芯片。这种芯片往往是个人计算机和高端工作站的核心CPU。最常见的微处理器是Motorola的68K系列和Intel的X86系列。
MCU(Micro Control Unit)微控制器,是指将计算机的 CPU、RAM、ROM、定时计数器和多种I/O接口集成在一片芯片上形成的芯片,比如51,avr这些芯片,内部除了CPU外还有RAM、ROM,直接加简单的外围器件(电阻,电容)就可以运行代码了。而MPU如x86这些就不能直接放代码了,它只不过是增强版的CPU,所以得添加RAM、ROM。MCU,MPU最主要的区别就是能否直接运行代码。
SOC(System on Chip)片上系统,MCU只是芯片级的芯片,而SOC是系统级的芯片,它既像MCU(51,avr)那样有内置RAM、ROM,同时又像MPU那样强大,不单单是放简单的代码,可以放系统级的代码,也就是说可以运行操作系统(将MCU的集成化与MPU的强处理力的优点二合一)。
SOPC(System On a Programmable Chip)可编程片上系统(FPGA),上面4点的硬件配置是固化的,就是说51单片机就是51单片机,不能变为avr,而avr就是avr不是51单片机,他们的硬件是一次性成型的,能改的只有软件配置,也就是改代码。而SOPC则是硬件配置,软件配置都可以修改。硬件是可以自己构建的,也就是说这个芯片是自己构造出来的,这颗芯片我们叫“白片”,什么芯片都不是,把硬件配置信息下载进去了,他就是相应的芯片了,可以让他变成51,也可以是avr,甚至arm。同时SOPC是在SOC基础上来的,所以他也是系统级的芯片。记得当把他变成arm时还得加外围ROM,RAM之类的,不然就是MPU了。
9.交叉编译
交叉编译指在一台计算机(通常称为主机,如 PC 机)上编译出能在另一种不同架构的目标设备(如单片机、嵌入式处理器)上运行的程序。由于主机和目标设备的硬件架构、指令集不同(比如 PC 机常用 x86 架构,而 STM32 单片机采用 ARM 架构),直接在主机上用本地编译器生成的程序无法在目标设备上运行,因此需要专门的交叉编译工具链。
交叉编译的核心是使用针对目标架构的编译器、汇编器和链接器,这些工具能将源代码转换为目标设备可识别的机器码。例如,开发 STM32 程序时,开发者在 Windows 或 Linux 系统(主机)上使用 arm-none-eabi-gcc 等交叉编译工具,将 C/C++ 代码编译成 ARM 架构的二进制文件,再通过下载工具烧录到单片机中运行。
这种方式的优势在于充分利用主机的强大计算能力和便捷的开发环境,同时满足目标设备的运行需求,尤其适合资源有限的嵌入式设备 —— 这些设备通常无法直接在自身上安装编译器或运行复杂的编译过程。交叉编译过程中需要正确配置目标设备的架构、处理器型号、内存布局等参数,以确保生成的程序能在目标硬件上正常运行,是嵌入式开发中连接开发环境与目标设备的关键环节。
10.寄存器
寄存器(Register)是CPU内部集成的高速存储单元,用于用于临时存放数据、指令和地址,是 CPU 与内存、外设之间数据交互的 “中转站”。它的核心特点是速度极快(纳秒级,比内存快 1-2 个数量级),但容量极小(通常以字节或字为单位,整个 CPU 的寄存器总量一般在几十到几百字节)。
寄存器的作用
寄存器是 CPU 运行的 “临时工作台”,主要功能包括:
- 暂存数据:存储 CPU 正在运算的数据(如加法运算中的两个操作数和中间结果)。
- 存放指令:存储即将执行的指令(或指令的地址)。
- 记录状态:存储 CPU 的运行状态(如是否产生进位、是否发生中断等)。
- 控制操作:部分寄存器可通过设置特定位,控制 CPU 的工作模式(如中断开关、特权级切换)。
寄存器与内存的区别
寄存器和内存都是存储设备,但定位完全不同,核心差异如下:
对比维度 | 寄存器(Register) | 内存(Memory,如 DRAM) |
---|---|---|
物理位置 | 集成在 CPU 内部 | 位于 CPU 外部(通过总线连接) |
速度 | 极快(纳秒级,与 CPU 主频匹配) | 较慢(几十纳秒,需通过总线传输) |
容量 | 极小(通常几十到几百字节) | 较大(GB 级,如 8GB、16GB) |
用途 | 临时存放 CPU 正在处理的数据 / 指令 | 长期存放程序和数据(断电丢失) |
访问方式 | 直接通过指令操作(如MOV R0, #5 ) | 通过地址总线和数据总线访问 |
例如,要控制 GPIO 引脚输出高低电平,需向对应的 GPIO 口的输出数据寄存器写入特定值;要设置串口的波特率,需配置串口的波特率寄存器;而通过读取状态寄存器,可以知道外设当前是否处于忙碌、完成或出错状态。
每个寄存器都有唯一的地址,CPU 通过访问这些地址来读写寄存器的值,进而实现对硬件的控制。不同外设(如定时器、ADC、SPI 等)都有各自对应的寄存器组,开发者需要根据芯片手册了解每个寄存器的功能、位定义及合法值,通过编写代码配置这些寄存器,才能让硬件按照预期工作。这种直接操作寄存器的方式能精确控制硬件行为,是嵌入式开发的底层基础,尽管许多开发中会使用库函数封装寄存器操作。
11.Cortex-M3寄存器组
Cortex-M3 处理器采用 32 位架构,其寄存器组可分为通用寄存器、特殊功能寄存器和程序状态寄存器三类,以下是详细说明:
通用寄存器
Cortex-M3 有 16 个 32 位通用寄存器(R0-R15),其中 R0-R12 为纯通用寄存器,R13-R15 有特殊用途:
寄存器 | 名称 / 用途 | 说明 |
---|---|---|
R0 | 通用寄存器 | 用于临时数据存储,支持所有数据操作指令 |
R1 | 通用寄存器 | 同上 |
... | ... | (R2-R12 功能相同,均为通用寄存器,无特殊用途) |
R12 | 通用寄存器(IP) | 通常用作函数调用的中间结果寄存器(Intra-Procedure Call Register) |
R13 | 栈指针(SP) | 分为 MSP (主栈指针,默认用于操作系统和异常处理)和 PSP (进程栈指针,用于用户任务),由 CONTROL 寄存器选择当前使用的 SP |
R14 | 链接寄存器(LR) | 存储函数调用的返回地址,函数返回时通过 BX LR 指令跳转回调用处 |
R15 | 程序计数器(PC) | 存储下一条要执行的指令地址,自动递增(Thumb 指令集下每次 + 2,32 位指令下 + 4) |
特殊功能寄存器
特殊功能寄存器用于 Cortex-M3 的核心核心控制和状态,只能通过特定指令(如 MRS
/MSR
)访问,主要包括:
寄存器 | 名称 | 功能说明 |
---|---|---|
xPSR | 程序状态寄存器组合 | 由三个子寄存器组成: 1. APSR (应用程序状态寄存器):存储条件标志位(N/Z/C/V)、Q 标志(DSP 相关)、GE位(大于等于标志)2. IPSR (中断程序状态寄存器):存储当前活跃的异常编号(0-255,0 表示无异常)3. EPSR (执行程序状态寄存器):存储 Thumb 状态位(T 位,Cortex-M3 始终为 1,因仅支持 Thumb-2 指令集) |
PRIMASK | 主屏蔽寄存器 | 1 位寄存器,置 1 时屏蔽所有可屏蔽中断(仅 NMI 和硬 fault 可响应) |
FAULTMASK | fault 屏蔽寄存器 | 1 位寄存器,置 1 时屏蔽所有异常(仅 NMI 可响应),优先级高于 PRIMASK |
BASEPRI | 基础优先级寄存器 | 8 位寄存器,屏蔽优先级低于设定值的中断(仅响应更高优先级的中断) |
CONTROL | 控制寄存器 | 2 位寄存器: - bit0:选择栈指针(0=MSP,1=PSP) - bit1:选择特权级(0 = 特权级,1 = 用户级) |
Cortex-M3 的寄存器组设计兼顾了高效性和实时性:
- 通用寄存器(R0-R15)满足日常数据处理需求,特殊用途寄存器(SP/LR/PC)简化了函数调用和栈管理;
- 特殊功能寄存器(xPSR、PRIMASK 等)提供了对中断、特权级和异常的精细控制,适配嵌入式实时系统的严苛要求。
12.保存、恢复现场的详细操作
保存和恢复现场的本质是“状态的完整备份与还原”,核心流程为:
- 保存:中断 / 切换发生时,将寄存器、状态等压入栈或专用存储区(硬件 + 软件协同);
- 处理:执行中断服务程序或切换到目标任务;
- 恢复:按相反顺序从存储区弹出状态,回到中断前的执行点。
对ARM Cortex-M3\M4具体而言:
“现场”:指程序执行到某一时刻的全部运行状态,包括:
- CPU 通用寄存器的值(如 R0-R15);
- 程序状态寄存器(如 xPSR,记录标志位、中断状态等);
- 栈指针(SP)、程序计数器(PC)等专用寄存器;
- (部分场景)内存中临时变量、外设状态等。
保存现场:在程序被中断(如中断请求、任务切换)时,将当前 “现场” 完整存储到安全区域(通常是栈或专用存储区),防止状态丢失。
恢复现场:当中断处理完成或任务重新调度时,将保存的 “现场” 从存储区读回寄存器,使程序恢复到中断前的状态继续执行。
13.ARM Cortex-M3和M4的区别
特性 | Cortex-M3 | Cortex-M4 |
---|---|---|
核心定位 | 通用嵌入式处理器,侧重控制类应用 | 增强型处理器,支持控制 + 信号处理 |
核心功能 | 基础控制能力,无硬件 DSP 和浮点单元 | 集成硬件 DSP 指令和可选 FPU(浮点运算),支持硬件浮点运算 |
典型应用场景 | 工业控制、智能家居、低端嵌入式设备 | 电机控制、音频处理、传感器融合、物联网网关等需要信号处理的场景 |
- 若仅需基础控制功能(如 GPIO 控制、简单通信协议),对成本和功耗敏感 → 选 Cortex-M3(如 STM32F1 系列);
- 若需信号处理(如音频滤波、电机矢量控制)或浮点运算(如传感器融合算法) → 选 Cortex-M4(如 STM32F4 系列、TI Tiva C 系列)。
Cortex-M4 完全兼容 Cortex-M3 的软件生态,是 Cortex-M3 的 “增强版”。
14.异常和中断
-
中断(外部事件):
由CPU 外部设备(如定时器、按键、传感器、串口)主动触发的请求,目的是通知 CPU “外部有事件需要处理”(如按键被按下、数据接收完成)。
本质是 “外部异步事件”,与 CPU 执行的指令流无关,随时可能发生。 -
异常(内部错误):
由CPU 内部事件触发(如程序执行错误、调试请求),是 CPU 在执行指令过程中 “自身遇到的特殊情况”(如除以零、访问无效内存、执行断点指令)。
本质是 “内部同步事件”,与当前执行的指令直接相关,通常在特定指令执行时发生。
对比维度 | 中断(Interrupt) | 异常(Exception) |
---|---|---|
触发源 | CPU 外部设备(定时器、GPIO、UART 等) | CPU 内部(程序错误、调试、指令执行异常等) |
同步性 | 异步(与程序执行流程无关,意味着中断随时可能到来) | 同步(与当前执行的指令相关,确定发生,与时钟是同步的) |
典型场景 | 按键输入、定时器超时、串口数据到达 | 除以零、空指针访问、断点调试、系统调用 |
处理优先级 | 通常可配置优先级(支持嵌套) | 固定优先级(部分可配置,如故障异常) |
响应延迟 | 需快速响应(如实时控制系统要求微秒级) | 需立即处理(如内存错误不处理会导致崩溃) |
ARM Cortex-M 举例 | 外部中断(EXTI)、定时器中断(TIM) | 硬故障(HardFault)、内存管理故障(MemManage)、调试异常(DebugMonitor) |
15.中断和DMA的区别
DMA是一种无须CPU的参与,就可以让外设与系统内存之间进行双向数据传输的硬件机制,使用 DMA可以使系统CPU从实际的I/O数据传输过程中摆脱出来,从而大大提高系统的吞吐率。
中断:是指CPU在执行程序的过程中,出现了某些突发事件时,CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU又返回源程序被中断的位置并继续执行。
所以中断和DMA的区别就是:DMA不需CPU参与,而中断是需要CPU参与的。
16.DMA
在没有 DMA 的系统中,外设与内存之间的数据传输需要 CPU 全程介入(例如:CPU 从外设寄存器读取数据,再写入内存),这会占用大量 CPU 时间,尤其在传输大数据量时(如视频、音频流),会导致 CPU 无法处理其他任务。
DMA 的出现解决了这一问题:它通过DMA 控制器(独立于 CPU 的硬件模块)直接管理外设与内存之间的数据传输,CPU 只需在传输开始前进行初始化配置,传输过程中可完全脱离,仅在传输完成或出错时通过中断通知 CPU。
流程:
-
初始化配置(CPU 介入)
CPU 向 DMA 控制器发送指令,设置关键参数:- 数据源地址(如外设的数据寄存器地址,如 UART 接收缓冲区);
- 目标地址(如内存中的数据缓冲区地址);
- 传输数据量(如 1024 字节);
- 传输方向(外设→内存、内存→外设、内存→内存);
- 传输模式(单次传输、循环传输等)。
-
数据传输(DMA 独立完成)
CPU 配置完成后,DMA 控制器接管总线(数据总线、地址总线),直接执行数据搬运:- 从数据源读取数据,写入目标地址;
- 自动更新源地址、目标地址和剩余传输量;
- 传输过程中,CPU 可执行其他任务(如运算、响应中断等),无需参与。
-
传输结束(通知 CPU)
当数据传输完成或发生错误时,DMA 控制器触发中断,通知 CPU:- CPU 响应中断,处理后续工作(如校验数据、启动下一次传输);
- 整个过程中,CPU 仅在初始化和结束阶段参与,中间传输完全由 DMA 完成。
优势:
-
提高系统效率
大数据量传输时(如摄像头采集图像、SD 卡读写),DMA 避免了 CPU 频繁搬运数据的开销,让 CPU 专注于更复杂的任务(如算法处理、逻辑决策)。 -
降低 CPU 负载
无需 CPU 参与数据传输,减少了 CPU 的占用时间,尤其适合嵌入式系统、实时系统等资源有限的场景。 -
提升传输速度
DMA 控制器直接操作总线,传输速度仅受总线带宽限制,比 CPU 通过指令搬运数据更快(尤其在高频传输场景)。
典型应用场景
- 外设数据采集:ADC(模数转换器)连续采样传感器数据,通过 DMA 直接写入内存,CPU 无需每次采样都介入;
- 通信数据传输:UART、SPI、I2C 等接口接收 / 发送大数据包时,用 DMA 自动完成,避免 CPU 被频繁中断;
- 存储设备读写:硬盘、SD 卡、Flash 等存储设备与内存之间的文件传输(如计算机中的硬盘 DMA 模式);
- 音频 / 视频处理:音频 Codec、摄像头模块与内存之间的实时数据流传输,保证数据连续性。
17.中断响应执行流程
中断响应执行流程是指 CPU 从检测到中断请求到完成中断处理并返回原程序的完整过程,这一流程需要硬件与软件协同工作,确保中断能被快速响应且程序能正确恢复执行。
中断响应流程可概括为:
外设请求(
中断触发) → 优先级仲裁(
控制器比较当前请求的优先级与正在处理的中断优先级) → 硬件保存现场(
自动保存关键寄存器到栈中) → 跳转ISR(
CPU 从中断向量表中找到当前中断对应的服务程序地址) → 软件处理(
执行中断服务程序并清除中断标志) → 恢复现场(
从栈中弹出之前自动保存的寄存器) → 返回原程序
18.中断和轮询哪个效率高?怎样决定是采用中断方式还是采用轮询方式去实现驱动?
中断是CPU处于被动状态下来接受设备的信号,而轮询是CPU主动去查询该设备是否有请求。
凡事都是两面性,所以,看效率不能简单的说那个效率高。如果是请求设备是一个频繁请求cpu的设备,或者有大量数据请求的网络设备,那么轮询的效率是比中断高。如果是一般设备,并且该设备请求 cpu的频率比较低,则用中断效率要高一些。主要是看请求频率。
19.什么是轮询?
轮询是计算机系统中CPU 主动查询外设状态以处理事件的一种基础机制,核心逻辑是 “CPU 周期性询问、外设被动响应”,无需外设主动向 CPU 发送信号。
具体如下:
- 发起查询:CPU 按固定周期(如每 10ms)主动访问外设的 “状态寄存器”,读取外设当前状态(例如 “是否有数据待读取”“操作是否完成”“是否发生错误”)。
- 状态判断:CPU 对比读取到的状态值与预设的 “事件触发条件”(如 “状态寄存器第 0 位为 1 表示有数据”):
- 若未满足触发条件(如无数据):CPU 不处理该外设,继续执行其他任务(或进入下一次查询循环);
- 若满足触发条件(如有数据):CPU 执行对应的处理逻辑(如读取数据、发送控制指令)。
- 循环重复:处理完成后,CPU 回到 “查询” 步骤,继续周期性询问外设状态,直到系统停止或外设断开。
在事件频繁规律、硬件资源有限的场景下,是比中断更合适的解决方案。在实际系统中,也常出现 “中断 + 轮询” 的混合策略(如中断通知 “有事件”,轮询批量处理数据),以平衡效率与资源消耗。
20.状态机
系统在任一时刻仅处于一个确定的状态,当外部事件(输入)触发时,会按照预设规则从当前状态 “跳转” 到另一个状态,并可能执行对应状态的动作。
任何状态机都由 4 个基本部分构成,缺少任一要素都无法形成完整的逻辑闭环:
-
状态(State)
系统在某一时刻的行为模式或运行状态,分为两种关键类型:- 初始状态(Initial State):系统启动时的默认状态(仅 1 个)。
- 常规状态 / 终止状态:常规状态是系统运行中的中间状态(如 “设备待机”“数据传输中”);终止状态是系统逻辑结束的状态(可选,如 “任务完成”)。
-
事件(Event)
触发状态切换的外部输入或内部条件,是状态变化的 “驱动力”。
示例:按键按下(外部事件)、定时器超时(内部事件)、数据接收完成(硬件事件)。 -
转移(Transition)
系统从 “当前状态” 在某个 “事件” 触发下,切换到 “目标状态” 的规则。
注意:转移是有条件的—— 同一事件在不同当前状态下,可能触发不同转移(如 “按键按下” 在 “待机状态” 下触发 “启动”,在 “运行状态” 下触发 “暂停”)。 -
动作(Action)
状态切换时或状态存续期间执行的具体操作。
分为两种场景:- 进入动作:进入某个状态时执行(如进入 “数据传输状态” 时,初始化串口)。
- 离开动作:离开某个状态时执行(如离开 “数据传输状态” 时,关闭串口)。
优点:
- 逻辑清晰,易维护:将复杂流程拆分为 “状态 - 事件 - 转移”,避免
if-else
嵌套,新逻辑只需新增状态 / 表项,无需修改原有代码。 - 行为可预测:任一时刻状态唯一,给定事件后转移结果确定,调试时可快速定位 “状态异常” 问题。
- 资源占用低:裸机中状态机通常用枚举、数组实现,无额外内存开销,适合 MCU 等资源受限场景。
- 复用性强:同一状态机逻辑(如按键处理、协议解析)可移植到不同项目,只需调整 “动作函数”。
21.当一个异常出现以后,ARM微处理器会执行哪几步操作?
- 将下一条指令的地址存入相应链接寄存器LR,以便程序在处理异常返回时能从正确的位置重新开始执行。若异常是从ARM状态进入,则LR寄存器中保存的是下一条指令的地址(当前PC+4或PC+ 8,与异常的类型有关);若异常是从Thumb状态进入,则在LR寄存器中保存当前PC的偏移量,这样,异常处理程序就不需要确定异常是从何种状态进入的。例如:在软件中断异常SWI,指令MOV PC,R14_svc总是返回到下一条指令,不管SWI是在ARM状态执行,还是在Thumb状态执行。
- 将CPSR复制到相应的SPSR中。
- 根据异常类型,强制设置CPSR的运行模式位。
- 强制PC从相关的异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序处
注意:
CPSR: 程序状态寄存器(当前程序状态寄存器),在任何处理器模式下被访问
SPSR:程序状态保存寄存器(saved programstatus register),每一种处理器模式下都有一个状态寄存器SPSR,SPSR用于保存CPSR的状态,以便异常返回后恢复异常发生时的工作状态
22.ARM内核架构
1. ICode总线:ICode 中的 I 表示 Instruction,即指令。我们写好的程序编译之后都是一条条指令,存放在 FLASH 中,内核要读取这些指令来执行程序就必须通过 ICode 总线,它几乎每时每刻 都需要被使用,它是专门用来取指的。
2.DCode总线:DCode 中的 D 表示 Data,即数据,那说明这条总线是用来取数的。我们在写程序的时候,数据有常量和变量两种,常量就是固定不变的,用 C 语言中的 const 关键字修饰,是放到内部的 FLASH 当中的,变量是可变的,不管是全局变量还是局部变量都放在内部的 SRAM。因为数据可以被 Dcode 总线和 DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵来仲裁,决定哪个总线在取数。
3.系统总线:系统总线主要是访问外设的寄存器,我们通常说的寄存器编程,即读写寄存器都是通 过这根系统总线来完成的
(1)FSMC的英文全称是 Flexible static memory controller,叫灵活的静态的存储器控制器, 是 STM32F10xx 中一个很有特色的外设,通过 FSMC,我们可以扩展内存,如外部的 SRAM,NANDFLASH 和 NORFLASH。
(2)内部的闪存存储器即 FLASH,我们编写好的程序就放在这个地方。内核通过 ICode 总 线来取里面的指令。
(3)DMA总线(Direct Memory Access)即直接存储器访问。主要用来传输数据,这个数据可以是某个外设的数据寄存存器,可以在SRAM,可以在内部的FLASH。
(4)AHB到APB的桥。AHB(Advanced High performance Bus)系统总线高级高性能总线
APB(Advance Peripheral BUS)外围总线。
(5)看门狗模块(watchdog timer):定期查看芯片内部的情况,一旦发生错误向芯片发出重启信号。看门狗命令在程序的中断中拥有最高的优先级。
23.STM32是大端还是小端?
小端模式。
24.SysTick
SysTick(系统滴答定时器)是 ARM Cortex-M 系列内核内置的24 位向下计数定时器,专为操作系统(如 RTOS)提供 “系统节拍”(定时中断),也可用于普通定时、延时等场景。无需占用外部定时器资源。
- 硬件集成:属于 Cortex-M 内核外设,所有 Cortex-M 系列 MCU(如 M0/M3/M4/M7)均标配,接口和功能统一,移植性极强。
- 计数特性:24 位递减计数器,最大计数值为
2²⁴-1=16,777,215
,计数到 0 后自动重载(从LOAD
寄存器值重新开始)。 - 时钟源:可选择两种时钟源(由内核外设
Sys_cfg
配置):- 内核时钟(HCLK)的 1/8(默认,适合低功耗);
- 内核时钟(HCLK)本身(高频,适合高精度定时)。
- 中断触发:计数到 0 时可触发
SysTick_handler
中断,用于实现定时中断(如 RTOS 的任务调度、延时函数)。
25.什么是哈佛结构和冯诺依曼结构?
冯诺依曼结构主要用于通用计算机领域,需要对存储器中的代码和数据频繁的进行修改,统一编址有利于节约资源。
哈佛结构主要用于嵌入式计算机,程序固化在硬件中,有较高的可靠性、运算速度和较大的吞吐。