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

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. 欧拉系统初体验与编译安装FFmpeg的过程记录

    目录 源起 1. 系统下载 2. 系统安装 2.1 磁盘分区 2.2 软件数量 2.3 安装完毕 3.进入系统 4.安装FFmpeg 4.1 下载FFmpeg 4.2 解压程序 4.3 检查环境 4. ...

  2. CF1204A 题解

    洛谷链接&CF 链接 本篇题解为此题较简单做法及较少码量,并且码风优良,请放心阅读. 题目简述 给定一个二进制字符串 \(S\),求这个二进制数包含 \(4 ^ k\) 的个数. 特殊的:若 ...

  3. 计算机二级考试 C语言篇

    本篇仅适用于计算机二级考试C语言篇 首先介绍一下二级考试时间问题(以本人考试2022年为例): 一. 2022年全国计算机二级考试时间   2022年全国计算机考试举办4次,(3月.5月.9月.12月 ...

  4. mysql 主从复制 + thinkphp 读写分离

    好处:加快查询速度.数据库热备份等 注意:要跨服务器,先准备一个虚拟机或者docker,同一个服务器意义不大,而且风险大. 注意:本文档学习原理使用,线上可使用阿里云rds自带的读写分离 主从复制: ...

  5. Java代码实现七夕魔方照片墙

    创建一个七夕魔方照片墙是一个相对复杂的任务,涉及到前端展示和后端数据处理.在这里,我会提供一个简化的Java后端示例,用于生成一个模拟的"照片墙"数据模型,并给出一个基本的前端HT ...

  6. 如何实现对ELK各组件的监控?试试Metricbeat

    一.前言 开发排查系统问题用得最多的手段就是查看系统日志,ELK 是 Elastic 公司开源的实时日志处理与分析解决方案,已经为日志处理方案的主流选择. 而在生产环境中,如何针对 ELK 进行监控, ...

  7. 【Vue】自己编写排名组件

    一.需求分析 这里我是用Echarts的柱状图,倒置下y轴x轴就实现了,然后产品说跟UI不一致 我一看UI这种又给我整不会了,然后想拿Echarts改改参数搞定,同事和群友都是说自己做,不要用Echa ...

  8. 【Java】【常用类】Math 数学类

    一些常用的数学计算方法 public class MathTest { public static void main(String[] args) { int a = -10; // 获取绝对值 i ...

  9. 【Vue】13 VueRouter Part3 路由守卫

    单页应用中,只存在一个HTML文件,网页的标签,是通过title标签显示的,我们在单页应用中如何修改? JS操作: window.document.title = "标签名称" 也 ...

  10. 灵巧手 —— 智能仿生手 —— 人形机器人(humanoid)

    产品主页: https://www.brainco.cn/#/product/brain-robotics 国内销售的一款产品,美国华人生产的,灵巧度非常高的一款仿生手产品.