随言:

目前的电子产品功能越来越多,随之而来的就是代码越来越庞大,代码所需要的存放空间也越来越大。

比如:用ST做GUI界面,面临最大的问题就是芯片内部flash最大才2M。在现在这个时代,2M其实也放不了几张图片。

故ST在某些M4 M7内核芯片上增加了QSPI外设,让用户把代码放在外部存储执行。

也同时提供了两种代码启动方式 XiP 和 BootROM模型。

STM32CubeIDE QSPI间接模式和内存映射模式 读写W25Q64:STM32CubeIDE QSPI间接模式和内存映射模式 读写W25Q64_sudaroot的博客-CSDN博客_qspi内存映射

MDK KEIL 下载算法外部存储QSPI FLASH:MDK KEIL 下载算法程序 外部存储QSPI FLASH_sudaroot的博客-CSDN博客

STM32CubeProgrammer STM32CubeIDE下载算法  外部存储QSPI Flash:STM32CubeProgrammer STM32CubeIDE下载算法 外部存储QSPI Flash_sudaroot的博客-CSDN博客

参考资料:

文档:

ST官网或者ST社区搜索文件索引号:AN5188

《AN5188 Application note External memory code execution on STM32F7x0 Value line and STM32H750 Value line MCUs》

例程:

..\STM32Cube\Repository\STM32Cube_FW_H7_V1.8.0\Projects\STM32H750B-DK\Templates

正文:

刚才提到有两种启动代码方式: XiP 和 BootROM。

其实就是个bootloader,加上个用户APP。不知道的bootloader的IAP的文章写的好详细了。

而APP就是我们写的产品功能逻辑业务代码了。

1、XiP

XiP: 在从外部闪存(QSPI或FMC-NOR闪存)“就地执行”。 用户应用程序代码应与目标执行存储器地址(外部QSPI或FMC-NOR闪存)链接。

上面这1句话意思是:XiP是可以在外部闪存直接执行代码的,就像芯片在内部flash 的地址0x0800 0000直接执行一样,称为“就地执行”。

上面这2句话意思是:用户应用程序代码编译的时候链接地址要改成外部闪存的地址,如STM32 H7系统给QSPI Flash在系统总线分配的地址是0x9000 0000,那么代码的地址就要改成0x9000 0000。

XiP模型基于直接从用于代码存储的外部非易失性存储器中执行代码。 此执行模型需要内存映射支持,以授予CPU对已执行代码的用户应用程序的直接访问权。 XiP模型可通过FMC / QSPI接口在外部NOR / QSPI闪存上使用。

下面的流程图显示了XiP模型的操作流程(英文不好没关系,看中文)。

小结:首先你要知道XiP启动方式是一个bootloader,这个bootloader做了一件很与众不同的事情就是把QSPI FLASH映射到了系统总线0x9000 0000 这个地址上。

映射上去以后,只要我们访问0x9000 0000这个地址,系统总线就会自动去读QSPI FLASH 0地址的数据。记住是自动去读,

比如:uint32_t temp = *((uint32_t *)0x90000000)就能直接拿到QSPI FLASH第0~3地址数据。

当映射完成后自然是准备跳转到用户程序执行。准备工作就是关闭全部中断和cache。

2、BootROM

BootROM: 从内部闪存启动,配置外部RAM存储器(SDRAM或SRAM),从代码存储区复制用户应用程序二进制文件(SDCARD或SPI-Flash存储器)连接到外部SDRAM或外部SRAM,然后跳转到用户应用程序。 用户应用程序代码应与目标执行存储器地址(外部SDRAM或SRAM)链接。

BootROM模型基于从选定的易失性内存执行的代码。当二进制数据存储在没有内存映射接口的内存中时,这种执行模型是合适的(比如SDCARD)。当二进制数据存储在吞吐量较低的内存中(如用于SPI-NOR(使用具有一行的QSPI进行模拟)时,此模型也适用)。根据的用户配置,外部内存引导应用程序配置了以下两个易失性内存:SDRAM、SRAM、PSRAM或内部SRAM。在此模型中,在外部内存引导应用程序执行之前,二进制数据将从非易失性内存复制到一个易失性内存。第二个易失性存储器用于数据。

下面的流程图说明了BootROM模型的操作流程。

小结:这种模型就很通用了,适用于凡是有FMC能驱动外部RAM的任意一款ST芯片。细看流程图其实就是把外部的ROM复制到外部的RAM(如SRAM, SDRAM),然后在外部RAM上“就地执行”。

当然编译时的链接地址肯定是外部RAM的地址了。至于外部ROM随意都可以,什么SPI FLASH、TF卡、I2C存储器都可以,无非就是复制到外部RAM慢一点,启动慢一点。最后跳转到外部RAM运行用户程序。

比如:STM32F407ZG + SRAM(32MB) + TF卡,把程序编译成二进制放到TF卡里面,每当我把新的程序更新到TF卡,运行的程序就更新了,就有点像玩Linux TF卡启动的感觉了。

如果是SPI FLASH则需要重新写下载算法。这个模型很有意思...~!@#

3、XiP模型bootloader编写

首先,你要准备好一份测试过没有问题QSPI FLASH 代码,

我以前做过笔记,STM32CubeIDE QSPI间接模式和内存映射模式 读写W25Q64:STM32CubeIDE QSPI间接模式和内存映射模式 读写W25Q64_sudaroot的博客-CSDN博客_qspi内存映射

故我自己复制粘贴就好了,由于这次我用的是STM32H750VB + W25Q64硬件,还要微微调整一下。

static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *QSPIHandle);这些函数在上面文章讲过了,这不讲了。

#include <stdio.h>
#include "w25qx_qspi.h"typedef  void (*pFunction)(void);#define APPLICATION_ADDRESS            QSPI_BASEstatic uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *QSPIHandle);pFunction JumpToApplication;int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* Enable I-Cache---------------------------------------------------------*/SCB_EnableICache();/* Enable D-Cache---------------------------------------------------------*/SCB_EnableDCache();/* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_QUADSPI_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 */printf("Sudaroot XiP BootLoader\r\n");/* 1.W25Qx Init */W25Qx_QSPI_Init();/* 2.Enable MemoryMapped mode */QSPI_EnableMemoryMappedMode(&hqspi);/* 3.Disable CPU L1 cache before jumping to the QSPI code execution *//* Disable I-Cache */SCB_DisableICache();/* Disable D-Cache */SCB_DisableDCache();/* 4.Disable Systick interrupt */HAL_SuspendTick();/* 5.Initialize user application's Stack Pointer & Jump to user application */JumpToApplication = (pFunction) (*(__IO uint32_t*) (APPLICATION_ADDRESS + 4));__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);JumpToApplication();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}/*** @brief  Configure the QSPI in memory-mapped mode* @retval QSPI memory status*/
static uint32_t QSPI_EnableMemoryMappedMode(QSPI_HandleTypeDef *QSPIHandle)
{QSPI_CommandTypeDef      s_command;QSPI_MemoryMappedTypeDef s_mem_mapped_cfg;/* Configure the command for the read instruction */s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;s_command.Instruction       = QUAD_INOUT_FAST_READ_CMD;s_command.AddressMode       = QSPI_ADDRESS_4_LINES;s_command.AddressSize       = QSPI_ADDRESS_24_BITS;s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;s_command.DataMode          = QSPI_DATA_4_LINES;s_command.DummyCycles       = 6;s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_HALF_CLK_DELAY;s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;/* Configure the memory mapped mode */s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;s_mem_mapped_cfg.TimeOutPeriod     = 0;return HAL_QSPI_MemoryMapped(QSPIHandle, &s_command, &s_mem_mapped_cfg);
}int __io_putchar(int ch)
{HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 1000);return ch;
}

4、BootROM模型bootloader编写

我有空就写,或者自己去看ST的例程。用的比较少。

5、经验分享

1、做这个bootloader的系统时钟一定要和APP的系统时钟一致,否则跳转到APP后在初始化时

系统时钟导致不一致,总线去读取QSPI FLASH的数据都是错的,程序必然跑飞卡死。其中主要是QSPI时钟。

2、在bootloader 中QSPI内存映射后,系统会把QSPI当做系统一部分。故不能在APP初始化或者使用关于QSPI外设的事物。

如不能使用QSPI flash的引脚   或者  不能重新初始化QSPI外设,否则则跑飞。切记~!!!

6、结束

在这里肯定有人疑惑哪个模型好运行速度快?

我只想说适合你的项目就好了,不用纠结。

非要说速度快的,还有一种模型,混合运行的模型。

把启动相关和想快速运行的代码链接地址设置内部flash上,把一些不重要的代码链接地址放在外部ROM上。

这样就没有bootloader和APP这个概念了,就是一个程序了,但是还是少不了定制下载算法。

全篇完。

本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。
笔记是以最简单的方式,只展示最核心的原理。
若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。
若无积分等无法下载源码,可加入QQ群657407920下载交流经验。感谢~!

STM32CubeIDE XiP 和 BootROM介绍, XiP外部内存QSPI FLASH执行用户代码相关推荐

  1. BEP 7:CUDA外部内存管理插件(下)

    BEP 7:CUDA外部内存管理插件(下) Numba依赖 向库中添加EMM插件的实现自然会使Numba成为库的依赖项,而以前可能没有.为了使依赖关系可选,如果需要的话,可以有条件地实例化并注册EMM ...

  2. jdk 1.8 内存可见性_JDK 14中的常规,安全和确定性外部内存访问

    jdk 1.8 内存可见性 在" JDK 14 Rampdown:Build 27 "一文中,我总结了JDK 14 Early Access Build #27中新增的许多针对JD ...

  3. JDK 14中的常规,安全和确定性外部内存访问

    在" JDK 14 Rampdown:Build 27 "一文中,我总结了JDK 14 Early Access Build #27中新增的许多针对JDK 14的功能. 已经存在另 ...

  4. BEP 7:CUDA外部内存管理插件(上)

    BEP 7:CUDA外部内存管理插件(上) 背景和目标 在CUDA阵列接口使得能够共享不同的Python之间的数据库的访问CUDA设备.但是,每个库都与其它库区别对待.例如: • Numba在内部管理 ...

  5. 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )

    文章目录 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) 二.内存管理流程 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) " 堆内存 " ...

  6. 优化SQL Server的内存占用之执行缓存

    优化SQL Server的内存占用之执行缓存篇 优化SQL Server的内存占用之执行缓存 在论坛上常见有朋友抱怨,说SQL Server太吃内存了.这里笔者根据经验简单介绍一下内存相关的调优知识. ...

  7. 写java线程导致电脑内存不足_如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码...

    程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...

  8. 【1.6万字长文】华为战略管理方法论介绍(含开发战略到执行DSTE、业务领先模型BLM、业务执行力模型BEM、组织绩效和战略解码)

    第一本全方位阐述华为端到端战略管理体系的著作<华为战略管理法:DSTE实战体系>出版了!!当当网.京东均可下单购买. 第一本全方位阐述华为端到端战略管理体系的著作<华为战略管理法:D ...

  9. 内存和FLASH的区别

    1.什么是内存      什么是内存呢?在计算机的组成结构中,有一个很重要的部分,就是存储器.存储器是用来存储程序和数据的部件,对于计算机来说,有了存储器,才有记忆功能,才能保证正常工作.存储器的种类 ...

最新文章

  1. 亚马逊首席技术官预测2021年将改变世界的八大技术趋势
  2. python增强对比度_python增加图像对比度的方法
  3. centos7设置mongodb远程连接(亲测)
  4. 设计模式是什么鬼(单例)
  5. linux线程同步 eventfd,用 eventfd 在线程之间通信
  6. 序列化、模块 day21
  7. 为什么你看了很多书,却依然没有洞见?
  8. Redis配置文件解读
  9. 自动开票失败可能出现的错误信息
  10. wincc几个常用c语言编程软件,WINCC几个常用C语言编程
  11. Centos 6.4 开启 VNC
  12. Hdu-5053 the Sum of Cube(水题)
  13. 2022年信息系统监理师考试大纲
  14. 安卓手机上有适合学生的日程app?
  15. 如何修改jadx的默认内存
  16. Oracle作业第四章
  17. 网络规划设计师水平考试备考资料(9.网络分析与设计案例)
  18. php session 过期,session过期是什么意思
  19. TMS320F28335时钟(1) -----PLL倍频器的初始化详解
  20. 动图怎么拆分成静图?简单快速分解gif的方法

热门文章

  1. 设置360浏览器的背景为护眼模式(浅豆绿色)
  2. 2022最全Hbuilder打包成苹果IOS-App的详解
  3. html5 div 拱桥形状制作,纯CSS3+DIV实现小三角形边框效果的示例代码
  4. 分享电脑日常使用的小技巧
  5. R语言使用cph函数和rcs函数构建限制性立方样条cox回归模型、检验模型是否满足等比例风险、是否存在非线性关系、使用rms包的Predict函数计算指定连续变量和风险比HR值的关系并可视化
  6. 半角和全角的区别 java_全角和半角区别
  7. ios html调起高德地图,iOS开发笔记 调起本地地图导航(百度、高德、腾讯、苹果自带)...
  8. word2vec 的个人理解
  9. 三大报再呼救市:A股估值到了崩溃边缘
  10. Z-Wave 700 秘钥生成、固件签名、及OTA过程