ZYNQ筆記(5):軟中斷實現核間通訊

  ZYNQ包括一個 FPGA 和兩個 ARM,多個 ARM 核心相對獨立的運行不一樣的任務,每一個核心可能運行不一樣的操做系統或裸機程序,可是有一個主要核心,用來控制整個系統以及其餘從核心的容許。所以咱們能夠在 CPU0 和 CPU1 中獨立跑不一樣的應用程序,發揮雙核的非對稱性架構的優點和性能。架構

   從軟件的角度來看,多核處理器的運行模式主要有三種:app

  ① AMP(非對稱多進程):多個核心相對獨立的運行不一樣的任務,每一個核心可能運行不一樣的操做系統或裸機程序,可是有一個主要核心,用來控制整個系統以及其它從核心的運行。函數

  ② SMP(對稱多進程):一個操做系統同等的管理各個內核,例如 PC 機。性能

  ③ BMP(受約束多進程):與 SMP 相似,但開發者能夠指定將某個任務僅在某個指定內核上執行默認狀況下。優化

  裸機程序 ZYNQ 僅運行一個 CPU,這裏主要講解 AMP 模式下,兩個 CPU 同時運行的裸機程序開發方法。spa

1、核間中斷原理(軟中斷SGI)操作系統

  軟中斷的 ID 都是從0到15,而且都是上升沿觸發,主要用於核間中斷或者 CPU 本身中斷本身。設計

  中斷函數以下:3d

XScuGic_SoftwareIntr(&InterruptController,   //指向GIC指針 INTC_CPU0, //須要中斷的CPU ID
                     XSCUGIC_SPI_CPU0_MASK);   //使能該CPU會接受中斷

 

2、ARM啓動過程指針

1.ARM 裏有個 ROM,存儲了一段程序,ROM起來後從 SD 卡讀取數據 2.啓動 FSBL(First Boot Loader)第一啓動項(有模板) 3.加載 bit(FPGA配置程序),同時加載 elf(ARM應用程序),若是是操做系統則 elf 替換成 uBoot

 

3、搭建軟件 CPU0 和 CPU1 非對稱環境

1.建立 amp_fsbl 用於生成燒寫鏡像的時候加載 core0 和 core1的代碼。

①啓動 Vivado,建立 ZYNQ,勾選  SD卡 和 UART 便可,並加載 SDK 開發環境

②進到 SDK ,點擊 File --- New --- Application Project,命名爲 amp_fsbl 並選擇 CPU0

③選擇 FSBL,finish

④修改 main.c 函數來啓動 core1,須要兩個步驟,首先把 CPU1 應用程序地址寫入到 0xfffffff0地址中,這是啓動 CPU1 命令的地址,而後執行 sev 指令加載 CPU1 應用程序。具體參考 UG585 的啓動代碼章節。

在 main.c 函數的 main 函數上方插入這段代碼:

 1 #define sev() __asm__("sev")
 2 #define CPU1STARTADR 0xFFFFFFF0
 3 #define CPU1STARTMEM 0x2000000
 4 
 5 void StartCpu1(void)  6 {  7     #if 1
 8     fsbl_printf(DEBUG_GENERAL,"FSBL: Write the address of the application for CPU 1 to 0xFFFFFFF0\n\r");  9  Xil_Out32(CPU1STARTADR, CPU1STARTMEM); 10     dmb(); //waits until write has finished
11     fsbl_printf(DEBUG_GENERAL,"FSBL: Execute the SEV instruction to cause CPU 1 to wake up and jump to the application\n\r"); 12  sev(); 13     #endif
14 }

在 main.c 函數的 load鏡像位置加入代碼: StartCpu1(); 

2.建立 app_cpu0 應用程序

①從新建立一個新的 File --- New --- Application Project,命名爲 app_cpu0,這時選擇的是 CPU0

②選擇 helloworld 模板便可

③將 helloworld.c 更名爲 mian.c,而且用以下代碼替換掉內容

 1 #include <stdio.h>
 2 #include "platform.h"
 3 #include "xil_printf.h"
 4 
 5 #define COMM_VAL (*(volatile unsigned long *)(0xFFFF0000)) //無優化無符號長整形地址轉成指針
 6 
 7 int main()  8 {  9     COMM_VAL=0; 10 
11     //Disable cache on OCM
12     Xil_SetTlbAttributes(0xFFFF0000,0x14de2); 13     while(1) 14  { 15         print("Hello World cpu0 \n\r"); 16         COMM_VAL =1; 17         while(COMM_VAL == 1) 18  { 19  } 20  } 21     return 0; 22 }

該指針指向的地址爲片上存儲的共享內存(OCM)。能夠指定這裏面的任意一個地址。定義的指針變量以下所示: #define COMM_VAL (*(volatile unsigned long *)(0x00020000)) 該變量CPU0和CPU1均可以在裏面讀寫數據,能夠達到CPU0和CPU1的數據交互。OCM的地址以下圖所示。

④打開 Scr 目錄中的文件 lscript.ld,點擊下方的 Source 作以下修改:CPU0 的代碼空間改成 1E00000

CPU1運行程序的地址改成fsbl裏面指定的起始地址。後面爲長度,有一點須要注意:CPU0的起始地址加上CPU0的長度以後不能超過CPU1的起始地址。也就是兩個CPU佔用的DDR的地址不能重疊。若程序很大,則CPU0須要的LENGTH就大,所以CPU1的起始地址數值就大。DDR地址範圍以下所示:

3.建立 app_cpu1 應用程序

①從新建立一個新的 File --- New --- Application Project,命名爲 app_cpu1,這時選擇的是 CPU1

②選擇 helloworld 模板便可

③將 helloworld.c 更名爲 mian.c,而且用以下代碼替換掉內容

 1 #include <stdio.h>
 2 #include "platform.h"
 3 #include "xil_printf.h"
 4 
 5 #define COMM_VAL (*(volatile unsigned long *)(0xFFFF0000))
 6 int main()  7 {  8     //Disable cache on OCM
 9     Xil_SetTlbAttributes(0xFFFF0000,0x14de2); 10     while(1) 11  { 12         while(COMM_VAL == 0) 13  { 14  } 15     print("Hello World cpu1 \n\r"); 16     sleep(2); 17     COMM_VAL=0; 18  } 19     return 0; 20 }

④打開 Scr 目錄中的文件 lscript.ld 點擊下方的 Source 作以下修改起始地址改成 0x2000000 長度 0x1F00000

4.增長編譯選項(設置 CPU1 的BSP setting 爲 AMP 模式)

app_cpu1_bps --- 右鍵 --- Board Suport Package Setting,點擊 driver --- ps7_cortexa9_0,添加指令

5.讓雙核跑起來

①點擊 app_cpu0 --- 右鍵 --- Debug As --- Debug Configurations...

② 點擊選項卡的 Application,勾選 0 和 1,而後點擊 Debug,yes

③默認停到第一行,鏈接好串口,選擇APU --- ARM --- #0,單步慢慢走能夠看到有信息打印出,#2也是同樣的。若是讓 #0 和 #1 都一直執行,則串口會一直交替打印。

 

4、軟中斷的註冊和使用

 

參考資料:

    [1]V3學院FPGA教程

    [2]何賓, 張豔輝. Xilinx Zynq-7000嵌入式系統設計與實現[M]. 電子工業出版社, 2016.

相關文章
相關標籤/搜索