ZYNQ-双核AMP通信(二)

简介: ZYNQ-双核AMP通信(二)

写在前面


承接前文:ZYNQ-双核AMP通信(一),前文对双核AMP架构通信的相关内容进行了简单的介绍,本文完成AMP架构通信的程序并验证。

开发环境


vivado 18.3&SDK,PYNQ-Z2开发板。

工程设计


CPU0 接收串口的数据,并写入OCM 中,然后利用软件产生中断触发 CPU1; CPU1 接收到中断后,根据从 OCM 中读出的数据并用串口打印,并在控制结束后触发 CPU0 中断,实现了双核 CPU 通信的功能。

系统框图


image.png

硬件平台搭建


首先新建工程,创建 block design。添加ZYNQ7 ip,根据本次工程需要对IP进行配置。勾选本次工程使用的资源。

image.png

这里添加SPI和SD的资源是为了进行双核的固化程序的验证。

硬件系统构建完成如下:

image.png

然后我们进行generate output product 然后生成HDL封装。这里只用到了MIO引脚,所以不需要进行管脚分配,XADC测量是内部的电压信息,并且使用的是PS_XADC接口。点击导出硬件资源(不包含bit流文件,因为只用到了PS资源),接着launch SDK。

SDK软件部分


新建应用工程,这里可以先进行创建CPU0的程序,这里和之前配置相同,无需特殊更改。点击NEXT后,完成建立一个空工程。

image.png

然后修改cpu0的DDR的地址空间,打开src文件夹中的lscript.ld文件,该文件是链接脚本,可以进行配置应用程序的地址空间的大小。在图中可以看到OCM的两块区域的对应的大小和起始地址以及该应用程序的DDR的起始地址和大小。

image.png

这里修改cpu0占用ddr的一半空间也即把0x1FF00000修改为0x0FF00000

image.png

完成修改后ctrl + s 保存即可完成地址映射的修改。

同样的操作进行新建xpu1工程创建。处理器选择ps7_1

image.png

创建完成后修改ddr的地址映射,这里需要进行简单的计算,cpu0的起始地址为0x100000,大小为0x0FF00000,所以cpu1的起始地址为两者之和,也即为0x1000000

所以对cpu1的程序修改地址映射如下图:

image.png

打开板级支持包的设置界面

image.png

同时加入AMP的一个交叉编译的宏定义-DUSE_AMP=1,添加在末尾。

image.png

cpu0程序


#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_flag = 0;           //接收标志
char char_input='\0';
//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_flag == 0){
      xil_printf("CPU0:请输入字符\r\n");
      scanf("%c",&char_input);
      if(char_input != 13){
        //向共享的地址中写入输入的数据
        Xil_Out8(SHARE_BASE,char_input);
        xil_printf("CPU0: %c\n",char_input) ;
        //给CPU1触发中断
        XScuGic_SoftwareIntr(&Intc,SOFT_INTR_ID_TO_CPU1,CPU1_ID);
      }
      rec_flag = 1;
    }
  }
  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("CPU0 : Soft Interrupt from CPU1\n");
  rec_flag = 0;
}

cpu1程序


#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 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
//函数声明
void cpu1_intr_init(XScuGic *intc_ptr);
void soft_intr_handler(void *CallbackRef);
//全局变量
XScuGic Intc;               //中断控制器驱动程序实例
int soft_intr_flag = 0;     //软件中断的标志
char read_data;
//CPU1 main函数
int main()
{
  //S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0
  Xil_SetTlbAttributes(SHARE_BASE,0x14de2);    //禁用OCM的Cache属性
  //CPU1中断初始化
  cpu1_intr_init(&Intc);
  while(1){
    if(soft_intr_flag){
      read_data = Xil_In8(SHARE_BASE);//从共享OCM中读出数据
      xil_printf("CPU1:%c\n",read_data) ;
      //给给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("CUP1:Soft Interrupt from CPU0\n") ;
  soft_intr_flag = 1;
}

下载程序


和之前不同这次需要在config界面进行勾选,确保两个cpu的程序都下载进去。如下图:

image.png

运行效果


image.png

固化双核程序


创建fsbl程序。

image.png

点击next,选择FSBL点击finish。

image.png

选中cpu0的工程,右击创建镜像工程,

image.png

添加cpu1的elf文件

image.png

添加完成创建镜像即可。

烧录flash操作如下图:

image.png

references


  1. 正点原子开发视频
  2. UG585
  3. xapp1079
目录
相关文章
|
存储 缓存 开发工具
ZYNQ-双核AMP通信(一)
ZYNQ-双核AMP通信(一)
1318 0
ZYNQ-双核AMP通信(一)
|
8月前
|
传感器 监控 芯片
嵌入式系统中MCU与SoC通信方式的选择与应用
嵌入式系统中MCU与SoC通信方式的选择与应用
277 3
|
8月前
|
开发工具 芯片 Perl
【ZYNQ】裸机 PS + PL 双网口实现之 ZYNQ 配置
【ZYNQ】裸机 PS + PL 双网口实现之 ZYNQ 配置
1109 0
|
传感器 5G 数据处理
ZYNQ(FPGA)与DSP之间GPIO通信
基于 TI KeyStone 架构 C6000 系列 TMS320C6657双核C66x 定点/浮点 DSP以及 Xilinx Zynq-7000 系列 XC7Z035/045 SoC 处理器设计的高端异构多核评估板,由核心板与评估底板组成。 DSP采用 TMS320C6657 双核C66x 定点/浮点,每核主频1GHz/1.25GHz。 Xilinx Zynq SoC处理器采用的XC7Z035/045集成PL端Kintex-7架构+PS 端双核ARM Cortex-A9 ,28nm可编程逻辑资源。
ZYNQ(FPGA)与DSP之间GPIO通信
|
数据采集 数据处理 异构计算
ZYNQ(FPGA)与DSP之间SRIO通信实现
XQ6657Z35-EVM多核开发板通过SPI、EMIF16、uPP、SRIO 通信接口将DSP 与Zynq 结合在一起,组成DSP+Zynq 架构,实现了需求独特、灵活、功能强大的DSP+Zynq 高速数据采集处理系统。
ZYNQ(FPGA)与DSP之间SRIO通信实现
|
网络协议 测试技术 芯片
基于ZYNQ+DSP平台Zynq7035/45 FPGA高速串行接口的千兆以太网UDP例程设计和使用说明
Xilinx XC7Z035/45-2FFG676I PL端高速串行接口的千兆以太网UDP例程设计和使用说明
基于ZYNQ+DSP平台Zynq7035/45 FPGA高速串行接口的千兆以太网UDP例程设计和使用说明
|
数据处理 SoC Perl
ZYNQ与DSP之间EMIF16通信
介绍说明XQ6657Z35-EVM 高速数据处理评估板ZYNQ与DSP之间EMIF16通信的功能、使用步骤以及各个例程的运行效果。
ZYNQ与DSP之间EMIF16通信
|
数据处理 SoC Perl
Xilinx Zynq7035 PL SFP光口通信例程
本文主要介绍说明XQ6657Z35-EVM 高速数据处理评估板SPF光口通信例程的功能、使用步骤以及各个例程的运行效果。
Xilinx Zynq7035 PL SFP光口通信例程
15 玩转STM32之IIC通信(芯片硬件篇)(上)
15 玩转STM32之IIC通信(芯片硬件篇)
15 玩转STM32之IIC通信(芯片硬件篇)(下)
15 玩转STM32之IIC通信(芯片硬件篇)