一、PIO寄存器介绍

Avalon®-MM主机外设(如CPU)通过四个32位寄存器控制并与PIO核通信,如下所示。该表假设PIO核的I/O端口被配置为n位宽度。

image-20240712145028146

以上截图来自Intel Embedded Peripherals IP User Guide

data寄存器

如果将PIO硬件配置为输入或仅输入输出模式,则从数据读取将返回输入端口上存在的值。如果PIO Core硬件配置为仅输出模式,则从数据寄存器读取将返回输出端口上的值。而如果将PIO Core硬件配置为双向模式,则从数据寄存器中读取将返回取决于方向寄存器值的值,设置为1将返回输出端口上存在的值,设置为0将返回未定义的值。

写入数据会将值存储到驱动输出端口的寄存器中。如果PIO核心硬件配置为仅输入模式,则写入数据无效。如果PIO内核硬件处于双向模式,则仅当方向寄存器中的相应位设置为1(输出)时,寄存器值才会出现在输出端口上。

direction寄存器

假设端口是双向的,则方向寄存器控制每个PIO端口的数据方向。当方向上的位n设置为1时,端口n驱动数据寄存器相应位中的值。

仅当将PIO硬件配置为双向模式时,方向(direction)寄存器才存在。在仅输入,仅输出和输入输出模式下,方向寄存器不存在。在这种情况下,读取方向返回未定义的值,写入方向无效。模式(输入,输出,输入输出或双向)在系统生成时指定,并且无法在运行时更改。

复位后,所有方向寄存器位均为0,因此所有双向I / O端口均配置为输入。如果这些PIO端口连接到设备引脚,则引脚将保持高阻抗状态。在双向模式下,您将需要写入方向寄存器以更改PIO端口(0输入,1输出)的方向。

interruptmask寄存器

将中断屏蔽寄存器中的某个位置1,可以启用相应PIO输入端口的中断。中断行为取决于PIO内核的硬件配置。

仅当硬件配置为生成IRQ时,中断屏蔽寄存器才存在。如果内核无法生成IRQ,则读取中断屏蔽将返回未定义的值,而写入中断屏蔽则无效。

复位后,中断屏蔽的所有位均为零,因此所有PIO端口的中断均被禁用。

edgecapture寄存器

每当在输入端口n上检测到边沿时,边沿捕获寄存器中的位n就会设置为1。Avalon-MM主外设可以读取边缘捕获寄存器,以确定是否在任何PIO输入端口上发生了边缘。如果边缘捕捉寄存器位已预先设置,则in_port切换活动将不会更改值。

如果关闭了为边缘捕获寄存器启用位清除选项,则将任何值写入边缘捕获寄存器都将清除寄存器中的所有位。否则,向寄存器中的特定位写入1只会清除该位。

在Platform Designer中生成IP的过程中指定了要检测的边缘类型。仅当硬件配置为捕获边缘时,edgecapture寄存器才存在。如果未将内核配置为捕获边缘,则从edgecapture读取将返回未定义的值,并且写入edgecapture无效。

中断行为

PIO内核输出单个IRQ信号,该信号可以连接到系统中的任何主外围设备。主机可以读取数据寄存器或边缘捕获寄存器,以确定哪个输入端口引起了中断。

当硬件配置为电平敏感中断时,只要数据和中断屏蔽寄存器中的相应位为1,就确定IRQ。当硬件配置为边缘敏感中断时,只要边缘捕获和中断掩码中的相应位为IRQ,就置位。寄存器为1。IRQ一直保持有效,直到通过禁用中断屏蔽中的相应位或写入边沿捕获来明确确认为止。

 

注:截图中还有第4和第5两个寄存器没有截图出来,原因是目前PIO的这两个寄存器是预留的,暂没有启用。

 

二、读写PIO寄存器

参考intelFPGA\22.1std\ip\altera\sopc_builder_ip\altera_avalon_pio\inc\altera_avalon_pio_regs.h获取PIO寄存器读写宏定义函数。

读写寄存器0(data寄存器)

#define IORD_ALTERA_AVALON_PIO_DATA(base)             IORD(base, 0) //读寄存器0
#define IOWR_ALTERA_AVALON_PIO_DATA(base, data)       IOWR(base, 0, data)//写寄存器0

读写寄存器1(direction寄存器)

#define IORD_ALTERA_AVALON_PIO_DIRECTION(base)        IORD(base, 1) //读寄存器1
#define IOWR_ALTERA_AVALON_PIO_DIRECTION(base, data)  IOWR(base, 1, data)//写寄存器1

读写寄存器2(interruptmask寄存器)

#define IORD_ALTERA_AVALON_PIO_IRQ_MASK(base)         IORD(base, 2) //读寄存器2
#define IOWR_ALTERA_AVALON_PIO_IRQ_MASK(base, data)   IOWR(base, 2, data)//写寄存器2

 

读写寄存器3(edgecapture寄存器)

#define IORD_ALTERA_AVALON_PIO_EDGE_CAP(base)         IORD(base, 3) //读寄存器3
#define IOWR_ALTERA_AVALON_PIO_EDGE_CAP(base, data)   IOWR(base, 3, data)//写寄存器3

 

所以可以直接调用可以直接调用函数IOWR(base, offset, data)和IORD(base, offset)来读写这4个寄存器。

应用举例:

#define KEY_BASE 0x50050//外设基地址定义
IOWD(LED_BASE, 3);//读取寄存器3的值
IOWR(KEY_BASE, 3, 0x00);//将0x00写入到3寄存器

 

其中,base是要访问的IO口的基地址,data是要写入的数据。offset取值是0、1、2、3,代表PIO四个不同的寄存器。