時間:2014-07-30 17:12:36來源:萬有盛 朱路群
關(guān)鍵詞:TI:美國德州儀器公司
DSP:泛指TI生產(chǎn)的數(shù)字處理器芯片,此處專指TI生產(chǎn)的TMS2803x系列芯片
FLASH:電可擦除只讀存儲器
OTP:一次可編程存儲器
RAM:DSP內(nèi)部的讀寫存儲器
眾所周知,美國德州儀器(TI)公司的DSP芯片28xx系列由于其優(yōu)異的性能、強(qiáng)大的功能和極高的可靠性廣泛應(yīng)用于電機(jī)控制領(lǐng)域,筆者也在對這款芯片的開發(fā)應(yīng)用中有不少心得在這里提出來與大家共同探討一下。本次先討論一下對這款芯片的引導(dǎo)程序部分的個人見解。
關(guān)于該類芯片的存儲器的地址分配很多資料都有詳細(xì)介紹這里不覆訴,下面先看看該類芯片出廠固化的部分的程序或數(shù)據(jù)空間的分配:
看上述表格可以得知默認(rèn)的情況下當(dāng)CPU復(fù)位時會自動跳轉(zhuǎn)到0X3FFFC0處執(zhí)行程序,同時看到該處的空間只有64個字的空間而每個向量都占用會兩個字空間,所以0X3FFFC0到0X3FFFFF處可以放下32個中斷向量,但TI只用了其中16個,按順序包含“RESET”、“INT1…INT14”,“DLOGINT”等。其中最重要的一個矢量就是CPU復(fù)位矢量RESET占用0X3FFFC0、0X3FFFC1這兩個字的地址,一般這里放的都是跳轉(zhuǎn)到用戶主程序的執(zhí)行代碼:
WD_DISABLE.set1
.ref_c_int00
.globalcode_start
.sect"codestart"
code_start:
.ifWD_DISABLE==1
LBwd_disable
.else
LB_c_int00
.endif
.ifWD_DISABLE==1
.text
wd_disable:
SETCOBJMODE
EALLOW
MOVZDP,#7029h>>6
MOV@7029h,#0068h
EDIS
LB_c_int00
.endif
.end
以上是TI公布的標(biāo)準(zhǔn)的一段啟動代碼,“code_start”代碼段被“*.cmd”文件定位于0X3FFFC0地址處??梢钥吹皆摱未a是用匯編編寫的,條件編譯偽指令使得:若用戶想禁用看門狗就在最前面定義WD_DISABLE常量為1,編譯后0X3FFFC0處就編譯為“LBwd_disable”語句,將執(zhí)行完關(guān)掉看門狗代碼段后跳轉(zhuǎn)到“_c_int00”處,否則若定義WD_DISABLE=0的情況,地址0X3FFFC0處直接編譯為“LB_c_int00”。稍微留意一點(diǎn)可以發(fā)現(xiàn):兩種編譯方式最終結(jié)果都要跳轉(zhuǎn)到“_c_int00”處,這個“_c_int00”就是主程序main()的首地址,當(dāng)然用戶也可以用匯編編寫一個用“_c_int00”申明首地址的匯編代碼處。當(dāng)然,若用戶即申明了以“_c_int00”為名稱的匯編段,而且即使有main()為主程序的C源代碼段也不矛盾,執(zhí)行完“_c_int00”代碼段后執(zhí)行一個“LB_main”指令,編譯后也是能跳轉(zhuǎn)到主程序處的。
0X3FFFC2~0X3FFFDE的其他的向量在ENPIE標(biāo)志(PIECTRL寄存器中的位)為0時才真正有效,實(shí)際使用中這些向量大家都會放到PIE的向量表里,由于PIE向量表位于RAM區(qū),這樣做有利于增加中斷響應(yīng)的速度,所以這些向量這里不做詳細(xì)敘述。
其實(shí),并非CPU復(fù)位總是從0X3FFFC0處開始執(zhí)行,它有一個這樣的過程:CPU復(fù)位時真正的PC值是指向0X3FF8A1處,該處將執(zhí)行一段廠家固化的代碼然后檢查TRST引腳和GPIO的引腳決定進(jìn)入那種引導(dǎo)模式,下面討論一下2803X的復(fù)位后的工作順序:
第一步:初始化各標(biāo)志位:VMAP=1,OBJMODE=0,AMODE=0,M0M1MAP=1;
第二步:初始化主時鐘控制寄存器,將廠內(nèi)優(yōu)化的ADC偏置值和ADC的REF值寫入ADC相應(yīng)寄存器以提高ADC轉(zhuǎn)換精度;
第三步:初始化仿真寄存器、外設(shè)時鐘寄存器,初始化引腳電平弱上拉,初始化AIO引腳為ADC;
第四步:判斷TRST引腳是否為1:
是-則代表仿真器已連接,若EMU_KEY和EMU_MODE位都無效則等待用戶設(shè)置這兩個位,用戶設(shè)置后進(jìn)入不同的引導(dǎo)狀態(tài),進(jìn)入第五步B;
否-則代表仿真器未連接,檢查兩個GPIO引腳的狀態(tài),進(jìn)入不同的引導(dǎo)狀態(tài)進(jìn)入第五步A。
第五步A:GPIO選擇引導(dǎo)狀態(tài)表如下:
注:1等待模式:2803X只是進(jìn)入ROM死循環(huán),其他的C2000芯片這里不討論。
2:獲取模式:在默認(rèn)情況下,只要OTP_KEY寄存器不等于0x55AA或者OTP_BMODE寄存器無效,程序跳轉(zhuǎn)至0X3FFFC0處執(zhí)行。
從以上可以看出用于電機(jī)驅(qū)動的
第五步B:仿真引導(dǎo)模式見下表:
以上都有一種“獲取模式”該模式詳細(xì)內(nèi)容見下表:
可以看到CPU重上電或硬件復(fù)位時都要經(jīng)過以上過程而我們常用的都是基于FLASH的引導(dǎo)運(yùn)行,仿真也是這樣除非小程序會載入RAM運(yùn)行,而用于電機(jī)驅(qū)動的程序由于功能需要越來越多,它們都不是小程序所以這里重點(diǎn)討論FLASH的引導(dǎo)問題。
很多使用DSP的用戶認(rèn)為:DSP讀取FLASH時需要等待周期,而讀RAM時卻不需要等待,所以認(rèn)為把程序載入到RAM里運(yùn)行才能發(fā)揮DSP的最高效率,這種想法固然有一定的道理但是當(dāng)程序量遠(yuǎn)遠(yuǎn)超過DSP的RAM容量時載入無法使用,更何況電機(jī)控制要占用很大的數(shù)據(jù)RAM空間,若分段載入執(zhí)行還不如直接在FLASH內(nèi)執(zhí)行來的快。
其實(shí)TI公司早就考慮到FLASH的等待時間問題,使用了所謂“管道”技術(shù),即一次從FLASH按順序載入64字(一頁)的指令到流水線,除了發(fā)生轉(zhuǎn)移而不必考慮FLASH的等待時間影響了DSP的運(yùn)行速度。但是默認(rèn)情況下CPU上電或復(fù)位時是關(guān)掉“管道”功能且等待時間都設(shè)到最大,這就要用戶根據(jù)芯片具體型號重新設(shè)定FLASH的工作模式,下面看一段TI公布的標(biāo)準(zhǔn)代碼:
voidInitFlash(void){
EALLOW;
FlashRegs.FPWR.bit.PWR=3;//FLASH電源正常打開—最大
FlashRegs.FOPT.bit.ENPIPE=1;//管道模式使能
FlashRegs.FBANKWAIT.bit.PAGEWAIT=1;//頁讀取等待時間
FlashRegs.FBANKWAIT.bit.RANDWAIT=1;//隨機(jī)讀取等待時間
FlashRegs.FOTPWAIT.bit.OTPWAIT=1;//一次可編程OTP讀取等待時間,未用可不設(shè)
FlashRegs.FSTDBYWAIT.bit.STDBYWAIT=0x01FF;//電源組泵從待機(jī)到激活的等待時間
FlashRegs.FACTIVEWAIT.bit.ACTIVEWAIT=0x01FF;//FLASH從待機(jī)到激活的等待時間
EDIS;
asm("RPT#7||NOP");//設(shè)置完成需等待一段空操作時間
}
代碼中,關(guān)鍵動作步驟是:
1.打開電源;
2.打開管道模式;
3.設(shè)置頁讀取等待時間(查看芯片具體型號的資料);
4.設(shè)置隨機(jī)讀取等待時間(查看芯片具體型號的資料);
5.等待一段空操作周期;
其他部分可以不必設(shè)置,默認(rèn)情況已經(jīng)設(shè)置完成。
需要注意的是FLASH的寄存器操作代碼是不能放在FLASH空間來執(zhí)行的,否則會造成意外情況如:CPU復(fù)位等,那系統(tǒng)是怎么做的呢?看看以下TI公布的標(biāo)準(zhǔn)代碼:
voidMemCopy(Uint16*SourceAddr,Uint16*SourceEndAddr,Uint16*DestAddr)
{
while(SourceAddr
{
*DestAddr++=*SourceAddr++;
}
return;
}
#pragmaCODE_SECTION(RAM_InitFlash,"ramfun");//“ramfun”被定義在RAM處
voidRAM_InitFlash(void)//預(yù)留空程序以方便拷貝
{;
}
而在主程序中:
//……
MemCopy((Uint16*)&InitFlash,(Uint16*)&ServiceDog,(Uint16*)&RAM_InitFlash);//“InitFlash()”函數(shù)結(jié)束位置定義了“ServiceDog”段
RAM_InitFlash();
//……
通過以上代碼可以看到:先將FLASH的InitFlash()函數(shù)段全部拷貝到RAM里,然后調(diào)用該段RAM函數(shù)就完成了FLASH的寄存器操作。當(dāng)然這里需要特別注意“*.CMD”文件中對兩段程序段的地址重定義。
以上介紹了C環(huán)境下的FLASH的設(shè)置,但是筆者認(rèn)為:雖然TI的編譯系統(tǒng)CCS對C和C++都支持,但是由于編譯器不能靈活應(yīng)用全部的DSP指令,所以要編一個效率高節(jié)省資源的好程序還是要應(yīng)用匯編指令編程。這里隨便舉個例子進(jìn)行對比,例子的作用是判斷某標(biāo)志位Sign的bit0是否置位,若置位則調(diào)用一段子程序Subroutine()然后清除該位,下面看看兩種方法效率的對比:
C++程序:
//申明變量:
structBIT
{
Uint16Bit0:1;
Uint16Bit1:1;
Uint16Bit2:1;
Uint16Bit3:1;//寫完成延時:完成
//……
};
unionSIGN
{unsignedintall;
structBITbit;
};
main()
{//……
externvoidSubroutine(void);
unionSIGNSign;
//……
if(Sign.bit.Bit0)
{Sign.bit.Bit0=0;
Subroutine();
}
//……
}
該段程序經(jīng)過CCS編譯后看一看該段程序反匯編的結(jié)果:
“MOVZDP,#0X200
TBIT@0X12,#0
SBFC$DW$L$_main$37$E,NTC
TCLR@0X12,#0
LCR_Subroutine
”
匯編程序:
MOVZDP,#0X200
TCLR@Sign,#0
XCALL_Subroutine,TC
可以看到存儲空間C編譯結(jié)果占:13個字,匯編的結(jié)果占9個字,而執(zhí)行速度:若條件為假C的編譯結(jié)果為6個時鐘,流水線打斷指令預(yù)取可能需重裝;匯編占用6個周期,無打斷流水線的操作。若條件為真,不包含調(diào)用函數(shù)部分但包含返回:C編譯結(jié)果需要19個(加上LRET的8個時鐘)時鐘,而匯編需要16個(加上XRET的7個時鐘)時鐘,二者都有打斷了流水線的操作。而打斷流水線的話以前預(yù)取的指令就可能丟掉,重新在新地址預(yù)取指令,可以看到不管是從節(jié)省占用存儲空間的角度還是從執(zhí)行速度的角度都是匯編產(chǎn)生的結(jié)果來的優(yōu)越,特別是像判斷一個條件決定放那個數(shù)到變量的情況匯編可以利用如“MOV@DATA,AL,GT”等條件存儲指令而不用跳轉(zhuǎn)以致打亂流水線使“命中率”提高以提高指令執(zhí)行效率,而且代碼的長度也會縮小,諸如此類就不一一例舉了。
別看以上的例子好像優(yōu)勢不是很大,但是當(dāng)程序足夠大,足夠復(fù)雜時產(chǎn)生的總和就相當(dāng)可觀,正因為如此所以下面再談一談匯編組成的FLASH控制寄存器初始化的例子:
MOVLXAR0,#8000H
MOV*XAR0++,#2800H;mov@0a80h,#1
MOV*XAR0++,#1H
MOV*XAR0++,#2806H;mov@0a86h,#0
MOV*XAR0++,#0101H
MOV*XAR0++,#2807H;mov@0a87h,#1
MOV*XAR0++,#1H
MOV*XAR0++,#0F6FFH
MOV*XAR0++,#7700H;RPT#7||NOP
MOV*XAR0++,#07H
MOV*XAR0++,#06H;7614h=lret
MOVZDP,#_FLASH
LC#8000H
以上代碼直接將初始化FLASH寄存器的機(jī)器碼寫入至從0x8000地址開始的RAM空間而后直接調(diào)用,程序短小精悍執(zhí)行速度快。
經(jīng)過以上引導(dǎo)處理就可以高效的執(zhí)行用戶代碼了,下面再看看引導(dǎo)區(qū)里還有那些其他比較重要的內(nèi)容:
一.IQmath表
1:正弦/余弦表,對于電機(jī)控制而言該表最為重要,開始地址為0x3FE000,長度為1282個字,為長整型Q30格式,所以每個數(shù)據(jù)占用兩個字的空間,0~511個數(shù)據(jù)相對于0~360度的正弦值,后面還有90度(128個數(shù)據(jù))的數(shù)據(jù),這樣只要用戶將角度值加90度(π/2)查表就能非常方便獲得余弦值而再查余弦值時無需重復(fù)考慮溢出問題。
2:歸一化反轉(zhuǎn)表,使歸一化反轉(zhuǎn)計算過程收斂更快。
3:歸一化平方根表,使開方計算收斂更快。
4:還有反正切、舍入飽和表等等表此處不一一介紹了。
二.片上引導(dǎo)ROMIQmath函數(shù):包含常用的有:開方運(yùn)算、反正切運(yùn)算、等等。
總結(jié):
一.DSP由于其復(fù)位后引導(dǎo)方式的特殊性所以我們通常使用FLASH運(yùn)行程序的用戶應(yīng)該注意以下幾點(diǎn):
1:硬件上GPIO37和GPIO34引腳要保證上電時為高電平狀態(tài),最好將懸空或其設(shè)計為輸出引腳使用以保證電平的確定性;
2:軟件上需要初始化FLASH的寄存器,把DSP效率提升到最高。
3:其他外設(shè)也要根據(jù)芯片參數(shù)盡量的提高芯片性能,如初始化PLL、PWM等寄存器,限于篇幅且其他資料詳盡這里就不介紹了。
二:編程時注意的效率提升:
1:盡量使用效率高的指令,能一條指令完成的不用兩條,如:乘和加直接用乘加指令,取數(shù)和移位直接用移位取數(shù)指令,檢測某位和置位某位直接置位標(biāo)志就會檢測原來的位……諸如此類等等;
2:盡量不打斷流水線,盡量減少跳轉(zhuǎn)語句,熟練使用條件置數(shù)、條件調(diào)用、MAX、MIN等指令就可以做到這點(diǎn)。
3:程序跳轉(zhuǎn)時盡量使用短跳轉(zhuǎn)如SBF、BF等指令提高跳轉(zhuǎn)速度,當(dāng)然這要看需跳轉(zhuǎn)的位置地址的距離。
標(biāo)簽:
中國傳動網(wǎng)版權(quán)與免責(zé)聲明:凡本網(wǎng)注明[來源:中國傳動網(wǎng)]的所有文字、圖片、音視和視頻文件,版權(quán)均為中國傳動網(wǎng)(m.u63ivq3.com)獨(dú)家所有。如需轉(zhuǎn)載請與0755-82949061聯(lián)系。任何媒體、網(wǎng)站或個人轉(zhuǎn)載使用時須注明來源“中國傳動網(wǎng)”,違反者本網(wǎng)將追究其法律責(zé)任。
本網(wǎng)轉(zhuǎn)載并注明其他來源的稿件,均來自互聯(lián)網(wǎng)或業(yè)內(nèi)投稿人士,版權(quán)屬于原版權(quán)人。轉(zhuǎn)載請保留稿件來源及作者,禁止擅自篡改,違者自負(fù)版權(quán)法律責(zé)任。