随言:
在外地出差,闲着也是闲着,写写笔记。
STM32CubeIDE QSPI间接模式和内存映射模式 读写W25Q64:https://blog.csdn.net/sudaroot/article/details/109097135
MDK KEIL 下载算法外部存储QSPI FLASH:https://blog.csdn.net/sudaroot/article/details/109517371
STM32CubeProgrammer STM32CubeIDE下载算法 外部存储QSPI Flash:https://blog.csdn.net/sudaroot/article/details/109565934
结束:
下面是已经编辑好的源码,
工程有HAL库版本的,寄存器版本的(移植某点原子)。
可以根据自己的硬件自行更改。
附上链接:https://download.csdn.net/download/sudaroot/13092616

硬件: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、参考资料
文档: https://www.keil.com/support/docs/3656.htm https://arm-software.github.io/CMSIS_5/Pack/html/flashAlgorithm.html https://www.keil.com/support/man/docs/uv4/uv4_fl_flash_algorithms.htm https://www.keil.com/pack/doc/CMSIS/Pack/html/algorithmFunc.html
例程:
MDK有自己的下载模板,路径在安装keil文件夹中C:\Keil_v5\ARM\Flash\_Template\Test

上图是一个Keil的下载算法的空白模板,需要自己填充。其中Test文件是一个STM32F1的下载算法的测试程序(标准库)。
但是呢,其实Keil的安装pack包中就有ST的下载算法程序。我电脑的pack包安装路径如下,我参考例程。
C:\Users\47245\AppData\Local\Arm\Packs\Keil\STM32H7xx_DFP\2.7.0\CMSIS\Flash\STM32H747I_eval_QSPI
如果不知道的可以随便找个pack包看看自己电脑的安装路径。

如果不是最新的pack包,有个很好的网址上面有最新的包。
更新MDK Pack软件包http://www.armbbs.cn/forum.php?mod=viewthread&tid=96992
首先要记住MDK下载算法程序,只是一个临时加载在SRAM上运行的程序。
2、FlashDev.c
下面是官方说明文档的说明。

比如现在用的是W25Q64 是QSPI FLASH芯片,大小是8MByte,编程页大小是256字节,最小擦除单位是4KB。
下面我在编程页写4096字节,是为了提高写入的效率。还有注意一下最后是相对于起始地址的偏移地址。
struct FlashDevice const FlashDevice =
{
FLASH_DRV_VERS, // 驱动程序版本,请勿修改!
"W25Q64_STM32H743I_HAL", // 设备名称,自定义
EXTSPI, // 设备类型,扩展SPI设备
0x90000000, // 设备起始地址,因为QSPI挂载的地址是0x9000 0000
0x00800000, // 设备大小以字节为单位 (8MB)
0x00001000, // 编程页面大小(4096)
0x00, // 保留,必须为0
0xFF, // 擦除内存的值
1000, // 程序页面超时1000毫秒
6000, // 擦除扇区超时6000毫秒
//指定扇区的大小和地址
0x1000, 0x000000, //扇区大小8kB(8个扇区),偏移地址
SECTOR_END
};
注意:
该设备名称通常以工具来识别闪存算法显示。确保此名称反映设备名称。
该程序页面大小规定了使用功能编程块大小ProgramPage。对于块大小小的设备,最好指定物理块大小的倍数,因为这会减少与目标设备的通信开销。快速编程的最佳块大小为1024字节,但是系统本身并不限制该大小值。
3、FlashPrg.c
文件FlashPrg.c包含必需的Flash编程功能Init,UnInit,EraseSector和ProgramPage。(可选)根据设备功能(或加快执行速度),可以实现功能EraseChip,BlankCheck和Verify。
以下功能可用于创建新的Flash编程算法:

初始化函数
int Init (unsigned long adr, unsigned long clk, unsigned long fnc);
函数Init初始化微控制器以进行Flash编程。每当尝试将程序下载到Flash时都会调用它。
参数adr指定设备的基地址。
参数clk指定用于对设备进行编程的时钟频率。
参数fnc是一个数字:
返回值
因此,可以为每个单独的Flash编程步骤实现不同的初始化部分。
擦除扇区函数
int EraseSector(unsigned long adr);
参数
返回值
函数EraseSector删除从参数adr指定的地址开始的扇区内容。
每当使用uVision菜单Flash - Erase或尝试将程序下载到Flash
并且在Flash Download Setup对话框中设置了Erase Sectors
选项时,就会调用该函数。
页编程(页写入)函数
int ProgramPage(unsigned long adr,unsigned long sz,unsigned char * buf);
参数:
返回值:
功能ProgramPage用于将代码写入闪存。调用它可以将程序下载到Flash。由于闪存通常以块或页的形式组织,
因此函数ProgramPage的参数不得跨越这些闪存页的对齐边界。页面大小在结构FlashDevice中指定为值Program Page Size。
参数adr指定要编程的页面的起始地址。主机编程系统将其与闪存页面的起始地址对齐。
参数sz指定数据缓冲区中的数据大小。主机编程系统确保不跨越页面边界。
参数buf指向包含要编程数据的数据缓冲区。
取消初始化函数
int UnInit(unsigned long fnc);
UnInit函数可取消初始化微控制器,并在擦除,编程或验证步骤结束时调用。
参数fnc是一个数字:
返回值
因此,可以为每个单独的Flash编程步骤实现不同的反初始化部分。
其他函数略过。。。
看到MDK下载时有三个选项,对应的是三个流程。

 

可以看到每个流程都会调用一次初始化函数init()和反初始化函数uinit()。
理论大概就这么多。
编程的话,你可以下载我的源码看,
但是我最建议的是复制一份MDK中的ST pack包中的下载程序,
然后简单修改一下里面关于控制QSPI flash的指令,这样修改出来的成功最高也是最稳定最快的一种。
编程:
1、先准备好一份用STM32CubeIDE或者STM32CubeMX生成的QSPI代码并且测试无问题。
2、复制MDK 的 H7 系列Pack包的安装路径找到例程,如下我电脑例程路径,
C:\Users\47245\AppData\Local\Arm\Packs\Keil\STM32H7xx_DFP\2.7.0\CMSIS\Flash\STM32H747I_eval_QSPI
把STM32H747I_eval_QSPI这个文件复制一份到桌面重命名为test,右键文件夹,取消只读属性。
还有把FlashOS.h也复制到桌面test文件夹中。

3、打开工程,我用的是STM32H743IIT6,那么对应把工程设备也设置成对应的芯片。
 
4、会发现缺少很多文件。缺少的HAL库文件
- 生成的QSPI工程中复制Driver到工程文件夹中。
- STM32Cube系列安装包中..\STM32Cube\Repository\STM32Cube_FW_H7_V1.8.0的Driver文件夹。
添加文件即可。在MDK中把缺少的文件补上且包含正确的头文件路径。
还有别忘了把工程的system_stm32h7xx.c也复制到test文件夹下。
 
我用的是STM32Cube里面的Driver文件,复制到test文件夹下,删除Driver文件中的BSP文件夹。

5、把FlashDev.c 和 FlashPrg.c 中的
#include "..\FlashOS.H" 修改成 #include ".\FlashOS.H"
6、编译一下,发现HAL库文件都没问题了。SystemClock_Config()只会出现一个未定义错误。

这个错误没关系,毕竟用的芯片不同,里面的宏定义有点差别。
到时候把准备好的工程中的SystemClock_Config()覆盖过去即可。
7、修改FlashDev.c,W25Q64,前面写好了。
8、现在就是把准备好的QSPI Flash测试工程,按照函数功能复制填充到STM32H747I_QSPI.c
GPIO和系统时钟初始化,W25Qxx的初始化流程,还有就是检查函数功能指令和传输方式。
比如像BSP_QSPI_Read()这个QSPI读函数,最好就是检查修改一下指令和几线传输。
最后把cmd.exe /C copy "!L" "..\@L.FLM" 这个 命令 修改成 cmd.exe /C copy "!L" ".\@L.FLM",在当前文件夹生成FLM文件。

修改生成的FLM文件名字。

test工程我就不修改了。挺累的。半完工的工程到时候我上传上去。
如果使用test工程的话,就简单修改一下QSPI检查修改传输指令和几线协议还有地址位数,移植时不用折腾太多。
9、生成的FLM文件,放到MDK安装目录下,如我的C:\Keil_v5\ARM\Flash,
我生成的FLM文件名字叫W25Q64_STM32H743I_HAL.FLM
随便找一个点亮LED的工程。修改一下flash链接地址,具体修改数值,看你FlashDev.c定义。

工程添加下载算法

如果点击下载过程中出现算法初始化失败,那就是给的SRAM大小太小了。改大红框数值就好了。


如果出现这个错误:no algorithm found for: 09000000h - 09003137h
那就是你算法的起始地址写错了。
10、如果擦除下载和校验都顺利的话,那么就成功了。
但是程序肯定不会运行的,缺少一个启动程序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、编译,放到MDK的\Keil_v5\ARM\Flash文件夹下面。
4、测试下载。
5、如果不成功有可能void SystemClock_Config(void)这个时钟函数有问题,
我一般是用Cube系列软件生成的,再粘贴过来。
全篇完。
本人是一个嵌入式未入门小白,博客仅仅代表我个人主观见解,记录成长笔记。 笔记是以最简单的方式,只展示最核心的原理。 若有与 大神大大 见解有歧义,我绝对坚信 大神大大 见解是对的,我的是错的。 若无积分等无法下载源码,可私聊私发。 感谢~! |