打印

FPGA NIOS的PIO核使用原理(以驱动LED灯为例)

[复制链接]
3381|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
固桐|  楼主 | 2013-5-28 09:56 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一、PIO核概述

PIO核是具有Avalon总线接口的并行输入/输出(parallel input/output,即PIO)核,在Avalon存储器映射( Avalon Memory-Mapped,即 Avalon-MM)从端口和通用I/O端口之间提供了一个存储器映射接口,I/O端口既可以连接到片上用户逻辑,也可以连接到连接外设到FPGA的IO引脚。PIO核是SOPC Builder内部集成的模块,易于集成到由SOPC Builder
创建的任何系统中。
二、功能描述
每个PIO核可以提供最多32个I/O端口。像微处理器这样的智能主机通过读/写寄存器映射的Avalon-M M接口控制PIO端口。在主机控制下,PIO核捕获输入端口的数据,并驱动数据到输出端口。当PIO端口直接与I/O引脚相连时,主机通过写PIO核中的控制寄存器对I/O引脚进行三态控制。
三、寄存器描述与中断
Avalon-MM的主外设(例如CPU)通过4个32位寄存器控制并与PIO通信,表1-1假设PIO核的I/O端口被配置为n位宽度,
Ø  数据寄存器
读从Data(数据)寄存器返回的呈现在输入端口的值。如果PIO核硬件被配置为output-only(只输出)模式,读Data寄存器将返回一个未定义的值。
写Data寄存器将存储值到寄存器中以驱动输出端口。如果PIO核硬件被配置为input-only(只输入)模式,写Data寄存器无影响。如果PIO核硬件被配置为双向模式,则仅当在  Direction(方向)寄存器中相应的位被置1(输出)时,被寄存的值才会出现在输出端口上。
Ø  方向寄存器
Direction(方向)寄存器控制每个PIO端口的数据方向,假定端口是双向的,当位n在方向寄存器中被置1时,端口n在Dat寄存器的相应位驱动输出值。
仅当PIO核硬件被配置为双向模式时,Direction寄存器才存在。模式(输入、输出或双向)在系统创建时指定,并且在运行时不能修改。在输入或输出模式中,Direction寄存器不存在,在这种情况下,读Direction返回一个未定义的值,写Direction无影响。
在复位后,方向寄存器的所有位都是0,所以所有双向I/O端口都被配置为输入。如果那些PIO端口被连接到FPGA器件的引脚,则这些引脚保持高阻状态。在双向模式,为了改变PIO端口的方向,要重新编程Direction寄存器。
Ø  中断屏蔽寄存器
设置Interruptmask(中断屏蔽)寄存器中的位为1允许相应PIO输入端口中断。中断行为取决于PIO核的硬件配置。详见“中断行为”。
Interruptmask寄存器仅当硬件被配置为能产生IRQ时才存在。如果PIO核不能产生IRQ,读Interruptmask返回一个未定义的值,写Interruptmask无影响。
在复位后,所有Interruptmask寄存器的位都是0,所以所有的PIO端口中断都被禁用。
Ø  边沿捕获寄存器
如果Edgecapture(边沿捕获)寄存器中的位n被设置位1,在输入端口n上的边沿将会被探测到。Avalon-MM主外设能够读Edgecapture寄存器以确定是否有一个边沿出现在任何PIO输入端口。写任何值到Edgecapture将清除寄存器中的所有位。
要探测的边沿的类型在系统创建时就已经选定在硬件中。Edgecapture寄存器只能在硬件被配置位捕获边沿时存在。如果PIO核没有被配置成捕获边沿,读Edgecapture将返回一个未定义的值,写Edgecapture无影响。
Ø  输出置位和输出清零寄存器
可以使用输出置位和输出清零(Outset和Outclear)寄存器置1或清0指定的输出端口的位。例如,要设置输出端口的第六位,可以写0x40(0100 0000)到outset寄存器。写0x08(0000 1000)到Outclear寄存器可清0输出端口的第3位。
这两个寄存器只有在选择Enable individual bit set/clearoutput register寄存器为开启时才可用。
Ø中断行为
PIO核输出一个能够连接到任意在系统中的主外设的单个IRQ信号。主外设既能够读Data寄存器,也能够用Edgecapture寄存器来确定哪一个输入端口引发出了中断。
当硬件被配置为电平敏感中断时,当Data和Interruptmask寄存器中相应的位是1时,IRQ被确定。当硬件被配置为边沿敏感中断时,当Edgecapture和Interruptmask寄存器中相应的位是1时,IRQ被确定。IRQ保持确定直到禁用Interruptmask中相应的位或者写Edgecapture相应的位以明确地确认为止。
四、输入输出
PIO核的I/O端口既可以连接片上逻辑,也可以连接片外逻辑,PIO核可以配置为输入、输出或双向。若用来控制双向I/O引脚,则PIO核提供具有三态控制的双向模式。

读和写数据寄存器的硬件逻辑是独立的。读数据寄存器返回当前输入端口的值;写数据寄存器影响驱动输出端口的值。由于这些端口是独立的,因此读数据寄存器并不返回上次写入的数据。
对于Nios II处理器的用户,Altera提供了定义PIO核寄存器的HAL系统库头文件。与PIO核相关的软件文件是altera_avalon_pio_regs.h(在安装路径里可以找到),该文件定义了PIO
核的寄存器映射,提供符号常量来访问底层硬件,应用程序开发者不要修改这些文件。

五、程序实例
1、使用库函数
//-----------------Include files-------------------------//
#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "stdio.h"
#include "unistd.h"
//-----------------Function------------------------------//

int main (void)
{
        while (1)
        {

        IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, 1);//led 亮
        usleep(500000);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_LED_BASE, 0);//led 灭
         usleep(500000);

}

}


2、使用寄存器驱动LED灯
#include"system.h"
//----------------- Typedef------------------------------//
typedef struct
{
   volatile unsigned long int DATA;
   volatile unsigned long int DIRECTION;
   volatile unsigned long int INTERRUPT_MASK;
   volatile unsigned long int EDGE_CAPTURE;
   volatile unsigned long int OUTSET;
   volatile unsigned long int OUTCLEAR;
  }PIO_T;

#define LED ((PIO_T *)(PIO_LED_BASE|1<<31))
int main()
{

  while(1)
  {
       LED->DATA = 1;
           usleep(500000);
       LED->DATA = 0;
       usleep(500000);
    }

  return 0;
}
(PIO_LED_BASE | 1 << 31)”是将PIO基地址的最高位置1(因为Nios内核选用f(快速)型,这时需要将最高位置1来旁路掉缓存,从而直接与外设通讯),并通过”(PIO_T*)“将其强制转换为一个PIO_T指针,再用宏定义让标示符LED代替PIO_T指针,接下来直接使用“LED->DATA=1”语句使LED亮,用“LED->DATA=0”语句使其灭。





相关帖子

沙发
GoldSunMonkey| | 2013-5-28 23:23 | 只看该作者
期待

使用特权

评论回复
板凳
LMQQ| | 2013-5-29 23:37 | 只看该作者
期待啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

15

帖子

1

粉丝