1.簡介
zynq系列開發板有兩個板載Cortex-A9處理器,兩個ARM可以協同處理數據。
多核處理器硬件上的劃分
??1.同構多核:系統中的多個處理器在結構上是相同的;
????????優點是硬件和軟件設計上較為簡單,通用性高。
??2.異構多核:系統中的處理器結構上是不同的;
????????優點是在某些特定場合,專用的硬件加速核可以提高性能。
ZYNQ中的兩個Cortex-A9處理器+可編程邏輯器件FPGA組成了異構多核處理器。
多核處理器從軟件運行方式上劃分
??AMP(Asymmetric Muti-processing):非對稱多處理
????多個內核相對獨立的運行不同的任務,每個內核相互隔離,可以運行不同的操??作系統或者裸機程序。
??SMP(Symmetric Muti-processing):
????多個處理器運行一個操作系統,這個操作系統同等的管理多個內核。
??BMP(Bound Muti-processing):混合多模式
????BMP與SMP類似,但是開發者可以指定將某個任務僅在某個指定內核上執行。
AMP模式下要注意不要兩個CPU一起訪問同一個地址或者共享外設。
2.CPU之間通訊原理
2.1 通訊步驟
1.系統初始化
2.啟動CPU1
3.和CPU1進行通訊
4.共享CPU外設
2.2 CPU資源
??CPU資源分為私有資源和公共資源。私有資源是每個CPU都有的資源,只能被各自的CPU訪問,訪問時無需注意沖突。公共資源為CPU之間共享的資源,訪問時要注意訪問沖突。
??私有資源: L1Cache、PPI(Private peripheral interrupts)、MMU(Memory management unit)。
??公共資源: L2Cache、DDR存儲器、OCM(on chip memory)、ICD(Interrupt control distributor)、全局時鐘和其他外等。
??OCM用來和CPU之間的通訊的,與DDR相比,OCM具有更高的性能和更低的延遲。用于小數據量(256KB一下)用OCM更好。
??避免同時訪問的方法
??DDR:CPU0只能訪問0x00100000至0x001FFFFF,CPU1只能訪問0x00200000到0x002FFFFF(可人為更改)
??L2Cache:CPU0使用,CPU1不使用。
??ICD:中斷來自PL,連接到CPU1。
??Timer(定時器):只有CPU1使用。
??OCM:OCM的某一地址進行標志。當標志為0時這個地址是某個CPU私有的;為1時,這個地址是另一個CPU私有的。或者軟件產生中斷的方式。
2.3 軟件設計
軟件設計分為三個階段
1.First stage boot loader(FSBL):第一啟動階段
2.Bare-metal application for CPU0:裸機應用程序
3.Bare-metal application for CPU1:裸機應用程序
FSBL
??一直運行在CPU上面,是開發板上電之后啟動先啟動Boot rom,后啟動FSBL,負責配置PL然后拷貝兩個處理器的應用程序(ELF)加載到DDR中,然后開始運行第一個應用程序。
Bare-metal application Code
??兩個CPU運行各自的裸機的程序,CPU負責初始化共享外設,并且負責啟動CPU1.
CPU0 Application
??內存的起始地址為0x00100000。這個起始地址可以在鏈接腳本進行修改的。
??CPU0的配置步驟:
??1.配置MMU來禁止cache緩存功能0xFFFF0000至0xFFFFFFFF來保證兩個CPU訪問OCM的一致性。地址映射不可修改。
??2.初始化ICD
??3.啟動CPU1
??4.通過串口打印信息
??5.設置OCM的地址作為信號量
??6.等待地址里面的信號量被清除。
??Boot rom代碼執行后,CPU1也會在OCM的0xFFFFFF00地址上執行一段代碼。功能是檢查地址0xFFFFFFF0的值是否為1來等待事件到來。
??CPU0啟動CPU1是通過向地址0x00200000寫入地址0xFFFFFFF0然后CPU0運行Set Event(SEV)命令啟動CPU1。CPU1會讀取0xFFFFFFF0里面的值0x00200000。然后跳轉到該地址執行程序。
??CPU1的配置步驟
3 如何避免多個CPU同時訪問OCM
??CPU0向OCM寫入一個數據之后,給CPU1產生軟件中斷。讓CPU1知道CPU0已經不再操作該地址。此時CPU1讀取數據,讀取完畢后產生一個中斷通知CPU0。
??軟件中斷(SGIs):中斷來自CPU內部,每個CPU可以中斷自己或者另外的CPU或者一起中斷,每個CPU有16個中斷號,編號為0到15。向寄存器(ICDSGIR)寫入中斷號并且指定CPU。目標的CPU即可產生中斷。
??OCM:PS的片上存儲器,包括256KB的RAM和128KB的ROM(BootROM)。地址范圍為0x00000000到0002FFFF的三個64KB加上0xFFFF_0000到0xFFFF_FFFF共256KB。
4 程序設計
4.1 程序任務
??CPU0接收串口數據并寫入OCM中,然后利用軟件中斷觸發CPU1;CPU1接收到中斷后,根據從OCM中讀出的數據控制呼吸燈的頻率,并在控制結束后觸發CPU0的中斷,實現雙核CPU通信的功能。
4.2 系統框圖

4.3 軟件操作

4.4 代碼
4.4.1 CPU0_UART
//****************************************Copyright (c)***********************************////原子哥在線教學平臺:www.yuanzige.com//技術支持:www.openedv.com//淘寶店鋪:http://openedv.taobao.com//關注微信公眾平臺微信號:"正點原子",免費獲取ZYNQ & FPGA & STM32 & LINUX資料。//版權所有,盜版必究。//Copyright(C) 正點原子 2018-2028//All rights reserved//----------------------------------------------------------------------------------------// File name: cpu0_uart// Last modified Date: 2019/6/8 1736// Last Version: V1.0// Descriptions: CPU0應用程序//----------------------------------------------------------------------------------------// Created by: 正點原子// Created date: 2019/6/8 1736// Version: V1.0// Descriptions: The original version////----------------------------------------------------------------------------------------//****************************************************************************************// #include "xparameters.h"#include "xscugic.h"#include "xil_printf.h"#include "xil_exception.h"#include "xil_mmu.h"#include "stdio.h" //宏定義#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中斷ID#define SHARE_BASE 0xffff0000 //共享OCM首地址#define CPU1_COPY_ADDR 0xfffffff0 //存放CPU1應用起始地址的地址#define CPU1_START_ADDR 0x10000000 //CPU1應用起始地址 #define CPU1_ID XSCUGIC_SPI_CPU1_MASK //CPU1 ID#define SOFT_INTR_ID_TO_CPU0 0 //軟件中斷號 0 ,范圍:0~15#define SOFT_INTR_ID_TO_CPU1 1 //軟件中斷號 1 ,范圍:0~15 //"SEV"指令喚醒CPU1并跳轉至相應的程序#define sev() __asm__("sev") //C語言內嵌匯編寫法 send event指令 //函數聲明void start_cpu1();void cpu0_intr_init(XScuGic *intc_ptr);void soft_intr_handler(void *CallbackRef); //全局變量XScuGic Intc; //中斷控制器驅動程序實例int rec_freq_flag = 0; //接收到呼吸燈頻率設置的標志int freq_gear; //頻率檔位 //CPU0 main函數int main(){ //S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0 Xil_SetTlbAttributes(SHARE_BASE,0x14de2); //禁用OCM的Cache屬性 //S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0 Xil_SetTlbAttributes(CPU1_COPY_ADDR,0x14de2);//禁用0xfffffff0的Cache屬性 //啟動CPU1 start_cpu1(); //CPU0中斷初始化 cpu0_intr_init(&Intc); while(1){ if(rec_freq_flag == 0){ xil_printf("This is CPU0,Please input the numbers 1~5 to change " "breath led frequency "); scanf("%d",&freq_gear); if(freq_gear >= 1 && freq_gear <=5){ xil_printf("You input number is %d ",freq_gear); //向共享的地址中寫入輸入的數據 Xil_Out8(SHARE_BASE,freq_gear); //給CPU1觸發中斷 XScuGic_SoftwareIntr(&Intc,SOFT_INTR_ID_TO_CPU1,CPU1_ID); rec_freq_flag = 1; } else{ xil_printf("Error,The number range is 1~5 "); xil_printf(" "); } } } return 0 ;} //啟動CPU1,用于固化程序void start_cpu1(){ //向 CPU1_COPY_ADDR(0Xffffffff0)地址寫入 CPU1 的訪問內存基地址 Xil_Out32(CPU1_COPY_ADDR, CPU1_START_ADDR); dmb(); //等待內存寫入完成(同步) sev(); //通過"SEV"指令喚醒CPU1并跳轉至相應的程序} //CPU0中斷初始化void cpu0_intr_init(XScuGic *intc_ptr){ //初始化中斷控制器 XScuGic_Config *intc_cfg_ptr; intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID); XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr, intc_cfg_ptr->CpuBaseAddress); //設置并打開中斷異常處理功能 Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr); Xil_ExceptionEnable(); XScuGic_Connect(intc_ptr, SOFT_INTR_ID_TO_CPU0, (Xil_ExceptionHandler)soft_intr_handler, (void *)intc_ptr); XScuGic_Enable(intc_ptr, SOFT_INTR_ID_TO_CPU0); //CPU0軟件中斷} //軟件中斷函數void soft_intr_handler(void *CallbackRef){ xil_printf("This is CPU0,Soft Interrupt from CPU1 "); xil_printf(" "); rec_freq_flag = 0;}
4.4.2 CPU1_LED
//****************************************Copyright (c)***********************************////原子哥在線教學平臺:www.yuanzige.com//技術支持:www.openedv.com//淘寶店鋪:http://openedv.taobao.com//關注微信公眾平臺微信號:"正點原子",免費獲取ZYNQ & FPGA & STM32 & LINUX資料。//版權所有,盜版必究。//Copyright(C) 正點原子 2018-2028//All rights reserved//----------------------------------------------------------------------------------------// File name: cpu1_led// Last modified Date: 2019/6/8 1736// Last Version: V1.0// Descriptions: CPU1應用程序//----------------------------------------------------------------------------------------// Created by: 正點原子// Created date: 2019/6/8 1736// Version: V1.0// Descriptions: The original version////----------------------------------------------------------------------------------------//****************************************************************************************//
#include "xparameters.h"#include "xscugic.h"#include "xil_printf.h"#include "xil_exception.h"#include "xil_mmu.h"#include "stdio.h"#include "breath_led_ip.h"
//宏定義#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID //中斷ID#define SHARE_BASE 0xffff0000 //共享OCM首地址
#define CPU0_ID XSCUGIC_SPI_CPU0_MASK //CPU0 ID#define SOFT_INTR_ID_TO_CPU0 0 //軟件中斷號 0 ,范圍:0~15#define SOFT_INTR_ID_TO_CPU1 1 //軟件中斷號 1 ,范圍:0~15
#define LED_IP_BASEADDR XPAR_BREATH_LED_IP_0_S0_AXI_BASEADDR //LED IP基地址#define LED_IP_REG0 BREATH_LED_IP_S0_AXI_SLV_REG0_OFFSET //LED IP寄存器地址0#define LED_IP_REG1 BREATH_LED_IP_S0_AXI_SLV_REG1_OFFSET //LED IP寄存器地址1
//函數聲明void cpu1_intr_init(XScuGic *intc_ptr);void soft_intr_handler(void *CallbackRef);
//全局變量XScuGic Intc; //中斷控制器驅動程序實例int soft_intr_flag = 0; //軟件中斷的標志int freq_gear; //頻率檔位
//CPU1 main函數int main(){ int freq_step = 0; //S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0 Xil_SetTlbAttributes(SHARE_BASE,0x14de2); //禁用OCM的Cache屬性
//CPU1中斷初始化 cpu1_intr_init(&Intc); //打開呼吸燈 BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR, LED_IP_REG0, 1); while(1){ if(soft_intr_flag){ freq_gear = Xil_In8(SHARE_BASE); //從共享OCM中讀出數據 xil_printf("CUP1 Received data is %d
",freq_gear) ; switch(freq_gear){ case 1 : freq_step = 20;break; case 2 : freq_step = 50;break; case 3 : freq_step = 100;break; case 4 : freq_step = 200;break; case 5 : freq_step = 500;break; default : freq_step = 50;break; } //設置呼吸燈頻率,最高位為1,設置有效 BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,(0x80000000|freq_step)); //給給CPU0觸發中斷 XScuGic_SoftwareIntr(&Intc,SOFT_INTR_ID_TO_CPU0,CPU0_ID); soft_intr_flag = 0; } } return 0 ;}
//CPU1中斷初始化void cpu1_intr_init(XScuGic *intc_ptr){ //初始化中斷控制器 XScuGic_Config *intc_cfg_ptr; intc_cfg_ptr = XScuGic_LookupConfig(INTC_DEVICE_ID); XScuGic_CfgInitialize(intc_ptr, intc_cfg_ptr, intc_cfg_ptr->CpuBaseAddress); //設置并打開中斷異常處理功能 Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, intc_ptr); Xil_ExceptionEnable();
XScuGic_Connect(intc_ptr, SOFT_INTR_ID_TO_CPU1, (Xil_ExceptionHandler)soft_intr_handler, (void *)intc_ptr);
XScuGic_Enable(intc_ptr, SOFT_INTR_ID_TO_CPU1); //CPU1軟件中斷}
//軟件中斷函數void soft_intr_handler(void *CallbackRef){ xil_printf("This is CUP1,Soft Interrupt from CPU0
") ; soft_intr_flag = 1;}
-
處理器
+關注
關注
68文章
20253瀏覽量
252236 -
硬件
+關注
關注
11文章
3595瀏覽量
69011 -
Zynq
+關注
關注
10文章
630瀏覽量
49448
原文標題:ZYNQ之雙核通訊原理以及程序設計
文章出處:【微信號:ZYNQ,微信公眾號:ZYNQ】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
嵌入式多核處理器硬件結構分析與對排序算法進行并行化優化
多核處理器設計九大要素
典型的支持多核處理器的RTOS功能解析
集成電路多核處理器虛擬化技術
多核處理器片上存儲系統研究
多核處理器會取代FPGA嗎?
ZYNQ多核處理器硬件上的劃分
評論