CMSIS标准与各种库的发展历史+哈弗架构+CPU统一编址 📅 发布时间:2026/9/12 19:51:32 👁 浏览次数: 目录一、CMSIS与HAL库1CMSIS标准与历史遗留问题标准库的诞生2HAL库的发展背景3为什么ST不直接在CMSIS-Driver上封装HAL库而是反过来4胶水层有什么用二、为什么STM32采用哈弗架构而PC却采用冯诺依曼架构呢1哈弗架构、冯诺依曼架构基本定义2从指令流水线角度分析性能差异3ST官方参考手册中的结构图三、统一编址CPU只看得到存储空间无需分辨外设1统一编址与独立编址2STM32的存储器映象统一编址的小缺点与常见地址分段一、CMSIS与HAL库在STM32的学习中我们常常会在目录中看到CMSIS的字眼但它表达了什么意思与ARM、ST又有什么样的关系1CMSIS标准与历史遗留问题标准库的诞生CMSIS的全称是Cortex‑Microcontroller Software Interface Standard即Cortex‑M 微控制器软件接口标准。是ARM公式推出的一套软件规范目的是将自己的CortexM内核方便的交给ST等MCU厂商使用、并让各MCU具备一定跨厂商平台的能力。CMSIS在现在分为CMSIS-Core和CMSIS-DeviceCMSIS-Driver分别规范着内核CPU、MCU板载外设的定义与操作。其中CMSIS-Core是ARM写好的关于内核CPU的描述信息操作函数集合MCU厂商只能调用接口而不允许修改。而ARM并不知道厂商拿到自己的CPU后会做成什么结构的MCU所以CMSIS-Device是由ARM规范ST等公司维护的MCU板载外设的描述信息。最后CMSIS-Driver同样是ARM规范接口MCU厂商维护的一套寄存器操作函数。这里的Core既包含了信息与接口定义也包含了实现。因为全部都由ARM自己实现所以打包成一个文件夹CMSIS-Core了。但是由于历史发展问题ARM在早期并没有提供对于MCU的CMSIS而仅仅只提供了CPU内核的CMSIS于是各个厂商如ST、NXP不得不写出自己的外设库函数比如ST公司就在这个背景下写出了标准库SPL成为一代经典。2HAL库的发展背景随着时间发展ST公司推出的MCU越来越多产线越来越大标准库各自为战的维护成本较高毕竟每一款MCU的寄存器都不同标准库内部的寄存器操作也需要有所改变。更重要的是标准库使得不同系列F1、F4、F7等的MCU函数接口也不同用户更改起来太繁琐了。于是ST开始转向HAL库HAL 库最大的特点就是统一了不同 STM32 系列的 API 接口。让让ST公司的所有基于CortexM开发的MCU只有一套库函数同样是 GPIO 初始化、串口发送F1、F4、H7 等不同芯片的函数名、参数形式基本保持一致。开发者在更换芯片型号时只需要修改底层硬件配置上层业务代码可以大量复用极大降低了跨系列移植的成本。最终HAL库就发展成了如下状态其中还提出了两个问题下面我们逐一解答。3为什么ST不直接在CMSIS-Driver上封装HAL库而是反过来同样是历史原因CMSIS-Driver的提出时间甚至比HAL还晚当它提出时ST公司已经将HAL库写好了。不过我个人觉得假设CMSIS-Driver先被推出ST公司还是有很大概率绕过它自己写一套HAL库的毕竟CMSIS-Driver为了兼容市面上各种MCU做出了不小的牺牲函数接口设计十分复杂多处使用回调函数、状态机等高级语法函数调用层级极为复杂不利于裸机场景追求极致性能。而 HAL 库面向 ST 自家芯片内部可以更贴近寄存器操作减少多层抽象跳转兼顾易用性与执行效率。4胶水层有什么用因为在ARM提出CMSIS-Driver后很多ARM官方组件中间件如USB协议等都是基于该标准写的但是各厂商都已经实现了自己的HAL库所以只能在自己的HAL库加一层外壳在函数内部将参数、返回值等修改成符合CMSIS-Driver标准的用于适配。普通裸机开发几乎用不到胶水层我们写HAL_GPIO_WritePin、HAL_UART_Transmit直接调用 HAL 库不经过胶水层。当使用 RTOS、第三方中间件时这些软件只识别 CMSIS‑Driver 这套标准化接口此时胶水层就起到桥梁作用把 HAL 库的硬件能力包装成标准接口供中间件调用。所以胶水层不是给我们写业务代码用的是给软件组件做适配用的。关于CMSIS各种文件的层级结构可以参考我之前在学习标准库时候创建keil工程所写的笔记更为详细keil如何创建一个工程_keil新建工程-CSDN博客https://blog.csdn.net/2303_79336820/article/details/147227353二、为什么STM32采用哈弗架构而PC却采用冯诺依曼架构呢1哈弗架构、冯诺依曼架构基本定义在这里我们先给出结论哈弗架构中I/D线分离能够降低流水线气泡从而提高运行实时性这里的实时性强调的是确定性而不是足够快冯・诺依曼架构指令、数据共用同一套总线、同一个存储器地址空间。CPU 取指令和读写数据要争抢同一条总线无法并行访问。哈佛架构指令、数据拥有互相独立的两套总线指令通路、数据通路物理分开可以同时取指令 读写数据。2从指令流水线角度分析性能差异由于计算机组成原理的设计一条指令运行需要按照以下周期顺序即取指周期---间指周期---执行周期---中断周期。在冯诺依曼架构中指令和数据是通过一条线传输的如果你的执行周期刚好是拷贝数据那么本应该流水线同步进行的取指会受到一定推迟产生气泡。然后等到该拷贝执行周期结束后才能取指执行其余操作。这意味着冯诺依曼架构在面临大量数据修改、拷贝的场景很容易产生流水线气泡降低整体的运行效率。而哈弗架构中指令和数据是分开的两条路径即使当前的执行周期是数据拷贝相关的工作指令仍然能正常加入到CPU中从而流水线的执行CPU中没有使用到的硬件单元如ALU等。从而减少流水线气泡出现的可能提高整体运行效率。而这一点点的提升在电机控制FOC等场景中极为关键能大大提高实时性所以STM32这种强调实时的MCU就会采用哈弗架构了。不过在现代计算机中通常会结合二者的优势即在靠近CPU设计缓存使用哈弗架构分为两条路径减少气泡而在远离CPU的内存处使用冯诺依曼架构让操作系统等复杂软件工作在同一地址空间内更加方便修改。3ST官方参考手册中的结构图因为官方手册就是这样描述的但是不知道为什么图却画错了。这一点对于我们上面分析流水线气泡有了更深入的理解哈弗架构中对于气泡的提升仅仅限于常量而变量仍然会存在于内存中从system-bus路径走容易与其他外设访存冲突形成冯诺依曼中同样的气泡问题。不过单片机场景通常是固定的代码Flash更为频繁。所以哈弗架构已经一定程度上提高了实时性。三、统一编址CPU只看得到存储空间无需分辨外设1统一编址与独立编址刚刚我们讨论的是哈弗架构中数据、指令流转过程中的性能问题但各个外设、内存的数据是怎么被CPU访问到的呢难道CPU需要有识别不同外设的能力吗其实CPU才不管这些在CPU的视角看所有的外设、内存都只是一个存储空间。我CPU只是发送指令告诉总线去哪个地址访问数据至于区分动作则是总线矩阵来实现的。上面这种编址方式称为存储器统一编址存储器映射 I/O另一种叫做独立编址I/O 映射 I/O典型为 X86 架构。CPU 拥有两套完全隔离的地址空间访问内存、访问外设端口需要使用两套不同的访问指令。2STM32的存储器映象统一编址的小缺点与常见地址分段STM32采用的就是统一编址模式在数据手册中会有如下图片很明显的看到ST将外设、内存、Flash等不同的硬件组件分别映射到了不同的地址范围内。完美的将32位CPU的4GB空间划分成block了。但统一编址也带来了一个缺点外设的地址空间会占用一部分地址空间会挤占可供内存使用的地址范围。不过单片机场景内存需求不大这个影响可以忽略。 独立编址最早诞生于古老的 16 位 x86 处理器当时 CPU 总内存地址仅有 1MB地址资源十分宝贵所以把外设放到完全独立的 IO 端口空间避免抢占有限的内存地址。到 32 位 PC 时代X86 变成独立编址 MMIO 统一编址两套机制共存。逐渐延续至今。