dsPIC33C 器件具有4M x 24位的程序存儲(chǔ)器地址空間,下面是Flash大小為256KB的程序存儲(chǔ)器地址的映射關(guān)系。
整個(gè)Flash結(jié)構(gòu)分為活動(dòng)區(qū)域和非活動(dòng)區(qū)域,用戶可用的是活動(dòng)區(qū)域,而活動(dòng)區(qū)域可分為用戶程序存儲(chǔ)區(qū)和器件配置,其中前兩個(gè)字節(jié)0x000000~0x000002為復(fù)位入口向量,0x000004~0x0001FE為中斷向量表IVT,0x000200為主程序的入口地址,正常情況下代碼從此處開(kāi)始存放。
用戶程序存儲(chǔ)空間(User Application Firmware,0x200開(kāi)始)分配一般是把Bootloader部分放在前,應(yīng)用程序放在后的結(jié)構(gòu)。這首先是實(shí)際的引導(dǎo)加載程序空間,是Bootloader代碼所在的位置,包括IVT和AIVT。引導(dǎo)加載程序空間只能通過(guò)對(duì)新的BootLoader程序進(jìn)行編程來(lái)修改。第二個(gè)存儲(chǔ)空間是應(yīng)用程序存儲(chǔ)空間或應(yīng)用程序代碼所在的位置。應(yīng)用程序存儲(chǔ)空間的一部分包括重新映射的中斷向量(Remapped Applicartion IVT)。該內(nèi)存映射顯示在下面的程序內(nèi)存使用情況中。通過(guò)使用引導(dǎo)程序?qū)⒋a從外部設(shè)備傳輸?shù)酱舜鎯?chǔ)區(qū)域,可以在此處對(duì)應(yīng)用程序代碼進(jìn)行重新編程。 MCU在上電和復(fù)位都是從Bootloader開(kāi)始執(zhí)行,BootLoader運(yùn)行后判斷當(dāng)前是否需要進(jìn)入升級(jí)狀態(tài)。如果不需要升級(jí),就直接運(yùn)行Flash原有的應(yīng)用程序;如果需要升級(jí),則進(jìn)入升級(jí)狀態(tài)。
Bootloader程序存放時(shí),是按照正常情況下從0x000200開(kāi)始存放。但是存放Bootloader程序的空間起始地址不應(yīng)該緊接著此地址,因?yàn)槿绻@樣擦除第一個(gè)閃存存儲(chǔ)頁(yè)也會(huì)擦除Bootloader的程序。因此,自舉程序的起始地址必須為0x800,為什么是0x800?
因?yàn)閐sPIC33C一頁(yè)有1024指令字,一行有128指令字,一個(gè)指令字為32位(實(shí)際24位,高8位為虛字節(jié),始終保持為0),由于dsPIC33C系列都是16位單片機(jī),因此每個(gè)指令字占2個(gè)16位數(shù)據(jù),占2個(gè)地址,實(shí)際擦除的地址跨度為2048,即0x800。
下面是dsPIC33C 單分區(qū)閃存代碼存儲(chǔ)區(qū)大小的情況。
Flash為256KB大小的具有90112指令字,704行,88頁(yè),下面是具體頁(yè)的分布情況。
所以弄清楚了頁(yè)的分布后,對(duì)Bootloader程序空間分配完畢之后,應(yīng)用程序的存放需要添加相應(yīng)的偏移量(可對(duì)照此表)。
定義存儲(chǔ)空間的大小和位置主要涉及確定當(dāng)前BootLoader的大小以及將來(lái)容納新功能所需的任何可用空間。 在最終確定此空間的大小之前,提供額外空間非常重要。 如果將來(lái)需要更改分配的BootLoader閃存空間的大小,則需要同時(shí)更改應(yīng)用程序的啟動(dòng)位置,然后重新映射中斷向量表的位置也需要更改。 對(duì)應(yīng)的兩個(gè)更改處意味著該應(yīng)用程序?qū)o(wú)法與較早的引導(dǎo)加載程序一起使用。 必須在項(xiàng)目開(kāi)始時(shí)就保留足夠的空間,以便將來(lái)提供額外的增長(zhǎng)空間。 一旦確定了為引導(dǎo)加載程序分配的閃存大小,即可將其余的閃存分配給應(yīng)用程序和重新映射的中斷向量表。
BootLoader程序空間的大小必須是設(shè)備頁(yè)面大小的倍數(shù)。 對(duì)于頁(yè)面大小為512條指令(1024個(gè)字)的設(shè)備,頁(yè)面大小必須為0x400的倍數(shù)。 同樣,對(duì)于具有1024條指令(2048個(gè)字)的頁(yè)面大小的設(shè)備,頁(yè)面大小必須為0x800的倍數(shù)。
比如Bootloader程序地址入口為0x800,分配2k指令字的大小,同時(shí)由于應(yīng)用程序也不可緊跟自舉程序之后,它必須從下一個(gè)閃存存儲(chǔ)頁(yè)的開(kāi)始處開(kāi)始存放,那么應(yīng)用程序的入口地址為0x1800.
TBLRDx和TBLWTx指令提供了讀或?qū)懗绦蚩臻g內(nèi)任何地址的最低有效字和最高有效字的直接方法,非常適合某些應(yīng)用。
對(duì)于表指令,程序存儲(chǔ)器可被視為并排放置的兩個(gè)16位字寬的地址空間,每個(gè)地址空間都有相同的地址范圍,由于程序存儲(chǔ)器只有24位寬,所以后一個(gè)空間的高字節(jié)不存在(盡管它是可尋址的),被稱(chēng)為“虛擬字節(jié)”。低位字的地址始終為偶數(shù),而高位字的地址為奇數(shù)。
由于程序存儲(chǔ)器地址始終在低位字處按字對(duì)齊,所以在代碼執(zhí)行的過(guò)程中地址將遞增或遞減2。這種尋址模式也與數(shù)據(jù)存儲(chǔ)空間尋址兼容,且為訪問(wèn)程序存儲(chǔ)空間中的數(shù)據(jù)提供了可能。下圖是一個(gè)取值示例,PC<22:1>指針遞增1相當(dāng)于PC<22:0>加2.
在MCU運(yùn)行時(shí),對(duì)內(nèi)部Flash進(jìn)行擦除、編程(注意,建議不要對(duì)當(dāng)前程序運(yùn)行區(qū)域進(jìn)行擦寫(xiě),會(huì)導(dǎo)致運(yùn)行異常)。
Flash編程采用的方式是"與"模式,即編程時(shí),將數(shù)據(jù)與Flash地址上的數(shù)據(jù)"與"操作。因此,如果一個(gè)地址上的數(shù)據(jù)位不是全都為1,那么編程該地址的結(jié)果就是錯(cuò)誤的,所以我們?cè)诓僮鱂lash時(shí)要有一個(gè)共識(shí),一個(gè)程序存儲(chǔ)字可以在擦除之前被編程兩次,但僅限于(1)兩次編程操做使用相同的數(shù)據(jù)或(2)包含1的位被設(shè)置為0,但為0的位不能設(shè)置為1;所以一般不建議在不擦除的情況下對(duì)數(shù)據(jù)進(jìn)行第二次編程,應(yīng)該將該地址所有數(shù)據(jù)位置1.我們?cè)撊绾卧诰幊糖皩?duì)應(yīng)地址的數(shù)據(jù)位全部置1呢?
那就是擦除,F(xiàn)lash擦除會(huì)把對(duì)應(yīng)區(qū)域的數(shù)據(jù)位全部置1。但是擦除不能僅擦除一個(gè)地址的數(shù)據(jù),而是必須擦除一頁(yè)的數(shù)據(jù),假設(shè)我們擦除0x000000,實(shí)際會(huì)擦除0x000000-0x0007FF,擦除其中任意地址,都會(huì)擦除該頁(yè)。所以dsPIC33C擦除操做是按頁(yè)擦除,按行進(jìn)行寫(xiě)?;蛘呖梢韵葘⒃擁?yè)內(nèi)所有數(shù)據(jù)讀出來(lái),然后擦除flash頁(yè),再修改讀出來(lái)的數(shù)據(jù),最后重新寫(xiě)入該頁(yè)所有數(shù)據(jù)。
需要提醒的是,由于配置字在用戶存儲(chǔ)區(qū)域最后一頁(yè),擦除最后一頁(yè)會(huì)觸發(fā)代碼保護(hù),所有地址數(shù)據(jù)全部清零。以dsPIC33CK256MP506為例,0x02BF00~0x02BFFC為配置字存放的地方,所以0x02B800之后的地址不能被擦除。
在雙分區(qū)閃存模式下,器件的存儲(chǔ)器均分為兩個(gè)物理部分,稱(chēng)為分區(qū)1 和分區(qū)2。每個(gè)分區(qū)都包含自己的程序存儲(chǔ)器和配置字。在程序執(zhí)行期間,只可執(zhí)行其中一個(gè)分區(qū)中的代碼,該分區(qū)為活動(dòng)分區(qū)。另一個(gè)非活動(dòng)分區(qū)不可用于執(zhí)行但可進(jìn)行編程。
支持的三種擦除工作分別是:批量擦除,非活動(dòng)區(qū)域擦除和頁(yè)擦除。
批量擦除是擦除用戶所有存儲(chǔ)區(qū)。
非活動(dòng)分區(qū)擦除操作可以在運(yùn)行時(shí)從活動(dòng)分區(qū)執(zhí)行。它將擦除非活動(dòng)分區(qū)中的所有用戶存儲(chǔ)區(qū)和閃存配置字。非活動(dòng)分區(qū)擦除命令僅在器件處于雙分區(qū)閃存模式之一時(shí)有效。這個(gè)功能在做Liveupdate時(shí)非常有用,當(dāng)活動(dòng)區(qū)處于工作時(shí),這時(shí)可以對(duì)非活動(dòng)區(qū)進(jìn)行擦寫(xiě)修改某些內(nèi)容,然后實(shí)現(xiàn)活動(dòng)區(qū)與非活動(dòng)區(qū)的無(wú)縫切換,對(duì)MCU實(shí)現(xiàn)不掉電升級(jí),此類(lèi)應(yīng)用在服務(wù)器電源應(yīng)用中比較多。
后面的BootLoader實(shí)現(xiàn)均是在基于單分區(qū)模式下。