ZYNQ7000 PL与PS交互(一): PL到PS中断的使用与实现

这篇具有很好参考价值的文章主要介绍了ZYNQ7000 PL与PS交互(一): PL到PS中断的使用与实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、 ZYNQ7000中断类型

翻译以xilinx用户手册ug585,知道ZYNQ7000有几类中断即可。

PS基于ARM架构,使用了两个Cortex-A9处理器和GIC PL390中断控制器。中断结构与CPU密切相关,并接收来自IO外设和可编程单元PL的中断请求。

本章主要信息:

  • 私有、共享和软件中断。
  • GIC功能介绍
  • 中断优先级和处理
    z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

1.1 中断概述

1.1.1 Zynq 中断三大类

  • SGI(Software Generated Interrupt),软件生成的中断,共 16个端口,中断号0~15;

    软件生成的中断路由到一个或者两个CPU。通过编写ICDSGIR寄存器来生成SGI。

  • PPI(Private Peripheral Interrupt,),CPU 私有外设中断,有 5 个,中断号16~31;

每个CPU都有一组私有的外设中断,包括全局定时器、私有看门狗定时器、私有定时器以及从PL端输入的FIQ/IRQ。

  • SPI(Shared Peripheral Interrupt),共享外设中断,来自于 44 个 PS 端的IO 外设以及 16 个 PL 端的中断,中断号32~95。

    共享外设中由PL和PS中的多个IO和存储控制器生成。被路由到一个CPU或者两个CPU。来自PS外设的中断也会被路由到PL。

  • 一共:16+16+64=96

1.1.2 通用中断控制器 GIC

通用中断控制器(GIC)是一个集中的资源,用于管理从PS和PL发送到CPU的中断。控制器在CPU接口接受下一个中断时,对中断源进行启用、禁用、屏蔽和确定中断源的优先级,并以编程的方式将它们发送到选定的CPU(或CPU)。此外,该控制器还支持安全扩展,以实现一个具有安全感知能力的系统。

该控制器是基于ARM通用中断控制器架构版本1.0(GIC v1),非矢量的。

寄存器通过CPU私有总线访问,以实现快速的读/写响应,以避免互连中的临时阻塞或其他瓶颈。

中断分配器在将具有最高优先级的中断源发送给单个CPU之前,集中了所有的中断源。硬件确保一个针对多个CPU的中断一次只能被一个CPU占用所有的中断源都由一个唯一的中断ID号来标识。所有中断源都有自己的可配置优先级和目标CPU列表。

以下为中断控制器框图,主要的控制器部分为 ICCICDICC 连接 SGI 和 PPIICD 连接 SPI可配置两者的寄存器来控制中断。

1.1.3 复位和时钟

中断控制器通过复位子系统写入SLCR中的A9_CPU_RST_CTRL寄存器的PERI_RST位来进行复位。同样的复位信号也会复位CPU专用定时器和专用看门狗定时器(AWDT)。

中断控制器使用​CPU_3x2x时钟​ (CPU频率的一半)运行。

1.1.4 结构图

共享的外围设备中断由各种系统子系统生成,这些子系统包括PS中的I/O外设PL中的逻辑。中断源信息如图7-2所示。
z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

1.2功能描述

1.2.1 SGI 中断(软件产生中断)

每个CPU都可以使用软件生成的中断(SGI)来中断自己、另一个CPU或两个CPU。有16个软件生成的中断(见表7-1)。
z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

通过将SGI中断号写入ICDSGIR寄存器并指定目标CPU来生成SGI中断。这种写入操作是通过CPU自己的私有总线进行的。每个CPU都有自己的SGI寄存器集来生成16个软件生成的中断中的一个或多个。CPU可以中断自己,另一个CPU,或者两个CPU。

通过读取ICCIAR(中断确认)寄存器或将1写入ICDICPR(中断清除-待定)寄存器的相应位来清除中断

所有 SGI 都是边缘触发的, SGI 的敏感类型是固定的,不能更改, ICDICFR0 寄存器是只读的,因为它指定了所有 16 个 SGI 的敏感类型。

1.2.2 PPI 中断(CPU 私有中断)

PPI 中断(CPU 私有中断),共 5 个 IRQ ID 号

每个 CPU 都连接到一组私有的五个外设中断。PPI 如图7-2所示。
z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

PPI 的灵敏度类型是固定的,不能更改, 因此,ICDICFR1 寄存器是只读的,因为它指定了所有 5 个 PPI 的敏感类型。

注意,来自 PL 的快速中断 (FIQ) 信号中断 (IRQ) 信号被反转然后发送到中断控制器。

因此,它们在 PS-PL 接口处为高电平有效,尽管 ICDICFR1 寄存器将它们反映为低电平有效。
z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件
z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

1.2.3 SPI (共享外设中断)

SPI (共享外设中断),共 60 个 IRQ ID 号。

来自不同模块的一组大约 60 个中断可以路由到一个或两个 CPU 或 PL。中断控制器为 CPU 管理这些中断的优先级和接收, 除了IRQ #61 到#68 和#84 到#91 之外,所有中断敏感类型都由请求源固定并且不能更改, 必须对 GIC 进行编程以适应这种情况。

所有SPI中断类型的重置默认值都是活动的高级级别。然而,需要软件使用ICDICFR2和ICDICFR5寄存器对中断32、33和92进行编程,以提高边缘灵敏度。SPI中断列于表7-3中。

引导 ROM 不会对这些寄存器进行编程, 因此,SDK 设备驱动程序必须对 GIC 进行编程以适应这些敏感性类型。

对于电平敏感类型的中断,请求源必须为中断处理程序提供一种机制,以便在中断被确认后清除中断。此要求适用于任何具有高灵敏度类型的 IRQF2P[n](来自 PL)。

对于上升沿敏感中断,请求源必须提供足够宽的脉冲以供 GIC 捕捉。这通常是至少 2 个 CPU_2x3x 周期。此要求适用于任何具有上升沿灵敏度类型的 IRQF2P[n](来自 PL)。

ICDICFR2 到 ICDICFR5 寄存器配置所有 SPI 的中断类型。每个中断都有一个 2 位字段,用于指定敏感类型和处理模型。
z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

1.2.3.1 PL端的中断

PS 最大可以接收16 个来自 PL 的中断信号,都是上升沿或高电平触发。

中断号IRQ_ID与IRQP2F对应关系:

  • IRQ_ID[68:61]对应IRQP2F[7:0]。
  • IRQ_ID[91:84]对应IRQP2F[15:8]。

1.2.4 等待中断事件信号(WFI)

CPU可以进入一个等待状态,在那里它等待产生一个中断(或事件)信号。对发送到PL的中断信号的等待在《第3章,应用程序处理单元》中被描述。

1.3 中断寄存器

ICC和ICD寄存器是pl390 GIC寄存器集的一部分。有60个SPI中断。这远远少于pl390所能支持的功能,因此在ICD中的中断启用、状态、优先级和处理器目标寄存器比pl390要少得多。表7-4列出了ICC和ICD寄存器的摘要。

用 Xilinx 的 API 函数就可以很好的控制中断,如果有兴趣可以深入了解中断寄存器,可以对其机制有更好的认识。

z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

  • ICDICFR: 配置寄存器,用于配置触发方式,电平触发或边沿触发,共有 6 个,每个寄存器 32 位,
    每两位表示一个中断,32*6/2=96 个中断号,能覆盖所有中断。

    • ICDICFR0:IRQ ID #0~#15
    • ICDICFR1:IRQ ID #16~#31
    • ICDICFR2:IRQ ID #32~#47
    • ICDICFR3:IRQ ID #48~#63
    • ICDICFR4:IRQ ID #64~#79
    • ICDICFR5:IRQ ID #80~#95
      对于 SPI 中断 0b01:高电平触发 0b11:上升沿触发
  • ICDIPR: 中断优先级寄存器,设置优先级, 共 24 个寄存器,每 8 位代表一个中断号,共 96 个中断号。

  • ICDIPTR: CPU 选择寄存器,24 个寄存器,每 8 位代表一个中断号,24*32/8共 96 个。

    0bxxxxxxx1: CPU interface 0

    0bxxxxxx1x: CPU interface 1

  • ICDICER: 中断关闭寄存器,3 个寄存器,每 1 位代表一个中断号,32*3共 96 个

  • ICDISER: 中断使能寄存器,3 个寄存器,每 1 位代表一个中断号,32*3共 96 个

关于其余的寄存器,大家可以研究 UG585 的寄存器表中的 mpcore 部分

1.3.1 写保护锁定

中断控制器提供了防止对关键配置寄存器写入访问的工具。这是通过写入APU_CTRL[CFGSDISABLE]位来完成的。APU_CTRL寄存器是EPP的系统级控制寄存器集,SLCR的一部分。这将控制了安全中断控制寄存器的写入行为。

如果用户希望设置可CFGSDISABLE的位,则建议在软件配置了中断控制器寄存器后的用户软件启动过程中完成。只能通过通电复位(POR)清除。在设置了CFGSDISABLE位之后,它将受保护的寄存器位更改为只读,因此,即使在安全域中执行流氓代码,这些安全中断的行为也不能改变。

1.4 编程模式

1.4.1 中断优先级

所有的中断请求(PPI、SGI和SPI)都被分配了一个唯一的ID号 控制器使用ID号进行仲裁。中断分配器保存每个CPU的待定中断列表,然后在将其发布给CPU接口之前选择最高优先级的中断通过选择最低的ID来解决相同优先级的中断。

优先级化逻辑在物理上被复制,以允许为每个CPU同时选择最高优先级的中断。中断分配器包含中断、处理器和激活信息的中心列表,并负责触发对CPU的软件中断。

SGI和PPI分发器寄存器被存储起来,以便为每个连接的处理器提供一个单独的副本。硬件确保一个针对多个CPU的中断一次只能被一个CPU占用。

中断分配器将最高待起中断发送到CPU接口。它接收回中断已被确认的信息,然后可以改变相应中断的状态。只有承认该中断的CPU才能结束该中断。

1.4.2 中断处理

在ARM文档中描述了当一个IRQ行取消断言时,GIC对一个待决中断的响应:IHI0048B_gic_architecture_specification.pdf(参见附录A,附加资源)。请参见第1.4.2节中的说明和第3.2.4节中的附加信息。

如果中断在GIC中的中断挂起,并且IRQ被取消断言,那么GIC中的中断将变得不活动(CPU永远不会看到它)。

如果中断在GIC中是活动的 (因为CPU接口已经确认了中断),那么软件ISR通过首先检查GIC寄存器,然后轮询I/O外围中断状态寄存器来确定原因。

1.4.3 ARM编程

ARM GIC体系结构规范包括以下编程内容:

  • GIC寄存器访问
  • 分发器和CPU接口
  • 对GIC安全扩展的影响
  • PU接口寄存器
  • 保存和恢复控制器状态

1.4.4 遗留的中断和安全扩展

当使用遗留中断(IRQ,FIQ),并且中断处理程序以安全模式(通过ICCICR[AckCtl]=1)访问IRQ和FIQ时,在读取中断ID时偶尔会发生竞争条件。还存在在IRQ处理程序中看到FIQ ID的风险,因为GIC只知道处理程序读取的安全状态,而不知道哪种类型的处理程序。

有两个可行的解决方案:

  • 只向重入IRQ处理程序发送IRQ,并在GIC中使用抢占特性。
  • 使用ICCICR[AckCtl]=0中的FIQ和IRQ,并使用TLB表在非安全模式下处理IRQ,并在安全模式下处理FIQ。

二、PL到PS中断的使用与实现

2.1 打开PS的PL中断

新建Block Design,在Vivado中对PS进行配置,打开PL-PS中断端口,对应的中断号为【91:84】,【68:61】。
z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

2.2 连接PL的中断到PS的IRQ_F2P接口

下图中,PL的中断源来自PL的三个按键开关,并通过一个Concat IP连接到一起。此时三个按键是有顺序的,SW1对应的PL第一个中断号61,SW1对应的PL第一个中断号62,SW1对应的PL第一个中断号63。

z7 pl端信号中断到 ps,ZYNQ,嵌入式硬件

2.3 生成bit文件

添加PL端引脚约束,之后Generate the output products,Create a HDL wrapper,Generate Bitstream,Export Hardware(注意勾选include biestream),最后launch SDK进行测试。

2.4 编写SDK PS端代码

#include <stdio.h>
#include "xscugic.h"
#include "xil_exception.h"

#define INT_CFG0_OFFSET 0x00000C00
// 全局宏定义
// Parameter definitions
// PL端中断ID
#define SW1_INT_ID              61
#define SW2_INT_ID              62
#define SW3_INT_ID              63

#define INTC_DEVICE_ID          XPAR_PS7_SCUGIC_0_DEVICE_ID
#define INT_TYPE_RISING_EDGE    0x03
#define INT_TYPE_HIGHLEVEL      0x01
#define INT_TYPE_MASK           0x03
//全局结构体
static XScuGic INTCInst;

static void SW1_intr_Handler(void *param);
static void SW2_intr_Handler(void *param);
static void SW3_intr_Handler(void *param);
static int IntcInitFunction(u16 DeviceId);
//各个中断的回调函数
static void SW1_intr_Handler(void *param)
{
    int sw_id = (int)param;
    act_sync_send_en = 1;

    printf("SW%d intr, act_sync_send_en :%d\n\r", sw_id, act_sync_send_en);
}

static void SW2_intr_Handler(void *param)
{
    int sw_id = (int)param;
    act_sync_send_en = 2;

    printf("SW%d intr, act_sync_send_en :%d\n\r", sw_id, act_sync_send_en);
}

static void SW3_intr_Handler(void *param)
{
    int sw_id = (int)param;
    act_sync_send_en = 3;

    printf("SW%d intr, act_sync_send_en :%d\n\r", sw_id, act_sync_send_en);
}
//中断类型设置:上升沿/高电平
void IntcTypeSetup(XScuGic *InstancePtr, int intId, int intType)
{
    int mask;

    intType &= INT_TYPE_MASK;
    mask = XScuGic_DistReadReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4);
    mask &= ~(INT_TYPE_MASK << (intId%16)*2);
    mask |= intType << ((intId%16)*2);
    XScuGic_DistWriteReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4, mask);
}
//中断初始化
int IntcInitFunction(u16 DeviceId)
{
    XScuGic_Config *IntcConfig;
    int status;

    // Interrupt controller initialisation
    // 查找设备的配置信息
    IntcConfig = XScuGic_LookupConfig(DeviceId);
    status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Call to interrupt setup
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                                 (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                                 &INTCInst);
    //使能IRQ中断
    Xil_ExceptionEnable();
	// 链接各个中断的(中断号、中断回调函数、中断回调函数参数)和中断句柄
    // Connect SW1~SW3 interrupt to handler
    status = XScuGic_Connect(&INTCInst,
                             SW1_INT_ID,
                             (Xil_ExceptionHandler)SW1_intr_Handler,
                             (void *)1);
    if(status != XST_SUCCESS) return XST_FAILURE;

    status = XScuGic_Connect(&INTCInst,
                             SW2_INT_ID,
                             (Xil_ExceptionHandler)SW2_intr_Handler,
                             (void *)2);
    if(status != XST_SUCCESS) return XST_FAILURE;

    status = XScuGic_Connect(&INTCInst,
                             SW3_INT_ID,
                             (Xil_ExceptionHandler)SW3_intr_Handler,
                             (void *)3);
    if(status != XST_SUCCESS) return XST_FAILURE;
	//设置各个中断的触发类型:上升沿或者高电平
    // Set interrupt type of SW1~SW3 to rising edge
    IntcTypeSetup(&INTCInst, SW1_INT_ID, INT_TYPE_RISING_EDGE);
    IntcTypeSetup(&INTCInst, SW2_INT_ID, INT_TYPE_RISING_EDGE);
    IntcTypeSetup(&INTCInst, SW3_INT_ID, INT_TYPE_RISING_EDGE);
	//使能各个中断
    // Enable SW1~SW3 interrupts in the controller
    XScuGic_Enable(&INTCInst, SW1_INT_ID);
    XScuGic_Enable(&INTCInst, SW2_INT_ID);
    XScuGic_Enable(&INTCInst, SW3_INT_ID);

    return XST_SUCCESS;
}

int main(void)
{
    print("PL int test\n\r");
    IntcInitFunction(INTC_DEVICE_ID);
    while(1);
    return 0;
}

2.5 SDK中断处理流程总结

所以在最后总结一下PL产生中断,PS处理中断,在SDK中大致的流程:

  1. 中断初始化:
    a. 通过XGpioPs_LookupConfig函数,找到所设备的基址;
    b. 通过XGpioPs_CfgInitialize函数,初始化设备配置;
    c. 通过Xil_ExceptionRegisterHandler函数,进行中断异常注册;
    d.通过Xil_ExceptionEnable函数,使能中断异常注册;
  2. 通过XScuGic_Connect函数,链接中断号、中断处理程序、回调参数;
  3. 通过IntcTypeSetup函数,设置中断触发模式;
  4. 通过XScuGic_Enable函数,中断使能。

参考:
文章来源地址https://www.toymoban.com/news/detail-852654.html

到了这里,关于ZYNQ7000 PL与PS交互(一): PL到PS中断的使用与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • zynq7000学习(1)——vivado环境下PL配置

    一、新建工程:       现开发板型号为xc7z100ffg900-2  选择芯片 (选择芯片7100的话,就输入xc7z100  后面的-1和-2是速度等级), 更改项目名为system 。 Create Block Design (创建模块化的设计)——设置设计名称为system。     这时会出现design窗口和source窗口、画布窗口,source中出

    2024年02月13日
    浏览(56)
  • ZYNQ通过AXI DMA实现PL发送连续大量数据到PS DDR

    硬件:ZYNQ7100 软件:Vivado 2017.4、Xilinx SDK 2017.4   ZYNQ PL 和 PS 的通信方式有 AXI GPIO、BRAM、DDR等。对于数据量较少、地址不连续、长度规则的情况,BRAM 比较适用。而对于传输速度要求高、数据量大、地址连续的情况,比如 ADC,可以通过 AXI DMA 来完成。 1、硬件设计 1.1 ZYNQ7

    2024年02月04日
    浏览(40)
  • zynq pl访问ps ddr

    在 xilinx mpsoc 平台上进行 Linux 软件开发,不可避免的会涉及到 PS 与 PL 之间的数据交互。这个 系列 介绍一种 基于 DDR 的信息交互方式 。 这篇文章首先介绍下 如何从系统中“偷”内存 。 交互流程: PS 写入数据到 DDR 中,使用中断通知 PL,PL 从协商好的 DDR 中读取数据; PL 写

    2024年02月01日
    浏览(49)
  • PS和PL使用BRAM进行数据交互

    BRAM(Block RAM)是 PL 部分的存储器阵列,PS 和 PL 通过对 BRAM 进行读写操作,来实现数据的交互。在 PL 中,通过输出时钟、地址、读写控制等信号来对 BRAM 进行读写操作。而在 PS 中,处理器并不需要直接驱动 BRAM 的端口,而是通过 AXI BRAM 控制器来对 BRAM 进行读写操作。AXI BR

    2024年02月02日
    浏览(38)
  • zynq板上PS端给PL端复位

    最近接触zynq板-zcu104,记录一些实验笔记。 LED闪烁 在vivado中新建一个工程,命名为led-test。添加top.v文件。 其中,top模块接入zcu104开发板的clk_300_p/n信号,通过clock wizard转换为单端始终clock,接入到led闪烁模块led.v 其中,led模块通过一个24bit的计数器,经过相等间隔厚,让led灯

    2024年02月11日
    浏览(38)
  • zynq的PL向PS提供时钟和复位

    最近买了一块矿卡蚂蚁T9+,它的资源比EBAZ4205丰富。 需要矿卡资料包的朋友可以从这下载。里面包含蚂蚁T9+和EBAZ4205原理图和几个EBAZ4205例程,还有一些相关的pdf文档。 link 首先从fpga学起,可惜PL没有焊晶振,只好从PS端引,下面以点灯为例。 打开vivado,工具栏file -- project -

    2024年02月15日
    浏览(47)
  • zynq 使用AXI_dma 传输==pl到ps,linux驱动开发,应用层处理DMA数据

    在使用zynq输出处理时,会使用到pl和ps的数据传输,可供使用的方案有多种,由于我们的数据量较大打算,因此使用用以下两种方案处理: 1.使用pl直接写ddr3, 2.使用dma, 本次详细介绍使用axi_dma如何将pl的数据在linux应用层接收数据并处理,以及遇到的问题 fpga工程,我们使用

    2024年02月03日
    浏览(55)
  • 自定义ZYNQ的PL端数据处理器,通过DMA等进行交互(附GitHub源码)

    摘要:在ZYNQ中设计了自定义的PL端数据处理器,通过DMA连接到AXI总线,完成了PS和该PL端的数据交互等功能。 开发板型号:Zynq-7000 SoC XC7Z305 FPGA 开发平台:Vivado 2019.1; Vivado SDK 2019.1 Github源码 :https://github.com/CY0807/Vivado_FIFO_Test.git (1)vivado_project存放了vivado和sdk原始工程文件

    2024年01月21日
    浏览(44)
  • FPGA----UltraScale+系列的PS侧与PL侧通过AXI-HP交互(全网唯一最详)附带AXI4协议校验IP使用方法

    1、之前写过一篇关于ZYNQ系列通用的PS侧与PL侧通过AXI-HP通道的文档,下面是链接。 FPGA----ZCU106基于axi-hp通道的pl与ps数据交互(全网唯一最详)_zcu106调试_发光的沙子的博客-CSDN博客 大家好,今天给大家带来的内容是,基于AXI4协议的采用AXI-HP通道完成PL侧数据发送至PS侧(PS侧数

    2024年02月13日
    浏览(49)
  • ZYNQ——PL端流水灯的实现

    本文介绍的是在ZYNQ 7020黑金开发板上实现PL端流水灯的例子,开发板上PL端的LED灯总共有4个,在原理图中找到 PL LED 如下图所示,通过看图可知,给 LED 置低电平时灯才亮。 这里预想的实验结果是:在1秒钟内,4个LED各亮0.25秒,看起来就像流水灯一样。 LED:4个,赋值为0时即点

    2024年02月09日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包