随言:

在外地出差,闲着也是闲着,写写笔记。

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博客

理论来说,STM32CubeProgrammer和 STM32 ST-LINK Utility下载算法程序是一样的,都能相互使用。

但是不知道为什么,STM32CubeProgrammer调用外部存储下载程序没有问题,STM32 ST-LINK Utility调用却失败。

不过也没关系了。不过没关系了,生产就用STM32CubeProgrammer,开发就用STM32CubeIDE。

所以一开始我是以STM32 ST-LINK Utility的例程去编程,然后无论我怎么测试都不行。但是我把生成的stldr下载算法文件放到

STM32CubeProgrammer这个软件试试,结果能正常下载,真的是耽误了我不少时间。

至于STM32 ST-LINK Utility为什么不行,搜索了一下,都没找解决相关问题的资料,故我放弃了,改用STM32CubeProgrammer。

结束:

下面是已经编辑好的源码,

工程有HAL库版本的,寄存器版本的(移植某点原子)。

可以根据自己的硬件自行更改。

附上链接:STM32CubeProgrammerFlashAlgorithm.rar_stm32cubeide外部flash下载-嵌入式文档类资源-CSDN下载

硬件:STM32H743IIT6 + W25Q64

/**QUADSPI GPIO Configuration
        PF6     ------> QUADSPI_BK1_IO3
        PF7     ------> QUADSPI_BK1_IO2
        PF8     ------> QUADSPI_BK1_IO0
        PF9     ------> QUADSPI_BK1_IO1
        PB2     ------> QUADSPI_CLK
        PB6     ------> QUADSPI_BK1_NCS

正文:

1、资料

文档:

《UM0892 User manual STM32 ST-LINK utility software description》

例程:

我是用STM32 ST-LINK Utility安装路径下的N25Q512A_STM32F769I-EVAL,因为这个是用HAL库写的。

C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader\N25Q512A_STM32F769I-EVAL

2、Dev_Inf.c file

该文件中定义了存储信息结构。

下面显示了此构造函数定义的信息类型的示例:

#if defined (__ICCARM__)
__root struct StorageInfo const StorageInfo = {
#else
struct StorageInfo const StorageInfo = {
#endif
"External_Loader_Name",      // 设备名 + 版本号
MCU_FLASH,                   // 设备类型
0x08000000,                  // 设备开始地址
0x00100000,                  // 设备大小 (1MBytes/8Mbits)
0x00004000,                  // 页编程大小 16KBytes
0xFF,                        // 擦除后的默认值
// 指定扇区的大小和地址(下面的示例)
0x00000004, 0x00004000,      // Sector Num : 4 ,Sector Size: 16KBytes
0x00000001, 0x00010000,      // Sector Num : 1 ,Sector Size: 64KBytes
0x00000007, 0x00020000,      // Sector Num : 7 ,Sector Size: 128KBytes
0x00000000, 0x00000000,      // 结束

比如现在用的是W25Q64 是QSPI FLASH芯片,大小是8MByte,编程页大小是256字节,最小擦除单位是4KB。

下面我在编程页写4096字节,是为了提高写入的效率。

/* This structure containes information used by ST-LINK Utility to program and erase the device */
#if defined (__ICCARM__)
__root struct StorageInfo const StorageInfo  =
{
#else
struct StorageInfo const StorageInfo  =
{
#endif"STM32H743_W25Q64_REG",                      // Device Name + version numberSPI_FLASH,                                        // Device Type    0x90000000,                                           // Device Start Address0x00800000,                                        // Device Size in Bytes (8MBytes/64Mbits)0x1000,                                            // Programming Page Size 4096Bytes0xFF,                                             // Initial Content of Erased Memory
// Specify Size and Address of Sectors (view example below)0x00000800, 0x00001000,                       // Sector Num : 2048  ,Sector Size: 4KBytes0x00000000, 0x00000000,
};

3、Loader_Src.c file

  • int Init (void):Init函数,定义用于连接到外部存储器的GPIO,进行初始化,使用的IP的时钟。
  • int Write (uint32_t Address, uint32_t Size, uint8_t* buffer):它对用RAM范围内的地址定义的缓冲区进行编程。
  • int SectorErase (uint32_t StartAddress, uint32_t EndAddress):它擦除由起始地址和结束地址定义的存储扇区。
  • int Read (uint32_t Address, uint32_t Size, uint16_t* buffer):其中“地址” =读取操作的起始地址,“大小” =读取操作的大小,“缓冲区” =指向读取数据的指针。注意:对于QSPI / OSPI(Quad-SPI / Octo-SPI)存储器,可以在Init函数中定义存储器映射模式,在这种情况下,Read函数无效。
  • uint64_t Verify (uint32_t FlashAddr, uint32_t RAMBufferAddr, uint32_t Size):选择“编程时验证”模式时将调用此功能。这个功能检查编程的存储器是否对应于存储器中定义的缓冲区内存。
  • int MassErase (void):全部擦除,删除全部内存。

4、编程:

这次移植一下寄存器版本。HAL版本移植很简单,把缺失的文件补上,然后上根据硬件修改QSPI参数。

1、先把STM32 ST-LINK utility安装文件夹下的例程复制到桌面,重命名为test。

C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader\N25Q512A_STM32F769I-EVAL

2、重新选择芯片设备。

把红框的文件都删除了。

找到正点原子的寄存器QSPI测试代码。把下面文件夹的代码复制到我们的test文件夹,添加到工程中。

Dev_Inf.c 上面写出来了,下面是Loader_Src.c

#include "sys.h"
#include "sys.h"
#include "delay.h"
#include "w25qxx.h"
#include "led.h"
#include "qspi.h"
#include "usart.h"#define     SPI_FLASH_CHECK     0x0FFFFFFF/*** Description :* Initilize the MCU Clock, the GPIO Pins corresponding to the* device and initilize the FSMC with the chosen configuration* Inputs    :*      None* outputs   :*      R0             : "1"            : Operation succeeded*            "0"             : Operation failure* Note: Mandatory for all types of device*/
int Init (void)
{__disable_irq(); Stm32_Clock_Init(100, 1, 2, 2); //设置时钟,400Mhzdelay_init(400);             //延时初始化W25QXX_Init();                   //初始化W25QXXreturn 1;
}/*** Description :* Read data from the device* Inputs    :*      Address       : Write location*      Size          : Length in bytes*      buffer        : Address where to get the data to write* outputs   :*      R0             : "1"           : Operation succeeded*            "0"             : Operation failure* Note: Mandatory for all types except SRAM and PSRAM*/
int Read (uint32_t Address, uint32_t Size, uint8_t* buffer)
{Address = Address & SPI_FLASH_CHECK;W25QXX_Read(buffer, Address, Size);return 1;
}/*** Description :* Write data from the device* Inputs    :*      Address       : Write location*      Size          : Length in bytes*      buffer        : Address where to get the data to write* outputs   :*      R0           : "1"            : Operation succeeded*                     "0"            : Operation failure* Note: Mandatory for all types except SRAM and PSRAM*/
int Write (uint32_t Address, uint32_t Size, uint8_t* buffer)
{Address = Address & SPI_FLASH_CHECK;W25QXX_Write_NoCheck(buffer, Address, Size);return 1;
}/*** Description :* Erase a full sector in the device* Inputs    :*     None* outputs   :*     R0             : "1" : Operation succeeded*            "0" : Operation failure* Note: Not Mandatory for SRAM PSRAM and NOR_FLASH*/
int MassErase (void)
{W25QXX_Erase_Chip();return 1;
}/*** Description :* Erase a full sector in the device* Inputs    :*      SectrorAddress    : Start of sector*      Size          : Size (in WORD)*      InitVal       : Initial CRC value* outputs   :*     R0             : "1" : Operation succeeded*           "0" : Operation failure* Note: Not Mandatory for SRAM PSRAM and NOR_FLASH*/
int SectorErase (uint32_t EraseStartAddress, uint32_t EraseEndAddress)
{EraseStartAddress = EraseStartAddress & SPI_FLASH_CHECK;EraseEndAddress = EraseEndAddress & SPI_FLASH_CHECK;EraseStartAddress = EraseStartAddress -  EraseStartAddress % W25QxJV_SUBSECTOR_SIZE;    //Erase 4KByteswhile (EraseEndAddress >= EraseStartAddress){W25QXX_Erase_Sector(EraseStartAddress);EraseStartAddress += W25QxJV_SUBSECTOR_SIZE;        //Erase 4KBytes}return 1;
}/*** Description :* Calculates checksum value of the memory zone* Inputs    :*      StartAddress  : Flash start address*      Size          : Size (in WORD)*      InitVal       : Initial CRC value* outputs   :*     R0             : Checksum value* Note: Optional for all types of device*/
uint32_t CheckSum(uint32_t StartAddress, uint32_t Size, uint32_t InitVal)
{uint8_t missalignementAddress = StartAddress % 4;uint8_t missalignementSize = Size ;int cnt;uint32_t Val;uint8_t value;StartAddress = StartAddress & SPI_FLASH_CHECK;StartAddress -= StartAddress % 4;Size += (Size % 4 == 0) ? 0 : 4 - (Size % 4);for(cnt = 0; cnt < Size ; cnt += 4){W25QXX_Read(&value, StartAddress, 1);Val = value;W25QXX_Read(&value, StartAddress + 1, 1);Val += value << 8;W25QXX_Read(&value, StartAddress + 2, 1);Val += value << 16;W25QXX_Read(&value, StartAddress + 3, 1);Val += value << 24;if(missalignementAddress){switch (missalignementAddress){case 1:InitVal += (uint8_t) (Val >> 8 & 0xff);InitVal += (uint8_t) (Val >> 16 & 0xff);InitVal += (uint8_t) (Val >> 24 & 0xff);missalignementAddress -= 1;break;case 2:InitVal += (uint8_t) (Val >> 16 & 0xff);InitVal += (uint8_t) (Val >> 24 & 0xff);missalignementAddress -= 2;break;case 3:InitVal += (uint8_t) (Val >> 24 & 0xff);missalignementAddress -= 3;break;}}else if((Size - missalignementSize) % 4 && (Size - cnt) <= 4){switch (Size - missalignementSize){case 1:InitVal += (uint8_t) Val;InitVal += (uint8_t) (Val >> 8 & 0xff);InitVal += (uint8_t) (Val >> 16 & 0xff);missalignementSize -= 1;break;case 2:InitVal += (uint8_t) Val;InitVal += (uint8_t) (Val >> 8 & 0xff);missalignementSize -= 2;break;case 3:InitVal += (uint8_t) Val;missalignementSize -= 3;break;}}else{InitVal += (uint8_t) Val;InitVal += (uint8_t) (Val >> 8 & 0xff);InitVal += (uint8_t) (Val >> 16 & 0xff);InitVal += (uint8_t) (Val >> 24 & 0xff);}StartAddress += 4;}return (InitVal);
}/*** Description :* Verify flash memory with RAM buffer and calculates checksum value of* the programmed memory* Inputs    :*      FlashAddr     : Flash address*      RAMBufferAddr : RAM buffer address*      Size          : Size (in WORD)*      InitVal       : Initial CRC value* outputs   :*     R0             : Operation failed (address of failure)*     R1             : Checksum value* Note: Optional for all types of device*/
uint64_t Verify (uint32_t MemoryAddr, uint32_t RAMBufferAddr, uint32_t Size, uint32_t missalignement)
{uint32_t InitVal = 0;uint32_t VerifiedData = 0;uint8_t TmpBuffer = 0x00;uint64_t checksum;Size *= 4;MemoryAddr = MemoryAddr & SPI_FLASH_CHECK;checksum = CheckSum((uint32_t)MemoryAddr + (missalignement & 0xf), Size - ((missalignement >> 16) & 0xF), InitVal);while (Size > VerifiedData){W25QXX_Read(&TmpBuffer, MemoryAddr + VerifiedData, 1);if (TmpBuffer != *((uint8_t*)RAMBufferAddr + VerifiedData))return ((checksum << 32) + MemoryAddr + VerifiedData);VerifiedData++;}return (checksum << 32);
}

在当前工程文件夹中生成stldr文件,cmd.exe /C copy "!L" ".\@L.stldr"

把生成好的stldr放到STM32CubeProgrammer安装文件夹的ExternalLoader里面。

打开STM32CubeProgrammer软件。如下图操作。

如果连接不上0x90000000,尝试多几次连接。

如果下载校验都成功,那么就成功了。

如果是使用STM32CubeIDE下载,则先要把stldr文件放到

C:\ ST \ STM32CubeIDE_1.3.0 \ STM32CubeIDE \ plugins \ com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_1.3.0.202002181050 \ tools \ bin \ ExternalLoader \

打开STM32CubeIDE软件,修改下载配置

如果擦除下载和校验都顺利的话,那么就成功了。

但是程序肯定不会运行的,缺少一个启动程序MemBoot。

同理,仿真也不行,必须有启动程序MemBoot才能仿真。

移植到其他芯片

如果移植到其他芯片的话,不是和我使用的H743一致,只需按照下面修改即可。

比如我借了一块的H750板子,下面是引脚分配图。FLASH芯片也是W25Q64

PE2     ------> QUADSPI_BK1_IO2
    PB2     ------> QUADSPI_CLK
    PD11     ------> QUADSPI_BK1_IO0
    PD12     ------> QUADSPI_BK1_IO1
    PD13     ------> QUADSPI_BK1_IO3
    PB6     ------> QUADSPI_BK1_NCS

以W25Q64_STM32H743I_HAL工程这个代码为例。

1、修改设备芯片STM32H750VB

2、修改QSPI引脚,因为H750板子还是W25Q64,并不是其他的芯片,故W25Q64驱动无需改动,否则改之。

把回调函数void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)

void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi)引脚修改完成即可。

3、编译,放到STM32CubeProgrammer安装文件夹的ExternalLoader里面文件夹下面。

4、测试下载。

5、如果不成功有可能void SystemClock_Config(void)这个时钟函数有问题,

我一般是用Cube系列软件生成的,再粘贴过来。

全篇完。

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

STM32CubeProgrammer STM32CubeIDE下载算法 外部存储QSPI Flash相关推荐

  1. STM32CubeIDE XiP 和 BootROM介绍, XiP外部内存QSPI FLASH执行用户代码

    随言: 目前的电子产品功能越来越多,随之而来的就是代码越来越庞大,代码所需要的存放空间也越来越大. 比如:用ST做GUI界面,面临最大的问题就是芯片内部flash最大才2M.在现在这个时代,2M其实也 ...

  2. 【设计经验】3、ISE中烧录QSPI Flash以及配置mcs文件的加载速度与传输位宽

    一.软件与硬件平台 软件平台: 操作系统:Windows 7 64-bit 开发套件:ISE14.7 硬件平台: FPGA型号:XC6SLX45-CSG324 QSPI Flash型号:W25Q128 ...

  3. android逐行写入读取_Android外部存储-读取,写入,保存文件

    android逐行写入读取 Android external storage can be used to write and save data, read configuration files ...

  4. J-Flash中添加MDK制作的QSPI Flash下载算法方法

    在JLINK的电脑端驱动V6.84a上测试的. 1.MDK的QSPI Flash下载算法制作方法和制作好的算法看教程第80章和配套的例子即可 http://www.armbbs.cn/forum.ph ...

  5. 手把手系列--编写Keil MDK 外部FLASH下载算法

    声明:博文中涉及到的版权软件只用于教学使用 一.目的         完整工程下载地址:         链接:https://pan.baidu.com/s/1xtr8m_KGsyx64wN6rcn ...

  6. 【STM32H7教程】第85章 STM32H7的SPI 总线应用之SPI Flash的STM32CubeProg下载算法制作

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第85章       STM32H7的SPI 总线应用之SPI ...

  7. STM32F429外部SPI下载算法

    STM32F429外部SPI下载算法 一.使用CubeMX新建工程 二.Flash驱动 三.在上项目基础上 制作FLM下载算法 四.修改代码 五.注意问题 六.工程下载 感谢安富莱及正点原子的开源教程 ...

  8. 手把手系列--验证自己编写的STM32H750XBH6_ArtPi平台Keil MDK Flash下载算法

    一.目的         本文配套的完整工程地址         链接:https://pan.baidu.com/s/1CVN1oKVKvlE_osn9fePxbg          提取码:6u5 ...

  9. QSPI Flash存储控制器(概述)

    QSPI Flash存储控制器(概述) 1. 特征概述 内存映射的直接操作模式,用于Flash数据传输和执行Flash存储的代码: 软件设置的间接操作模式,用于低延迟.非计算密集Flash数据传输: ...

  10. Keil uVision5 下载程序 add flash programming algorithm选项缺少需要的下载算法的解决办法

    用Keil5在下载程序,选择下载算法时,可能会出现找不到对应芯片的情况: 这个时候就需要下载安装,Keil的Legacy support for Arm支持包了: http://www2.keil.c ...

最新文章

  1. 缓存机制与局部性原理
  2. 3台廉价机器每秒写入2百万!Kafka为什么那么快?
  3. hdfs数据节点分发什么协议_分布式文件系统HDFS解析
  4. 网络安全课程学习内容
  5. 正则表达式之子表达式 ‘()’ 中表达式 '[]' 大表达式 '{}'
  6. linux 运行库 编译参数,Linux/CentOS 升级C基本运行库CLIBC的注意事项(当想解决GLIBC_2.x找不到的编译问题)...
  7. mysql启动日志指令_简单整理MySQL的日志操作命令
  8. EasyUI - Layout 布局控件
  9. Ueditor编辑器 .Net 版
  10. IP这么火究竟什么才是有价值的IP
  11. 生意参谋指数之指数推理原值
  12. 韦东山ARM裸机学习笔记——S3C2440的串口驱动编程原理
  13. hdu 2036 改革春风吹满地【求多边形面积模板】
  14. [渝粤教育] 西北农林科技大学 国际贸易实务 参考 资料
  15. 怎样学习AI-Adobe
  16. 服务器网卡驱动_教你星际蜗牛C款i211网卡服务器咋装Windows sevs2012R2服务器下
  17. 我写了一个语音识别引擎
  18. PowerDesigner中pdm设置1:n,1:1,n:n的对应关系
  19. 开源配置管理系统的选择和搭建
  20. 谁是IPFS中国区“奶王”?IPFS.FUND周欢当仁不让

热门文章

  1. 网络-单播、多播(组播)和广播的区别
  2. C#将大量数据批量写入Excel中
  3. word文档,中文输入模式下打出英文标点原因(微软拼音输入法为例)
  4. 通过Redis入侵服务器
  5. 空压机物联网解决方案
  6. 计算机系统动态库修复,电脑系统windows7出现无法定位动态链接库user32.dll错误提示解决措施...
  7. 如何一键重装Win7系统 便捷重装Win7系统教程
  8. python显示安装失败_Win7安装Python失败 提示Setup failed
  9. 假定我们要建立一个学术论文数据库,存储如下信息: •学术期刊有期刊编号、期刊名、发行单位; •作者有作者编号、作者姓名、电子邮件; •论文有论文编号、论文标题、摘要、正文; •每篇论文只被一个
  10. Office中常见度量单位(转)