Cortex-M3内核或M4/M7等和调试系统都是ARM公司设计,由ARM公司授权给其他芯片厂商,由其他芯片厂商添加内部总线、外设、存储器、时钟和复位 、IO以及芯片外部的外壳。除了内核和调试系统都是有芯片制造商设计开发,比如说ST公司等等。总结成一句话:MCU厂商,经ARM公司授权(授权内核、调试系统,调试系统内嵌到内核里面,绑定在一起的),添加不同的外设 = 各种XX32芯片(例如:ST公司的STM32,还有其他公司的APM32、GD32、MM32、HC32等》)。
上表中的AHB为高级高性能总线,APB为高级外围总线,二者之间需要一个连接的桥梁。主动单元可以主动发起通信或者给被动单元发送工作指令,被动单元不能向主动单元发送, 该内容参考STM32F10xxx参考手册_V10(中文版).pdf 2.1小节。
下图是F1系统框架简图,以总线矩阵为分界线,左侧为主动单元,总共有四个主动单元,DCode总线也就是D-Bus,System总线也就是S-Bus,以及DMA1和DMA2;右侧为被动单元,要访问APB1或者APB2上的外设,就要经过AHB系统总线再经过桥才能访问挂载在APB1或者APB2上的外设。ICode总线直接连接Flash接口,不需要经过总线矩阵,所以ST公司并没有将其罗列进主动单元或者被动单元,它也属于主动单元,只是没有列进去,没有经过总线矩阵。FLASH中存储程序,内核就可以不通过总线矩阵直接读取程序指令,因为总线上很多条路,可能需要等待。
在F1系列中官方给定最大时钟频率为72MHz(不考虑超频的情况,正常稳定工作为72MHz),总线时钟频率:AHB:72MHz (Max);APB1:36MHz (Max);APB2:72MHz (Max)。分APB1和APB2不同频率总线的原因是,不同外设需要的频率不同,满足不同外设的频率需求。
在STM32F103ZET6数据手册中,首先找到总线矩阵(Bus Matrix),然后找到四个主动单元、四个被动单元。
下图为M3内核,左侧为芯片外部的接口,可以理解为引出到芯片引脚上的接口,左侧上半部分是跟踪调试用不到,下半部分是下载仿真接口,比如说JTAG接口、SWD接口,右侧的为跟踪调试控制器和左侧上班部分一起使用也用不到。
下图AHB总线上的左侧SDIO用于连接外部的SD卡;左侧的是复位和时钟,连接外部高速晶振;下方是通向APB1和APB2的桥,APB1最大时钟频率为36MHz,右侧很多外设挂载在APB1总线上,
ICode总线也就是Ibus总线,直接连接到内部的FLASH。
当然还有简图上没有的,首先是电源部分:
电源管理部分,后面学习低功耗模式会用到,还有独立看门狗IWDG,后备区域电池VBAT 、RTC等。
此处讲解的为非互联型的小容量、中容量、大容量产品F1系列框架图,在F1系列中还有互联型产品系统框架图,也是类似的,只是添加了网口的主动单元。所以互联型产品中有5个主动单元,且有3个被动单元,在正点原子开发板都不是用的互联型的。
在F4系统架构中有8个主控总线和7个被控总线。下表中的OTG为主从、HS为高速。如果是F407芯片,将每一辅助没有SRAM3。AHB1总线包含挂载APB1、APB2、AHB1总线上的所有外设,AHB2上并没有桥。
首先还是看总线矩阵,S0-S7总共有8个对应的就是8个主控总线。竖直方向M0-M6有7个接口对应被控总线。主控总线连接的是主动发起通信的一方,有小圆圈○的代表路是通的,CCM RAM只能存数据,优点访问速度快(直接和内核连接,通过D总线连接),缺点不支持DMA。
总线时钟频率(红色对应F407,右侧为F429):
AHB1/2:168/180MHz (Max)
APB1:42/45MHz (Max)
APB2:84/90MHz (Max)
F40系统框架总图如下:
首先找到总线矩阵,左侧为8个主控总线,DMA2中有存储器、外设总线所以有根总线指向它;右侧为7个被控总线,D总线和I总线访问FLASH,AHB3其实就是简图中M6连接的FSMC静态存储器控制器;M4内核包含JTAG接口、SWD接口、调试跟踪接口(用不到)、MCU、ETM、NVIC、FPU。CCM data RAM只能存储数据,直接和D-BUS总线连接,被内核直接访问,速度快。AHB3主要挂载了FSMC外设,用于扩展外部存储器。
AXI多重AHB就是总线桥,一端通过AXIM总线连接内核,另一端有4个输出,其中一个用64位的总线连接到FLASH。另外三个连接到AHB总线。①上面一排就是12个主控制器,有3个接到总线桥,1个接到AHBP总线与内核连接。② 右侧为8个从控制器,右侧上方第一条是连接到内核,通过DTCM返回到RAM。DTCM RAM即可存放数据,也可存放指令。ITCM RAM支持CPU时钟速度访问,0个等待周期。
总线时钟频率:
AHB1/2:216MHz (Max)
APB1:54MHz (Max)
APB2:108MHz (Max)
AXI总线矩阵、AHB总线矩阵分成了三个域,低功耗模式时可以仅使用用到的域。①为总线主设备,②为总线从设备。
ITCM用于存放程序,DTCM用于存放数据。
总线时钟频率(主频480MHz):
AHB1/2/3/4:240MHz (Max)
APB1/2/3/4:120MHz (Max)
表中主设备18和从设备20个,表中数字21代表,经过2、1代表的总线矩阵。
32位的单片机可以有32根地址线(每根地址线有两种状态:导通或不导通);单片机内存地址访问的存储单元是按字节(8位)编址的(而不是bit)。1根地址线,有2个地址,那么最多可以访问2个字节的内存空间。
STM32寻址大小:2^32= 4G(4G是编号数,每个编号都可以访问一个字节)(字节);STM32寻址范围:0x0000 0000 ~ 0xFFFF FFFF
存储器指可以存储数据的设备(比如说SRAM、FLASH等),本身没有地址信息,对存储器分配地址的过程称为存储器映射。
下图是星忆可以的XRAM芯片,可以理解为SRAM的升级版,芯片有19根地址线(可以访问的地址编号个数为219=512K)、16根数据线(每个编号按2个字节进行编址,所以该芯片容量为2×512k=1024k=1MB)。将该芯片进行存储器映射,地址范围0512k,映射方式很多种,比如说映射到0~512k(从0x00x80000),还有其他映射方式如下所示:
上面的芯片一个地址可以访问两个字节,单片机一个地址可以访问一个字节。以下以F1系列为例,其他划分可以在正点原子任意型号开发板开发指南的5.3.3小节的存储器映射找到存储器划分。
ST将4GB(2^32)地址空间分成8个块。挂载在APB1、APB2上的外设全部映射在Block2存储块。具体的映射图可以参考STM32F103ZET6.pdf(英文版数据手册),H7系列可以查找参考手册《存储器组织结构》部分。
片内内存为64KB,其余为保留,保留空间较大,如果ST公司想扩展更多的内存,在保留空间里就可以映射很多的SRAM地址。
寄存器是单片机内部一种特殊的内存,可以实现对单片机各个功能的控制。普通的存储器SRAM只有存储数据的功能。简单来说,寄存器就是单片机内部的控制机构。学习STM32就是学习如何操作寄存器,从而来控制单片机进行工作,无论是HAL库开发、寄存器开发根本目的是操作寄存器,来控制STM32进行工作。
下面以八个开关比喻单片机内部一个8位寄存器,默认值都是0,也就是00000000,如果将右侧第一位置一,可能对单片机的某个功能产生影响。
内核寄存器可以为Cortex-M3/M4/M7内核中的寄存器,外设寄存器指的是片上外设。
寄存器是特殊的存储器,给寄存器地址命名的过程,就叫寄存器映射。将寄存器地址0x4001080C映射为寄存器名字为GPIOA_ODR,其中ODR为数据输出寄存器。
STM32的GPIO一组16个,例如PA0~PA15。① 寄存器名字,如果是A组就是GPIOA_ODR;②以GPIOA为例,基地址为0x40010800,偏移量是相对于基地址而言,则GPIOA_ODR地址为0x40010800+0x0C,寄存器复位值为0x0000 0000;③寄存器位表,寄存器从031有32个位,位1631保留;④功能描述,如果将位0置一,则GPIOA01口输出1,也就是3.3V,对寄存器位0写0,则输出0,也就是0V。
直接操作寄存器地址(地址0x4001 080C是GPIOA_ODR寄存器的地址,而对计算机而言地址只是一个数字,强转为指针类型的usigned int&
变为指针,指针就是地址,然后在前面加*
取指针的值,然后去操作该地址上的值,一次性赋值32位,也就是PA0~PA15全部输出1):
*(unsigned int *)(0x4001 080C) = 0XFFFF;
定义一个名字后再操作:
#define GPIOA_ODR *(unsigned int *)(0x4001 080C)
GPIOA_ODR = 0XFFFF;
为了方便编写代码及使用,我们将寄存器地址分为三个部分:
总线基地址:
APB1总线的基地址,也叫外设基地址(PERIPH_BASE),此表的偏移量:是相对外设基地址(PERIPH_BASE)来说的。(参考资料:STM32F10xxx参考手册_V10(中文版).pdf 2.3小节)
GPIO外设基地址及偏移量:
此表的偏移量:是相对APB2外设基地址(APB2PERIPH_BASE)来说的。
GPIOA外设基地址及偏移量:
此表的偏移量:是相对GPIOA外设基地址(GPIOA_BASE)来说的。
GPIOA_ODR寄存器地址计算过程:
1,获取外设挂在哪个总线上面?查:系统结构图
2,获取总线基地址,APB2总线基地址:0X4001 0000
3,获取外设地址偏移量,GPIOA相对APB2总线偏移量是:0X800
4,获取寄存器地址偏移量,ODR相对GPIOA外设基地址的偏移量是:0X0C
寄存器地址 = BUS_BASE_ADDR + PERIPH_OFFSET + REG_OFFSET
GPIOA_ODR = 0X4001 0000 + 0X800 + 0X0C = 0X4001 080C
使用结构体,可以很方便的完成对寄存器的映射:(详见:stm32f103xe.h,725行开始)结构体分配内存是连续的空间,每个变量是4个字节,总共28个字节,而寄存器偏移地址正好每次偏移4,刚好和该结构体对齐,所以利用该特点可以一次性映射7个寄存器地址。
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;
GPIOA_BASE: 0X4001 0800
在STM32中将基地址GPIOA_BASE
强转为GPIO_TypeDef*
类型指针,映射为GPIOA
一次性包含7个寄存器。
#define GPIOA ((GPIO_TypeDef *)GPIOA_BASE)
&GPIOA->CRL: 0X4001 0800
&GPIOA->CRH: 0X4001 0804
&GPIOA->IDR: 0X4001 0808
&GPIOA->ODR: 0X4001 080C
实际应用:
GPIOA-> ODR = 0XFFFF;