zoukankan      html  css  js  c++  java
  • 单片机-XIP-外部闪存就地执行代码

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

    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
    ");
      /* 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

    .

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    GoLang之网络
    GoLang之方法与接口
    GoLang之基础
    Twemproxy 缓存代理服务器
    判断点是否在三角形内
    C++中const 的各种用法
    解决java web中safari浏览器下载后文件中文乱码问题
    Spring MVC如何测试Controller(使用springmvc mock测试)
    java生成指定范围的随机数
    itextpdf添加非自带字体(例如微软雅黑)
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/14378690.html
Copyright © 2011-2022 走看看