STM32CubeProgrammer STM32CubeIDE下载算法 外部存储QSPI Flash
随言:
在外地出差,闲着也是闲着,写写笔记。
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相关推荐
- STM32CubeIDE XiP 和 BootROM介绍, XiP外部内存QSPI FLASH执行用户代码
随言: 目前的电子产品功能越来越多,随之而来的就是代码越来越庞大,代码所需要的存放空间也越来越大. 比如:用ST做GUI界面,面临最大的问题就是芯片内部flash最大才2M.在现在这个时代,2M其实也 ...
- 【设计经验】3、ISE中烧录QSPI Flash以及配置mcs文件的加载速度与传输位宽
一.软件与硬件平台 软件平台: 操作系统:Windows 7 64-bit 开发套件:ISE14.7 硬件平台: FPGA型号:XC6SLX45-CSG324 QSPI Flash型号:W25Q128 ...
- android逐行写入读取_Android外部存储-读取,写入,保存文件
android逐行写入读取 Android external storage can be used to write and save data, read configuration files ...
- J-Flash中添加MDK制作的QSPI Flash下载算法方法
在JLINK的电脑端驱动V6.84a上测试的. 1.MDK的QSPI Flash下载算法制作方法和制作好的算法看教程第80章和配套的例子即可 http://www.armbbs.cn/forum.ph ...
- 手把手系列--编写Keil MDK 外部FLASH下载算法
声明:博文中涉及到的版权软件只用于教学使用 一.目的 完整工程下载地址: 链接:https://pan.baidu.com/s/1xtr8m_KGsyx64wN6rcn ...
- 【STM32H7教程】第85章 STM32H7的SPI 总线应用之SPI Flash的STM32CubeProg下载算法制作
完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第85章 STM32H7的SPI 总线应用之SPI ...
- STM32F429外部SPI下载算法
STM32F429外部SPI下载算法 一.使用CubeMX新建工程 二.Flash驱动 三.在上项目基础上 制作FLM下载算法 四.修改代码 五.注意问题 六.工程下载 感谢安富莱及正点原子的开源教程 ...
- 手把手系列--验证自己编写的STM32H750XBH6_ArtPi平台Keil MDK Flash下载算法
一.目的 本文配套的完整工程地址 链接:https://pan.baidu.com/s/1CVN1oKVKvlE_osn9fePxbg 提取码:6u5 ...
- QSPI Flash存储控制器(概述)
QSPI Flash存储控制器(概述) 1. 特征概述 内存映射的直接操作模式,用于Flash数据传输和执行Flash存储的代码: 软件设置的间接操作模式,用于低延迟.非计算密集Flash数据传输: ...
- Keil uVision5 下载程序 add flash programming algorithm选项缺少需要的下载算法的解决办法
用Keil5在下载程序,选择下载算法时,可能会出现找不到对应芯片的情况: 这个时候就需要下载安装,Keil的Legacy support for Arm支持包了: http://www2.keil.c ...
最新文章
- 缓存机制与局部性原理
- 3台廉价机器每秒写入2百万!Kafka为什么那么快?
- hdfs数据节点分发什么协议_分布式文件系统HDFS解析
- 网络安全课程学习内容
- 正则表达式之子表达式 ‘()’ 中表达式 '[]' 大表达式 '{}'
- linux 运行库 编译参数,Linux/CentOS 升级C基本运行库CLIBC的注意事项(当想解决GLIBC_2.x找不到的编译问题)...
- mysql启动日志指令_简单整理MySQL的日志操作命令
- EasyUI - Layout 布局控件
- Ueditor编辑器 .Net 版
- IP这么火究竟什么才是有价值的IP
- 生意参谋指数之指数推理原值
- 韦东山ARM裸机学习笔记——S3C2440的串口驱动编程原理
- hdu 2036 改革春风吹满地【求多边形面积模板】
- [渝粤教育] 西北农林科技大学 国际贸易实务 参考 资料
- 怎样学习AI-Adobe
- 服务器网卡驱动_教你星际蜗牛C款i211网卡服务器咋装Windows sevs2012R2服务器下
- 我写了一个语音识别引擎
- PowerDesigner中pdm设置1:n,1:1,n:n的对应关系
- 开源配置管理系统的选择和搭建
- 谁是IPFS中国区“奶王”?IPFS.FUND周欢当仁不让
热门文章
- 网络-单播、多播(组播)和广播的区别
- C#将大量数据批量写入Excel中
- word文档,中文输入模式下打出英文标点原因(微软拼音输入法为例)
- 通过Redis入侵服务器
- 空压机物联网解决方案
- 计算机系统动态库修复,电脑系统windows7出现无法定位动态链接库user32.dll错误提示解决措施...
- 如何一键重装Win7系统 便捷重装Win7系统教程
- python显示安装失败_Win7安装Python失败 提示Setup failed
- 假定我们要建立一个学术论文数据库,存储如下信息: •学术期刊有期刊编号、期刊名、发行单位; •作者有作者编号、作者姓名、电子邮件; •论文有论文编号、论文标题、摘要、正文; •每篇论文只被一个
- Office中常见度量单位(转)