Zynq-Linux移植学习笔记之54-国产ZYNQ核间通信实现
1、背景介绍目前国产ZYNQ中使用四个ARM核,各ARM核之间可通过SGI方式进行通信,datasheet中描述如下:2、AMP工程修改说明核间通信可以让每个核上运行一个裸程序,实现裸程序之间的SGI中断响应。这里简单起见只在CPU0和CPU1上运行应用,修改如下按照上面步骤,先创建两个SDK工程,分别进行编译,SDK就是0核,SDK1就是1核,以此类推然后分别修改两个工程内helloworld中
·
1、背景介绍
目前国产ZYNQ中使用四个ARM核,各ARM核之间可通过SGI方式进行通信,datasheet中描述如下:
2、AMP工程修改说明
核间通信可以让每个核上运行一个裸程序,实现裸程序之间的SGI中断响应。这里简单起见只在CPU0和CPU1上运行应用,修改如下
按照上面步骤,先创建两个SDK工程,分别进行编译,SDK就是0核,SDK1就是1核,以此类推
然后分别修改两个工程内helloworld中的icf文件,改为在ddr中执行
这里注意中断栈大小也需要改大,否则会出现各种异常
3、核间中断代码设计
核间中断使用SGI方式,cpu0绑定一个中断,cpu1绑定一个中断,两个CPU实现互发中断
主要由FGicPs_SoftwareIntr函数进行中断触发
运行在CPU0上面的代码:
/*
* helloworld.c: simple test application
*
* This application configures UART 16550 to baud rate 9600.
* PS7 UART (JFM_QL_PS) is not initialized by this application, since
* bootrom/bsp configures it to baud rate 115200
*
* ------------------------------------------------
* | UART TYPE BAUD RATE |
* ------------------------------------------------
* uartns550 9600
* uartlite Configurable only in HW design
* ps7_uart 115200 (configured by bsp)
*/
#include <stdio.h>
#include "platform.h"
#include "fmsh_common.h"
#include "ps_init.h"
#include "fmsh_print.h"
#include "fmsh_gic.h"
/* CPU0占用14号软中断 */
#define SGI_ID_CPU1_INFO_CPU0 (14U)
/* CPU1占用15号软中断 */
#define SGI_ID_CPU0_INFO_CPU1 (15U)
/* CPU0给cpu1发SGI中断 */
#define CPU0_INFO_CPU1 (1<<1U)
volatile u32 wait_cpu1_ipi = 0;
void SGI_14_hanlder (void *InstancePtr)
{
wait_cpu1_ipi = 1;
fmsh_print("cpu0 rcv ipi!\n\r");
}
int main()
{
u32 Status;
u32 cnt = 0;
init_platform();
fmsh_print("Hello World! this is CPU0 !\n\r");
Status = FGicPs_SetupInterruptSystem(&IntcInstance);
if(Status!=GIC_SUCCESS)
{
fmsh_print("Gic setup failed\n\r");
return GIC_FAILURE ;
}
Status = FGicPs_Connect(&IntcInstance, SGI_ID_CPU1_INFO_CPU0,
(FMSH_InterruptHandler)SGI_14_hanlder, &IntcInstance);
if (Status != GIC_SUCCESS) {
return GIC_FAILURE;
}
FMSH_ExceptionRegisterHandler(FMSH_EXCEPTION_ID_IRQ_INT,
(FMSH_ExceptionHandler)FGicPs_InterruptHandler_IRQ,
&IntcInstance);
FGicPs_Enable(&IntcInstance, SGI_ID_CPU1_INFO_CPU0);
while(1)
{
cnt++;
wait_cpu1_ipi = 0;
delay_ms(5000);
delay_ms(5000);
delay_ms(5000);
//1. CPU0 send ipi to cpu1
/* 这个是CPU0给cpu1发15号中断 */
FGicPs_SoftwareIntr(&IntcInstance, SGI_ID_CPU0_INFO_CPU1, CPU0_INFO_CPU1);
//2. CPU0 wait for cpu1 ipi information
//while(!wait_cpu1_ipi);
// fmsh_print("\n\r CPU0 send interrupt 15 to CPU1 !\n\r");
// fmsh_print("\r\nthis is CPU0 !\n\r");
//delay_ms(5000);
}
}
运行在cpu1上面的代码
/*
* helloworld.c: simple test application
*
* This application configures UART 16550 to baud rate 9600.
* PS7 UART (JFM_QL_PS) is not initialized by this application, since
* bootrom/bsp configures it to baud rate 115200
*
* ------------------------------------------------
* | UART TYPE BAUD RATE |
* ------------------------------------------------
* uartns550 9600
* uartlite Configurable only in HW design
* ps7_uart 115200 (configured by bsp)
*/
#include <stdio.h>
#include "platform.h"
#include "fmsh_common.h"
#include "ps_init.h"
#include "fmsh_print.h"
#include "fmsh_gic.h"
#include "fmsh_gpio_public.h"
/* CPU0占用14号软中断 */
#define SGI_ID_CPU1_INFO_CPU0 (14U)
/* CPU1占用15号软中断 */
#define SGI_ID_CPU0_INFO_CPU1 (15U)
/* CPU1给cpu0发SGI中断 */
#define CPU1_INFO_CPU0 (1<<0U)
volatile u32 wait_cpu0_ipi = 0;
void SGI_15_hanlder (void *InstancePtr)
{
wait_cpu0_ipi = 1;
fmsh_print("cpu1 rcv ipi!\n\r");
}
int main()
{
u32 Status;
u32 cnt = 0;
init_platform();
delay_ms(5000);
fmsh_print("Hello World! this is CPU1 !\n\r");
Status = FGicPs_SetupInterruptSystem(&IntcInstance);
if(Status!=GIC_SUCCESS)
{
fmsh_print("Gic setup failed\n\r");
return GIC_FAILURE ;
}
Status = FGicPs_Connect(&IntcInstance, SGI_ID_CPU0_INFO_CPU1,
(FMSH_InterruptHandler)SGI_15_hanlder, &IntcInstance);
if (Status != GIC_SUCCESS) {
fmsh_print("failed \n\r");
return GIC_FAILURE;
}
FMSH_ExceptionRegisterHandler(FMSH_EXCEPTION_ID_IRQ_INT,
(FMSH_ExceptionHandler)FGicPs_InterruptHandler_IRQ,
&IntcInstance);
FGicPs_Enable(&IntcInstance, SGI_ID_CPU0_INFO_CPU1);
while(1)
{
cnt++;
wait_cpu0_ipi = 0;
//1. CPU1 send ipi to cpu0
/* 这个是CPU1给cpu0发14号中断 */
FGicPs_SoftwareIntr(&IntcInstance, SGI_ID_CPU1_INFO_CPU0, CPU1_INFO_CPU0);
// fmsh_print("\n\r CPU1 send interrupt 14 to CPU0 !\n\r");
//2. CPU1 wait for cpu0 ipi information
//while(!wait_cpu0_ipi);
delay_ms(5000);
}
}
4、创建固化程序
在创建固化程序时需要指定裸程序运行的CPU,如下
固化后系统上电能看到两个CPU互相收到对方的中断
这里实现的是通过中断实现核间通信,如果需要共享数据可以采用ocm那段空间。
更多推荐
已为社区贡献7条内容
所有评论(0)