圖3 程序測試
利用軟體中斷做通訊的例子
該例子中,cpu0和cpu1都註冊兩個軟體中斷,將1號軟體中斷註冊給cpu1,表示cpu0發送中斷給cpu1,將2號軟體中斷註冊給cpu0,表示cpu1發送中斷給cpu0;然後在程序運行時,cpu0觸發1號軟體中斷,此時cpu1正在運行主程序被該中斷中斷,進入中斷服務函數,其處理完中斷後觸發2號軟體中斷,此時該中斷會中斷cpu0,進入中斷服務函數,cpu0處理完中斷後回到主函數,再觸發1號軟體中斷,往復運行。
Cpu0代碼:
/*
* app_cpu0.c
*
* Created on: 2019年3月27日
* Author: dz
*/
#include "xil_cache.h"
#include "xparameters.h"
#include "xil_mmu.h"
#include "xil_misc_psreset_api.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "xuartps.h"
#include "stdio.h"
#include "sleep.h"
volatile u8 software_intr_received = 0;
#define CORE0_TO_CORE1_INTR_ID 0x01
#define CORE1_TO_CORE0_INTR_ID 0x02
void sys_intr_init(void);
void Setup_Intr_Exception(XScuGic * IntcInstancePtr);
void Scu_Intr_Init(XScuGic* IntancePtr,int Scu_Int_ID);
void Init_Software_Intr(XScuGic *GicInstancePtr, Xil_InterruptHandler IntrHanedler, u16 SoftwareIntrId, u8 CpuId);
void Gen_Software_Intr(XScuGic *GicInstancePtr, u16 SoftwareIntrId, u32 CpuId);
void Cpu0_Intr_Hanedler(void *Callback);
void Cpu1_Intr_Hanedler(void *Callback);
XScuGic ScuGic;
void delay(unsigned int count)
{
int i = 0;
for(i = 0;i
}
int main(void)
{
sys_intr_init();
xil_printf("cpu0 start!/r/n");
while(1)
{
if(XPAR_CPU_ID == 0)
Gen_Software_Intr(&ScuGic, CORE0_TO_CORE1_INTR_ID, XSCUGIC_SPI_CPU1_MASK);
/*Gen_Software_Intr(&ScuGic, CORE0_TO_CORE1_INTR_ID, XSCUGIC_SPI_CPU0_MASK);*/
else
Gen_Software_Intr(&ScuGic, CORE1_TO_CORE0_INTR_ID, XSCUGIC_SPI_CPU0_MASK);
delay(200000000);
if(1 == software_intr_received)
{
xil_printf("cpu0_main/r/n");
software_intr_received = 0;
}
}
return 0;
}
void sys_intr_init(void)
{ Scu_Intr_Init(&ScuGic,XPAR_SCUGIC_SINGLE_DEVICE_ID);
// if(XPAR_CPU_ID == 0)
Init_Software_Intr(&ScuGic, Cpu0_Intr_Hanedler, CORE0_TO_CORE1_INTR_ID, 0);
// else
Init_Software_Intr(&ScuGic, Cpu1_Intr_Hanedler, CORE1_TO_CORE0_INTR_ID, 1);
Setup_Intr_Exception(&ScuGic);
}
void Setup_Intr_Exception(XScuGic * IntcInstancePtr)
{
//connect hardware interrupt
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,(void *)IntcInstancePtr);
//enable hardware interrupt
Xil_ExceptionEnable();
}
void Scu_Intr_Init(XScuGic* IntancePtr,int Scu_Int_ID)
{
XScuGic_Config *ScuConfigPtr;
//find device
ScuConfigPtr = XScuGic_LookupConfig(Scu_Int_ID);
//config scuint
XScuGic_CfgInitialize(IntancePtr, ScuConfigPtr,ScuConfigPtr->CpuBaseAddress);
}
void Cpu0_Intr_Hanedler(void *Callback)
{
xil_printf("receive interrupt from core1!/r/n");
software_intr_received = 1;
}
void Cpu1_Intr_Hanedler(void *Callback)
{
xil_printf("receive interrupt from core0!/r/n");
software_intr_received = 1;
}
void Init_Software_Intr(XScuGic *GicInstancePtr, Xil_InterruptHandler IntrHanedler, u16 SoftwareIntrId, u8 CpuId)
{
int Status;
// XScuGic_SetPriorityTriggerType(GicInstancePtr, SoftwareIntrId, 0xB0, 0x2);
XScuGic_SetPriorityTriggerType(GicInstancePtr, SoftwareIntrId, 0xd0, 0x3);
Status = XScuGic_Connect(GicInstancePtr, SoftwareIntrId,
(Xil_InterruptHandler)IntrHanedler, NULL);
if (Status != XST_SUCCESS) {
xil_printf("core%d: interrupt %d set fail!/r/n", XPAR_CPU_ID, SoftwareIntrId);
return;
}
XScuGic_InterruptMaptoCpu(GicInstancePtr, CpuId, SoftwareIntrId); //map the the Software interrupt to target CPU
XScuGic_Enable(GicInstancePtr, SoftwareIntrId);//enable the interrupt for the Software interrupt at GIC
}
void Gen_Software_Intr(XScuGic *GicInstancePtr, u16 SoftwareIntrId, u32 CpuId)
{
int Status;
Status = XScuGic_SoftwareIntr(GicInstancePtr, SoftwareIntrId, CpuId);
if (Status != XST_SUCCESS) {
xil_printf("core%d: interrupt %d gen fail!/r/n", XPAR_CPU_ID, SoftwareIntrId);
return;
}
}
Cpu1代碼:
/*
* app_cpu0.c
*
* Created on: 2019年3月27日
* Author: dz
*/
#include "xil_cache.h"
#include "xparameters.h"
#include "xil_mmu.h"
#include "xil_misc_psreset_api.h"
#include "xil_exception.h"
#include "xscugic.h"
#include "xuartps.h"
#include "stdio.h"
#include "sleep.h"
volatile u8 software_intr_received = 0;
#define CORE0_TO_CORE1_INTR_ID 0x01
#define CORE1_TO_CORE0_INTR_ID 0x02
void sys_intr_init(void);
void Setup_Intr_Exception(XScuGic * IntcInstancePtr);
void Scu_Intr_Init(XScuGic* IntancePtr,int Scu_Int_ID);
void Init_Software_Intr(XScuGic *GicInstancePtr, Xil_InterruptHandler IntrHanedler, u16 SoftwareIntrId, u8 CpuId);
void Gen_Software_Intr(XScuGic *GicInstancePtr, u16 SoftwareIntrId, u32 CpuId);
void Cpu0_Intr_Hanedler(void *Callback);
void Cpu1_Intr_Hanedler(void *Callback);
XScuGic ScuGic;
void delay(unsigned int count)
{
int i = 0;
for(i = 0;i
;
}
int main(void)
{
sys_intr_init();
// Gen_Software_Intr(&ScuGic, CORE1_TO_CORE0_INTR_ID, XSCUGIC_SPI_CPU1_MASK);
xil_printf("cpu1 start!/r/n");
while(1)
{
if(1 == software_intr_received)
{
software_intr_received = 0;
if(XPAR_CPU_ID == 0)
Gen_Software_Intr(&ScuGic, CORE0_TO_CORE1_INTR_ID, XSCUGIC_SPI_CPU1_MASK);
/* Gen_Software_Intr(&ScuGic, CORE0_TO_CORE1_INTR_ID, XSCUGIC_SPI_CPU0_MASK);*/
else
Gen_Software_Intr(&ScuGic, CORE1_TO_CORE0_INTR_ID, XSCUGIC_SPI_CPU0_MASK);
delay(200000000);
xil_printf("cpu1_main/r/n");
}
}
return 0;
}
void sys_intr_init(void)
{ Scu_Intr_Init(&ScuGic,XPAR_SCUGIC_SINGLE_DEVICE_ID);
// if(XPAR_CPU_ID == 0)
Init_Software_Intr(&ScuGic, Cpu0_Intr_Hanedler, CORE0_TO_CORE1_INTR_ID, 0);
// else
Init_Software_Intr(&ScuGic, Cpu1_Intr_Hanedler, CORE1_TO_CORE0_INTR_ID, 1);
Setup_Intr_Exception(&ScuGic);
}
void Setup_Intr_Exception(XScuGic * IntcInstancePtr)
{
//connect hardware interrupt
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,(void *)IntcInstancePtr);
//enable hardware interrupt
Xil_ExceptionEnable();
}
void Scu_Intr_Init(XScuGic* IntancePtr,int Scu_Int_ID)
{
XScuGic_Config *ScuConfigPtr;
//find device
ScuConfigPtr = XScuGic_LookupConfig(Scu_Int_ID);
//config scuint
XScuGic_CfgInitialize(IntancePtr, ScuConfigPtr,ScuConfigPtr->CpuBaseAddress);
}
void Cpu0_Intr_Hanedler(void *Callback)
{
xil_printf("receive interrupt from core1!/r/n");
software_intr_received = 1;
}
void Cpu1_Intr_Hanedler(void *Callback)
{
xil_printf("receive interrupt from core0!/r/n");
software_intr_received = 1;
}
void Init_Software_Intr(XScuGic *GicInstancePtr, Xil_InterruptHandler IntrHanedler, u16 SoftwareIntrId, u8 CpuId)
{
int Status;
XScuGic_SetPriorityTriggerType(GicInstancePtr, SoftwareIntrId, 0xB0, 0x2);
// XScuGic_SetPriorityTriggerType(GicInstancePtr, SoftwareIntrId, 0xd0, 0x3);
Status = XScuGic_Connect(GicInstancePtr, SoftwareIntrId,
(Xil_InterruptHandler)IntrHanedler, NULL);
if (Status != XST_SUCCESS) {
xil_printf("core%d: interrupt %d set fail!/r/n", XPAR_CPU_ID, SoftwareIntrId);
return;
}
XScuGic_InterruptMaptoCpu(GicInstancePtr, CpuId, SoftwareIntrId); //map the the Software interrupt to target CPU
XScuGic_Enable(GicInstancePtr, SoftwareIntrId);//enable the interrupt for the Software interrupt at GIC
}
void Gen_Software_Intr(XScuGic *GicInstancePtr, u16 SoftwareIntrId, u32 CpuId)
{
int Status;
Status = XScuGic_SoftwareIntr(GicInstancePtr, SoftwareIntrId, CpuId);
if (Status != XST_SUCCESS) {
xil_printf("core%d: interrupt %d gen fail!/r/n", XPAR_CPU_ID, SoftwareIntrId);
return;
}
}
將上述程序生成boot.bin文件,然後下載到flash,啟動後通過串口助手可以收到cpu0與cpu1的列印信息,每間隔兩秒列印一次,如圖4所示。