Avalon®-MM主机外设(如CPU)通过四个32位寄存器控制并与PIO核通信,如下所示。该表假设PIO核的I/O端口被配置为n位宽度。
以上截图来自
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四个不同的寄存器。