ZYNQ学习

GPIO通过MIO连接PS,通过EMIO连接PL

GPIO分为4个bank[32 22    32 32],前两个是连接MIO,后面两个是连接EMIO(PS引脚不够用,需要EMIO扩展)

PS MIO控制led,无中断

#define MIO0_LED  11
#define MIO50_KEY  11
// 绑定PS端的管脚


int main(){

	//查找gpio配置信息
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    //初始化
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
	


	//配置管脚的方向 0:输入   1:输出(输出时候需要多一个输出使能函数)
    // 输出示例
	XGpioPs_SetDirectionPin(&Gpio, MIO0_LED, 1);
    //输出时候需要多一个输出使能函数
	XGpioPs_SetOutputEnablePin(&Gpio, MIO0_LED, 1);
    

    // 输入示例
	XGpioPs_SetDirectionPin(&Gpio, MIO50_KEY, 0x0);	
	//读取引脚的值
	u32 key_value1=XGpioPs_ReadPin(&Gpio, MIO50_KEY);


	//给输出引脚赋值
	XGpioPs_WritePin(&Gpio, MIO0_LED,key_value1);
	
	}

PS EMIO控制led,无中断

#define EMIO_KEY  54
// 因为GPIO前两个bank是连接MIO共32+22=54个,编号是 0-53
// 此处的key是用EMIO扩展的位宽一位PL端按键,所以编号在53基础上加1=54
// 54并不是实际的管脚,在生成bit文件之前已经给54号绑定了PL端的管脚
#define MIO0_LED  11
// 绑定PS端的管脚11

int main(){

	//查找gpio配置信息
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    //初始化
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
	

	//配置管脚的方向 0:输入   1:输出(输出时候需要多一个输出使能函数)
    // 输出示例
	XGpioPs_SetDirectionPin(&Gpio, MIO0_LED, 1);
    //输出时候需要多一个输出使能函数
	XGpioPs_SetOutputEnablePin(&Gpio, MIO0_LED, 1);
    

    // 输入示例
	XGpioPs_SetDirectionPin(&Gpio, EMIO_KEY, 0x0);	
	//读取引脚的值
	u32 key_value1=XGpioPs_ReadPin(&Gpio, EMIO_KEY);


	//给输出引脚赋值
	XGpioPs_WritePin(&Gpio, MIO0_LED,key_value1);
	
	}

PS gpio中断控制 流程

(只用PS端就只有MIO,如果要用PL端需要EMIO绑定PL的管脚,其他一样)

每个外设都有一个自己的中断号,需要中断控制器GIC收到中断请求之后做判断

中断服务函数IntrHandler()只是改变标志信号的值

真正的操作要在while里不断的检测中断,然后进行逻辑操作,while内部要

//先清除中断状态

XGpioPs_IntrClearPin(&Gpio, MIO50_KEY);
//再IntrHandler()中的关闭的中断打开,给gpio管脚中断 赋使能
XGpioPs_IntrEnablePin(&Gpio, MIO50_KEY);

int main(){

	//查找gpio配置信息,初始化
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
	
	//配置管脚的方向 0:输入   1:输出(输出时候需要多一个输出使能函数)
	XGpioPs_SetDirectionPin(&Gpio, MIO0_LED, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO0_LED, 1);
	XGpioPs_SetDirectionPin(&Gpio, MIO50_KEY, 0x0);
	
	
	//设置PS GPIO中断系统
	SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID);
    //查找中断控制器gic配置信息,初始化
    //中断固定三函数
    //关联中断函数
    //给gpio中断控制器 赋使能
    //单独给gpio一个管脚设置中断触发类型
    //单独给gpio一个管脚中断 赋使能


	while(1){
		//进入判断while,只要触发中断就开始执行
        if(key==1){
		//清除gpio管脚中断状态
		XGpioPs_IntrClearPin(&Gpio, MIO50_KEY);
		//执行相应的操作
			FUNCTIONAL
            key==0;
		//给gpio管脚中断 赋使能
		XGpioPs_IntrEnablePin(&Gpio, MIO50_KEY);
	}	
}



//设置PS GPIO中断系统
void SetupInterruptSystem(&Intc, &Gpio, GPIO_INTERRUPT_ID);
	{
		//查找中断控制器gic配置信息,初始化
		IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
		XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
						IntcConfig->CpuBaseAddress);
	
		//中断固定三函数
		Xil_ExceptionInit();
		Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
					(Xil_ExceptionHandler)XScuGic_InterruptHandler,
					GicInstancePtr);
		Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
		
		//关联中断函数,中断之后做出IntrHandler操作
		//在IntrHandler函数操作中需要关闭引脚的中断使能,
		//在后面对中断做完所有的响应之后打开
		XScuGic_Connect(GicInstancePtr, GpioIntrId,
					(Xil_ExceptionHandler)IntrHandler,
					(void *)Gpio);
					
		//给gpio中断控制器 赋使能
		XScuGic_Enable(GicInstancePtr, GpioIntrId);
		
		//单独给gpio一个管脚设置中断触发类型
		XGpioPs_SetIntrTypePin(Gpio, MIO50_KEY, XGPIOPS_IRQ_TYPE_EDGE_FALLING);
		
		//单独给给gpio一个管脚中断 赋使能
		XGpioPs_IntrEnablePin(&Gpio, MIO50_KEY);
		
	}
//中断服务函数	改变信号的值,在while里检测,然后才是真正的逻辑操作
	void IntrHandler(){
		//关闭引脚的中断使能
		XGpioPs_IntrDisablePin(&Gpio, MIO50_KEY);
		//中断触发后做出的响应
		XXXXXXXXXX;
        key=1;//中断操作
	}

AXI_GPIO中断

AXI GPIO是ZYNQ的一个IP核,它能够将PS侧的AXI4-Lite接口转成PL侧的IO口,可解决PS侧IO口不够用的问题。

软核:出场时不存在的电路,是pl端新建的

硬核:出场时就已经存在的电路

PL到PS的中断需要在zynq中配置打开interrupts,选中PL-PS,PL的中断有16个ID

//先给AXI gpio中断控制器 赋使能
 XScuGic_Enable(GicInstancePtr, AXI_GpioIntrId);
//然后把AXI的中断打开分两步:打开全局中断、打开通道中断

//打开全局中断
XGpio_InterruptGlobalEnable(AXI_Gpio);
//打开通道中断
XGpio_InterruptEnable(AXI_Gpio, u32 Mask);        

注意:AXI GPIO的中断是高电平敏感类型的信号

int main(){

	(led)
	//查找PS端gpio配置信息,初始化
	ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
	XGpioPs_CfgInitialize(&Gpio, ConfigPtr,ConfigPtr->BaseAddr);
	
	(key)
	//查找AXI gpio配置信息,初始化
	XGpio_Initialize(&AXI_Gpio, AXI_GPIO_DEVICE_ID);
	
	
	//配置PS gpio管脚的方向 
	//0:输入   1:输出(输出时候需要多一个输出使能函数)
	XGpioPs_SetDirectionPin(&Gpio, MIO0_LED, 1);
	XGpioPs_SetOutputEnablePin(&Gpio, MIO0_LED, 1);
	
	//配置AXI gpio的方向 
	//DirectionMask     0:输出   1:输入
	XGpio_SetDataDirection(&AXI_Gpio, GPIO_CHANNEL1,
			    u32 DirectionMask);	
	
	//给AXI GPIO设置中断系统
	SetupInterruptSystem(&Intc, &AXI_Gpio, AXI_GPIO_INTERRUPT_ID);

	while(1){
		//进入判断while,
      if(key==1){
		//先读取和AXI_GPIO相连的信号电平状态,进行判断,如何操作
		if(XGpio_DiscreteRead(&AXI_Gpio, unsigned Channel)){
		//清除AXI gpio中断状态
		XGpio_InterruptClear(&AXI_Gpio, u32 Mask);
		//执行相应的操作
			FUNCTIONAL
		//打开通道中断
		XGpio_InterruptEnable(&AXI_Gpio, u32 Mask);
	}	
}
}


//给AXI GPIO设置中断系统
SetupInterruptSystem(&Intc, &AXI_Gpio, AXI_GPIO_INTERRUPT_ID)
	{
		//查找中断控制器gic配置信息,初始化
		IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
		XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
						IntcConfig->CpuBaseAddress);
	
		//中断固定三函数
		Xil_ExceptionInit();
		Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
					(Xil_ExceptionHandler)XScuGic_InterruptHandler,
					GicInstancePtr);
		Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
		
		//关联中断函数,中断之后做出IntrHandler操作
		//在IntrHandler函数操作中需要关闭引脚的中断使能,
		//在后面对中断做完所有的响应之后打开
		XScuGic_Connect(GicInstancePtr, AXI_GpioIntrId,
					(Xil_ExceptionHandler)IntrHandler,
					(void *)AXI_Gpio);
					
		//给AXI gpio中断控制器 赋使能
		XScuGic_Enable(GicInstancePtr, AXI_GpioIntrId);
		
		//Priority   0 8 16 32... 248,数值越小优先级越高
		//Trigger    触发类型,看手册
		XScuGic_SetPriorityTriggerType(XScuGic *InstancePtr, u32 Int_Id,
					u8 Priority, u8 Trigger)
		
		//把AXI的中断打开分两步:打开全局中断、打开通道中断
		//打开全局中断
		XGpio_InterruptGlobalEnable(AXI_Gpio);
		//打开通道中断,一个通道32位
		//Mask    0:关闭中断    1:打开中断
		XGpio_InterruptEnable(AXI_Gpio, u32 Mask);		

	}
//中断服务函数
	IntrHandler(){
		//关闭通道中断使能
		XGpio_InterruptDisable(&AXI_Gpio, u32 Mask);
		//中断触发后做出的响应
		XXXXXXXXXX;
        key=1;
	}

AXI IO 自定义IP核

slv_reg0、1、2、3寄存器存储信号的数据,可以写可以读

从sdk写数据到slv_reg,slv_reg在ip核的verilog代码模板里连接这自己的逻辑功能模块的输入

在AXI接口的ip核模板里添加自己的逻辑代码,注意自己逻辑代码的parameter和引出的信号

MYSELF_IP_mWriteReg,MYSELF_IP_mReadReg这两个函数控制slv_reg的值,函数里的BaseAddress参数需要去 **_bsp - include -  xparameter.h找到自己的ip核基地址

#include "myself_ip.h"
#include "xparameters.h"//  函数中用到的ip核基地址存在这里
#include "xil_io.h"// write read需要这个头文件
#include "stdio.h"
#include "sleep.h"
// 寄存器地址偏移存在myself_ip.h
#define SLV_REG0_OFFSET	MYSELF_IP_S00_AXI_SLV_REG0_OFFSET
#define SLV_REG1_OFFSET	MYSELF_IP_S00_AXI_SLV_REG1_OFFSET
// ip核基地址存在xparameters.h
#define BaseAddress		XPAR_MYSELF_IP_0_S00_AXI_BASEADDR
int main(){
	printf("myip_open\n\r");
	int led_status=0;
    
    //ip核verilog的逻辑是ctrl2=100 led亮
	//MYSELF_IP_mWriteReg(BaseAddress, SLV_REG1_OFFSET, 0x00000064);//100

    //下面是使用write read
	while(1){

		led_status=MYSELF_IP_mReadReg(BaseAddress, SLV_REG0_OFFSET);
		printf("%d\n\r",led_status);
		if(led_status==0){
		MYSELF_IP_mWriteReg(BaseAddress, SLV_REG0_OFFSET, 0x00000001);
		printf("on\n\r");

		led_status=MYSELF_IP_mReadReg(BaseAddress, SLV_REG0_OFFSET);
		printf("%d\n\r",led_status);

		sleep(2);
		MYSELF_IP_mWriteReg(BaseAddress, SLV_REG0_OFFSET, 0x00000000);
		printf("off\n\r");

		led_status=MYSELF_IP_mReadReg(BaseAddress, SLV_REG0_OFFSET);
		printf("%d\n\r",led_status);

		sleep(2);
		}

	}
	return 0;
}

ddr3没写入数据之前,里面的数据是随机值

DMA

PL到DDR之间的数据传输,所以一般表示方向就有了 MM2S和 S2MM

MM2S:从地址映射的内存到 数据流接口,具体说从 DDR搬运数据到 PL。 

S2MM:从数据流接口到地址映射的内存接口,具体说从 PL搬运数据到 DDR。 

### 关于Zynq学习资料与教程 Zynq是一款由Xilinx推出的集成了ARM处理器和可编程逻辑的SoC器件,其核心特性在于能够通过硬件加速的方式实现高性能计算。因此,在学习Zynq的过程中,不仅需要掌握FPGA的基础知识,还需要了解ARM处理器及其软件开发环境。 #### 1. **基础知识** 为了更好地理解Zynq的工作原理以及如何进行开发,可以从以下几个方面入手: - **FPGA基础** FPGA是一种现场可编程门阵列,允许用户通过配置文件来定义电路的功能。学习FPGA的核心概念包括但不限于:组合逻辑、时序逻辑、状态机设计等[^2]。 - **Verilog/VHDL语言** Verilog和VHDL是两种主流的硬件描述语言,用于编写FPGA的设计代码。初学者可以选择其中一种进行深入学习。通常情况下,Verilog因其语法简洁而更受青睐[^4]。 - **ARM Cortex-A9架构** Zynq中的PS(Processing System)部分基于双核ARM Cortex-A9处理器。熟悉该架构有助于理解和优化运行在Zynq上的嵌入式Linux或其他实时操作系统的行为。 #### 2. **推荐学习路径** 以下是针对Zynq学习的一条清晰路径: - **官方文档与工具链** Xilinx提供了丰富的官方文档和技术支持,其中包括《Zynq-7000 All Programmable SoC Technical Reference Manual》等一系列权威参考资料。同时,Vivado Design Suite作为主要IDE,包含了从RTL综合到比特流生成的所有功能[^3]。 - **在线课程与视频教程** 可以参考一些高质量的教学视频,例如B站上的“【第一期】手把手教你学领航者&启明星ZYNQ之FPGA开发篇”,它详细讲解了从零开始搭建开发环境直至完成简单项目的全过程[^1]。 - **实践项目驱动法** 结合实际案例动手操作是非常有效的学习方式之一。比如尝试构建一个简单的LED闪烁程序或者图像处理流水线,这不仅能巩固理论知识还能积累实战经验。 #### 3. **具体资源链接** 下面列举了一些具体的公开可用资源供参考: - 黑金zynq7020资料库涵盖了大量关于此型号芯片的技术文章及实例工程下载地址[^2]; - Vivado HLS (High-Level Synthesis) 用户指南可以帮助程序员利用高级抽象层快速生成高效硬件模块[^3]; ```bash # 下载并安装最新版Vivado wget https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vivado-design-tools/archive.html sudo dpkg -i vivado_<version>_linux.deb ``` 以上命令展示了获取Vivado安装包的方法,并指导如何将其部署至本地系统中以便开展进一步工作。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值