目錄
前言
在單片機的實際應用中,通常會搭載一些片外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文件。
1.1 Loader_Src.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。
1.2 Dev_Inf.c文件
該文件定義了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