ZYNQ AMP詳解

本實驗是雙核AMP(Asymmetric Multiprocessing)實驗。雙核實驗需要CPU0向CPU1發出軟件中斷從而喚醒CPU1。CPU1對CPU0中的數據進行操作。

CPU0和CPU1共享一段內存空間(可以把這段共享空間當作數據交換的部分)。

 

首先要建立一個Vivado工程。這裏完成的思路是:CPU0接收串口發來的數據,發出軟件中斷,喚醒CPU1. CPU1通過AXI接口控制LED的閃爍頻率。

 

硬件部分:需要設計一個參數可調的分頻器(輸出頻率10Hz-0.2Hz之間)。另外,還需要設計一個LED燈閃爍的模塊,每當一個上升沿來臨時,輸出狀態的LED就反轉一下。(包括生成AXI總線的IP核的步驟,這裏就不詳細介紹了)

 

首先我們要明白:如果我們想要啓動CPU1,那麼只能通過CPU0喚醒CPU1。AMP相對比其餘兩種(分別是SMP、BMP)最大的優點點就是兩個內核Run不同或相同的裸機程序/OS。

       既然爲雙核,那麼這兩個核肯定有單獨的運行內存。難道只有單獨運行的內存嗎?不是這樣的,除了單獨的運行內存,當然也存在共享內存。(筆者認爲,在SDK中完全也可以不設置共享內存,讓兩個核各自做各自的工作,井水永遠不犯河水)。

如果既能讓CPU0和CPU1單獨實現工作,又能讓CPU0和CPU2完成通信豈不美哉?上邊說過,CPU0和CPU1共享一段內存,所謂共享就是CPU0能讀寫這段內存那麼CPU1照樣也能讀寫這段內存(就像學生宿舍裏邊的空調一樣,同學A能操作空調,同學B照樣能操作空調。如果只有A同學能操作這個空調,那麼這個空調恐怕不能叫做shared air conditioner而應該叫做privacy air conditioner)。當然,共享的事物總是有不足之處的,比如A同學正在拿着遙控器操作這個空調的同時,那麼其他同學就不能對這個共享空調進行操作了。類比可知,這個所謂的共享內存,是在一定的條件下,CPU0/CPU1才能進行操作,如果同時操作CPU0和CPU1就衝突“打架“了。

爲了保證這兩個CPU不打架,還是拿這兩個同學做類比:

A:我現在正在用這個遙控器,麻煩兄弟等一會再用。

B:好的,你先調合適的溫度,一會兒風向由我決定。

A:我好了,該你使用遙控器了。

B:好的,我知道了。

CPU0:我現在正在操作共享內存,麻煩兄弟等會兒再操作。

CPU1:好的,那我等一會兒再操作。

CPU0:我好了,該你讀寫共享內存了。

CPU1:那我就開始讀寫這塊內存了。

 

那麼究竟是什麼導致CPU0和CPU1如此協調呢?在參考了正點原子和ALINX兩家的例程後,筆者發現大致是這麼個運行機制:

CPU0開啓接收中斷號1的中斷;     CPU1開啓接收中斷號2的中斷;

CPU0向CPU1發送2號中斷;          CPU1向CPU0發送1號中斷;

我們讓這兩個CPU約定好,你那邊接收的中斷號就是我這邊發送出去的中斷號,你那邊發送的中斷號就是我這邊接收的中斷號。這樣一來,就形成了兩個CPU的相互配合。我們還可以列個表格,更加清晰的認識這種機制(先讀左半邊,後讀右半邊)。

CPU0:我現在正在操作共享內存,麻煩兄弟等會兒再操作。

CPU1:好的,那我等一會兒再操作。

CPU0:我好了,該你讀寫共享內存了。

CPU1:那我就開始讀寫這塊內存了。

CPU0:好的,啥時候到我了,請叫我!

CPU1:我好了,該你了。

CPU0:我現在正在操作共享內存,麻煩兄弟等會兒再操作。

CPU0:在我沒有發送2號中斷前,你不要讀寫共享內存。

CPU1:我知道了,我接收到2號中斷信號後再進行讀寫共享內存。

CPU0:我已經給你發送過2號中斷了。

CPU1:換我了。我沒有發送1號中斷前,你不要讀寫共享內存。

CPU0:OK,我接收到1號中斷信號後再進行讀寫共享內存。

CPU1:我發送過1號中斷了,該你了。

CPU0:在我沒有發送2號中斷前,你不要讀寫共享內存。

需要注意的是:用軟件中斷,必須要保證中斷號在0~15內(參見UG585)。

 

現在給出配置這種機制的全部過程:

  1. 在Vivado中,配置Processing System(只需要配置1次)
  2. 搭建您想實現的功能。(筆者是設計了一個能改變LED閃爍頻率的AXI的自定義IP;讓CPU0通過UART的中斷接收數字。將這個數字送入CPU1中,CPU1根據這個數字設定PL端LED的閃爍頻率)
  3. 啓動SDK,創建兩個工程,創建工程的步驟就不說了,網上一大堆。
  4. 設定兩個核的運行內存和共享內存。(注意!這兩個核的內存不能重複)
  5. 軟件程序設計(這個步驟繁瑣,後邊詳細介紹)。
  6. 下載配置。(網上也有,還可參考ALINX或正點原子的教程)
  7. 程序固化(可選)。

 

現在對軟件程序設計部分的步驟進行詳細的描述:

創建CPU0的APP並設置運行內存的大小:

 

經過計算得知:現在的CPU0的內存範圍:0x0010000~0X0FFFFFFF

按照這個,那麼CPU1的內存的基地址設置成0X10000000最符合常理。

創建CPU1的APP並設置內存的大小。

CPU1的內存基地址是0X10000000,大小同樣也設置成0X0FF00000。

那麼CPU1的內存範圍:0X1000_0000~0X1FEF_FFFF。

自認而然我們把0X1FF0_0000作爲共享內存的基地址(其實所謂的共享內存基地址只要不是在CPU0和CPU1內存的範圍內均可。正點原子是把下邊的ps7_ram_1設置成了共享內存;而ALINX是在DDR3的最後留出了256Byte的共享地址)

現在需要對CPU1的板級支持包做額外的配置,只有這樣CPU1才能正常工作,選中cpu1對應的bsp文件夾,右鍵選擇板級支持包設置,圖中顯示的地方補充輸入:  -DUSE_AMP=1

 

  

 

對CPU0進行程序設計(有關這兩個程序的設計實在有點亂,也有點長。需要可以留言留下郵箱,看到之後會發送到郵箱):

CPU0實現的功能有:串口接收中斷,設置軟件1號中斷(SGI #1),設置共享內存的基地址,設置CPU0的內存基地址及其大小,能夠向CPU1發送軟件2號中斷。

 

對CPU1進行程序設計:

CPU1實現的功能有:能接收CPU0發來的2號中斷,設置共享內存的基地址,設置CPU1的內存地址及其大小,能夠向CPU0發送1號中斷。將CPU0傳輸到共享內存的數據,傳輸到AXI的slv_reg0上。這樣就能控制LED閃爍的頻率了。

 

實驗效果:發送2就是對10Hz 進行2分頻。發送0x0A就是對10Hz進行10分頻(注意16進制發送,不發送新行)。LED也會從快速閃爍到慢速閃爍!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章