1. 初识MDK下载算法:为什么需要它?
如果你正在用STM32H7系列芯片做项目,尤其是需要大容量存储的时候,肯定会遇到内部Flash不够用的情况。这时候外挂QSPI Flash(比如W25Q256)就成了救命稻草,但问题来了:怎么把程序下载到这片外部Flash里呢?这就是MDK下载算法要解决的问题。
我刚开始接触这个的时候也挺头疼的,MDK自带的下载算法只支持内部Flash,对外部QSPI Flash无能为力。后来折腾了好久才明白,其实下载算法就是一段特殊的代码,MDK在下载程序时会先把这段代码加载到芯片的RAM里,然后通过它来操作外部Flash完成擦除、编程等操作。
说白了,下载算法就像是MDK和外部Flash之间的翻译官。没有它,MDK就不知道怎么跟你的W25Q256对话。这个算法最后会打包成一个.flm文件,放在MDK的安装目录里,这样每次下载时MDK就知道该怎么操作你的外部Flash了。
2. 准备工作:打造坚实的开发环境
工欲善其事,必先利其器。在开始制作下载算法之前,得先把环境搭好。我这里用的是STM32H743芯片和W25Q256JV Flash,但方法对其他H7系列芯片和QSPI Flash也是通用的。
首先得准备好MDK开发环境,我用的MDK 5.3以上版本。然后要安装STM32H7的DFP包,这个在MDK的Pack Installer里就能找到。HAL库也得准备好,建议用最新版本,避免一些已知的坑。
硬件连接很重要,QSPI的六根线(CLK、CS、IO0-IO3)一定要接对。我当初就因为IO2和IO3接反了,调试了一整天。建议对照芯片手册和板子原理图, double check一下引脚分配。
还得准备一个简单的测试工程,用来验证QSPI Flash是否能正常读写。这个很关键,如果基础读写都不行,那下载算法肯定也做不成。我一般会写个简单的测试程序,能擦除、写入、读取一个扇区就行。
3. 创建算法工程:从模板开始
MDK很贴心地提供了下载算法的模板工程,不用我们从零开始。模板一般在ARM\Packs\Keil\STM32H7xx_DFP\<version>\CMSIS\Flash目录下找。我建议直接复制一份模板,然后在上面修改。
新建工程的时候要注意几点:工程名最好能体现芯片和Flash型号,比如STM32H743_QSPI_W25Q256。器件类型要选对你用的具体型号,这个会影响一些底层配置。输出文件名也要改一下,默认的太泛了。
工程属性里有个很重要的设置:RO和RW段都要设置为位置无关。这个在Options -> Target里勾选"ROPI"和"RWP"I。位置无关代码意味着算法可以被加载到任意地址运行,这是必须的,因为MDK会把算法加载到RAM的某个空闲区域。
还有一个容易忽略的地方是分散加载文件(scatter file)。模板里一般自带一个,我们不需要大改,但要知道它是干嘛的。这个文件定义了代码和数据在内存中的布局,确保算法正确运行。
4. HAL库适配:瘦身与优化
HAL库功能很强大,但对下载算法来说太臃肿了。我们需要对它进行瘦身,去掉不必要的部分。主要修改三个文件:stm32h7xx_hal.c、stm32h7xx_hal_timebase.c和stm32h7xx_hal_msp.c。
最关键是处理时间相关的函数。下载算法里不能用中断,所以要把HAL库中基于systick的延时函数都替换成简单的循环等待。我在HAL_InitTick()函数里直接返回HAL_OK,避免systick初始化。
HAL库里的超时检测机制也得去掉。因为即使超时了,也意味着操作失败,跟死等没区别。我直接把超时检测注释掉,改成while循环等待操作完成。
内存分配相关的函数也要处理。下载算法里不应该用动态内存,所以要把malloc、free这些函数替换成静态分配。我一般定义一个大数组作为内存池,需要内存时从池里分配。
5. 时钟配置:让QSPI飞起来
时钟配置对QSPI性能影响很大。STM32H7的时钟树比较复杂,但咱们不需要用到所有功能,只要把QSPI需要的时钟配好就行。
我先配置PLL,让系统时钟跑到400MHz。H7的QSPI时钟来自PLL,最高可以到133MHz。但实际使用时要注意Flash的支持频率,W25Q256在QSPI模式下最高支持80MHz,所以我一般设置到80MHz。
VOS电压缩放也要配置。H7有三个电压范围:VOS1、VOS2、VOS3。VOS1性能最高,但功耗也最大。下载算法运行时不需要考虑功耗,所以直接用VOS1。
IO补偿单元一定要使能,特别是在高速运行时。这个很多人会忘记,导致信号完整性问题。使能方法很简单,调用HAL_EnableCompensationCell()就行。
6. FlashDev.c配置:告诉MDK你的Flash长什么样
FlashDev.c是下载算法的身份证,它告诉MDK你的Flash的各种参数。这个文件里就一个重要的结构体FlashDevice,我来详细说说每个字段的含义。
FLASH_DRV_VERS是驱动版本号,不要修改,MDK靠这个识别算法格式。设备名可以自己取,但建议包含芯片和Flash型号,这样在MDK的下拉菜单里容易找到。
起始地址很关键,QSPI Flash的内存映射地址是0x90000000,这个不能错。大小也要设对,W25Q256是32MB,即3210241024。
编程页大小设为4096字节,虽然W25Q256的物理页是256字节,但MDK是按页编程的,设大一点可以提高下载速度。擦除后的数值一般是0xFF,因为Flash擦除后就是全1。
等待时间要根据实际操作时间设置。页编程约需1ms,扇区擦除约需60ms,但建议设长一点,避免因工艺偏差导致超时。
7. FlashPrg.c实现:核心功能的编写
FlashPrg.c是下载算法的心脏,实现了初始化、擦除、编程等核心功能。每个函数都有特定的参数和返回值要求,不能随意改动。
Init函数是入口,负责初始化系统和QSPI外设。这里要注意的是,MDK会传入三个参数:基地址、时钟频率和功能代码。基地址通常是0x90000000,但我们实际操作时要减去这个地址,得到Flash内部的偏移地址。
UnInit函数在每次操作结束后调用,负责清理现场。我在这里会把QSPI重新设置为内存映射模式,这样MDK就可以直接读取验证数据了。
EraseSector函数实现扇区擦除。W25Q256的扇区是64KB,擦除前要检查地址是否在有效范围内。擦除完成后最好再读回来验证一下,确保擦除成功。
ProgramPage函数负责页编程。这里有个技巧:虽然Flash的物理页是256字节,但我们可以一次编程4KB,减少操作次数。编程时要分多次写入,每次256字节,直到写完一页。
8. QSPI驱动优化:让数据传输更高效
QSPI驱动是下载算法的底层支撑,它的性能直接影响到下载速度。STM32H7的QSPI支持多种工作模式,我们要根据Flash的特性选择最合适的。
我一般用Quad SPI模式,四线同时传输,速度比传统的SPI快很多。但要注意,W25Q256上电默认是SPI模式,需要先使能QE位,然后发送0x38命令切换到QPI模式。
指令配置很重要。不同的操作需要不同的指令格式:单线指令、双线指令、四线指令。快速读操作用0xEB指令,四线传输,带8个dummy cycle。
DMA传输能大幅提升性能。H7的QSPI支持MDMA,在大量数据传输时特别有用。我一般在编程和读取时启用DMA,减少CPU占用。
内存映射模式是最终目标。配置好之后,CPU可以直接通过0x90000000地址访问Flash内容,就像访问内部Flash一样。这对调试和验证特别有用。
9. 调试与验证:解决那些坑爹的问题
下载算法开发过程中会遇到各种问题,我总结了一些常见坑和解决方法。
最常见的是算法加载失败,提示"Could not load flash programming algorithm"。这通常是因为RAM空间不足,MDK没地方加载算法文件。解决方法是在Options -> Debug -> Settings -> Flash Download里增大RAM for Algorithm的值。
校验失败也是常见问题。有时候程序明明下载成功了,但校验时总是报错。这可能是时钟配置不对,或者信号完整性问题。建议用示波器看看QSPI的波形,确保信号质量。
性能优化很重要。一个好的下载算法应该尽可能快,我通过以下方法优化:使用四线模式、启用DMA、增大编程页大小、合理设置时钟频率。
最后一定要全面测试:擦除测试、编程测试、校验测试、边界测试(擦除最后一个扇区、编程最后一页)。只有全部通过,才能说算法是可靠的。
10. 实际使用:集成到开发 workflow
算法开发完成后,要把它集成到MDK中。把生成的.flm文件复制到MDK安装目录的ARM\Flash文件夹里,这样所有工程都能用了。
在项目的Options -> Debug -> Settings -> Flash Download里添加算法,设置好起始地址和大小。RAM for Algorithm要设足够大,一般至少0x2000。
下载配置也很重要。我习惯把算法加载到DTCM RAM(0x20000000),因为这块RAM速度最快。如果空间不够,也可以用AXI SRAM(0x24000000)。
调试时如果遇到问题,可以启用MDK的调试信息输出,在Debug -> Settings -> Trace里勾选"Enable"和"Trace Output",这样可以看到详细的下载过程信息。
还有一个技巧:如果项目里同时用了内部Flash和外部Flash,可以在Linker里配置分散加载文件,把不同的代码段放到不同的Flash中。比如把启动代码和核心算法放在内部Flash,把资源文件和大数据放在外部Flash。
经过这样一套流程,你的STM32H7就能愉快地使用QSPI Flash了。我在实际项目中用这个方案很久了,稳定性很好,下载速度也很快。虽然第一次配置有点麻烦,但一旦搞定,后续开发就轻松多了。
665



被折叠的 条评论
为什么被折叠?



