HTTP/1.1 404 Object Not Found Server: Microsoft-IIS/5.0 Date: Fri, 21 Nov 2008 20:06:52 GMT X-Powered-By: ASP.NET Connection: close Content-Type: text/html

404 Object Not Found

Calendar
if (chkdiv('calendar')) {document.getElementById('calendar').innerHTML='
<<  < 2008 - >  >>
12
3456789
10111213141516
17181920212223
24252627282930
';}
Placard
if (chkdiv('placard')) {document.getElementById('placard').innerHTML='欢迎来到我的机器视觉博客,机器视觉是我的研究方向之一,与其说是研究之一,不如说是爱好之一;希望各界的的朋友来交流讨论,我相信在这里能找到我们的交点;同时,我也相信在不久的将来,机器视觉将被我们中国人所改写.....让我们行动起来...为中国的视觉...为中国的腾飞...';}
Category
Latest Entries
Latest Comments
Last Messages
if (chkdiv('newmessage')) {document.getElementById('newmessage').innerHTML='\n';}
User Login
Links
HTTP/1.1 404 Object Not Found Server: Microsoft-IIS/5.0 Date: Fri, 21 Nov 2008 20:06:54 GMT X-Powered-By: ASP.NET Connection: close Content-Type: text/html

404 Object Not Found

Information
if (chkdiv('info')) {document.getElementById('info').innerHTML='
  • 日志:63
  • \n
  • 评论:15
\n
  • 留言:-7
  • \n
  • 访问:
\n';}
Search
Other
Welcome to my blog!
  NiosII Step By Step (4)--PIO
 

--本篇由Mr_Don版主撰写
   
俗话说柿子拣软的捏: )。我也抖胆放一篇NiosII Step by Step,给大家讲讲PIO。这只是我个人的理解,如果写得有什么问题或不足,欢迎大家跟帖指正交流。

PIOParallel Input/Output)是SOPCBuilder里面一个最常用的IP之一,而且相对简单,容易上手使用。个人感觉PIO可类比于单片机的GPIO管脚,用于用户自己定义的外设操作。一般来说,我们在SOPC系统中用PIO主要是因为方便,因为FPGA的管脚越来越多,内部逻辑资源越来越多,所以设计时几乎不用担心管脚的数目或者逻辑资源是否不够;相比之下单片机的GPIO可能会让用户感到数目不够,有时不够方便。所以在SOPC系统我们可以同时用很多使用PIO接口的设备。大体来说,这些设备主要分输入和输出两类:

输入类:按钮,自定义键盘等
输出类:LEDLCD定义接口连线等
标准件:如pwm步进电机等

如上图所示,在Nios/NiosII系统中,PIO接口IP可用于输入、输出、以及双向口三种类型。另外,SOPCBuilder中的PIO还支持中断检测。不过中断检测及处理只在其作为输入设备时可用。如果是用PIO连接一个输出设备(例如LED),则系统自动禁止中断。

这里只举一个button_pio4位)作为输入接口的例子,如下图:

可以看到,作为输入接口时,另外两个标签项也可选,先看看第二个标签项(作输出接口时另外两个标签选项是自动禁止的):

Edge Capture Register
下面的三个选项是指捕获输入动作时是检测哪一种,用户可以选择只检测上升沿(Rising Edge),这样PIO内部的Edge Capture Register只在有上升沿动作时接收数据。同样道理,另外的两个选项一看便知。对于Button,我们一般倾向于选双向沿均可监测到数据变化。
下面的Interrupt选项是指用户选择以什么方式作为中断的输入,一种是电平变化产生中断,一种是沿的变化产生中断。第一种方式只有在输入由低电平变化为高电平时才有效(不过用户可以根据需要,在做好的Nios模块外面的相应管脚上加上非门,使之由高电平变电平时生效);第二种方式只有当Edge Capture Register位是1(高电平)时才有用。

再来看一看第三个标签下面的东东:

这个标签下面的东西是用于仿真的。例如如果我们在测试输入设备时想给他一个激励,这里我用的是0x0001。什么意思呢?即表示最低位的button位为高电平1。如果我用的激励数据是0x0003,这又是什么意思呢?聪明的你一定会发现这表示激励使低两位的button位为1,呵呵。

下面我们来分析一个SOPCBuilder生成的HDL文件:
module led_pio (
                 // inputs:
                  address,
                  chipselect,
                  clk,
                  reset_n,
                  write_n,
                  writedata,

                 // outputs:
                  out_port
               );

  output  [  3: 0] out_port;
  input   [  1: 0] address;
  input            chipselect;
  input            clk;
  input            reset_n;
  input            write_n;
  input   [  3: 0] writedata;

  wire             clk_en;
  reg     [  3: 0] data_out;
  wire    [  3: 0] out_port;
  assign clk_en = 1;
  //s1, which is an e_avalon_slave
  always @(posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
          data_out <= 0;
      else if (chipselect && ~write_n && (address = = 0))
          data_out <= writedata[3 : 0];
end

  assign out_port = data_out;
endmodule

你一定立刻注意到这段描述的输入端口怎么有点似曾相识?没错,avalon总线的要求就是这样!回忆一下在SOPCBuilder下加入用户自定义逻辑的要求是不是必须得有这几个端口?呵呵。上面的代码并不难看懂,大家可以看到led_pio是如何被avalon总线驱动的。

关于PIO的软件编程,NiosIIIDE的样板工程里有很多程序可以参考,这里我就不赘述了,只是还想捎带介绍一下altera_avalon_pio_regs.h和另外一个细节。

这个头文件比较奇怪,它和其它设备的驱动文件独立开来,专门控制PIO设备。所以一定要记住在你对PIO外设进行编程时一定要包含这个头文件,否则会出错。

include <io.h>

#define IOADDR_ALTERA_AVALON_PIO_DATA(base)           __IO_CALC_ADDRESS_NATIVE(base, 0)
#define IORD_ALTERA_AVALON_PIO_DATA(base)           IORD(base, 0) 
#define IOWR_ALTERA_AVALON_PIO_DATA(base, data)    IOWR(base, 0, data)

#define IOADDR_ALTERA_AVALON_PIO_DIRECTION(base)      __IO_CALC_ADDRESS_NATIVE(base, 1)
#define IORD_ALTERA_AVALON_PIO_DIRECTION(base)        IORD(base, 1) 
#define IOWR_ALTERA_AVALON_PIO_DIRECTION(base, data) IOWR(base, 1, data)

#define IOADDR_ALTERA_AVALON_PIO_IRQ_MASK(base)       __IO_CALC_ADDRESS_NATIVE(base, 2)
#define IORD_ALTERA_AVALON_PIO_IRQ_MASK(base)         IORD(base, 2) 
#define IOWR_ALTERA_AVALON_PIO_IRQ_MASK(base, data) IOWR(base, 2, data)

#define IOADDR_ALTERA_AVALON_PIO_EDGE_CAP(base)       __IO_CALC_ADDRESS_NATIVE(base, 3)
#define IORD_ALTERA_AVALON_PIO_EDGE_CAP(base)         IORD(base, 3) 
#define IOWR_ALTERA_AVALON_PIO_EDGE_CAP(base, data) IOWR(base, 3, data)
 
可以看出,这里主要有DATADIRECTIONIRQ_MASKEDGE_CAP几个寄存器或位的宏定义,而你可以从SOPCBuilder生成的文件中找到相对应的硬件定义。这也说明了PIO实际上主要是由以上几个寄存器控制工作。因此,软件中只要对相应的寄存器针对基地址进行操作写入数据就可以了。

再来看看另一个值得注意的细节。我们可以从样板工程里发现类似于这样的语句:

volatile int edge_capture_button;
#ifdef BUTTON_PIO_BASE
void handle_button_interrupts(void* context, alt_u32 id)
{
  volatile int* edge_capture_ptr = (volatile int*) context;
  *edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);
  IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0);
}

void init_button_pio()
{
  void* edge_capture_ptr = (void*) &edge_capture_button;
  IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE, 0xf);
  IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE, 0x0);
  alt_irq_register( BUTTON_PIO_IRQ, edge_capture_ptr, handle_button_interrupts ); 
}
#endif

第一个函数是中断处理,这里暂不介绍。第二个函数是button的初始化函数。我们可以看到主要是三个步骤:将IRQ_MASK置为1(因为这个寄存器位在相应的硬件文件里要取and操作),EDGE_CAP则置为0,因为此时并没有输入设备的沿状态发生变化,因此表示按钮尚未按下;第三步则是中断注册,只要按照软件开发手册上说的去做就好了,不用在乎细节也是可以的,只要注册完毕,你的PIO外设就可以接收外部的输入啦,然后Nios会自动跳到相应的处理程序。

[ 阅读全文 | 回复(0) | 引用通告 | 编辑

  Post  by  jearome 发表于 2006-9-6 12:24:00
HTTP/1.1 404 Object Not Found Server: Microsoft-IIS/5.0 Date: Fri, 21 Nov 2008 20:06:54 GMT X-Powered-By: ASP.NET Connection: close Content-Type: text/html

404 Object Not Found

发表评论:

    昵称:
    密码: (游客无须输入密码)
    主页:
    标题:
if (chkdiv('blogname')) {document.getElementById('blogname').innerHTML='机器视觉之旅';}
HTTP/1.1 404 Object Not Found Server: Microsoft-IIS/5.0 Date: Fri, 21 Nov 2008 20:06:54 GMT X-Powered-By: ASP.NET Connection: close Content-Type: text/html

404 Object Not Found

Powered by Oblog.