Flash loader的基本原理
Flash是目前最主要的非易失性存儲(chǔ)器,眾多的MCU內(nèi)部都集成了Flash存儲(chǔ)器。但是Flash無法直接寫入,任何的Flash寫操作都必須是在Flash為空或者已經(jīng)擦除的單元內(nèi)進(jìn)行。
Flash的擦除一般是以塊為單位進(jìn)行,而且不同MCU內(nèi)部Flash以及串行Flash塊的大小是不一樣的,這就導(dǎo)致了每個(gè)設(shè)備的Flash寫操作可能并不相同。Flashloader就是調(diào)試工具(IDE和硬件調(diào)試器)為了解決Flash的編程問題而采用的一種方法。Flashloader實(shí)際上是運(yùn)行在MCU的RAM中的一段程序,調(diào)試工具先將Flashloader下載到RAM,再通過控制PC來執(zhí)行Flashloader中的函數(shù),完成對(duì)Flash的擦除和寫入。
Open Flashloader
對(duì)于主流的MCU芯片,通常J-Link都支持直接通過J-Link進(jìn)行代碼的
燒錄。但是,對(duì)于外擴(kuò)Flash,例如MCU外接了SPI Flash存儲(chǔ)器,用戶可能需要自己添加J-Link的支持,對(duì)其進(jìn)行燒錄。
默認(rèn)情況J-Link DLL有一個(gè)內(nèi)建數(shù)據(jù)庫,記錄了已支持的芯片型號(hào),并可以通過一個(gè)名為“JlinkDevice.xml”的xml文件來擴(kuò)展支持。實(shí)現(xiàn)J-Link的Flash燒錄算法有兩項(xiàng)工作要做。按照設(shè)備Flash類型修改JlinkDevice文件和修改Open Flashloader的源碼。
下面先來說一說JlinkDevice.xml文件的基本格式。
擴(kuò)展已存在的設(shè)備
如果是J-Link已經(jīng)支持的芯片,只是要添加一個(gè)新的Flash bank信息。用文本編輯器打開JlinkDevice.xml文件,添加如下信息:
標(biāo)簽的Name屬性必須與內(nèi)建數(shù)據(jù)庫中的已存在的設(shè)備命名完全一致;BaseAddr是要增加的Flash的基地址;其他屬性參見下面的新增設(shè)備。如果有多個(gè)Flash bank要擴(kuò)展,只需要重復(fù)標(biāo)簽。
新增一個(gè)設(shè)備
新增一個(gè)J-Link還未支持新的芯片,用文本編輯器打開JlinkDevice.xml文件,添加如下信息:
新增設(shè)備時(shí),Vendor、Name和Core是要求強(qiáng)制填寫的。如果還增加了FlashBankInfo,則WorkRAMAddr、WorkRAMSize也是強(qiáng)制要填寫的。
其中是<
Database>頂級(jí)標(biāo)簽,一個(gè)xml文件中只能存在一個(gè);
標(biāo)簽用于描述一個(gè)新的設(shè)備,沒有屬性說明,在xml文件里面可以存在多個(gè)。
標(biāo)簽用于添加設(shè)備的基本信息,其屬性值如下。
Vendor:指定設(shè)備供應(yīng)商名稱的字符串,強(qiáng)制屬性,例如Vendor=”ST”。
Name:設(shè)備名,強(qiáng)制屬性,例如Name=”STM32F407IE”。
WorkRAMAddr:指定J-Link在Flash編程等過程中可以使用的RAM區(qū)域地址的十六進(jìn)制值。不應(yīng)該被設(shè)備上的任何DMA使用。
WorkRAMSize:指定J-Link在Flash編程等過程中可以使用的RAM區(qū)域大小的十六進(jìn)制值。如果新設(shè)備未添加Flash Bank,則該屬性為可選。
Core:指定設(shè)備的內(nèi)核。當(dāng)新增設(shè)備時(shí),此屬性為必選屬性,例如Core= “ JLINK_CORE_CORTEX_M0 “。J-Link完整Core屬性值請(qǐng)查看J-Link用戶手冊(cè)中的Attribute values - Core。
標(biāo)簽用于指定設(shè)備的Flash Bank。使得IDE、J-Link Commander等軟件可以通過J-Link DLL的Flash下載功能對(duì)設(shè)備的Flash編程,其屬性值如下。
Name:指定Flash Bank的字符名稱,僅為了可視化的用途,不是必須屬性。例如Name=”SPI FLASH”。
BaseAddr:指定Flash Bank起始地址的十六進(jìn)制值。J-Link DLL使用BaseAddr和MaxSize來決定調(diào)試器執(zhí)行的哪些內(nèi)存寫操作需要通過Flashloader。
MaxSize:以十六進(jìn)制值指定Flash的大小,單位是字節(jié)。
Loader:指定Flashloader的ELF文件路徑的字符串。路徑可以是相對(duì)的或絕對(duì)的。
LoadType:指定Flashloader的類型。例如LoaderType = "FLASH_ALGO_TYPE_OPEN ",說明使用的算法是Open Flashloader算法。
AlwaysPresent:指定Flash是否始終存在,例如MCU片內(nèi)的Flash。
創(chuàng)建一個(gè)Flashloader的步驟
下面介紹如何修改Flashloader的源碼,創(chuàng)建一個(gè)自己的Flashloader。Segger官方有給出了Open Flash Loader的模板工程:(點(diǎn)擊最下方“閱讀原文”)
此模板是基于Cortex-M的,IDE使用的是SEGGER的Embedded Studio。下載模板工程文件后解壓,并下載安裝Embedded Studio for ARM,然后雙擊解壓后的Flashloader_V5.34.emProject文件, Embedded Studio會(huì)自動(dòng)打開工程。
實(shí)踐操作
下面將以STM32F103ZE芯片和W25Q128BV SPI Flash為例,修改Open Flashloader,讓J-Link能直接通過STM32F103ZE燒錄與之通過SPI連接的W25Q128BV。
W25Q128是華邦公司推出的一款SPI接口的NOR Flash芯片,16M字節(jié)大小,每頁256字節(jié),每扇區(qū)4k字節(jié)。擦除方式分為按單個(gè)扇區(qū)擦除,8個(gè)扇區(qū),16個(gè)扇區(qū)或整個(gè)芯片擦除。
1、修改FlashDev.c
FlashDev.c比較簡(jiǎn)單,只定義了一個(gè)名為FlashDevice設(shè)備的結(jié)構(gòu)體。但要注意,不要修改FlashDevice結(jié)構(gòu)體的section屬性。在這里我們只需要修改Flash設(shè)備名,F(xiàn)lash的基地址,F(xiàn)lash的總大小,F(xiàn)lash的頁大小(page),F(xiàn)lash擦除后的值,以及Flash的扇區(qū)信息。
Flash的扇區(qū)信息是一個(gè)結(jié)構(gòu)體數(shù)組,包含兩個(gè)成員,扇區(qū)大小的字節(jié)數(shù)和扇區(qū)的起始地址。但這里有一個(gè)需要注意的地方,結(jié)構(gòu)體數(shù)組的個(gè)數(shù)與不同大小扇區(qū)的數(shù)量有關(guān)。有一些MCU內(nèi)部的Flash有多個(gè)塊,并且塊的大小還不一樣,例如一款MCU內(nèi)部Flash分成4個(gè)16 KB的塊,1個(gè) 64 KB塊,1 個(gè)128 KB塊,所以不同大小的扇區(qū)數(shù)就是3。
扇區(qū)信息結(jié)構(gòu)體最后一個(gè)成員必須是“0xFFFFFFFF, 0xFFFFFFFF”,指示Flash扇區(qū)的結(jié)束。因?yàn)閃25Q128BV的扇區(qū)大小都是4KB,所以扇區(qū)信息結(jié)構(gòu)體元素個(gè)數(shù)為2(包括用于指示扇區(qū)結(jié)束的結(jié)構(gòu))。
2、修改FlashPrg.c
這個(gè)文件是Flashloader的核心,包含了Flash操作的各種函數(shù),其中必須要實(shí)現(xiàn)的函數(shù)有下面的4個(gè):
Init(),UnInit(),EraseSector(),ProgramPage()
Init()用于實(shí)現(xiàn)必要的硬件初始化,包括Flash的配置,解鎖操作等。UnInit()是初始化反操作,例如實(shí)現(xiàn)Flash的上鎖,防止誤操作。W25Q128寫和擦除操作是自動(dòng)上鎖的,也沒其他的必要操作,所以UnInit()只返回0表示操作成功即可。EraseSector()和ProgramPage()實(shí)現(xiàn)單個(gè)扇區(qū)的擦除和單個(gè)頁的寫入操作。這4個(gè)函數(shù)都返回0表示操作成功,返回1表示失敗。
此外有幾個(gè)可選實(shí)現(xiàn)的函數(shù),包括多扇區(qū)擦除,多頁寫入,全片擦除,擦除狀態(tài)檢測(cè)和校驗(yàn)等。
(1)、SEGGER_OPEN_Read()
這是一個(gè)針對(duì)非地址映射的Flash讀才需要的函數(shù),比如W25Q128這樣的SPI Flash,讀操作是通過SPI發(fā)生讀指令和地址,然后通過接收讀出的數(shù)據(jù)并存儲(chǔ)到緩存。
(2)、SEGGER_OPEN_Program
如果每次只寫一個(gè)頁,這樣效率勢(shì)必會(huì)比較低(PC端的工具軟件通過USB向J-Link傳輸命令和數(shù)據(jù),并設(shè)置PC調(diào)用ProgramPage()寫一個(gè)頁),如果一次操作寫多個(gè)頁效率自然提高了。
這個(gè)函數(shù)不需要修改,但這個(gè)函數(shù)有使用了兩個(gè)宏定義,需要在文件中修改這兩個(gè)宏定義:
#define PAGE_SIZE_SHIFT (8)
#define SECTOR_SIZE_SHIFT (12)
這是根據(jù)Flash的頁和扇區(qū)的大小來設(shè)定的,含義是2的冪,比如這里的設(shè)置頁的大小為2^ 8 = 256字節(jié),扇區(qū)大小為2^12=4096字節(jié)。
(3)、SEGGER_OPEN_Erase
同樣,當(dāng)要編程的數(shù)據(jù)超過一個(gè)扇區(qū)的時(shí)候,如果一次能擦除多個(gè)扇區(qū)可以提升效率。特別對(duì)W25Q128來說,擦除的速度是很慢的,如果要擦除64KB的時(shí)候,按照64KB塊擦除的時(shí)間要小于按照32KB塊擦除的時(shí)間,遠(yuǎn)小于按照4K扇區(qū)擦除的時(shí)間
(4)、BlankCheck()是為了檢測(cè)Flash是否已經(jīng)擦除。Flash擦除操作比較耗時(shí),如果要編程的地址范圍都已經(jīng)擦除了,就直接寫入,這樣可以加快Flash編程速度;EraseChip()是實(shí)現(xiàn)全片擦除功能;Verify()函數(shù)的用途是Flash編程完成之后,通過按字節(jié)回讀,驗(yàn)證寫入后的數(shù)據(jù)是否正確。這也是非地址映射的Flash需要實(shí)現(xiàn)的函數(shù)。
3、修改MemoryMap.xml
MemoryMap是Embedded Studio的內(nèi)存映射配置文件,用于指定MCU的RAM和Flash的基地址和大小。
4、調(diào)試和構(gòu)建Flashloader
調(diào)試是為了驗(yàn)證FlashPrg.c中這些實(shí)現(xiàn)的函數(shù)是否能夠如期工作,在main.c中將調(diào)試的宏定義開關(guān)打開:
#define DEBUG 1
#define SUPPORT_BLANK_CHECK 1
將工程配置切換到Debug,然后構(gòu)建代碼并下載到硬件中執(zhí)行。如果測(cè)試通過,再將配置切換到Release構(gòu)建Flashloader。
5、修改JlinkDevices.xml
我是直接在J-Link驅(qū)動(dòng)目錄下復(fù)制一份出來進(jìn)行修改,并用修改后的文件進(jìn)行替換。
按照前面的介紹,這里給STM32F103ZE增加了一個(gè)擴(kuò)展,擴(kuò)展了一個(gè)名為“SPI Flash”的Flash bank,基地址設(shè)置為0x09000000,大小為0x01000000(16MB)。
并將Flashloader的執(zhí)行文件設(shè)置為相對(duì)于JlinkDevices.xml的Devices\ST\STM32F1路徑,將生成的Flashloader執(zhí)行文件復(fù)制到該目錄中。
至此,修改Flashloader的工作全部完成了。
6、使用J-Link進(jìn)行測(cè)試
使用Embedded Studio建立一個(gè)工程進(jìn)行測(cè)試,在鏈接腳本中將Flash的地址改成指定的外擴(kuò)Flash地址,構(gòu)建代碼。
然后使用IDE的下載按鈕,將代碼下載到W25Q128:
燒錄功能正常。
使用J-Link Commander軟件的下載功能,將一個(gè)大約1MB的圖片bin文件,燒錄到W25Q128:
從測(cè)試結(jié)果來看,實(shí)現(xiàn)的Flashloader的正常工作的。
總結(jié)
J-Link是嵌入式開發(fā)中廣泛使用的硬件調(diào)試器,如果用戶掌握修改Flashloader的方法,可以讓工具變得更加得心應(yīng)手,不論硬件上外擴(kuò)了何種Flash,都可以使J-Link直接實(shí)現(xiàn)代碼和數(shù)據(jù)的
燒錄功能。如果需要了解更多有關(guān)J-Link或者Open Flashloader有關(guān)信息,可以參考J-Link用戶手冊(cè)以及SEGGER官網(wǎng)。