一、STM32系统框架
二、STM32的寻址范围?
三、存储器映射
四、寄存器映射
五、总结
ARM Cortex-M3 内核的总线结构以及相关概念。以下是对其中一些术语的简要解释:
总线矩阵是用于连接主动单元(主要是处理器内核)和被动单元(外设)的关键组件。它负责协调和管理数据和指令的传输,确保有效地连接不同的单元。在 ARM Cortex-M3 内核中,总线矩阵是连接 DCode 总线和 System 总线的关键组成部分。
AHB 到 APB 桥:
AHB 到 APB 桥是被动单元的一部分,它连接着所有的 APB 外设。这个桥是主动单元和被动单元之间的桥梁,允许数据在高性能总线(AHB)和外围总线(APB)之间传输。
外设:
外设是连接到被动单元的各种设备,如传感器、通信模块等。它们通过 APB 连接到主动单元,与 Cortex-M3 内核进行通信。
各个单元的工作时钟频率是至关重要的。在 ARM Cortex-M3 内核中:
这些频率指定了各个总线的最大工作速度,影响着整个系统的性能。
这样,通过总线矩阵的管理,主动单元和被动单元之间实现了高效的数据和指令传输,形成了 ARM Cortex-M3 内核的总线架构。
Cortex-M3 内核:
ARM Cortex-M3 是 ARM 公司推出的低功耗、高性能的 32 位 RISC 处理器内核。它通常用于嵌入式系统,具有较小的体积和功耗。
DCode 总线(D-Bus):
DCode 总线是用于连接 Cortex-M3 内核和 Flash 存储器的总线,用于传输数据。
System 总线(S-Bus):
System 总线用于连接 Cortex-M3 内核与外设和其他系统组件之间的通信。它负责处理系统中的数据和指令传输。
ICode 总线:
ICode 总线直接连接 Flash 存储器接口,用于指令传输。它不需要经过总线矩阵,以提高指令读取的效率。
DMA(直接内存访问):
DMA 是一种数据传输机制,允许外设和内存之间的直接数据传输,而无需 CPU 的干预。这有助于提高系统性能。
AHB(高级高性能总线):
AHB 是 Cortex-M3 内核连接到系统中高性能设备的总线。它是一种高级别总线,用于连接高性能的模块。
APB(高级外围总线):
APB 是 Cortex-M3 内核连接到外设的总线。它是一种低功耗、低速率的总线,适用于连接外围设备。
总线时钟频率:
描述了各个总线的最大时钟频率。AHB 的最大时钟频率为 72MHz,APB1 的最大时钟频率为 36MHz,APB2 的最大时钟频率为 72MHz。这些频率是系统中各个总线的最大工作频率。
总体而言,这些概念构成了 ARM Cortex-M3 内核及其周边组件的总线架构,提供了灵活而高效的数据和指令传输机制。
参考:STM32F10xxx参考手册_V10(中文版).pdf 2.1小节
路径:战舰 V4\资料\8,STM32参考资料\2,芯片资料\STM32F10xxx参考手册_V10(中文版).pdf
战舰 V4\资料\7,硬件资料\STM32F103ZET6(中文版).pdf
STM32F103xC、STM32F103xD和STM32F103xE增强型模块框图
F4 系列的系统架构包括主控总线和被控总线,这些总线连接了各种核心和外设,为处理器提供了高效的数据和指令传输通道。
Cortex M4 内核 I 总线:
连接 Cortex-M4 内核的指令总线,负责指令的读取。
Cortex M4 内核 D 总线:
连接 Cortex-M4 内核的数据总线,负责数据的读写。
Cortex M4 内核 S 总线:
连接 Cortex-M4 内核的系统总线,用于核心和外设之间的通信。
DMA1 存储器总线:
连接 DMA1 控制器和存储器,用于实现 DMA 操作。
DMA2 存储器总线:
连接 DMA2 控制器和存储器,支持存储器访问的 DMA 操作。
DMA2 外设总线:
连接 DMA2 控制器和外设,用于外设之间的数据传输。
以太网 DMA 总线:
专门用于连接以太网控制器的 DMA 总线。
USB OTG HS DMA 总线:
专用于连接 USB OTG 控制器的 DMA 总线。
内部 FLASH Icode 总线:
用于连接内部 Flash 存储器的指令总线。
内部 FLASH Dcode 总线:
用于连接内部 Flash 存储器的数据总线。
主要内部 SRAM1(112KB):
连接主要的内部 SRAM 区域,用于存储数据。
辅助内部 SRAM2(16KB):
连接辅助的内部 SRAM 区域,提供额外的存储空间。
辅助内部 SRAM3(64KB):
适用于某些型号(如 F42xxx 和 F43xxx),提供额外的内部 SRAM。
AHB1 外设(包括 AHB-APB 总线桥和 APB 外设):
连接 AHB1 外设总线,包括连接到 AHB-APB 总线桥的外设和直接连接到 AHB1 的外设。
AHB2 外设:
连接 AHB2 外设总线,用于连接直接连接到 AHB2 的外设。
CCM RAM 是 Core-Coupled Memory RAM,专用于存储数据,具有快速的访问速度,但不支持 DMA 操作。
这些频率限制了各个总线和外设的工作速度,影响着系统的性能。总体而言,F4 系列的系统架构提供了高度灵活性和性能,适用于不同应用场景的需求。
摘自:STM32F4xx参考手册_V4(中文版).pdf 2.1小节
路径:F429、F767\资料 A盘\8,STM32参考资料\STM32F4xx中文参考手册.pdf
摘自:STM32F7xx参考手册_V2(中文版).pdf 2.1小节
F7 系列的系统架构包括主系统架构和多重 AHB 总线矩阵,为 Cortex-M7 处理器提供高效的数据和指令传输通道。
AXI 转 AHB 总线桥:
AHB 总线矩阵:
多重 AHB 总线矩阵:
3x32 位 AHB 总线:
连接到内嵌 Flash 的 64 位 AHB 总线:
AHBP 总线:
DMA1 存储器总线:
DMA2 存储器总线:
DMA2 外设总线:
以太网 DMA 总线:
USB OTG HS DMA 总线:
LCD 控制器 DMA 总线:
DMA2D 存储器总线:
AHB 总线上的内嵌 Flash:
Cortex M7 AHBS 从接口:
主 SRAM1(240KB):
辅助 SRAM2(16KB):
AHB1 外设(包括 AHB-APB 总线桥和 APB 外设):
AHB2 外设:
FMC(外部存储器接口):
Quad SPI(四通道串行外围设备接口):
DTCM RAM:
ITCM RAM:
F7 系列的系统架构提供了强大的数据通路和丰富的外设支持,适用于高性能应用。
摘自:STM32H7xx参考手册_V3(中文版).pdf 2.1小节
H7 系列的系统架构包括主系统架构、AXI 总线矩阵、两个 AHB 总线矩阵(D2 域和 D3 域)、总线桥以及域间总线。
AXI 总线矩阵:
AHB 总线矩阵(D2 域和 D3 域):
总线桥:
域间总线:
AHB 总线主设备:
AXI 总线主设备:
AHB 总线从设备:
AXI 总线从设备:
ITCM(指令 Tightly-Coupled Memory):
DTCM(数据 Tightly-Coupled Memory):
H7 系列的系统架构提供了高性能的总线结构,支持多领域的并行数据传输,适用于处理复杂且高性能要求的应用。
在嵌入式系统中,总线主设备与总线从设备的互连是通过总线协议来实现的。主要的总线协议包括 AHB(Advanced High-performance Bus)、APB(Advanced Peripheral Bus)、AXI(Advanced eXtensible Interface)等。以下是它们的简要说明:
AHB(Advanced High-performance Bus):
APB(Advanced Peripheral Bus):
AXI(Advanced eXtensible Interface):
总线主设备和总线从设备通过相应的总线协议进行通信。连接过程中,总线主控制器负责发起总线事务,选择通信的从设备,并将数据传输到或从从设备读取。通信的具体协议规定了数据传输的格式、时序和控制信号。
在总线互连中,总线主设备通过总线协议的特定信号(例如,地址线、数据线、控制线等)与总线从设备进行数据传输。这种互连方式是基于硬件设计的总线架构,确保系统中的各个部件可以有效地协同工作。
STM32的寻址范围是从0x00000000到0xFFFFFFFF,即32位寻址范围,对应4GB的内存空间。这个范围包括了Flash存储器、SRAM(静态随机存储器)、外设寄存器等。在这个范围内,不同的地址区域用于存放程序代码、数据、系统寄存器等。
以下是一些常见的STM32地址范围:
这个寻址范围是非常大的,但实际上,不同的STM32型号可能只使用其中的一部分,具体的使用范围和映射关系需要查看芯片的数据手册。
在通常的32位单片机中,地址线的数量通常是32根,而每根地址线上有两种状态(高电平或低电平),因此总共有2^32个不同的地址。
32位的单片机有32根地址线: 即使每根地址线有两种状态(0或1,低电平或高电平),总地址数量为2^32。
单片机内存地址访问的存储单元按字节编址: 这是正确的,每个地址代表一个字节。即,每个地址可以存储8位二进制数据(一个字节)。
地址线根数和地址编号:
这种二进制的地址编码方式允许单片机访问非常大的内存范围,但实际上,芯片的内存容量通常受限于其硬件设计和制造技术。
存储器映射(Memory Mapping)是指将计算机中的存储器(包括RAM、ROM、寄存器等)的地址空间分配给不同的硬件或软件组件,使其能够被访问和操作。存储器映射创建了一个虚拟的地址空间,通过该空间,处理器和其他外设可以有效地进行通信。
以下是存储器映射的一些关键概念:
地址空间: 存储器映射创建了一个地址空间,其中包含了所有可寻址的存储单元。这个地址空间可以被划分成若干区域,每个区域对应一个设备或组件。
地址映射: 地址映射将逻辑地址(程序中使用的地址)映射到物理地址(实际的硬件地址)。这样,程序可以使用逻辑地址来访问存储器,而底层硬件负责将逻辑地址映射到实际的存储器位置。
内存映射 I/O: 存储器映射技术允许将某些设备的寄存器或控制器映射到内存地址空间,以便通过读写内存的方式来访问这些设备。这被称为内存映射 I/O。
外设寄存器映射: 外设(如串口、定时器、GPIO等)通常有相关的寄存器,这些寄存器被映射到存储器地址空间中的特定地址。通过写入或读取这些地址,可以配置和控制外设的行为。
物理地址 vs. 逻辑地址: 物理地址是硬件实际使用的地址,而逻辑地址是程序员在编写软件时使用的地址。存储器映射提供了一个桥梁,使得逻辑地址能够被正确映射到物理地址上。
存储器映射的灵活性使得计算机系统可以更方便地管理和访问各种硬件和外设,提高了系统的可扩展性和可编程性。
存储器映射是指将实际的存储器分配到特定的地址范围,从而方便处理器访问和控制。
对于星忆XM8A51216芯片,有19根地址线(A0到A18)和16根数据线(D0到D15)。地址线的数量决定了总的地址空间大小,16根数据线表示每个地址单元可以传输16位数据。
根据地址范围和映射描述,我们可以分析如下:
映射1:0 - 512K
映射2:1 – 512K + 1
映射3:100K – 612K
映射4:512K – 1024K
这些映射可以根据系统需求和硬件设计来调整,但需要确保不同映射之间没有重叠。
对于STM32F1系列,ST将4GB的地址空间划分为8个块,每个块有不同的功能和地址范围。以下是各存储块的功能和地址范围(以STM32F1为例):
Block 0: Code(FLASH)
Block 1: SRAM
Block 2: 片上外设
Block 3: FSMC Bank1&2
Block 4: FSMC Bank3&4
Block 5: FSMC寄存器
Block 6: 没用到
Block 7: Cortex M3内部外设
这样的划分使得不同的存储块用于不同的目的,有效地利用了整个32位地址空间。
对于 Block 0(FLASH),这里具体的功能划分如下:
FLASH或系统存储器别名区
保留
用户FLASH,用于存储用户代码
保留
系统存储器,存储出厂Bootloader
选项字节,配置读保护等
保留
这样的划分充分利用了 Flash 存储器的不同区域,包括用户代码区、系统存储器区、选项字节等,以满足不同的需求和配置。
对于 Block 1(SRAM),功能划分如下:
SRAM
保留
这样的划分使得 Block 1 主要用于存储数据,例如变量、缓冲区等,提供了一定的存储空间供程序运行使用。
对于 Block 2(外设),功能划分如下:
APB1总线外设
保留
APB2总线外设
保留
AHB总线外设
保留
这样的划分使得 Block 2 主要用于存储外设寄存器的地址,可以通过这些地址访问外设的寄存器来进行配置和控制。
参考资料:STM32F103ZET6.pdf(英文版数据手册)
数据手册:4 Memory mapping \ Figure 9. Memory map
路径:战舰 V4\资料\7,硬件资料\STM32F103ZET6.pdf
参考资料:STM32F10xxx参考手册_V10(中文版).pdf
路径:战舰 V4\资料\8,STM32参考资料\STM32F10xxx参考手册_V10(中文版).pdf
寄存器映射是指将每个寄存器分配一个唯一的地址,以便在程序中通过这个地址来访问寄存器。在嵌入式系统中,寄存器通常用于配置和控制外设、存储状态信息等。通过寄存器映射,程序可以通过读写特定的内存地址来实现对寄存器的访问。
在微控制器或微处理器的设计中,不同的寄存器用于不同的目的,例如配置、控制、状态检测等。这些寄存器的地址被定义为特定的数值,程序可以通过这些地址与寄存器进行交互。对于每个寄存器,通常都会有相应的位域,用于表示不同的配置选项、状态标志等信息。
以下是一个简化的例子,展示了寄存器映射的一部分:
地址: 寄存器
0x40000000: 控制寄存器
0x40000004: 数据寄存器
0x40000008: 状态寄存器
0x4000000C: 配置寄存器
...
通过访问这些地址,程序可以读取或写入相应的寄存器,从而实现对硬件的配置和控制。在编程时,开发者通常会使用硬件手册或数据表来查找寄存器的地址和相关的位域信息。
STM32寄存器主要可以分为两大类:内核寄存器和外设寄存器。
内核相关寄存器: 包括 R0~R15 寄存器,xPSR 寄存器,以及一些特殊功能寄存器。这些寄存器用于处理器的基本操作和状态管理。
中断控制寄存器: 包括 NVIC(Nested Vectored Interrupt Controller)和 SCB(System Control Block)相关寄存器。在 NVIC 中,有一系列寄存器用于控制中断的使能、优先级等,如 ISER(Interrupt Set Enable Register)、ICER(Interrupt Clear Enable Register)、ISPR(Interrupt Set Pending Register)等。SCB 包含一些系统级别的控制寄存器,如 VTOR(Vector Table Offset Register)、AIRCR(Application Interrupt and Reset Control Register)等。
SysTick 寄存器: 包括 CTRL(Control Register)、LOAD(Reload Value Register)、VAL(Current Value Register)和 CALIB(Calibration Value Register)四个寄存器。SysTick 是一个用于实现系统时钟节拍的定时器。
内存保护寄存器: 这些寄存器用于配置存储器的保护机制,但在一些 STM32 系列中可能并不包含。
调试系统寄存器: 包括 ETM(Embedded Trace Macrocell)、ITM(Instrumentation Trace Macrocell)、DWT(Data Watchpoint and Trace)等相关寄存器。这些寄存器用于支持调试和跟踪功能。
外设寄存器包括 STM32 上各种外设的配置和控制寄存器。这些外设寄存器用于配置和控制与 MCU 相连接的外围设备,如 GPIO、UART、I2C、SPI、TIM(定时器)、DMA、ADC、DAC、RTC(实时时钟)、I/WWDG(看门狗)、PWR(电源管理)、CAN(控制器局域网)、USB(通用串行总线)等。每个外设通常都有一组寄存器用于控制其行为、配置参数等。
在 STM32 系列中,每个寄存器都有其特定的地址,该地址通常采用寄存器映射的方式进行命名。给定一个例子,如寄存器地址 0x4001080C
和寄存器名字 GPIOA_ODR
:
0x4001080C
GPIOA_ODR
这表示该寄存器的物理地址是 0x4001080C
。在 STM32 系列中,寄存器名字通常包含外设名和功能描述,以便更好地理解和识别该寄存器的用途。在这个例子中,GPIOA_ODR
可能是 GPIO(通用输入/输出)模块中的一个输出数据寄存器(Output Data Register),用于控制 GPIOA 端口上的输出状态。
通常,具体的寄存器映射和寄存器名字的含义可以在 STM32 的参考手册或数据手册中找到,这些手册由芯片制造商提供,详细描述了芯片的内部结构、外设功能和寄存器的使用方法。
参考资料:STM32F10xxx参考手册_V10(中文版).pdf
当阅读芯片手册或数据手册时,寄存器描述通常包含以下几个重要部分:
寄存器名字: 这是寄存器的标识符,用于表示特定功能或外设的某个寄存器。
偏移量及复位值: 描述了该寄存器在整个寄存器映射中的偏移地址,通常给出了复位时寄存器的默认值。
寄存器位表: 列出了该寄存器的所有位,每个位对应一个特定的功能或配置选项。表格中可能包括位的名称、位的偏移量、位宽度等信息。
位功能描述: 对每个位进行详细的描述,解释了该位的作用、影响以及如何配置或使用。这是理解寄存器功能的关键部分。
让我们以具体的例子解读一个寄存器描述:
GPIOA_ODR (GPIOA output data register)
Offset: 0x14 Reset value: 0x0000 0000
Bits | 31:16 | 15:0 |
|-------|-------|
ODR | 0 | PortA |
|-------|-------|
在这个例子中:
寄存器名字: GPIOA_ODR
表示 GPIOA 端口的输出数据寄存器。
偏移量及复位值: 该寄存器的偏移量为 0x14
,复位时的默认值为 0x0000 0000
。
寄存器位表: 该寄存器只有一个位,即 ODR
,位宽度为 16 位。该位控制 GPIOA 端口的输出。
位功能描述: 该位的描述可能是 “PortA”,说明这个位用于控制 GPIOA 端口的输出状态。
这是一个简化的例子,实际的寄存器描述可能更加复杂,包含更多的位和功能描述。理解这些寄存器描述对于正确配置和使用芯片的外设非常重要。
在嵌入式开发中,直接操作寄存器地址是常见的做法。通过定义寄存器的地址,并使用指针访问这个地址,可以直接对寄存器进行读写操作。这种方式通常用于对寄存器位进行精确控制,例如配置 GPIO 的输入输出状态。
下面是一个简单的示例,演示如何通过直接操作寄存器地址或使用宏定义的方式控制 GPIOA 的输出状态:
// 直接操作寄存器地址
*(unsigned int *)(0x4001080C) = 0xFFFF; // 设置 GPIOA_ODR 寄存器的值为 0xFFFF
// 使用宏定义
#define GPIOA_ODR (*(volatile unsigned int *)(0x4001080C)) // 定义 GPIOA_ODR 的宏
GPIOA_ODR = 0xFFFF; // 设置 GPIOA_ODR 寄存器的值为 0xFFFF
在这个例子中,0x4001080C
是 GPIOA_ODR 寄存器的地址,volatile
关键字用于告诉编译器该变量是易变的,可能会被外部因素更改,因此编译器不会进行一些优化,确保每次都从内存中读取值。
使用宏定义的方式有助于提高代码的可读性和维护性。通过定义宏,可以将寄存器的地址封装在宏中,给这个地址起一个易于理解的名字,方便在代码中使用。这也是嵌入式开发中常见的一种编程风格。
寄存器地址计算的思路是将寄存器的地址拆分为三个部分,这样的设计有助于更灵活地应对不同的外设、总线等。具体而言,计算公式如下:
寄存器地址 = BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET \text{寄存器地址} = \text{BUS\_BASE\_ADDR} + \text{PERIPH\_OFFSET} + \text{REG\_OFFSET} 寄存器地址=BUS_BASE_ADDR+PERIPH_OFFSET+REG_OFFSET
其中:
这种寄存器地址计算的方法允许我们通过更改这三个部分的数值,轻松地适应不同的硬件配置和外设分布。在嵌入式系统中,通常由芯片厂商提供相应的寄存器映射表和基地址信息,开发人员可以据此进行地址计算和寄存器操作。
参考资料:STM32F10xxx参考手册_V10(中文版).pdf 2.3小节
获取外设挂在哪个总线上面?查系统结构图得知 GPIOA 外设挂在 APB2 总线上。
获取总线基地址,APB2 总线基地址为 0 X 40010000 0X4001 0000 0X40010000。
获取外设地址偏移量,GPIOA 相对于 APB2 总线的偏移量是 0 X 800 0X800 0X800。
获取寄存器地址偏移量,ODR 相对于 GPIOA 外设的基地址的偏移量是 0 X 0 C 0X0C 0X0C。
现在,可以使用寄存器地址计算公式计算 GPIOA_ODR 的地址:
GPIOA_ODR = BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET \text{GPIOA\_ODR} = \text{BUS\_BASE\_ADDR} + \text{PERIPH\_OFFSET} + \text{REG\_OFFSET} GPIOA_ODR=BUS_BASE_ADDR+PERIPH_OFFSET+REG_OFFSET
将具体数值代入:
GPIOA_ODR = 0 X 40010000 + 0 X 800 + 0 X 0 C = 0 X 4001080 C \text{GPIOA\_ODR} = 0X4001 0000 + 0X800 + 0X0C = 0X4001 080C GPIOA_ODR=0X40010000+0X800+0X0C=0X4001080C
因此,GPIOA_ODR 寄存器的地址是 0 X 4001080 C 0X4001 080C 0X4001080C。
0 X 40013804 0X40013804 0X40013804
使用结构体进行寄存器映射,可以更方便地访问和操作寄存器,提高代码的可读性和可维护性。定义一个结构体 GPIO_TypeDef
包含了 GPIO 相关寄存器的成员,然后使用结构体指针来访问寄存器,是一种常见的做法。
在上述例子中:
typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
#define GPIOA_BASE 0X4001 0800
#define GPIOA ((GPIO_TypeDef *)GPIOA_BASE)
// 访问 GPIOA 的 ODR 寄存器
GPIOA->ODR = 0XFFFF;
这样的代码更加清晰和易于维护。通过使用结构体,你可以直观地理解每个寄存器的作用,也方便了对硬件的配置和操作。
stm32f103xe.h
路径:战舰 V4\资料\4,程序源码\2,标准例程-HAL库版本\实验1 跑马灯实验\stm32f103xe.h