一、系统架构(中等容量芯片):
1.1组成部分
主系统由以下部分组成
1.1.1四个驱动单元:
Cortex—M3内核DCode总线(D-bus),和系统总线(S-bus);
通用DMA1和DMA2;
1.1.2四个被动单元:
SRAM(存储程序运行过程中产生的变量)
AHB到APB的桥1.2连接所有APB的设备
FSMC(静态存储控制器)
内部闪存存储器FLASH
这些都是通过一个多级的AHB总线架构相互连接的
如下图:
1.2总线介绍:
1.2.1ICode总线(指令总线)
将内核的指令总线与闪存指令接口相连接,指令预取在此总线上完成;
1.2.2DCode总线(数据总线)
将内核的数据总线与FLASH存储器的数据接口相连接(常量加载和调试访问);
1.2.3系统总线
将内核的系统总线(外设总线)到总线矩阵,总线矩阵协调内核与DMA间的访问;
1.2.4DMA总线
将DMA的AHB主控接口与总线矩阵相连,总线矩阵协调CPU的Dcode和DMA到SRAM,闪存和外设的访问;
1.2.5总线矩阵
协调内核系统总线和DMA主控总线之间的访问仲裁;
AHB外设通过总线矩阵与系统总线相连,允许DMA访问;
1.2.AHB/APB桥
俩个AHB/APB在AHB和俩个APB总线间提供同步连接,APB1限速36MHZ(内部低速总线),APB2(内部高速总线)限速72MHzz
二、存储器
2.1概念
程序存储器,数据存储器,寄存器和输入输出端口,被组织在同一个4G线性地址空间中;
可以通过地址的方法访问对应的存储器或寄存器
数据字节以小端的格式存放在寄存器中,一个字中的最低地址字节认为最低有效字节;
存储器主要分为八个主要空间块;
每块是512MB*8=4G;
0X0000 0000~0XFFFF FFFF;
2.2存储器的映像图
编程时如果要操作寄存器,找到起始地址,找到要配置的寄存器,找到偏移+起始地址,就是某一个寄存器的地址,然后操作某些位;
三、启动方式
可以通过BOOT[1:0]引脚选择三种不同的启动模式;
使用的STM32F103C8;
BOOT0:0
BOO1:0
对应启动方式 :从内部Flash中启动;
存储器的映射:0x0000 0000 ——0x0800 0000 映射的内部FLASH
四、启动文件
4.1产品分类
具体选择哪一个.s汇编文件,作为启动文件,根据容量和类型来选择;
分为:cl.s, hd.s, vl.s, ld.s, md.s, xl;
ld小容量:小于64kb;
md, 中容量:64kb和128kb;
hd大容量产品:大于128kb
cl:互联型产品: f105,f107系列;
vl:超值型产品: f100系列;
xl:超高密度产品:f101,f103系列;
stm32f103c8:选择启动文件-->c-64kb ,f通用性,103子产品系列 增强型-->startup_stm32f10x_md
4.2启动过程分析
创建了栈的大小;
1024个字节,1k大小;操作权限:读写,对齐方式:八字节对齐;
向量表的映射首地址RESET是0;reset复位从0地址开始,第一个执行就是reset;
异常向量表:
栈的顶部;
上电或者按下复位第一个启动就是:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
把SystemInit放在R0寄存器中,跳转到RO寄存器中去执行;首先执行的就是 SystemInit;
LDR R0, =SystemInit
4.2.1SystemInit函数作用:
初始化闪存接口
初始化设置PLL,并更新
初始化系统时钟;
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
把__main放到R0中,然后执行,也就是说执行的第二个函数,就是__main;
4.2.2__main函数的作用
*__main-属于C库的函数,功能是第一个完成全局/静态变量的初始化,第二个初始化堆栈,第三个库函数的初始化,第四个程序的跳转进入用户main函数入口;
LDR R0, =__main
BX R0