目录
前言
一、例程参考及讲解
1.1 Loader_Src.c文件
1.2 Dev_Inf.c文件
二、程序修改
三、实测
参考
在单片机的实际应用中,通常会搭载一些片外FLASH芯片,用于存储系统的一些配置文件,比如说图片、字体、配置文件等。在出厂设置时,如何通过离线的方式将这些配置文件烧录至片外FLASH中成为关键。当然,在大批量生产中,可以先通过FLASH离线烧录工具将所需的文件烧写至FLASH,再进行贴片,但如何在小批量生产中实现片外FLASH的离线烧录呢?且听本文细细道来。
本文主要采用的是片外片外FLASH型号为W25Q64(SPI通信),MCU为STM32F103VCT6。安装好STlink的下载工具 STM32 ST-LINK utility,本文安装目录为C:\Program Files (x86)\STMicroelectronics。
打开STM32 ST-LINK utility工具,点击External Loader,找到SPI FLASH的例程M25P64_STM3210E-EVAL。此后参考这个例程进行修改。Add External Loader 会罗列出C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader目录下所有的stldr文件。
进入C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader目录下,找到M25P64_STM3210E-EVAL例程。
打开工程文件,包含Loader_Src.c和Dev_Inf.c文件。
基于特定IP为内存开发外部加载程序需要下述函数。请注意,必须在外部加载程序中定义以下函数:
Init函数:Init函数定义用于连接外部存储器的GPIO,初始化所用IP的时钟,并定义使用的GPIO。
Write函数:Write函数对使用RAM范围内的地址定义的缓冲区进行编程。
SectorErase函数(Flash存储器):SectorErase函数擦除由起始地址和结束地址定义的存储器扇区。该函数在SRAM存储器中不能使用。函数原型为int SectorErase (uint32_t StartAddress, uint32_t EndAddress)其中,“StartAddress” = 要擦除的第一个扇区的地址,“EndAddress” = 要擦除的最后一个扇区的地址。
下面是可以定义的其他函数:
Read函数:该函数用来读取指定范围的存储器,并将读取的数据返回到RAM里的缓冲区中,函数原型为int Read (uint32_t Address, uint32_t Size, uint16_t* buffer),其中,“Address” = 读取操作的起始地址,“Size”= 读取操作的大小,“buffer”= 指向
读取后的数据的指针。对于QSPI/OSPI(Quad-SPI/Octo-SPI)存储器,可以在Init函数中定义存储器映射模式;这种情况下,Read函数无用。
Verify函数:选择“verify while programming”模式时会调用该函数。该函数检查编程的存储器是否与RAM中定义的缓冲区保持一致。它返回一个uint64,定义如下:checksum<<32 + AddressFirstError。其中“AddressFirstError”为第一次失配的地址,“Checksum”所编程缓冲区的校验和值。
MassErase函数:该函数擦除整个存储器;
校验和函数:Checksum函数计算已编程的存储器校验和。使用的算法是简单的按位求和算法。结果截断为32位字。使用在ST-LINK Utility中打开的文件计算校验和值,是一种更快的验证编程操作的方法。如果成功则返回1,失败则返回0。
该文件定义了StorageInfo结构。该结构定义的信息类型示例如下所示:
/* 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
"M25P64_STM3210E-EVAL", // Device Name + version number
SPI_FLASH, // Device Type
0x00000000, // Device Start Address
0x00800000, // Device Size in Bytes (8MBytes/64Mbits)
0x00000100, // Programming Page Size 16Bytes
0xFF, // Initial Content of Erased Memory
// Specify Size and Address of Sectors (view example below)
0x00000080, 0x00010000, // Sector Num : 128 ,Sector Size: 64KBytes
0x00000000, 0x00000000,
};
}
W25Q64参数如下所示。
/*
* W25Q64
* 1Page 包含256字节(0x00000100)
* 4Kbytes为1个Sector;=16 page
* 8个扇区为1个Block(32KB),或者16个扇区为一个block(64KB)
* 容量为8M字节,共有128个Block,2048个Sector
*/
所以将Dev_Inf.c中的结构体修改为以下内容。
/* 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
"W25Q64_STM32F1xx", // Device Name + version number
SPI_FLASH, // Device Type
0x00000000, // Device Start Address
0x00800000, // Device Size in Bytes (8MBytes/64Mbits)
0x00000100, // Programming Page Size 256Bytes
0xFF, // Initial Content of Erased Memory
// Specify Size and Address of Sectors (view example below)
0x00000800, 0x00001000, // Sector Num: 2048 Sector Size: 4KBytes
0x00000000, 0x00000000,
};
由于在SectorErase函数中,sFLASH_EraseSector是按照64KB大小的block来擦除的,擦除指令为0xD8,固此函数无需更改。其他函数也无需更改。
如下图所示,勾选Run #2,并将生成的stldr文件复制到C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader目录下,该条指令为cmd.exe /C copy "!L" "C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader\@L.stldr"
如下图所示,编译通过后,在C:\Program Files (x86)\STMicroelectronics\STM32 ST-LINK Utility\ST-LINK Utility\ExternalLoader目录下便会有对应的stldr文件。
如下图所示,打开STM32 ST-LINK utility工具,勾选刚才生成的stldr文件。
此后在External Loader下便有Mass Erase(整片擦除)、Sector Erase(块擦除)、Program(写片外Flash)、Read(读片外FLash)。
通过实际测量,将一个2M大小的文件写进W25Q64,耗时大概两分钟。可以通过修改SPI的速率来提速?
【1】http://www.stmcu.org.cn/module/forum/thread-614955-1-1.html?original