在MAXQ8913微控制器中從RAM執(zhí)行應(yīng)用程序
MAXQ8913及其它MAXQ®微控制器采用的Harvard存儲(chǔ)器映射架構(gòu)為用戶提供了極大的靈活性,可根據(jù)需要將不同的物理內(nèi)存(例如數(shù)據(jù)SRAM)映射為程序或數(shù)據(jù)內(nèi)存空間。在特定環(huán)境下,從數(shù)據(jù)SRAM執(zhí)行一個(gè)程序的部分代碼能夠提升性能并降低功耗。這些優(yōu)勢(shì)都是以應(yīng)用程序的更加復(fù)雜為代價(jià)。
本文引用地址:http://butianyuan.cn/article/188391.htm概述
MAXQ8913和其它許多MAXQ微控制器一樣,也包含了一個(gè)基于SRAM的內(nèi)置數(shù)據(jù)存儲(chǔ)區(qū)域,該存儲(chǔ)區(qū)域可被映射為數(shù)據(jù)內(nèi)存空間,或者選擇映射為程序內(nèi)存空間。內(nèi)置SRAM通常用作數(shù)據(jù)存儲(chǔ)器,而在程序閃存或掩膜ROM中執(zhí)行大部分程序代碼。然而,在特定環(huán)境下,從內(nèi)部SRAM執(zhí)行有限的部分代碼非常有用。
本應(yīng)用筆記介紹如何配置、裝載匯編程序,以便從內(nèi)部SRAM正確運(yùn)行,本文還討論了這種方法的優(yōu)勢(shì)和缺點(diǎn)。本應(yīng)用筆記給出的例程針對(duì)MAXQ8913編寫,使用基于匯編的MAX-IDE環(huán)境。用戶可下載本文所涉及的應(yīng)用程序代碼和項(xiàng)目文件。
本文討論的代碼都特別針對(duì)MAXQ8913微控制器編寫,所介紹的原理和方法也同樣適合其它含有可映射為程序空間的內(nèi)部SRAM的MAXQ微控制器。能夠以這種方式執(zhí)行代碼的其它MAXQ微控制器包括:MAXQ2000、MAXQ2010和MAXQ3210/MAXQ3212。
該代碼能很好地運(yùn)行在任何基于MAXQ8913并為MAXQ8913的串口0提供一路串行接口(RS-232或USB至串口轉(zhuǎn)換)的硬件。將一個(gè)終端模擬器連接到該串口,并設(shè)置為9600波特率、8個(gè)數(shù)據(jù)位、1個(gè)停止位、無奇偶校驗(yàn),即可查看例程的代碼輸出。
用戶可免費(fèi)下載MAX-IDE環(huán)境的最新安裝程序包和文檔資料。
MAX-IDE安裝程序
MAXQ核編譯指南
開發(fā)工具指南
在RAM中執(zhí)行代碼的優(yōu)勢(shì)
通常情況下,MAXQ微控制器的絕大多數(shù)應(yīng)用代碼都被設(shè)計(jì)為在主程序空間執(zhí)行,主程序空間通常是利用一片大的內(nèi)部閃存或(對(duì)于掩膜ROM器件)用戶指定的應(yīng)用ROM來實(shí)現(xiàn)。主程序空間為非易失存儲(chǔ)器,所以大多數(shù)情況下可用來保存應(yīng)用程序代碼。內(nèi)部SRAM被用來存儲(chǔ)變量、軟件棧,以及器件被關(guān)閉時(shí)不需要保存的類似數(shù)據(jù)。
然而,對(duì)于特定應(yīng)用,在數(shù)據(jù)SRAM中執(zhí)行某些代碼具有一定優(yōu)勢(shì)。
降低功耗
在大多數(shù)MAXQ微控制器中,當(dāng)在內(nèi)部SRAM (或固定用途ROM)中執(zhí)行代碼時(shí),相對(duì)于程序閃存而言,電源電流會(huì)減小。因?yàn)殚W存在不被存取時(shí)可被動(dòng)態(tài)斷電,所以這種情況下就能節(jié)省功率。如果某個(gè)應(yīng)用程序通常在大部分活動(dòng)時(shí)間內(nèi)執(zhí)行非常小的代碼量,在SRAM中執(zhí)行就能大大降低總體功耗。
直接訪問主程序空間存儲(chǔ)器
通常,從主程序閃存執(zhí)行的代碼不能直接讀取保存在主程序閃存中的數(shù)據(jù)。這種類型的數(shù)據(jù)可以包括隨應(yīng)用程序數(shù)據(jù)一起的常量字符串和數(shù)據(jù)表。若要讀取該數(shù)據(jù),應(yīng)用程序必須調(diào)用固定用途ROM中的專用數(shù)據(jù)傳遞函數(shù)。在RAM中執(zhí)行代碼則避開了這一限制,允許利用標(biāo)準(zhǔn)的數(shù)據(jù)指針直接讀取閃存中包含的數(shù)據(jù)。這就加快了存取操作。若一個(gè)小的算法花費(fèi)大量的時(shí)間遍歷閃存中存儲(chǔ)的查找表或其它常量數(shù)據(jù),那么在RAM中執(zhí)行該算法則能夠在非常短的時(shí)間內(nèi)完成運(yùn)算。
可重寫整個(gè)閃存
和大多數(shù)基于閃存的MAXQ微控制器一樣,MAXQ8913中的固定用途ROM含有在應(yīng)用程序控制下擦除和重寫程序閃存的標(biāo)準(zhǔn)函數(shù)。該過程能夠使用戶裝載器通過用戶指定接口(例如串口、SPI或I²C)重新裝載部分或全部應(yīng)用程序。然而,若用戶裝載程序位于閃存內(nèi),則不能擦除或重寫自身所占用的閃存。在RAM中執(zhí)行用戶裝載器,可以擦除整個(gè)閃存程序空間并重新寫入新的代碼,包括用戶裝載器本身。
在RAM中執(zhí)行代碼的缺點(diǎn)
在RAM中執(zhí)行應(yīng)用程序代碼也存在缺點(diǎn)和限制。有些缺點(diǎn)與具體工作相關(guān),而有些缺點(diǎn)則是MAXQ架構(gòu)所固有的。
有限的代碼空間
RAM一般比程序閃存小得多,這意味著在任何給定時(shí)間只能執(zhí)行少量代碼。但有可能在RAM中運(yùn)行一個(gè)例程,然后將其擦除并裝載第二個(gè)例程,隨后再運(yùn)行第二個(gè)例程,依此類推。
代碼映射
在RAM中執(zhí)行代碼之前,必須將其復(fù)制到RAM。這一過程需要時(shí)間和代碼空間。此外,代碼必須從某個(gè)位置復(fù)制,所以代碼實(shí)際上被存儲(chǔ)兩次:一次在閃存或程序ROM,一次在RAM。即使該代碼不是為了在閃存中執(zhí)行,也必須被存儲(chǔ)于其中,從而消耗了額外的空間。
不可直接存取RAM
當(dāng)在RAM中執(zhí)行代碼時(shí),RAM就不再是可見的數(shù)據(jù)存儲(chǔ)空間。這意味著不能利用數(shù)據(jù)指針直接從RAM存儲(chǔ)單元讀取或?qū)懭霐?shù)據(jù)。按照在閃存中運(yùn)行應(yīng)用代碼相同的方式,有可能避開這種限制。利用固定用途ROM數(shù)據(jù)傳遞函數(shù)(UROM_moveDP0和類似的函數(shù))可對(duì)RAM進(jìn)行讀取,以及通過在閃存中寫入類似的函數(shù),可直接對(duì)RAM進(jìn)行寫操作。然而,這種迂回方法也占用額外的時(shí)間和應(yīng)用程序空間。
編譯在RAM中執(zhí)行的代碼
在編寫將要在數(shù)據(jù)RAM中執(zhí)行的應(yīng)用代碼時(shí),必須要考慮一項(xiàng)主要因素。代碼的每個(gè)字都將被編譯至一個(gè)地址并被裝載至該地址的閃存中,但是將在不同地址的RAM中執(zhí)行。例如,如果一段代碼被裝載至以程序字地址0100h開始的閃存中,并被復(fù)制到以數(shù)據(jù)字地址0100h開始的RAM中,在RAM中就不可能跳至地址0100h來執(zhí)行代碼。在閃存中,地址0100h仍然是代碼的地址。在程序空間中,RAM中代碼的地址是其數(shù)據(jù)存儲(chǔ)地址加上偏移量A000h,如圖1所示。
圖1. MAXQ8913在RAM中執(zhí)行代碼時(shí)的內(nèi)存映射
為了執(zhí)行復(fù)制到RAM中數(shù)據(jù)內(nèi)存地址為0100h的應(yīng)用程序,必須跳至程序地址A100h。
在RAM中執(zhí)行代碼會(huì)為MAX-IDE編譯器造成困難。MAX-IDE并不知道將在與編譯地址不同的地址執(zhí)行代碼。例如,假設(shè)一個(gè)例程調(diào)用了閃存地址為0080h的subOne,而另一個(gè)位于0300h的例程調(diào)用了第一個(gè)例程。其代碼如下所示。
org 0080h
subOne:
....perform various calculations...
ret
...
org 0300h
subTw
call subOne
...and so on...
如果兩個(gè)例程均被復(fù)制到RAM并在此執(zhí)行,將會(huì)發(fā)生什么? 假設(shè)例程均被復(fù)制到RAM中與其在閃存中占用的程序地址相同的數(shù)據(jù)內(nèi)存地址,那么subOne將位于程序地址A080h,subTwo將位于A300h。
因?yàn)椤癱all subOne”所在行與目標(biāo)端標(biāo)簽subOne之間的距離超過了相對(duì)跳轉(zhuǎn)距離(+127/-128個(gè)字),所以指令就必須被重新編譯為絕對(duì)LCALL。然而,編譯器所持有的subOne的唯一地址是0080h,所以指令將被編譯為“LCALL 0080h”。當(dāng)subTwo執(zhí)行時(shí),它將不調(diào)用位于RAM中的subOne副本,而是調(diào)用位于閃存中的版本。
有兩種迂回方法可能解決這種困境。第一種方法也是最簡(jiǎn)單的方法,即強(qiáng)制編譯器始終使用相對(duì)跳轉(zhuǎn)和調(diào)用,并使例程在RAM中離得足夠近,使其能夠按照這一方式調(diào)用其它例程。總是使用SJUMP和SCALL,而不是JUMP和CALL機(jī)器碼(使編譯器可選擇短或長(zhǎng)跳轉(zhuǎn))。這將強(qiáng)制使用指令的相對(duì)跳轉(zhuǎn)版本。
然而,這種方法也存在限制。如果在RAM中運(yùn)行的代碼量長(zhǎng)于128個(gè)字,相對(duì)跳轉(zhuǎn)就有可能不足以長(zhǎng)到使RAM中的一個(gè)例程調(diào)用另一個(gè)例程。這種情況下的解決方法是通過ORG聲明為不同的例程使用固定的地址,然后定義包含其在RAM中的正確地址的等價(jià)變量。這些等價(jià)變量可被用于LCALL和LJUMP聲明中,如下所示。
subOne equ 0A080h
org 0080h
; subOne
....perform various calculations...
ret
...
org 0300h
subTw
lcall #subOne
...and so on...
這一過程強(qiáng)制編譯器為L(zhǎng)CALL使用正確的地址。
將代碼復(fù)制至RAM
在RAM中執(zhí)行代碼之前,必須首先將其復(fù)制到RAM。將大量代碼從閃存復(fù)制到RAM的最簡(jiǎn)單方式是使用應(yīng)用ROM copyBuffer函數(shù)。該函數(shù)的輸入?yún)?shù)為兩個(gè)數(shù)據(jù)指針(DP[0]和BP[Offs])和一個(gè)長(zhǎng)度值(LC[0])。它將指定數(shù)量的字節(jié)/字從源地址DP[0]復(fù)制到目標(biāo)地址BP[Offs];一次可復(fù)制最多256個(gè)字節(jié)/字。
我們的示例應(yīng)用程序?qū)⑵溟_始的512個(gè)字從閃存復(fù)制到RAM,然后跳轉(zhuǎn)至RAM中的副本開始執(zhí)行代碼。源指針(DP[0])指向程序閃存在應(yīng)用ROM的內(nèi)存映射中的地址,從8000h開始。請(qǐng)主意,為了避免無限循環(huán),在復(fù)制RAM的代碼之后,我們跳轉(zhuǎn)至RAM中副本的部分。
org 0020h
copyToRAM:
move DPC, #1Ch ; Ensure all pointers are operating in word mode.
move DP[0], #8000h ; Start of program flash from UROM's perspective.
move BP, #0 ; Start of data memory.
move Offs, #0
move LC[0], #256 ; The Offs register limits us to a 256-word copy.
lcall UROM_copyBuffer
move DP[0], #8100h ; Copy second half.
move BP, #0100h
move Offs, #0
move LC[0], #256
lcall UROM_copyBuffer
ljump #0A040h ; Begin execution of code from RAM.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Executing from RAM
;;
org 0040h
move LC[0], #1000
delayLoop:
move LC[1], #8000
sdjnz LC[1], $
sdjnz LC[0], delayLoop
;; Initialize serial port.
move SCON.6, #1 ; Set to mode 1 (10-bit asynchronous).
move SMD.1, #1 ; Baud rate = 16 x baud clock
move PR, #009D4h ; P = 2^21 * 9600/8.000MHz
move SCON.1, #0 ; Clear transmit character flag.
評(píng)論