在学习ZYNQ的过程中,笔者在b站上找了许多网课,但是都是直接上实验教程,并没有详细解释模块的用法。
PS和PL端的交互是ZYNQ的一个核心功能,使用AXI总线算是司空见惯了,可是当数据量比较小,或者如果我们只是想要起到PL向PS的“通知”作用的话,使用总线有点大材小用,因此我们还可以使用外部中断来实现这种“通知”的功能。
首先就是block design,这点不用多说,主要就是在中断配置界面中勾选PL-PS中断,如下图所示,可以看到,arm端提供了[91:84],[68:61]这些引脚供我们使用。
第二步,引脚引出,这里我使用concat ip,把多个引脚合并成一个多位宽的端口,连接到外部中断引脚IRQ上面,引出两个引脚到按钮上。
这里注意!!!外部引入到IRQ上的引脚顺序关系到这个引脚的中断号,从低到高的顺序恰好是61~68,84~91,也就是说我的按钮1对应的是61号中断id,按钮2对应的是62号。
第三步,打开SDK,写入如下代码:
/****************************************************************************** * * Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /* * helloworld.c: simple test application * * This application configures UART 16550 to baud rate 9600. * PS7 UART (Zynq) 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 bootrom/bsp) */ #include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "sleep.h" #include "xscugic.h" #include "xil_exception.h" #define SW1_INT_ID 61 #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 #define SW1_INT_ID 61 XScuGic ScuGic; void sw1_intr_callback() { print("interrupt!!!\n\r"); } int IntcInitFunction(uint16_t Deviceid){ int Status; //GIC中断控制器初始化 XScuGic_Config *IntcConfig; IntcConfig = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID); XScuGic_CfgInitialize(&ScuGic, IntcConfig,IntcConfig->CpuBaseAddress); //使能CPU全局中断 Xil_ExceptionInit(); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic); Xil_ExceptionEnable(); //connect sw interrupt to handler Status = XScuGic_Connect(&ScuGic, SW1_INT_ID,(Xil_ExceptionHandler)sw1_intr_callback,sw1_intr_callback); XScuGic_SetPriorityTriggerType(&ScuGic, SW1_INT_ID, 8, INT_TYPE_RISING_EDGE); XScuGic_Enable(&ScuGic, SW1_INT_ID); return 0; } int main() { init_platform(); IntcInitFunction(SW1_INT_ID); while(1){ sleep(1); print("Hello World\n\r"); } cleanup_platform(); return 0; }这里做出解释,核心部分其实只有IntcInitFunction这个函数,前三段初始化GIC中断控制器,中间初始化CPU中断,关键在于最后三段代码,connect设定了中断发生时将要执行的回调函数sw1_intr_callback,笔者在这个函数里面写的是串口输出,当然大家可以自行修改。setpriority设置了中断优先级和出发边沿。
最后上板测试,按下按键后确实会收到串口输出,我们实现了PL向PS的中断通知,当我们遇到传输数据场景时,也可以通过这套逻辑来实现数据传输通知,当然,外部中断F2P引脚也是可以接ip核或者内部模块的输出的。