ZYNQ 7020学习笔记之PL侧普通信号中断PS的实验

1、参考
UG585
网络笔记
2、理论知识
见中断部分

3、实验目的
练习使用PL侧的普通信号来中断PS处理器。

4、实验过程
建立工程,设置并初始化串口中断,在运行程序之后,如果串口接收到N(1-63)个字节数据,则产生串口中断,Zynq响应中断,将数据从RXFIFO读出之后写入到DDR3预定的地址中。

5、实验平台
Microphase ZUS zynq7020 开发板。 串口使用 uart1[48,49]. DDR选择 MT41J256M16 RE-125,32bit. BANK1 = 1.8v.

6、Vivado 建立工程
block design 如下:
在这里插入图片描述

7、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.
*
******************************************************************************/

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xscugic.h"
#include "xscutimer.h"
#include "xparameters.h"
#include "xil_exception.h"

#include <unistd.h>  //sleep()  usleep()

#define 	INTC_DEVICE_ID		 		XPAR_PS7_SCUGIC_0_DEVICE_ID
#define		INTC_PL_INTERRUPT_ID 	   	XPAR_FABRIC_MY_AXI4LITE_IP_0_PL_TO_ZYNQ_IRQ_INTR
#define		INT_TYPE_MASK				0x01
#define     INT_TYPE_RISING_EDGE        0X03
#define     INT_TYPE_HIGHLEVEL 			0X01
#define 	INT_CFG0_OFFSET 			0x00000C00  //(intID/16 )*4
#define 	INT_ENABLE_OFFSET 			0x00000100  //(intID/32 )*4
#define 	INT_CLEAR_OFFSET 			0x00000280  //(intID/32 )*4
#define 	INT_PRIORITY_OFFSET 		0x00000400  //(intID/4 )*4
#define 	INT_PROCESSORTARGET_OFFSET 	0x00000800  //(intID/4 )*4

#define 	INT_ICCPMR_OFFSET 	0xF8F00104
#define 	INT_ICCICR_OFFSET 	0xF8F00100


#define     BRAM_BASS_ADDRESS    0X40000000

XScuGic		INTCInst;

static	void	PLIRQIntrHandler(void	*	InstancePtr);  //中断处理功能函数
static  void 	CPU_Init(void);
static  void 	IntcTypeSetup(XScuGic *InstancePtr, int intId, int intType) ;
static  void 	IntcTypeEnable(XScuGic *InstancePtr, int intId, int intMask) ;
static  void 	IntcTypeClear(XScuGic *InstancePtr, int intId ) ;
static	int		InterruptSystemSetup(XScuGic	* XScuGicInstancePtr);   //中断系统建立
static  int		IntcInitFunction(u16 DeviceID);  //中断控制器初始化功能

int main()
{
    init_platform();
    CPU_Init();

    int status;

    //中断建立
     status = IntcInitFunction(INTC_DEVICE_ID);
     if(status != XST_SUCCESS)
    	 return		XST_FAILURE ;

    print(">>>>>>>>>>>> TEST Start >>>>>>>>>>>>>>>>\n\r");
    print(" Press the Key for PL begin write data to PS DDR3 : \n\r");
    while(1)
    {

    	;
    }


    cleanup_platform();
    return 0;
}


// 中断控制器初始化功能
static int IntcInitFunction(u16 DeviceId)
{
	XScuGic_Config	* IntcConfig ;
	int		status;

	printf("Enter the interrupt system >>>>>>\n");
	// 第二步, 对中断控制器进行初始化
	IntcConfig = XScuGic_LookupConfig(DeviceId);   //查找 GIC 的ID
	status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
	if(status != XST_SUCCESS)
		return XST_FAILURE;

	//第三步,建立中断系统
	status = InterruptSystemSetup(&INTCInst);
	if(status != XST_SUCCESS)
		return	XST_FAILURE ;

	//第四步,GPIO中断连接到GIC上
	status = XScuGic_Connect(&INTCInst, INTC_PL_INTERRUPT_ID,
			(Xil_ExceptionHandler)PLIRQIntrHandler, (void *)1);

	if(status != XST_SUCCESS)
			return	XST_FAILURE ;

  //******************//
	// 参考
    IntcTypeSetup(&INTCInst,  INTC_PL_INTERRUPT_ID, INT_TYPE_RISING_EDGE);   //重要
    IntcTypeEnable(&INTCInst,  INTC_PL_INTERRUPT_ID, INT_TYPE_MASK);

//*********************************//
	XScuGic_Enable(&INTCInst, INTC_PL_INTERRUPT_ID); //CIG允许中断

	return XST_SUCCESS ;
}


static int InterruptSystemSetup (XScuGic * XScuGicInstancePtr)
{
	//中断异常的处理,指定该中断异常的处理器
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
			(Xil_ExceptionHandler)XScuGic_InterruptHandler, XScuGicInstancePtr);

	Xil_ExceptionEnable();   //异常处理使能

	return XST_SUCCESS;


}


void IntcTypeSetup(XScuGic *InstancePtr, int intId, int intType)
{
  //Setup 包括 触发方式配置, 优先级配置,CPU连接。 设置某个中断信息的前提是不影响其他中断设置
    int mask;

   //设置边沿触发方式
    mask = XScuGic_DistReadReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4);     //read ICDICFR  *4,因为1个寄存器4个字节
    mask &= ~(0X3 << (intId%16)*2);  		//把读出的值对应2bit,清00,其他保持不变             //*2因为每个中断对应2bit
    mask |= intType << ((intId%16)*2);         	//把清0后的值对应2bit,写01,其他保持不变
    XScuGic_DistWriteReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4, mask);     //WRITE ICDICFR

    //设置优先级
    mask = XScuGic_DistReadReg(InstancePtr, INT_PRIORITY_OFFSET + (intId/4)*4);     //read 优先级状态
	mask &= ~(0XFE << (intId%4)*8);        //把读出的值对应8bit,清00,其他保持不变             //*8因为每个中断对应8bit
	mask |= 0XA0 << ((intId%4)*8);         //把清0后的值对应8bit,写A0,其他保持不变
	XScuGic_DistWriteReg(InstancePtr, INT_PRIORITY_OFFSET + (intId/4)*4, mask);     //WRITE ICDICFR

    //设置处理器CPIID
	mask = XScuGic_DistReadReg(InstancePtr, INT_PROCESSORTARGET_OFFSET + (intId/4)*4);     //read 优先级状态
	mask &= ~(0X03 << (intId%4)*8);        //把读出的值对应8bit,清00,其他保持不变             //*8因为每个中断对应8bit
	mask |= 0X01 << ((intId%4)*8);         //把清0后的值对应8bit,写A0,其他保持不变
	XScuGic_DistWriteReg(InstancePtr, INT_PROCESSORTARGET_OFFSET + (intId/4)*4, mask);     //WRITE ICDICFR

}

void IntcTypeEnable(XScuGic *InstancePtr, int intId,int intMask)
{
  // 本函数 只包括 使能中断。使能之前先判断是否需要屏蔽
    int mask;

    mask = XScuGic_DistReadReg(InstancePtr, INT_ENABLE_OFFSET + (intId/32)*4);
    mask &= ~(0x01 << (intId%32)*1);   //把对应的Enable bit 清0
    mask |= intMask << ((intId%32)*1); //把对应的Enable bit 与 mask
    XScuGic_DistWriteReg(InstancePtr, INT_ENABLE_OFFSET + (intId/32)*4, mask);     //WRITE ICDICFR
}

void IntcTypeClear(XScuGic *InstancePtr, int intId )
{
	//本函数仅包括清楚中断,注意只能清除本中断对应的寄存器位
	 int mask;

    mask = XScuGic_DistReadReg(InstancePtr, INT_CLEAR_OFFSET + (intId/32)*4);     //read  ICDICPR
    mask &= ~(0x01 << (intId%32)*1);
    mask |= 0x01 << ((intId%32)*1);
    XScuGic_DistWriteReg(InstancePtr, INT_CLEAR_OFFSET + (intId/32)*4, mask);     //WRITE  ICDICPR
}



void CPU_Init( )
{
    //中断优先级都是A0,优先级高于F0,CPU可接受这些中断
	Xil_Out32(INT_ICCPMR_OFFSET,0xF0);
    //处理器能接收IRQ,使能中断信号连接到处理器
	Xil_Out32(INT_ICCICR_OFFSET,0x07);
}


static void PLIRQIntrHandler(void * InstancePtr)
{
	//default led all turn off
	printf("\n************* test STARAT *********************\n");
    int i;
    int readdata;
	sleep(1);

	for(i = 0; i < 4; i++)
	{
		readdata = Xil_In32(BRAM_BASS_ADDRESS+i*4);              //读取数据函数。
		sleep(1);
		printf("the read address is 0x%04x, the read data is 0x%04x.\n", BRAM_BASS_ADDRESS+i*4, readdata);
	}

	printf("\n************* test finish *********************\n");
	// ***************************************************** //

	IntcTypeClear(&INTCInst,  INTC_PL_INTERRUPT_ID);
	IntcTypeEnable(&INTCInst,  INTC_PL_INTERRUPT_ID, INT_TYPE_MASK);

}

8 调试结果

在这里插入图片描述

posted @ 2019-08-23 15:49  远航路上ing  阅读(1340)  评论(0编辑  收藏  举报