S03_CH13_ZYNQ A9 TCP UART雙核AMP例程


S03_CH13_ZYNQ A9 TCP UART雙核AMP例程

13.1概述

ZYNQ中存在兩個獨立的ARM核,在很多應用場景中往往只需使用其中的1個核心即可。然而,對於復雜的設計,例如多任務,並行控制、處理等,單個核心將難以勝任。因此,為了盡可能發揮ZYNQ中雙ARM核的優勢和性能,進行雙核應用的開發顯得尤為重要。同時,也進一步為Xilinx下一代MPSOC多核異構處理器的使用打下基礎。

在ZYNQ中實現雙ARM核AMP應用可以參考Xilinx官方的XAPP1078和XAPP1079。在SDK中也有用於雙核應用開發的openamp庫可以使用。

本例程未使用openamp庫,通過自行設計的代碼實現了一個簡單的雙核應用,旨在說明:

l 雙核通過軟件中斷進行核間通信的原理及方法。

l 雙核通過共享內存進行數據交互的基本原理和設計方法。

l 雙核協同工作的基本模式。

l 雙核BOOT的方法。

本例程基於vivado 2015.4開發。

13.2基本原理

本例程在ARM核的CORE0建立一個TCP Server,CORE0通過TCP Server從外部TCP Client接收數據。當CORE0接收到1個TCP包后,將數據復制到DDR3中的緩存區域內,然后將數據信息(長度、首地址)放入CORE0和CORE1在DDR3的共享內存中。

接着,CORE0通過觸發軟件中斷通知CORE1數據信息已存入共享內存中,CORE1接到中斷后從共享內存讀出數據信息,並將對應長度的數據復制到緩存區中,然后通過UART將數據輸出。當CORE1通過串口完成數據輸出后,同樣通過觸發軟件中斷通知CORE0數據發送已完成,CORE0接到中斷后通過串口打印完成信息,然后開始接收下一個TCP包,重復上述過程。

最后,通過FSBL實現雙核的QSPI BOOT。

13.2.1軟件中斷

在UG585的Interrupts 部分7.2.1章節可以找到關於軟件中斷(SGI)的說明。簡而言之,軟件中斷就是CPU自己產生的中斷,可用於觸發自身和其他CPU。ZYNQ中共有16個軟件中斷可以使用,對應的中斷號為0~15,如下圖所示。通過軟件中斷可以實現CPU之間的相互通信。本例程使用了編號1和2的軟件中斷。

wpsE551.tmp

13.2.2共享內存通信

所謂共享內存就是,CORE0和CORE1在DDR3內存中約定一塊地址及長度已知的內存區域。然后,兩者之間便可通過這片區域進行數據的傳遞。

兩個核心各自擁有獨立的L1 DCache,並且共享同一個L2 DCache,在ZYNQ中存在一個Snoop Control Unit (SCU)用於維護CORE0和CORE1的L1 DCache與L2 DCache之間的一致性,無需用戶干預。因此,雖然CORE0和CORE1的共享內存區域位於DDR中,兩者之間的數據傳遞並不需要考慮DCache一致性的維護。但是,為了更好闡明多級存儲器結構的特性以及DCache一致性維護的問題,本例程在兩核間通過DDR3共享內存進行數據交互時加入了DCache一致性操作,最終達到的效果與不使用DCache一致性操作時相同。

DCache一致性維護的原理為:在多級存儲器結構中,CPU通過1級或多級Cache與DDR產生連接,CPU本身不直接訪問DDR,而是通過Cache訪問DDR。Cache中始終會暫存一小部分(通常是KB~幾MB量級)CPU最近訪問的DDR某些地址區域中的數據。因此,在應用程序中對DDR進行讀或寫操作,實際上都是CPU對Cache進行讀或寫操作。當DDR中某個地址范圍內的數據突然被除CPU以外的Master(如DMA)改變時,若此時Cache中保存了這些區域的數據,且這些數據在Cache中狀態為有效時,當CPU需要再次讀取DDR這片區域的數據時,就不會讓Cache去讀取DDR中此區域內最新的數據來更新Cache,再從Cache里讀取最新的數據,而是直接從Cache中讀取原來的舊數據,顯然這不是我們所期望的結果。這時,便引入了所謂的Cache一致性問題。

ZYNQ中存在ICache和DCache,ICache用於緩存可執行程序,DCache用於緩存數據。一般情況下,用於保存可執行程序的DDR地址范圍不會被除CPU以外的對象訪問。因此,一般不存在ICache的一致性問題。而DCache在很多應用中卻經常會被除CPU以外的對象訪問,所以存在一致性問題。

ZYNQ中維護DCache一致性的方法為:寫入方將數據寫入DDR對應地址區域后,需將殘留在DCache中相應地址范圍內的數據全部刷入DDR3中。讀取方在從DDR相應地址讀取數據之前,需將DCache中DDR相應地址范圍內的數據全部設置為invalid,然后CPU會再次通過DCache從DDR3中讀取該地址范圍內最新的數據。

13.2.3雙核BOOT

裸機雙核BOOT的方法參考自Xilinx的XAPP1079。首先,通過FSBL實現CORE0的BOOT。當CORE0啟動進入main函數后,配合FSBL再實現CORE1的啟動。

具體原理參考XAPP1079,此處不作贅述。

13.3驅動程序

CORE0工程的驅動程序文件位於c_driver文件夾中的core0文件夾中,CORE1工程的驅動程序文件位於c_driver文件夾中的core1文件夾中。需要說明的是,core0和core1的工程在DDR所占用的地址區域進行如下划分:

l CORE0: 0x00100000~0x01FFFFFF,見下圖core0的lscript.ld文件設置。

wpsE561.tmp

l CORE1: 0x02000000~0x02FFFFFF,見下圖core1的lscript.ld文件設置。

wpsE562.tmp

設計雙核應用,兩個工程的內存分配是一個關鍵的前提,程序所占用的DDR空間不能發生重合,應完全分隔開。

13.3.3 CORE0工程
13.3.3.1 main函數

main函數的完成的功能如下:

l 配置Timer及其中斷

l 初始化中斷控制器

l 初始化軟件中斷

l 初始化LWIP協議棧

l 建立TCP Server,啟動Timer

l 配合FSBL啟動CORE1

l 持續從LWIP協議棧接收數據,若接收到CORE1觸發的軟件中斷,則作出響應。

13.3.3.2建立TCP Server

基於LWIP庫在ARM中建立一個TCP Server,IP地址為192.168.1.10,端口號為5010。

l lwip庫設置

見“基於TCP的QSPI Flash bin文件網絡燒寫”例程。

l 程序解析

見“基於TCP的QSPI Flash bin文件網絡燒寫”例程。

13.3.3.3 初始化軟件中斷

通過software_intr.c中的Init_Software_Intr()函數初始化軟件中斷,對於CORE0,該函數完成如下功能。

l 初始化CORE1到CORE0的軟件中斷,中斷號為2,設置中斷優先級和觸發方式。

l 綁定該中斷的中斷服務函數為Cpu0_Intr_Hanedler。

l 將該中斷映射至CORE0,並使能。

13.3.3.4 啟動CORE1

通過main.c中的Start_cpu1()函數配合FSBL完成CORE1的啟動。Start_cpu1()原理如下:

l 將FSBL工程位於OCM中的.stack區域和vector table區域的cache禁用。

l 將CORE1工程代碼的位於DDR中的起始地址0x02000000(見core1的lscript.ld)寫入FSBL的vector table中定義的cpu1_catch地址內。CORE1工程代碼的起始地址由如下宏所定義。若core1的lscript.ld中代碼位於DDR的起始地址發生更改,則該宏定義也必須進行相應更改。

#define APP_CPU1_ADDR 0x02000000

l 復位CORE1及其時鍾

l 使能CORE1及其時鍾

13.3.3.5 數據寫入共享內存

CORE0通過TCP協議接收外部TCP Client發送的數據包,並將數據信息寫入CORE0和CORE1共享內存中。共享內存首地址定義為:

#define SHARED_BASE_ADDR0x08000000

為共享內存區域在shared_mem.h中定義結構體shared region,其中包含了兩核間所需交互的數據長度及數據指針。

typedefstruct

{

u32data_length;

u8* dataload;

}shared_region;

CORE0通過shared_mem.c中的put_data_to_region()函數將所需傳遞的數據長度及指針存入shared region結構體中。在put_data_to_region函數中調用Xil_DCacheFlushRange函數將DCache中該數據指針所指向內存區域的數據刷入DDR中,進行DCache一致性維護。

CORE0將此結構體放置於共享內存首地址SHARED_BASE_ADDR,CORE1便可以從該地址讀取CORE0所需傳遞的數據信息,從而進一步獲取數據。

13.3.3.6 觸發軟件中斷

CORE0通過調用shared_mem.c中的Gen_Software_Intr函數觸發CORE0到CORE1的軟件中斷,中斷號為1,中斷目標CPU設置為CORE1。

13.3.3.7響應軟件中斷

當CORE1向CORE0觸發中斷號為2的軟件中斷時,CORE0調用Cpu0_Intr_Hanedler函數響應此中斷。然后,CORE0通過串口打印相應信息。

13.4 CORE1工程

13.4.1 main函數

main函數的完成的功能如下:

l 配置Timer及其中斷

l 初始化中斷控制器

l 初始化軟件中斷

l 等待CORE0觸發的軟件中斷,將CORE0通過共享內存傳遞的數據由串口輸出

l 串口數據輸出完成后觸發CORE1到CORE0的軟件中斷

13.4.2初始化軟件中斷

通過software_intr.c中的Init_Software_Intr()函數初始化軟件中斷,對於CORE1,該函數完成如下功能。

l 初始化CORE0到CORE1的軟件中斷,中斷號為1,設置中斷優先級和觸發方式。

l 綁定該中斷的中斷服務函數為Cp1_Intr_Hanedler。

l 將該中斷映射至CORE1,並使能。

13.4.3響應軟件中斷

當CORE0向CORE1觸發中斷號為1的軟件中斷時,CORE1調用Cpu1_Intr_Hanedler函數響應此中斷。然后,CORE1開始從共享內存中讀取CORE0所傳遞的數據。

13.4.4共享內存數據讀出

CORE1從共享內存區域SHARED_BASE_ADD地址中獲取CORE0傳遞的數據信息,通過shared_mem.c中的get_data_from_region()函數將CORE0傳遞的數據長度及指針讀出,並復制到本地緩存中。

在get_data_from_region函數中,在將CORE0傳遞的數據復制到本地緩存區域之前,調用Xil_DCacheInvalidateRange函數將DCache中該數據指針所指向內存區域的數據設置為invalid,進行DCache一致性維護。

13.4.5觸發軟件中斷

當CORE1將從共享內存中讀取的數據通過串口輸出完畢后,CORE1通過調用shared_mem.c中的Gen_Software_Intr函數觸發CORE1到CORE0的軟件中斷,中斷號為2,中斷目標CPU設置為CORE0。以此通知CORE0,CORE1串口輸出數據完成。

13.5工程創建及設置關鍵步驟

l CORE1工程創建時Processor要選擇ps_cortexa7_1,不要選成ps_cortexa7_0,如下圖所示。

wpsE573.tmp

l 創建FSBL工程后,需替換其bsp的standalone庫。

首先,設置工程目錄下sdk_repo文件夾的路徑,sdk_repo文件夾中包含了需要使用的standalone庫,如下圖所示。用戶需要根據自己所建工程的實際路徑進行修改,使用原工程的路徑設置將產生錯誤。

wpsE574.tmp

其次,更改FSBL工程的bsp中standalone的版本,將其更換為sdk_repo文件夾中的5.19版本,如下圖所示。該版本standalone庫來自xapp1079,只有使用該版本的standalone庫才可實現雙核BOOT,自帶的standalone庫無法實現。

wpsE575.tmp

l 設置CORE1工程的編譯選項

在CORE1工程的bsp中要增加編譯選項“-DUSE_AMP=1”,如下圖所示。該編譯選項將影響到CORE1工程代碼里中斷控制器SCUGIC的初始化函數以及Cache操作函數的編譯,若不增加該選項,可能會出現CORE0和CORE1中斷異常和Cache一致性維護異常。

wpsE585.tmp

13.6工程調試關鍵步驟

l system debugger里同時添加core0和core1工程文件,如下圖所示。Debug時先讓CORE0運行,再讓CORE1運行。

wpsE586.tmp

wpsE587.tmp

l Debug時一定要注釋CORE0工程中main函數里的Start_cpu1函數,否則在debug時,CORE1將無法正常工作。只有當需要生成BOOT.bin文件時,才需要使用該函數。

13.7網絡調試助手操作方法

在SDK中下載程序至ZYNQ中。打開網絡調試助手,選擇TCP Client方式,輸入ARM中定義的TCP Server的IP地址和端口號,然后點擊連接按鍵,建立TCP連接。輸入任意文字信息發送。如圖所示。

wpsE588.tmp

SDK終端串口輸出的信息如下圖所示。

wpsE599.tmp

繼續通過網絡調試助手發送信息,串口輸出如下圖所示。

wpsE59A.tmp

wpsE59B.tmp

13.8生成BOOT.bin

切記在生成BOOT.bin文件時不要注釋CORE0工程中main函數里的Start_cpu1函數,否則將無法BOOT CORE1。生成BOOT.bin文件時依次添加FSBL工程的elf,bit文件,CORE0和CORE1的elf文件,如下圖所示。

wpsE5AC.tmp

13.9雙核BOOT驗證

將BOOT.bin文件燒入QSPI flash中,重啟開發板。SDK串口終端輸出信息,如下圖所示。當提示“core1:application start”,代表CORE0和CORE1都已成功啟動。

wpsE5AD.tmp

使用網絡調試助手進行TCP連接並發送數據,串口輸出如下圖所示。此時,驗證了雙核BOOT后,CORE0和CORE1均運行正常。

wpsE5AE.tmp


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM