Instruction指令。我们写好的程序经过编译之后都是一条条指令,存放在FLASH 中,内核要读取这些指令来执行程序就必须通过ICode 总线,它几乎每时每刻都需要被使用,它是专门用来取指的。该总线将Cortex™-M3内核的指令总线与闪存Flash指令接口相连接。指令预取在此总线上完成。
DCode 总线是用来取数
的。
常量就是固定不变的,用C 语言中的const 关键字修饰
,是放到内部的FLASH
当中的
变量是可变的,不管是全局变量还是局部变量都放在内部的SRAM
。因为数据可以被Dcode 总线和DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过一个总线矩阵
来仲裁
,决定哪个总线在取数。该总线将Cortex™-M3内核的DCode总线与闪存存储器的数据接口相连接(常量加载和调试访问)。
系统总线主要是访问外设的寄存器(register)
,我们通常说的寄存器编程,即读写寄存器都是通过这根系统总线来完成的。此总线连接Cortex™-M3内核的系统总线(外设总线)到总线矩阵,总线矩阵协调着内核和DMA间的访问。
Direct Memory Access
即直接存储器访问.
使用DMA,cpu就不用兜圈子,所以DMA不占cpu资源.
DMA 总线也主要是用来传输数据,这个数据可以是在某个外设的数据寄存器,可以在SRAM,可以在内部的FLASH。因为数据可以被Dcode 总线和DMA 总线访问,所以为了避免访问冲突,在取数的时候需要经过总线矩阵
来仲裁,决定哪个总线在取数. 此总线将DMA的AHB主控接口与总线矩阵相联,总线矩阵协调着CPU的DCode和DMA到 SRAM、闪存和外设的访问。
总线矩阵
用于主控总线之间的访问仲裁管理,仲裁采用循环调度算法
。 有了总线矩阵,就可以让主设备和从设备进行并行访问,提升了访问效率,同时也降低了功耗。 需要注意的是,虽然总线矩阵使得多个主设备可以并行访问不同的从设备,但在一个定义的时间段内,只有一个主设备拥有总线矩阵的控制权,如果有多个主设备同时出现总线请求时就得进行仲裁。
总线矩阵协调内核系统总线和DMA主控总线之间的访问仲裁,仲裁利用轮换算法。在互联型产品中,总线矩阵包含5个驱动部件(CPU的DCode、系统总线、以太网DMA、DMA1总线和DMA2总线)和3个从部件(闪存存储器接口(FLITF)、SRAM和AHB2APB桥)。在其它产品中总线矩阵包含4个驱动部件(CPU的DCode、系统总线、DMA1总线和DMA2总线)和4个被动部件(闪存存储器接口(FLITF)、SRAM、FSMC和AHB2APB桥)。 AHB外设通过总线矩阵与系统总线相连,允许DMA访问。
参考cortex-M3手册
从AHB 总线延伸出来的两条APB2 和APB1 总线
,上面挂载着STM32 的外设。我们经常说的GPIO、串口、I2C、SPI 这些外设就挂载在这两条总线上,这个是我们学习STM32 的重点,就是要学会编程这些外设去驱动外部的各种设备。
AHB/APB桥(APB) 两个AHB/APB桥在AHB和2个APB总线间提供同步连接。
APB1操作速度限于36MHz
,APB2操作于全速(最高72MHz)。
在每一次复位以后,所有除SRAM和FLITF以外的外设都被关闭,在使用一个外设之前,必须设置寄存器RCC_AHBENR来打开该外设的时钟。
注意: 当对APB寄存器进行8位或者16位访问时,该访问会被自动转换成32位的访问:桥会自动将8位或者32位的数据扩展以配合32位的向量。
内部的闪存存储器即FLASH,我们编写好的程序就放在这个地方。内核通过ICode 总线来取里面的指令。
内部的SRAM,即我们通常说的RAM,程序的变量,堆栈等的开销都是基于内部的SRAM。内核通过DCode 总线来访问它。
FSMC 的英文全称是Flexible static memory controller
,叫灵活的静态的存储器控制器
,是STM32F10xx 中一个很有特色的外设,通过FSMC,我们可以扩展内存,如外部的SRAM,
NANDFLASH(与非门闪存)和NORFLASH(非门闪存)。
注意:FSMC 只能扩展静态的内存,即名称里面的
S:static,不能是动态的内存,比如SDRAM 就不能扩展。
存储器本身没有地址,给存储器分配地址的过程叫存储器映射
被控单元的FLASH,RAM,FSMC 和AHB 到APB 的桥(即片上外设),这些功能部件共同排列在一个4GB 的地址空间内。操作时通过C语言访问地址.
存储器映射是指把芯片中或芯片外的FLASH,RAM,外设,BOOTBLOCK等进行统一编址。即用地址来表示对象。用户只能用而不能改。用户只能在挂外部RAM或FLASH的情况下可进行自定义。
Cortex-M3是32位的内核,因此其PC指针可以指向2^32=4G的地址空间,从0x0000_0000到0xFFFF_FFFF空间。
对比一下Cortex-M3存储器结构:
图中可以很清晰的看到,STM32的存储器结构和Cortex-M3的很相似,stm32还添加了flash和SDRAM.
STM32的存储器地址空间被划分为大小相等的8块区域,每块区域大小为512MB。
对STM32存储器知识的掌握,实际上就是对Flash和SRAM这两个区域知识的掌握。因此,下面将重点描述Flash和SRAM的知识。
存储器本身没有地址,给存储器分配地址的过程叫存储器映射.
在存储器Block2 这块区域为片上外设
,它们以四个字节为一个单元,共32bit,每一个单元对应不同的功能,当我们控制这些单元时就可以驱动外设工作。我们可以找到每个单元的起始地址,然后通过C 语言指针的操作方式来访问这些单元,如果每次都是通过这种地址的方式来访问,不仅不好记忆还容易出错,这时我们可以根据每个单元功能的不同,以功能为名给这个内存单元取一个别名,这个别名就是我们经常说的寄存器
,这个给已经分配好地址的有特定功能的内存单元
取别名的过程就叫寄存器映射
。
基地址
偏移地址
寄存器地址访问
//常规写法
#define GPIOB_ODR (unsignedint*)(0x40010c0c)
* GPIOB_ODR = 0xFF;
//类似封装的写法
#define GPIOB_ODR *(unsigned int *)(GPIOB_BASE+0x0C)
//指针套一个指针 基地址+偏移地址 = 0xFFFF
GPIOB_ODR = 0xFF;
ODR:output data register
这样编程效率低,所以诞生了库函数,然后又有基于cmsis的HAL库编程.
以下是STM32参考手册RM0008中的一段原话:
不同类型的STM32单片机的SRAM大小是不一样的,但是他们的起始地址都是0x2000 0000,终止地址都是0x2000 0000+其固定的容量大小。
SRAM的理解比较简单,其作用是:
用来存取各种动态的输入输出数据、中间计算结果以及与外部存储器交换的数据和暂存数据。
STM32的Flash,严格说,应该是Flash模块。
对闪存编程参考STM32F10xxx闪存编程参考手册
.
该Flash模块包括:
Flash主存储块(Main memory)
Flash信息块(Information block)
Flash存储接口寄存器块(Flash memory interface)
三个组成部分分别在0x0000 0000到0xFFFF FFFF不同的区域,如图(小容量的STM32)所示:
图中完全可以看出Flash模块中的三个组成部分在整个存储器中的位置。
具体的内部区域的意义及功能请参见编程手册PM0042,里面很详细。
Peripherals:外设的存储器映射,对该区域操作,就是对相应的外设进行操作;
SRAM:运行时临时存放代码的地方;
Flash:存放代码的地方;
System Memory:STM32出厂时自带的你只能使用,不能写或擦除;
Option Bytes:可以按照用户的需要进行配置(如配置看门狗为硬件实现还是软件实现);
后面就可以编写代码、程序运行、寄存器设置、ICP、IAP.