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那段空间。

Logo

更多推荐