声明:此博文所述我未实践,目的是知识整理。

1.  常说的 "单片机的norflash上可以执行代码 “ 这句话该如何理解?

CPU做取指、译码、执行。

常说的哪些介质可以执行程序,实际上指的是CPU可以从那里取指,以供后续译码和执行。

2.  单片机一般在内部norfalsh上执行代码

Soc读取内部NorFlash时可以总线式访问,这对SoC来说更方便,由SoC直接以地址方式来访问,而且,NorFlash不需要初始化,时序简单。

PS:nandflash接口管理复杂,需要专门的控制器。

3. 单片机内部norflash上执行代码面临的困局

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

如果嫌弃你单片机的norflash不够大呢?你换再大的单片机norflash也大不了多少了,所以:

方案1. 使用ST在M7内核芯片上增加的QSPI控制器,让用户把代码放在外部存储就地执行。

方案2. 使用sdram,将代码搬运到sdram内执行。

方案1 对应的方式称为XIP 。

方案2 对应的方式称为 BootROM,顾名思义,从ROM搬运代码到RAM去执行,所以叫BootROM。

4. norflash不够的解决方案1 -- XIP

(1). 在外部闪存(外部QSPI或FMC-NOR闪存)“就地执行”。

(2). 用户应用程序代码应链接到目标执行存储器地址(外部QSPI或FMC-NOR闪存)。

(3). 需要内存映射支持

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

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

XIP模型操作流程

XiP启动方式实际是借助一个bootloader,这个bootloader做了一件很与众不同的事情,就是把QSPI FLASH映射到了系统总线0x9000 0000 这个地址上。

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

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

当映射完成后,先关闭全部中断和cache,然后跳转到用户程序执行。

借助STM32H7的QSPI、XIP的方式,我们就可以实现让程序在W25QXX系列芯片内跑起来了。

5 . norflash不够的解决方案2 -- BootROM

(1). 从闪存启动,配置外部RAM存储器(SDRAM或SRAM),

先从闪存复制用户应用程序二进制文件(SDCARD或SPI-Flash存储器)到外部SDRAM或外部SRAM,然后跳转执行用户应用程序。

(2). 用户应用程序代码应链接到目标执行存储器地址(外部SDRAM或SRAM)。

这种模型就很通用了,适用于凡是有FMC能驱动外部RAM的任意一款ST芯片。当然链接地址肯定是外部RAM存储器的地址了。至于闪存,随意都可以,什么SPI FLASH、TF卡、I2C存储器都可以。

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

6. XiP模型bootloader编写

参考博文:https://blog.csdn.net/sudaroot/article/details/110128506?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase

#include <stdio.h>
#include "w25qx_qspi.h" typedef void (*pFunction)(void); #define APPLICATION_ADDRESS QSPI_BASE static 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;
}

参考资料:

安富莱_STM32-V7开发板_用户手册,含BSP驱动包设计(V3.1).pdf

STM32CubeIDE QSPI间接模式和内存映射模式 读写W25Q64

https://blog.csdn.net/sudaroot/article/details/109097135

.

单片机-XIP-外部闪存就地执行代码的更多相关文章

  1. 新的微芯片MCU增加了来自外部闪存的安全引导保护

    新的微芯片MCU增加了来自外部闪存的安全引导保护 New Microchip MCU Adds Secure Boot Protection from External Flash 对于从外部SPI闪 ...

  2. 原创:应用串行NOR闪存提升内存处理能力

    在嵌入式系统中,NOR闪存一直以来仍然是较受青睐的非易失性内存,NOR器件的低延时特性可以接受代码执行和数据存储在一个单一的产品.虽然NAND记忆体已成为许多高密度应用的首选解决方案,但NOR仍然是低 ...

  3. NANDflash和NORflash的区别(设计师在使用闪存时需要慎重选择)

    NANDflash和NORflash的区别(设计师在使用闪存时需要慎重选择)     NOR和NAND是现在市场上两种主要的非易失闪存技术.Intel于1988年首先开发出NOR flash技术,彻底 ...

  4. 闪存中的NorFlash、NandFlash及eMMC三者的区别【转】

    本文转载自:https://blog.csdn.net/Blazar/article/details/77843655 快闪存储器(英语:Flash Memory),是一种电子式可清除程序化只读存储器 ...

  5. Google浏览器插件之闪存过滤器

    一件很有意思的事情引发的无聊尝试. 博客园有个很有趣的功能,就是闪存,翻阅到07年园长对闪存的定义:      记录一闪而过的想法,高兴或者不高兴都可以发一下.我用这个一直以来的想法就是,想到点啥发点 ...

  6. [Perl]抓取个人的所有闪存+格式化保存为文本

    以下代码保存为utf8文本格式 环境:ActivePerl v5.16 built for MSWin32-x86 两个要调整的地方: for my $i (17..45) {  这里改成自己对应的页 ...

  7. 用 VeraCrypt 加密闪存盘

    导读 很多安全专家偏好像 VeraCrypt 这类能够用来加密闪存盘的开源软件,是因为可以获取到它的源代码.要是你需要在 Windows 系统,苹果的 OS X 系统或者 Linux 系统上加密以及访 ...

  8. python3使用requests发闪存

    闪存ing.cnblogs.com是博客园类似推特.饭否的服务, 我写了以下程序可以完成发闪存的操作,目的是顺便练习使用requests库. requests是一个python 轻量的http客户端库 ...

  9. HTTP.sys远程执行代码漏洞

    远程执行代码漏洞存在于 HTTP 协议堆栈 (HTTP.sys) 中,当 HTTP.sys 未正确分析经特殊设计的 HTTP 请求时会导致此漏洞. http://bbs.safedog.cn/thre ...

  10. js基础梳理-究竟什么是执行上下文栈(执行栈),执行上下文(可执行代码)?

    日常在群里讨论一些概念性的问题,比如变量提升,作用域和闭包相关问题的时候,经常会听一些大佬们给别人解释的时候说执行上下文,调用上下文巴拉巴拉,总有点似懂非懂,不明觉厉的感觉.今天,就对这两个概念梳理一 ...

随机推荐

  1. oeasy教您玩转vim - 2 - # 使用帮助

    回忆上节课内容 更新和运行 vim 进入和退出 vim 存活了下来 从中我们知道 vim 有两种模式:正常模式(Normal mode)和命令行模式 (Command-Line mode) 为了您能更 ...

  2. Django 不通过外键实现多表关联查询

    Django不通过外键实现多表关联查询 by:授客 QQ:1033553122 测试环境 Win 10   Python 3.5.4   Django-2.0.13.tar.gz 需求 不通过外键,使 ...

  3. Aic 应用开发基础一(概念与场景)

    Agi通用人工智能应用概念与场景 大家看到,自美国OpenAI主导的GPT发布以来,全球科技领域掀起了革命性的浪潮.比如最近看到的aigc 人工绘图,智能机器人等行业,很多新概念掘起, 随着人工智能技 ...

  4. redis如何实现主从同步

    redis实现主从同步分为两种:全量同步和增量同步:第一次连入集群的slave需要进行全量同步,那些断开后重连的slave需要进行增量同步 每个redis都有自己的replid,他们是master的标 ...

  5. 4、SpringMVC之获取请求参数

    4.1 环境搭建 创建名为spring_mvc_demo2的新module,过程参考3.1节 4.1.1.创建请求控制器 package org.rain.controller; import org ...

  6. 【RabbitMQ】12 日志监控 & 消息追踪

    一.日志和监控 RabbitMQ日志存放目录 [root@localhost ~]# ll /var/log/rabbitmq/ 总用量 176 -rw-r-----. 1 rabbitmq rabb ...

  7. 【SpringMVC】09 对JSON的应用

    前面JavaWeb的JSON回顾: https://www.cnblogs.com/mindzone/p/12820877.html 上面的这个帖子我都还没有实际写进Servlet使用,要Mark一下 ...

  8. 很好用的python游戏环境:强化学习算法走迷宫游戏环境(导航问题 navigation):分享一个python语言的迷宫游戏环境

    项目的GitHub地址(作者:莫凡): https://github.com/MorvanZhou/mmaze 运行的示例代码: import mmaze start = (0, 0) end = ( ...

  9. MindSpore框架 加载文本数据集 示例

    代码原地址: https://www.mindspore.cn/tutorial/training/zh-CN/r1.2/use/load_dataset_text.html ============ ...

  10. 苹果系统Mac升级后之前的网络软件不可用——Mac系统维护——Mac系统升级后软件报错——mac系统升级后导致软件兼容报错

    ========================================== 博士同学最近联系我,说是自己的mac系统升级后之前可以用的网络软件不可用使用了,由于平时工作需要,这个网络软件如果 ...