网站建设高端设计,哈密网站建设,长沙网站维护,网站备案 假通信地址目录 参考资料#xff1a;
利用 Boot 选择不同的启动方式#xff1a;
单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM)#xff1a;
1. Cortex-M 内核芯片——启动原理#xff1a;
1.1. 启动流程#xff1a;
1.2. 根据单片机的存储器映射和架构图#xff1a;启动…目录 参考资料
利用 Boot 选择不同的启动方式
单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM)
1. Cortex-M 内核芯片——启动原理
1.1. 启动流程
1.2. 根据单片机的存储器映射和架构图启动空间必须在代码区域0x0000 0000 ~ 0x1FFF FFFF
1.3. 地址映射原理 存储器别名(memory alias)“技术
1.3.1. 举例
1.3.2. 引出一个问题为什么可以从其他地址读 0x0000 0000 的中断向量表
1.3.3. 那么新的问题来怎么规定/配置内存重映射
1.3.4. 问题既然设置到0x0800 0000这么麻烦为什么不直接使用0x0000 0000
2. 根据不同的启动方式会将配置的启动地址(主 FLASH/系统存储器/嵌入式 SRAM)映射到 0x0000 0000(系统中断向量表) 上
2.1. 从系统存储器(System Memory)启动
2.2. 从主 Flash(Main Flash Memory)启动这个是平时使用最多的方式将程序下载到STM32内部Flash然后从Flash启动。
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
2.3. 从嵌入式 SRAM 启动内部 SRAM【比较好奇】
2.3.1. 为什么可以从 SRAM 启动
至于为什么STM32还能从SRAM启动ST官方资料https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf中的3.4节 给出的说明是
请注意从SRAM启动与在SRAM中运行代码是两个不同的概念。
2.3.2. 为什么需要从SRAM启动【应用】
2.3.3. 从 SRAM 启动
实现原理
实现步骤MCU的三种启动方式 - EdgeAI Lab
2.3.4. 【补充】在 SRAM 中运行代码
实现步骤在SRAM中运行代码 - EdgeAI Lab 参考资料
MCU的三种启动方式 - EdgeAI Lab
立芯嵌入式的视频
在SRAM中运行代码 - EdgeAI Lab
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
还有一些在标题附近 利用 Boot 选择不同的启动方式 单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM) 如上图所示STM32内部
一共有两块物理存储设备 内部 Flash内部 SRAM
三块存储区域 Main Flash Memory ——正常单片机启动方式(0x0800 0000~0x0807 FFFF)System Memory ——一般存有 BootLoader 程序(0x1FFF 0000~0x1FFF 7A0F)
一般系统存储器又叫 BootROM SRAM ——比较特殊在不想影响 FLASH 程序下调试可用(0x2000 0000)
一般调试用因为断电后数据会消失 这三块存储区域也就是STM32的三个启动空间。
1. Cortex-M 内核芯片——启动原理
1.1. 启动流程
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
M3M4内核芯片上电复位后要固定从0x0000 0000地址读取中断向量表获取复位中断服务程序的入口地址后进入复位中断服务程序
其中0x0000 0000是栈顶地址0x0000 0004存的是复位中断服务程序地址 1.2. 根据单片机的存储器映射和架构图启动空间必须在代码区域0x0000 0000 ~ 0x1FFF FFFF
存储器指可以存储数据的设备(FLASH/SRAM/ROM)本身没有地址信息对存储器分配地址的过程称为存储器映射 单片机默认启动方式 Cortex®-M3 CPU上电后开始找中断向量表 默认从0x0000 0000地址处取得栈顶地址MSP通过ICode bus从0x0000 0004地址处取得PC的值复位向量然后开始执行代码进入复位中断服务程序
因为ICode bus只能访问代码区域0x0000 0000 ~ 0x1FFF FFFF所以启动空间必须在代码区域
【ICode 总线】
1.3. 地址映射原理 存储器别名(memory alias)“技术
1.3.1. 举例
STM32内部Flash就位于代码区域采用从主 FLASH 启动方式并且通过“ 存储器别名(memory alias)“技术
代码区域——(0x0000 0000 ~ 0x1FFF FFFF)
主 FLASH——(0x0800 0000~0x0807 FFFF) 可以将STM32的Main Flash Memory的地址空间0x0800 0000 ~ 0x0801 FFFF映射到0x0000 0000 ~ 0x0001 FFFF对于System memory也是同样的道理。所以STM32可以从Main Flash Memory和System memory启动。
1.3.2. 引出一个问题为什么可以从其他地址读 0x0000 0000 的中断向量表
既然ARM规定了M3M4内核要从地址0x0000 0000读取中断向量表而STM32设置Flash地址到0x0800 0000怎么办 解决方法 STM32支持了个内存重映射功能将地址0x0800 0000开始的内容重映射到首地址0x0000 0000中这样就解决了从0x0000 0000读取中断向量表的问题。
1.3.3. 那么新的问题来怎么规定/配置内存重映射
你怎么保证0x08000 0000首地址存的就是中断向量表我们不可以随意设置吗解决方法 保证中断向量表存到0x0800 0000这个涉及到分散加载的一个小知识以MDK为例 如果大家看xxx.S启动文件里面通过AREA定义了一个名叫RESET的段这段存的就是中断向量表。
; Vector Table Mapped to Address 0 at ResetAREA RESET, DATA, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size 这个名字很重要MDK对应的xxx.sct分散加载里面通过下面这句将这个RESET段放在了0x0800 0000优先存储。
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x00200000 { ; load region size_regionER_IROM1 0x08000000 0x00200000 { ; load address execution address*.o (RESET, First)*(InRoot$Sections).ANY (RO).ANY (XO)}RW_IRAM2 0x24000000 0x00080000 { ; RW data.ANY (RW ZI)}
} 这样我们就解决了0x0800 0000首地址存储中断向量表一旦程序开始运行后我们就可以随意设置中断向量表的位置了。比如想将中断向量表存到内部SRAM我们就可以操作寄存器SCB-VTOR 重新安排然后将0x0800 0000的内容复制到设置的地址内即可。【上电启动后改为从内部 SRAM 启动】
1.3.4. 问题既然设置到0x0800 0000这么麻烦为什么不直接使用0x0000 0000
因为我们需要从不同的地址启动以达到不同的启动程序BootLoader 程序/正常 APP 应用程序M3、M4 内核 M7 内核 2. 根据不同的启动方式会将配置的启动地址(主 FLASH/系统存储器/嵌入式 SRAM)映射到 0x0000 0000(系统中断向量表) 上
2.1. 从系统存储器(System Memory)启动 System Memory中是ST预置的bootloader程序用于通过串口下载用户程序到Flash。
一般系统存储器启动的话会存放 BootLoader 程序
程序下载完毕后重新将启动模式设置为 “从Flash启动” 然后开机运行用户程序。 【BootLoader】当选择系统存储器启动从 0x0000 0000 跳转至对应地址启动映射 我们可以提前在系统存储器写入 BootLoader 程序各种通信接口的然后以该方式启动
此时用 IAP 下载工具烧录程序单片机执行 BootLoader 程序会以对应的通信接口返回指定数据符合通信要求后(收发特定数据)。
IAP 下载工具开始发送烧录程序(hex 文件)由单片机的 BootLoader 程序利用对应通信接口一一接收然后逐个刷新到 Flash 上(Flash memory-主 Flash[0x0800 0000 - 0x0807 FFFF 512KB 标定大小 ])
一般出厂会自带 Boot 程序一般系统存储器又叫 BootROM 2.2. 从主 Flash(Main Flash Memory)启动这个是平时使用最多的方式将程序下载到STM32内部Flash然后从Flash启动。
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
还是将 0x0800 0000 映射到 0x0000 0000由 AHB 总线映射 2.3. 从嵌入式 SRAM 启动内部 SRAM【比较好奇】
在SRAM中运行代码 - EdgeAI Lab
2.3.1. 为什么可以从 SRAM 启动
至于为什么STM32还能从SRAM启动ST官方资料https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf中的3.4节 给出的说明是
STM32F10xxx微控制器实现了一个特殊的机制使得STM32不仅能够从Flash memory 和 System memory启动也能够从SRAM启动。从内嵌SRAM启动SRAM仅能在地址0x2000 0000处被访问。
STM32F10xxx microcontrollers implement a special mechanism to be able to boot also from SRAM and not only from main Flash memory and System memory.Boot from the embedded SRAM: SRAM is accessible only at address 0x2000 0000.
以上说明并不清楚ST官方对此含糊其辞从SRAM启动的具体细节无从知晓但是通过实验我们发现
将STM32设置为从SRAM启动a. 配置启动模式引脚BOOT01BOOT11b. 并修改链接脚本将所有代码全部放入SRAM中系统复位后PC指针总是指向0x2000 0108。所以我们在地址0x2000 0108插入设置SP指针和PC指针的指令就可以实现从SRAM启动了。 请注意从SRAM启动与在SRAM中运行代码是两个不同的概念。
从SRAM启动 也属于在SRAM中运行代码但不同的是程序下载到SRAM后在MCU不断电的情况下程序可以一直运行并且按下复位键后可以重新运行。
在SRAM中运行代码 将所有的代码放到SRAM运行此时MCU的启动模式可以是从Main Flash Memory启动将部分代码放到SRAM运行此时MCU的启动模式可以是从Main Flash Memory启动关于在SRAM中运行代码请参考这篇文章在SRAM中运行代码 - EdgeAI Lab
2.3.2. 为什么需要从SRAM启动【应用】
可能的原因有以下几点参考资料《ARM Cortex M3 M4权威指南》15.7节MCU经典书籍 - EdgeAI Lab
所使用的设备可能具有OTP ROM仅可进行一次编程因此在最终确定前是不会将程序编程到芯片中的。有些微控制器中没有内部Flash存储器需要使用外部的存储器在软件开发期间可能会想用内部的SRAM进行测试。对于产品测试或者特定方面的测试不想改动Flash中现有的程序实现某些新功能的测试工作此时可以将测试代码下载到SRAM中运行。【在 Flash 烧一次后不想改变现有 Flash 程序但是想调试可以利用 SRAM 空间进行调试】对于Flash存储器比较小的系统可能想在启动阶段将程序从Flash复制到SRAM中以提高性能并在SRAM中执行程序以达到最佳性能。在 SRAM 中也是可以放一个小的 BootLoader 程序也可以搞 IAP 下载【应用案例Jlink 下载算法启动后跑到 SRAM 中】
2.3.3. 从 SRAM 启动
实现原理
还是将 0x2000 0000 映射到 0x0000 0000由 AHB 总线映射 实现步骤MCU的三种启动方式 - EdgeAI Lab
拿 M3(F103C8T6RAM大小为20K) 举例
修改启动模式
将引脚BOOT0BOOT1都设置为1将STM32配置为从SRAM启动。
设置中断向量表偏移
添加宏定义 VECT_TAB_SRAM 该宏定义影响的代码
// system_stm32f10x.c
// SystemInit()
#ifdef VECT_TAB_SRAMSCB-VTOR SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#elseSCB-VTOR FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
修改启动代码
按照如下所示修改startup_stm32f10x_md.s文件
; 此处省略n行代码; Vector Table Mapped to Address 0 at Reset
; 此处修改AREA RESET, DATA, READONLY 为 AREA RESET, CODE, READONLYAREA RESET, CODE, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size__Vectors DCD __initial_sp ; Top of StackDCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI HandlerDCD HardFault_Handler ; Hard Fault HandlerDCD MemManage_Handler ; MPU Fault Handler; 此处省略n行代码DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend; 下面是需要新添加的内容:DCD 0DCD 0DCD 0DCD 0DCD 0DCD 0DCD 0LDR R0, 0x20000000LDR SP,[R0]LDR R0, 0x20000004 LDR PC,[R0]ALIGN 4
; 以上是需要添加的代码; 此处省略n行代码
修改链接脚本
按照下图所示方式即可在Keil编辑器中打开链接脚本 打开链接脚本文件后将内容修改如下
; 以STM32F103C8T6为例
; 从SRAM启动终端向量表RESET段必须位于启动空间的0地址
; InRoot$$Sections 必须位于root区域执行地址与装载地址相同的区域LR_IROM1 0x20000000 0x00005000 { ;装载地址为SRAM首地址RW_IRAM1 0x20000000 0x00005000 { ;执行地址装载地址*.o (RESET, First)*(InRoot$$Sections).ANY (RO).ANY (XO).ANY (RW ZI)}
}
修改Keil中的Flash Download设置
因为是直接从SRAM启动并执行程序不需要对Flash进行操作所以把Flash相关操作全部去掉。 以上就是完整的配置现在编译项目并点击调试就能看到程序成功在SRAM中运行了。关闭调试后只要STM32不断电SRAM中的程序就可以一直运行并且按下复位键后程序会重新运行。
2.3.4. 【补充】在 SRAM 中运行代码
实现步骤在SRAM中运行代码 - EdgeAI Lab 我的原文笔记https://www.yuque.com/u41716106/ni1clp/bhxgk39vmaev9p26?singleDoc#
《【个人理解】MCU三种启动方式(Boot选择)[主Flash/系统存储器(BootLoader)/嵌入式SRAM]》