在我的職業(yè)生涯中,我一直從事模擬和混合信號系統(tǒng)、FPGA架構(gòu)、I/O和信號完整性方面的工作。所以我真的是一個搞硬件的人,讓我有時有一點負(fù)罪感的是我曾認(rèn)為嵌入式軟件適合其他人來做。
隨著射頻(RF)數(shù)據(jù)轉(zhuǎn)換器的問世,情況發(fā)生了變化。我們現(xiàn)在已經(jīng)將世界一流的RF ADC和DAC集成到Zynq UltraScale +架構(gòu)中了。因此,傳統(tǒng)的射頻和模擬工程師不可避免地以前所未有的方式接觸到了嵌入式系統(tǒng)。
射頻數(shù)據(jù)轉(zhuǎn)換器解決方案
如果您對數(shù)據(jù)轉(zhuǎn)換器解決方案很熟悉,那您就會知道它是以IP核的形式被封裝到Vivado Design Suite中的。這讓您可以通過賽靈思提供的軟件驅(qū)動來管理射頻模數(shù)轉(zhuǎn)換器(RF-ADC)和射頻數(shù)模轉(zhuǎn)換器(RF-DAC)塊的狀態(tài)和控制。
《Zynq UltraScale + RFSoC RF數(shù)據(jù)轉(zhuǎn)換器IP產(chǎn)品指南》(PG269)提供了有關(guān)此IP的所有詳情,并且還提供了有關(guān)該驅(qū)動的詳細(xì)附錄。
開始在RF-ADC和RF-DAC上進(jìn)行調(diào)試
RF分析儀工具是一個不錯的起點。
RF分析儀是基于MicroBlaze的設(shè)計,具有通信層,可以部署到任何電路板上的任何器件上。它還帶有一個GUI,讓您可以將RF-ADC接收的內(nèi)容可視化,并可通過RF-DAC來實現(xiàn)激勵生成和發(fā)射函數(shù)。至關(guān)重要的是,該應(yīng)用是通過軟件驅(qū)動構(gòu)建的。
如果您試圖追蹤RF系統(tǒng)中的問題,RF分析儀非常強(qiáng)大,而且由于它獨(dú)立工作,不依賴于設(shè)計或電路板,因此可以用來驗證系統(tǒng)的RF部分。
一個常見的用例是您希望在系統(tǒng)中調(diào)試RF-ADC和RF-DAC,并需要編寫一個小應(yīng)用以在運(yùn)行時進(jìn)行測試。鑒于RF分析儀和定制設(shè)計都需要使用軟件驅(qū)動,我決定編寫一個博客幫助您了解驅(qū)動,并展示一下如何開始用它來進(jìn)行調(diào)試。在下一個博客中,我會展示一次拆箱,帶您一起來看看RF分析儀工具。
有可能您對RF數(shù)據(jù)轉(zhuǎn)換器系統(tǒng)已經(jīng)很熟悉了,那就把了解驅(qū)動想成是在您的知識基礎(chǔ)上再增添一點知識,而不是去了解完全未知的事物吧。
在這篇博客中,我會介紹以下內(nèi)容:
如何構(gòu)建驅(qū)動
數(shù)據(jù)結(jié)構(gòu)
使用應(yīng)用編程接口(API)來制作一個簡單的應(yīng)用
我們現(xiàn)在還是來制作一個Baremetal應(yīng)用吧。在稍后的博客中,我們會在此基礎(chǔ)上介紹如何制作Linux應(yīng)用。
構(gòu)建驅(qū)動:
RFDC驅(qū)動的一個優(yōu)點是它是使用Libmetal構(gòu)建的。Libmetal是賽靈思開發(fā)的開源軟件堆棧,提供用來訪問器件的、處理器件中斷、請求跨Linux、Realtime OS和baremetal內(nèi)存的通用用戶API。
這對我們來說意味著什么?嗯,這意味著我們真正感興趣的驅(qū)動部分是在用戶空間實現(xiàn)的,因此我們不必?fù)?dān)心與硬件交談的機(jī)制。這還意味著API在Linux和Baremetal應(yīng)用中很常見,因此您不需要了解兩組API調(diào)用,也不用擔(dān)心如何將代碼從Baremetal移植到Linux。
XRFdc驅(qū)動程序源代碼在下圖中顯示得更詳細(xì)。驅(qū)動的源代碼可以在賽靈思的SDK安裝中找到,也可以在Github上單擊這里找到。
在這個圖中,在底部您會看到xrfdc_hw.h文件。這個報頭文件包含您可能會認(rèn)為是RF ADC和DAC塊的寄存器地址映射。這個文件并不是編寫來供用戶使用的,而是用于驅(qū)動的內(nèi)部機(jī)制。應(yīng)該不需要用到此文件中的標(biāo)識符,甚至不需要研究它們,因為它們在編寫應(yīng)用時無法真正幫到您。
其他報頭文件(例如xrfdc.h和xrfdc_mts.h)更重要,因為它們內(nèi)含以下內(nèi)容:
API調(diào)用所需的所有數(shù)據(jù)結(jié)構(gòu)。
用于實現(xiàn)API調(diào)用的代碼中的內(nèi)聯(lián)(輔助)函數(shù)。
用于應(yīng)用的宏(這很有用,因為您可以在適當(dāng)?shù)臅r候使用宏XRFDC_ADC_TILE/XRFDC_DAC_TILE,而不是將ADC塊的值0或DAC塊的值1傳遞給API。這讓讀取和理解代碼變得易如反掌。)
最重要的是,這些文件顯示的是將用于您的應(yīng)用的API調(diào)用原型。
接下來,您將看到的是API調(diào)用的源代碼。這是我們實現(xiàn)用戶API調(diào)用功能的地方。通常,不需要非常詳細(xì)地研究各個API調(diào)用是如何實現(xiàn)的。
xrfdc.c:這是用于應(yīng)用的API的主體。
xrfdc_intr.c:用于實現(xiàn)管理RF數(shù)據(jù)轉(zhuǎn)換器中斷所需的API調(diào)用。
xrfdc_mixer.c:包含XRFdc驅(qū)動中混頻器設(shè)置的接口函數(shù)。
xrfdc_mts.c:包含XRFdc驅(qū)動的多塊同步函數(shù)。
XRFdc軟件驅(qū)動的工作原理
我們已經(jīng)看到了驅(qū)動源中包含的內(nèi)容,現(xiàn)在我們來談?wù)勀枰盟鼇碜鍪裁础?/p>
如上所述,xrfdc.h報頭文件應(yīng)該是您最常引用的文件。這個文件中提供了數(shù)據(jù)結(jié)構(gòu)和API函數(shù)原型。數(shù)據(jù)結(jié)構(gòu)和API調(diào)用在(PG269)的附錄D中也有詳細(xì)記錄。
我們先來談?wù)剶?shù)據(jù)結(jié)構(gòu)。
數(shù)據(jù)結(jié)構(gòu)是一種信息組織方法,用于將有關(guān)RF數(shù)據(jù)轉(zhuǎn)換器的信息組織成有意義的組。我喜歡將數(shù)據(jù)結(jié)構(gòu)看成是一個“容器”。一個全職軟件開發(fā)者可能會說這是一個C ++術(shù)語,不應(yīng)該這樣使用,但這個比喻對我有用。
我想指向的示例數(shù)據(jù)結(jié)構(gòu)是RF-ADC或RF-DAC塊中的鎖相環(huán)(PLL)。看一下,我們可以看到它描述了我們可能需要知道的關(guān)于PLL的一切,例如,它是否已啟用、它的輸入時鐘、它輸出的示例時鐘等。
一旦這樣的結(jié)構(gòu)存在,我們就可以在API之間輕松地來回傳遞它,并且可能還可以從一個API中讀取,或在另一個API中進(jìn)行修改。
您還可以在另一個結(jié)構(gòu)中找到結(jié)構(gòu)。例如,XRFdc_PLL_Settings是XRFdc_DAC_Tile的一個成員。
由于結(jié)構(gòu)是透明的,因此您可以在代碼中單獨(dú)對它的一個成員進(jìn)行修改。一個例子是復(fù)雜混頻器中數(shù)控振蕩器頻率的變化。
MixerSettings結(jié)構(gòu)有一個稱為Freq(表示頻率)的成員,因此我們可以按如下方式在代碼中對它進(jìn)行更改。
MixerSettings.Freq = 2000;//MHz
一旦理解了數(shù)據(jù)結(jié)構(gòu)的基礎(chǔ)知識,我們就需要掌握可以使用的API調(diào)用了。這些是應(yīng)用的構(gòu)建塊。
各個API調(diào)用機(jī)制被抽取并傳遞給用戶。它們在XRFdc.c文件中被實現(xiàn)。如果您想使用調(diào)用,只需要知道三件事。
要使用的ADC或DAC塊中的函數(shù)。
您需要將其作為輸入傳遞。
這通常意味著您可以告訴它您在塊中需要的RF塊類型、塊ID和單個塊。
API可能需要被傳遞一個結(jié)構(gòu)才能使用。
您會得到什么作為輸出。
例如,它可能會返回結(jié)構(gòu)的內(nèi)容。
此驅(qū)動中只使用了幾種不同類型的API:
有些管理調(diào)用可以用來控制塊,例如XRFdc_StartUp/XRFdc_Shutdown。這些塊用來啟動或關(guān)閉單個RF-ADC或RF-DAC塊。
有些API調(diào)用可以啟用高級狀態(tài)報告,例如,XRFdc_GetIPStatus/XRFdc_GetBlockStatus。
還有針對各個子塊的Get和Set API調(diào)用。例如,您可以分別使用XRFdc_GetMixerSettings和XRFdc_SetMixerSettings同時用get和set來進(jìn)行復(fù)雜的混頻器設(shè)置。
請務(wù)必注意,在IP中也會配置一些Get和Set調(diào)用,例如復(fù)雜的混頻器設(shè)置。有些調(diào)用只能在運(yùn)行時完成。一個例子是RF-ADC閾值標(biāo)志和正交調(diào)制校正(QMC)。
最后,其中一些更改將需要重新啟動塊。更改PLL設(shè)置就是一個這樣的例子。
你好,RFDC
我們現(xiàn)在對驅(qū)動已經(jīng)有所了解,可以為Zynq UltraScale + RFSoC ZCU111評估板制作第一個非常簡單的應(yīng)用了。
在本示例中,我打算只捕獲一些ADC數(shù)據(jù)。我們可以隨時擴(kuò)展對以后的博客的設(shè)計。我正在發(fā)送一些IQ數(shù)據(jù)模式,我將用混頻器將其混合到基帶并將其輸出到設(shè)計中的系統(tǒng)集成邏輯分析器塊。
在本示例中,我們只想展示一些高級狀態(tài)和管理API以及我們先前討論過的一些get和set API。我們只檢查IP的狀態(tài),并確保啟動塊的方法正確無誤。然后我們將回讀數(shù)據(jù)路徑的狀態(tài)。最后,我們要檢查一下混頻器的設(shè)置。
在我們實現(xiàn)此設(shè)計并獲得比特流之后,我們可以導(dǎo)出硬件切換文件(HDF)并啟動SDK。如果您想了解有關(guān)嵌入式設(shè)計和SDK的更多信息,也許值得花點時間查看本教程。
HDF文件在SDK中創(chuàng)建硬件平臺,因此它知道設(shè)計中使用的所有外設(shè)及其地址。接下來要做的是制作一個電路板支持包。這需要硬件定義,并提供您需要的所有相關(guān)驅(qū)動和庫。
操作演示
單擊“File > New > Board Support Package”。
選擇剛剛創(chuàng)建的硬件平臺,然后單擊“下一步”。
系統(tǒng)會提示您包含某些庫。確保您勾選包含libmetal,然后單擊“OK”。在這個階段,我們擁有制作我們的應(yīng)用所需的一切。
現(xiàn)在,您可以單擊“File > New > Application Project”創(chuàng)建示例。
確保指向硬件平臺和剛剛創(chuàng)建的BSP。
單擊“Next”,然后選擇一個空白工程。
我在這篇博客中已提供了我的應(yīng)用的源代碼。您可以導(dǎo)入我的應(yīng)用并將其用作模板。
我們一起來看看一些主要功能。
我們需要先包含xparameters.h文件(這個文件中有我們需要的所有硬件參數(shù))和我們前面提到的xrfdc.h文件(這個文件中有API調(diào)用的驅(qū)動結(jié)構(gòu)和函數(shù)原型)。
在本示例中,我有一個ZCU111電路板,而且我需要在啟動時對時鐘進(jìn)行編程。為了實現(xiàn)這一點,我添加了一些文件(這些文件來自驅(qū)動程序源中的“examples”文件夾)。
您將看到我創(chuàng)建XRFdc頂層結(jié)構(gòu)的靜態(tài)實例。這里的想法是我們有一個結(jié)構(gòu)實例,而且我們可以從任何我們可能需要的API或函數(shù)指向它。
static XRFdc RFdcInst; /* RFdc driver instance */
在main函數(shù)中,我們聲明了我們需要的所有結(jié)構(gòu):
int Status;
XRFdc_Config *ConfigPtr;
XRFdc *RFdcInstPtr = &RFdcInst;
XRFdc_BlockStatus BlockStatus;
XRFdc_IPStatus myIPStatus;
XRFdc_Mixer_Settings MixerSettings = {0};
請注意,我們只是指向我們剛剛創(chuàng)建的驅(qū)動的靜態(tài)實例。
下一步是初始化驅(qū)動。這一步每次都必須做。簡單說來,我們將獲得xrfdc_g文件中的配置表,并通過XRFdc_LookupConfig函數(shù)使用xparameters中的值和設(shè)置來填充表。然后我們將其存儲在配置指針ConfigPtr中。完成此操作后,我們調(diào)用XRFdc_CfgInitialize API并通過配置填充RFdcInstPtr。
現(xiàn)在我們就可以在我們的應(yīng)用中使用該驅(qū)動了。
您會看到我將輸入時鐘編程到ADC塊。
我用XRFdc_GetIPStatus來檢查我啟用的ADC塊的狀態(tài)。
Status = XRFdc_GetIPStatus(RFdcInstPtr, &myIPStatus);
if (Status != XRFDC_SUCCESS) {
return XRFDC_FAILURE;
}
int powerup_status;
int tile_state;
powerup_status = myIPStatus.ADCTileStatus[0].PowerUpState;
tile_state = myIPStatus.ADCTileStatus[0].TileState;
printf("ADC PowerUp Status: %u\n", powerup_status);
printf("ADC Tile State: %u\n", tile_state);
在本示例中,我希望看到塊狀態(tài)為15。這表示該塊已到達(dá)其啟動狀態(tài)機(jī)的末尾,并且加電狀態(tài)為1,這意味著它已啟用并處于活動狀態(tài)。
我使用的下一個API調(diào)用是XRFdc_GetBlockStatus。這應(yīng)該告訴我們采樣頻率的設(shè)置,以及數(shù)字?jǐn)?shù)據(jù)路徑的配置方式。請注意,我現(xiàn)在在用XRFDC_ADC_TILE抽取此API調(diào)用的塊類型。
Status = XRFdc_GetBlockStatus(RFdcInstPtr, XRFDC_ADC_TILE, 0, 0, &BlockStatus);
if (Status != XRFDC_SUCCESS) {
return XRFDC_FAILURE;
}
最后,我會使用XRFdc_GetMixerSettings并在混頻器上打印一些細(xì)節(jié)。
我進(jìn)行了更改,然后用XRFdc_SetMixerSettings來寫入新設(shè)置。
在此之后,我會生成一個塊事件并將所做的更改應(yīng)用到硬件。
隨后,XRFdc_GetMixerSettings應(yīng)該會顯示我們已在硬件中將混頻器比例從0更改為2或從AUTO更改為1.0,并且我的混頻器設(shè)置也已更改。
那現(xiàn)在我們在SDK中的調(diào)試器里來運(yùn)行一下這個應(yīng)用。
右鍵單擊應(yīng)用程序,然后選擇“運(yùn)行方式...”,然后選擇“運(yùn)行配置”。我使用系統(tǒng)調(diào)試器,然后也選擇對FPGA進(jìn)行編程的選項。
您也可以選擇“Debug As”,這將啟用調(diào)試透視圖并適應(yīng)代碼的步進(jìn)等。
我們現(xiàn)在來看看UART串行控制臺出來的結(jié)果。
(我使用內(nèi)置的SDK終端進(jìn)行連接,但可以使用任何終端仿真器。)
您可以看到它執(zhí)行以下操作:
說“Hello!”
對ZCU111電路板上的時鐘進(jìn)行編程。
將塊狀態(tài)設(shè)置為15,這意味著塊已完全啟動,并且AXI流上有有效數(shù)據(jù)出來。
報告數(shù)字?jǐn)?shù)據(jù)路徑的阻止?fàn)顟B(tài)。
顯示混頻器設(shè)置的讀取,并確認(rèn)修改。
最后一次檢查顯示RF-ADC的數(shù)據(jù)正傳遞給系統(tǒng)ILA。
總結(jié)語
現(xiàn)在您可以開始編寫一些應(yīng)用了。我已經(jīng)附上了用來構(gòu)建我的硬件塊設(shè)計的Tcl腳本和用于我的ZCU111工程的XDC文件。而且,還附上了該應(yīng)用的C代碼。
如果您有可能想要編寫來與RF數(shù)據(jù)轉(zhuǎn)換器通信的任何應(yīng)用,它應(yīng)該是一個很好的起點。我會鼓勵您用自己的裸機(jī)應(yīng)用進(jìn)行練習(xí)。
我打算在這篇博客的基礎(chǔ)添加一些內(nèi)容,并突出顯示RFSoC的其他一些不錯的設(shè)計和調(diào)試功能。接下來,我打算展示拆箱并瀏覽RF分析儀工具(這個工具允許您在任何平臺上對任何RFSoC器件進(jìn)行調(diào)試)。
下次見!
-
射頻
+關(guān)注
關(guān)注
104文章
5535瀏覽量
167469 -
嵌入式系統(tǒng)
+關(guān)注
關(guān)注
41文章
3553瀏覽量
129113 -
模擬工程師
+關(guān)注
關(guān)注
1文章
19瀏覽量
13545
發(fā)布評論請先 登錄
相關(guān)推薦
評論