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