Zynq中 PS接收PL中断

阅读: 评论:0

Zynq中 PS接收PL中断

Zynq中 PS接收PL中断

参考:

.html
.php?mod=viewthread&tid=1255
.php?mod=viewthread&tid=1097

//中断寄存器相关
米联手册以及UG585手册。

实验中搭建了基于ZC706开发板的实验工程,在PL端通过按键产生中断,PS接受到之后点亮相应的LED。主要学习了在外设(PL)产生的中断请求,在PS端进行处理。

一、搭建工程

具体实验就不在这里展开了,搭建参考米联手册《S02_CH07_ ZYNQ PL 中断请求》。
这里记录下重点步骤:
1)选择开发型号(Zc706)、设置串口(uart1)、设置电压(1.8,1.8)、设置时钟(默认配置)
2)设置内存型号


3)使能中断(特别是PL到PS的中断)

4)添加按键IP核并配置(记得中断)

5)添加LED的IP核并配置

6)之后就是手动连接中断线、自动布局;
验证设计(F6)、产生输出generate output files、产生wrap文件、产生约束文件
三部曲仿真、执行、生成bit文件;启动SDK,进行PS端开发。

二、zynq中断学习


由上图可知,zynq的中断分为三种:

1.软件中断(SGI,Software generatedinterrupts,中断号0-15)(16–26 reserved) :被路由到一个或者两个CPU上,通过写ICDSGIR寄存器产生SGI.

2.私有外设中断(PPI,private peripheralinterrupts ,中断号27-31):每个CPU都有一组PPI,包括全局定时器、私有看门狗定时器、私有定时器和来自PL的FIQ/IRQ.

3.共享外设中断(SPI,shared peripheralinterrupts,中断号32-95):由PS和PL上的各种I/O控制器和存储器控制器产生,这些中断信号被路由到相应的CPU.

中断控制器(GIC,generic interrupt controller ):用于集中管理从PS和PL产生的中断信号的资源集合。控制器可以使能、关使能、屏蔽中断源和改变中断源的优先级,并且会将中断送到对应的CPU中,CPU通过私有总线访问这些寄存器。

从下面的表格中可以看到中断向量的具体值。PL 到 PS 部分一共有 20 个中断可以使用。其中 4 个是快速中断。

ZYNQ 2 个 CPU 都具备各自 16 个软件中断。
ZYNQ CPU 私有端口中断,这些中断都是固定死的,不能修改。
ZYNQ PS 和 PL 共享中断
共享中断就是一些端口共用一个中断请求线, PL部分有16个共享中断,他们的触发方式可以设置:

这里也可以看到中断号是从61开始的。

二、SDK逻辑代码分析

中断处理基本流程:(具体函数参考 SCUGIC API)
1. 中断初始化
2. 调用中断建立函数
3. Xilinx中断触发使能
4. 连接中断操作函数
5. 配置中断触发信号
6. 使能中断控制器

其中,寄存器 地址 中断号
ICDICFR0 0xF8F01C00 #0-#15
ICDICFR1 0xF8F01C04 #27-#31(16-26保留)
ICDICFR2 0xF8F01C08 #32-#47(36保留)
ICDICFR3 0xF8F01C0C #48-#63
ICDICFR4 0xF8F01C10 #64-#79
ICDICFR5 0xF8F01C14 #80-#95(93/94/95保留)
该代码在PL端通过按键产生中断,PS接受到之后点亮相应的LED.

#include "xparameters.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xgpio.h"
#include <stdio.h>// Parameter definitions#define INTC_DEVICE_ID      XPAR_PS7_SCUGIC_0_DEVICE_ID   //中断基地址设备ID
#define LED_DEVICE_ID       XPAR_LED_4BITS_DEVICE_ID
#define BTNS_DEVICE_ID      XPAR_SWS_3BITS_DEVICE_ID
#define INTC_GPIO_INTERRUPT_ID XPAR_FABRIC_SWS_3BITS_IP2INTC_IRPT_INTR
#define BTN_INT             XGPIO_IR_CH1_MASK // This is the interrupt mask for channel one
#define DELAY 100000000XGpio   LEDInst;
XGpio   BTNInst;
XScuGic INTCInst;
static int btn_value;  //按键值//----------------------------------------------------
// 函数声明
//----------------------------------------------------
static void BTN_Intr_Handler(void *baseaddr_p);
static int InterruptSystemSetup(XScuGic *XScuGicInstancePtr);
static int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr);#define INT_CFG0_OFFSET 0x00000C00
#define INT_TYPE_RISING_EDGE    0x03
#define INT_TYPE_HIGHLEVEL      0x01
#define INT_TYPE_MASK           0x03/** //Xil_Out32(((((InstancePtr)->Config->DistBaseAddress)) +* ((0x00000C00 + (intId/16)*4))), ((u32)(((u32)(mask)))))* 此时,我们就知道了第一个参数是一个指向要处理的中断的指针:((InstancePtr)->Config->DistBaseAddress))* 在xparameters.h中,找到了中断的基地址,XPAR_PS7_SCUGIC_0_DIST_BASEADDR 0xF8F01000* 第二个参数是寄存器偏移。* 寄存器的地址= F8F01000+((0x00000C00+(61/16)*4))= F8F01C0C* 参考手册UG584 p1497 看寄存器功能* 第三个参数设置寄存器掩码*/
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);
}
//----------------------------------------------------
//  中断处理函数
// - called by the buttons interrupt, performs push buttons read
//----------------------------------------------------void BTN_Intr_Handler(void *InstancePtr)
{unsigned char led_val = 0;// Ignore additional button pressesif ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) !=BTN_INT) {return;// Disable GPIO interruptsXGpio_InterruptDisable(&BTNInst, BTN_INT);}btn_value = XGpio_DiscreteRead(&BTNInst, 1);printf("btn value:%dn",btn_value);switch (btn_value){case 1: led_val = 0x01; break;case 2: led_val = 0x02; break;case 4: led_val = 0x04; break;default:break;}XGpio_DiscreteWrite(&LEDInst,1,led_val);// Acknowledge GPIO interrupts(void)XGpio_InterruptClear(&BTNInst, BTN_INT);// Enable GPIO interruptsXGpio_InterruptEnable(&BTNInst, BTN_INT);}
//----------------------------------------------------
// MAIN FUNCTION
//----------------------------------------------------
int main (void)
{int status;// 初始化按键status = XGpio_Initialize(&BTNInst, BTNS_DEVICE_ID);if(status != XST_SUCCESS) return XST_FAILURE;//初始化LEDstatus = XGpio_Initialize(&LEDInst, LED_DEVICE_ID);if(status != XST_SUCCESS) return XST_FAILURE;// 设置按键IO的方向为输入XGpio_SetDataDirection(&BTNInst, 1, 0xFF);//设置LED IO的方向为输出XGpio_SetDataDirection(&LEDInst, 1, 0x00);// 初始化中断控制器status = IntcInitFunction(INTC_DEVICE_ID, &BTNInst);if(status != XST_SUCCESS) return XST_FAILURE;while(1){}return (0);
}
//----------------------------------------------------
// INTERRUPT SETUP FUNCTIONS
//----------------------------------------------------
int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr)
{//中断控制器配置实例XScuGic_Config *IntcConfig;int status;// Interrupt controller initialization//找到scugic实例(根据设备ID查找中断向量)IntcConfig = XScuGic_LookupConfig(DeviceId);//初始化scugic(状态检测,对中断初始化,成功返回XST_SUCCESS)status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);if(status != XST_SUCCESS) return XST_FAILURE;// Call interrupt setup functionstatus = InterruptSystemSetup(&INTCInst);if(status != XST_SUCCESS) return XST_FAILURE;// 注册中断函数status = XScuGic_Connect(&INTCInst,INTC_GPIO_INTERRUPT_ID,(Xil_ExceptionHandler)BTN_Intr_Handler,(void *)GpioInstancePtr);if(status != XST_SUCCESS) return XST_FAILURE;//设置中断触发类型为上升沿IntcTypeSetup(&INTCInst,INTC_GPIO_INTERRUPT_ID,INT_TYPE_RISING_EDGE);// Enable GPIO interruptsXGpio_InterruptEnable(GpioInstancePtr, 1);XGpio_InterruptGlobalEnable(GpioInstancePtr);// 使能我们的按键中断(中断号61)XScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);return XST_SUCCESS;
}int InterruptSystemSetup(XScuGic *XScuGicInstancePtr)
{// Register GIC interrupt handler//通用异常处理程序,中断后统一由GIC先处理,然后在HanderTable中查找相应的处理函数Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,XScuGicInstancePtr);//使能异常处理Xil_ExceptionEnable();return XST_SUCCESS;}
三、zynq linux 中断号如何对应
1) 在裸机驱动中设备号与硬件中断号的对应关系

在zynq 的PL端配置外设中断 ,不涉及dts。
比如zynq中的外设中断号从#61开始,配置成按键button,按下按键时,Linux系统接收中断进行处理。
此时就需要在Linux的驱动中按照物理中断号注册,也就是硬件中断号。

    //注册中断ret = request_irq(61, TxDoneHandler, IRQF_TRIGGER_RISING,"TXDONE_INT", NULL);if(ret){printk("request TXDONE_INT failed! ret = %dn", ret);return -1;}
2) 在设备树dts中设备号与硬件中断号的对应关系

在linux系统下,中断号跟BD中zynq7000 processer中配置的生成的中断号不是直接对应的,中间有一个“-32” 的关系,如下

For Shared Periperal interrupts, the value in the device tree is the (IRQ - 32) ;

例子 interrupts = <0x0 0x32 0x0>; 中间的参数0X32是中断号 50

uart@e0001000 {compatible = "xlnx,ps7-uart-1.00.a";reg = <0xe0001000 0x1000>;interrupts = <0x0 0x32 0x0>;interrupt-parent = <&gic>;clock = <50000000>;
};The second value is the interrupt number. The translate function adds 16to SPIs and 32 to non-SPIs, so for interrupts generated by fabric logicin a Zynq, the number in the DTS file should be the hardware number (asshown in Xilinx Platform Studio, XPS) minus 32.翻译:第二个参数是中断号。传递的过程中会区分是否为spi中断,如果是spi中断则加16,非spi则加32 ,
所以在devicetree中的生成的中断号是实际中断号减去32 ;

本文发布于:2024-01-29 00:48:53,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170646053611512.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:ZYNQ通过AXI
下一篇:Zynq
标签:Zynq   PS   PL
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23