ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变

ARM已经在国内流行得一塌糊涂,各类教程、开发板(S3C2440,6410)层出不穷,归结下来,传统ARM开发包括以下几个步骤:

(1)硬件电路板设计(对于Zedboard,相当于设计逻辑电路,PL工程师负责);

(2)基本模块裸机代码测试(UART,DDR2,其他外设);

(3)移植操作系统(如Linux,uCLinux,uCOS等);

(4)编写相应操作系统的驱动程序(可从(2)中移植过来);

(5)编写应用程序(或移植已有的应用程序)、界面设计(Qt);

一个有ARM开发经验的工程师,接触Zynq时很容易陷入误区:到底哪一部分需要由逻辑完成,哪一部分由ARM完成?Zynq资料庞杂,怎样进行有效的学习?

从前面基本介绍我们知道,Zynq内部PS就是ARM工程师的战场,调试代码都是基于PS进行,如果出现问题(硬件问题、驱动问题、软件版本问题)如何定位是一项非常耗时的任务,尤其加入了逻辑设计之后,调试难度大大增加了。所以在一颗芯片中集成了ARM和FPGA虽然提高了性能,但也带来任务划分不明确,调试复杂等新问题。Zynq官方例程的网址为http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_2/ug873-zynq-ctt.pdf,步骤较多,让人分不清到底是在做软件设计还是硬件开发。

本节在参考了上面例程的基础上,进一步做了几个小例子来说明Zynq其实可以和普通ARM开发一样简单易学。将ARM设计与逻辑设计完全解耦,有利于我们加深对zynq内部结构的理解。

ARM工程师开发Zynq用到的软件环境主要有:

PlanAhead+XPS:建立硬件工程,相当于在一个万用板上自己搭建一个单片机最小系统,我们需要将单片机的IO口连接不同的外设(LED,按键,液晶屏,串口等);

SDK:建立软件工程,编写基本模块程序;建立Bootloader工程;

arm-xilinx-linux-gnueabi-gcc:交叉编译工具,编写基于Linux的应用程序和驱动程序;

 

几乎所有ARM工程师都是从单片机开始学习,而且第一个实验一般都是流水灯实验。ZedBoard上既然有一个ARM芯片,有8个LED,能不能用ARM点亮它们,并实现流水灯效果呢?我们来试试吧!

 

笔者安装软件为ISE14.5,其他版本操作类似。

(1)硬件电路板设计 

首先,运行PlanAhead软件(安装完成后,一般在桌面上会有快捷方式)。

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第1张图片

单击“Create New Project ”,新建工程,为了方便叙述,连续点6次“Next”,直到出现下图:

 

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第2张图片

左上框中选择“board”,在下面框中找到ZedBoard并选中,点Next,一直到Finish,结束。

在主面板左侧,点“Add Source”,添加一个嵌入式模块(这就是ARM核),选择如图所示。

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第3张图片

Next,点“Create Sub-Design”

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第4张图片

随便起个名吧,保留默认,OK,Finish。这个步骤主要功能是添加我们的ARM核心到万用板上,但是还没有连线。

 

这时PlanAhead会自动调用XPS,在XPS中,当有提问是否用BSB建立基本系统时,选“是”。OK,Next,出现下图:

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第5张图片

把原先右侧的所有硬件都Remove掉,因为我们需要自己连线。点Finish。

看到了一个彩色的庞大系统,如下图所示。

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第6张图片

主窗口显示的就是Zynq内部结构图,主窗口上面有四个标签,“Zynq”表示图形化显示,“Bus Interface”表示总线连接,“Ports”表示芯片外部IO连接,“Address”表示Zynq系统的地址映射。主窗口下有3个标签,有设计总结报告、系统组成显示、图形设计显示。默认用系统组成显示,另外两种可以在设计完成后观察。

 

我们点击Zynq系统组成框图中左上侧绿色的"I/O Peripherals“框,弹出IO口外设配置选项,展开最下侧的GPIO(点加号),勾上EMIO,并设置IO数目为8,如下图所示:

 

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第7张图片

 

 点关闭,然后从主窗口上面标签的Zynq标签切换到Ports标签,展开processing_system7_0(点加号),找到GPIO_0,将它设置为连接到外部引脚,如图所示。

什么是EMIO?什么是MIO?这是Zynq里面比较独特的特性。MIO就是ARM自己的手脚,完全由自己支配;而EMIO,则是FPGA的手脚,如果不做任何处理,ARM说什么对它们根本不起作用。Zynq有一种机制,可以通过布线,将一部分FPGA手脚连接到ARM上,接受ARM指挥,这样就可以方便地扩展ARM的IO口,使ARM也像FPGA那样,任意设置外部引脚,非常灵活。这个实验中,我们用了8个FPGA引脚接受ARM控制,上面操作已经设置完毕了。

 

接下来,需要检查硬件是否有错误。点击菜单Project->Design Rule Check,如果在XPS Console窗口中输出如下内容,表示没有错误:

Running system level update procedures...
Running UPDATE Tcl procedures for OPTION SYSLEVEL_UPDATE_PROC...
Running system level DRCs...
Performing System level DRCs on properties...
Running DRC Tcl procedures for OPTION SYSLEVEL_DRC_PROC...
Done!


 

这时彻底关闭XPS,回到PlanAhead中。在Project Manager的Source窗口中,找到module_1.xmp,单击右键,选择Create Top HDL,如下图所示:

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第8张图片

这时生成了顶层HDL模块,名称为module_1_stub.v,打开这个文件,内容如下:

//-----------------------------------------------------------------------------
// module_1_stub.v
//-----------------------------------------------------------------------------

module module_1_stub
  (
    processing_system7_0_MIO,
    processing_system7_0_PS_SRSTB,
    processing_system7_0_PS_CLK,
    processing_system7_0_PS_PORB,
    processing_system7_0_DDR_Clk,
    processing_system7_0_DDR_Clk_n,
    processing_system7_0_DDR_CKE,
    processing_system7_0_DDR_CS_n,
    processing_system7_0_DDR_RAS_n,
    processing_system7_0_DDR_CAS_n,
    processing_system7_0_DDR_WEB_pin,
    processing_system7_0_DDR_BankAddr,
    processing_system7_0_DDR_Addr,
    processing_system7_0_DDR_ODT,
    processing_system7_0_DDR_DRSTB,
    processing_system7_0_DDR_DQ,
    processing_system7_0_DDR_DM,
    processing_system7_0_DDR_DQS,
    processing_system7_0_DDR_DQS_n,
    processing_system7_0_DDR_VRN,
    processing_system7_0_DDR_VRP,
    processing_system7_0_GPIO_pin
  );
  inout [53:0] processing_system7_0_MIO;
  input processing_system7_0_PS_SRSTB;
  input processing_system7_0_PS_CLK;
  input processing_system7_0_PS_PORB;
  inout processing_system7_0_DDR_Clk;
  inout processing_system7_0_DDR_Clk_n;
  inout processing_system7_0_DDR_CKE;
  inout processing_system7_0_DDR_CS_n;
  inout processing_system7_0_DDR_RAS_n;
  inout processing_system7_0_DDR_CAS_n;
  output processing_system7_0_DDR_WEB_pin;
  inout [2:0] processing_system7_0_DDR_BankAddr;
  inout [14:0] processing_system7_0_DDR_Addr;
  inout processing_system7_0_DDR_ODT;
  inout processing_system7_0_DDR_DRSTB;
  inout [31:0] processing_system7_0_DDR_DQ;
  inout [3:0] processing_system7_0_DDR_DM;
  inout [3:0] processing_system7_0_DDR_DQS;
  inout [3:0] processing_system7_0_DDR_DQS_n;
  inout processing_system7_0_DDR_VRN;
  inout processing_system7_0_DDR_VRP;
  inout [7:0] processing_system7_0_GPIO_pin;

  (* BOX_TYPE = "user_black_box" *)
  module_1
    module_1_i (
      .processing_system7_0_MIO ( processing_system7_0_MIO ),
      .processing_system7_0_PS_SRSTB ( processing_system7_0_PS_SRSTB ),
      .processing_system7_0_PS_CLK ( processing_system7_0_PS_CLK ),
      .processing_system7_0_PS_PORB ( processing_system7_0_PS_PORB ),
      .processing_system7_0_DDR_Clk ( processing_system7_0_DDR_Clk ),
      .processing_system7_0_DDR_Clk_n ( processing_system7_0_DDR_Clk_n ),
      .processing_system7_0_DDR_CKE ( processing_system7_0_DDR_CKE ),
      .processing_system7_0_DDR_CS_n ( processing_system7_0_DDR_CS_n ),
      .processing_system7_0_DDR_RAS_n ( processing_system7_0_DDR_RAS_n ),
      .processing_system7_0_DDR_CAS_n ( processing_system7_0_DDR_CAS_n ),
      .processing_system7_0_DDR_WEB_pin ( processing_system7_0_DDR_WEB_pin ),
      .processing_system7_0_DDR_BankAddr ( processing_system7_0_DDR_BankAddr ),
      .processing_system7_0_DDR_Addr ( processing_system7_0_DDR_Addr ),
      .processing_system7_0_DDR_ODT ( processing_system7_0_DDR_ODT ),
      .processing_system7_0_DDR_DRSTB ( processing_system7_0_DDR_DRSTB ),
      .processing_system7_0_DDR_DQ ( processing_system7_0_DDR_DQ ),
      .processing_system7_0_DDR_DM ( processing_system7_0_DDR_DM ),
      .processing_system7_0_DDR_DQS ( processing_system7_0_DDR_DQS ),
      .processing_system7_0_DDR_DQS_n ( processing_system7_0_DDR_DQS_n ),
      .processing_system7_0_DDR_VRN ( processing_system7_0_DDR_VRN ),
      .processing_system7_0_DDR_VRP ( processing_system7_0_DDR_VRP ),
      .processing_system7_0_GPIO_pin ( processing_system7_0_GPIO_pin )
    );

endmodule


可以看到,module_1_stub只是对我们用XPS创建的嵌入式模块module_1用verilog语言进行一层包装,相当于芯片制造业中将晶圆向外引线,做最后的邦定。我们后面会讲,在这一步也可以进行用户逻辑开发。

接着需要添加约束文件(UCF),还是在Project Manager中Add Source,这次类型选第一个“Constraints”,如图所示

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第9张图片

仍然点Create File,名称随便起,我们输入system,最后确认,回到主窗口。这时看到Project Manager中添加了system.ucf

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第10张图片

双击该文件,添加内容如下:

NET "processing_system7_0_DDR_Addr[0]" LOC = M4;
NET "processing_system7_0_DDR_Addr[1]" LOC = M5;
NET "processing_system7_0_DDR_Addr[2]" LOC = K4;
NET "processing_system7_0_DDR_Addr[3]" LOC = L4;
NET "processing_system7_0_DDR_Addr[4]" LOC = K6;
NET "processing_system7_0_DDR_Addr[5]" LOC = K5;
NET "processing_system7_0_DDR_Addr[6]" LOC = J7;
NET "processing_system7_0_DDR_Addr[7]" LOC = J6;
NET "processing_system7_0_DDR_Addr[8]" LOC = J5;
NET "processing_system7_0_DDR_Addr[9]" LOC = H5;
NET "processing_system7_0_DDR_Addr[10]" LOC = J3;
NET "processing_system7_0_DDR_Addr[11]" LOC = G5;
NET "processing_system7_0_DDR_Addr[12]" LOC = H4;
NET "processing_system7_0_DDR_Addr[13]" LOC = F4;
NET "processing_system7_0_DDR_Addr[14]" LOC = G4;
NET "processing_system7_0_DDR_BankAddr[0]" LOC = L7;
NET "processing_system7_0_DDR_BankAddr[1]" LOC = L6;
NET "processing_system7_0_DDR_BankAddr[2]" LOC = M6;
NET "processing_system7_0_DDR_CAS_n" LOC = P3;
NET "processing_system7_0_DDR_CKE" LOC = V3;
NET "processing_system7_0_DDR_CS_n" LOC = P6;
NET "processing_system7_0_DDR_Clk" LOC = N4;
NET "processing_system7_0_DDR_Clk_n" LOC = N5;
NET "processing_system7_0_DDR_DM[0]" LOC = B1;
NET "processing_system7_0_DDR_DM[1]" LOC = H3;
NET "processing_system7_0_DDR_DM[2]" LOC = P1;
NET "processing_system7_0_DDR_DM[3]" LOC = AA2;
NET "processing_system7_0_DDR_DQ[0]" LOC = D1;
NET "processing_system7_0_DDR_DQ[1]" LOC = C3;
NET "processing_system7_0_DDR_DQ[2]" LOC = B2;
NET "processing_system7_0_DDR_DQ[3]" LOC = D3;
NET "processing_system7_0_DDR_DQ[4]" LOC = E3;
NET "processing_system7_0_DDR_DQ[5]" LOC = E1;
NET "processing_system7_0_DDR_DQ[6]" LOC = F2;
NET "processing_system7_0_DDR_DQ[7]" LOC = F1;
NET "processing_system7_0_DDR_DQ[8]" LOC = G2;
NET "processing_system7_0_DDR_DQ[9]" LOC = G1;
NET "processing_system7_0_DDR_DQ[10]" LOC = L1;
NET "processing_system7_0_DDR_DQ[11]" LOC = L2;
NET "processing_system7_0_DDR_DQ[12]" LOC = L3;
NET "processing_system7_0_DDR_DQ[13]" LOC = K1;
NET "processing_system7_0_DDR_DQ[14]" LOC = J1;
NET "processing_system7_0_DDR_DQ[15]" LOC = K3;
NET "processing_system7_0_DDR_DQ[16]" LOC = M1;
NET "processing_system7_0_DDR_DQ[17]" LOC = T3;
NET "processing_system7_0_DDR_DQ[18]" LOC = N3;
NET "processing_system7_0_DDR_DQ[19]" LOC = T1;
NET "processing_system7_0_DDR_DQ[20]" LOC = R3;
NET "processing_system7_0_DDR_DQ[21]" LOC = T2;
NET "processing_system7_0_DDR_DQ[22]" LOC = M2;
NET "processing_system7_0_DDR_DQ[23]" LOC = R1;
NET "processing_system7_0_DDR_DQ[24]" LOC = AA3;
NET "processing_system7_0_DDR_DQ[25]" LOC = U1;
NET "processing_system7_0_DDR_DQ[26]" LOC = AA1;
NET "processing_system7_0_DDR_DQ[27]" LOC = U2;
NET "processing_system7_0_DDR_DQ[28]" LOC = W1;
NET "processing_system7_0_DDR_DQ[29]" LOC = Y3;
NET "processing_system7_0_DDR_DQ[30]" LOC = W3;
NET "processing_system7_0_DDR_DQ[31]" LOC = Y1;
NET "processing_system7_0_DDR_DQS[0]" LOC = C2;
NET "processing_system7_0_DDR_DQS[1]" LOC = H2;
NET "processing_system7_0_DDR_DQS[2]" LOC = N2;
NET "processing_system7_0_DDR_DQS[3]" LOC = V2;
NET "processing_system7_0_DDR_DQS_n[0]" LOC = D2;
NET "processing_system7_0_DDR_DQS_n[1]" LOC = J2;
NET "processing_system7_0_DDR_DQS_n[2]" LOC = P2;
NET "processing_system7_0_DDR_DQS_n[3]" LOC = W2;
NET "processing_system7_0_DDR_DRSTB" LOC = F3;
NET "processing_system7_0_DDR_ODT" LOC = P5;
NET "processing_system7_0_DDR_RAS_n" LOC = R5;
NET "processing_system7_0_DDR_VRN" LOC = M7;
NET "processing_system7_0_DDR_VRP" LOC = N7;
NET "processing_system7_0_DDR_WEB_pin" LOC = R4;
NET "processing_system7_0_MIO[0]" LOC = G6;
NET "processing_system7_0_MIO[1]" LOC = A1;
NET "processing_system7_0_MIO[2]" LOC = A2;
NET "processing_system7_0_MIO[3]" LOC = F6;
NET "processing_system7_0_MIO[4]" LOC = E4;
NET "processing_system7_0_MIO[5]" LOC = A3;
NET "processing_system7_0_MIO[6]" LOC = A4;
NET "processing_system7_0_MIO[7]" LOC = D5;
NET "processing_system7_0_MIO[8]" LOC = E5;
NET "processing_system7_0_MIO[9]" LOC = C4;
NET "processing_system7_0_MIO[10]" LOC = G7;
NET "processing_system7_0_MIO[11]" LOC = B4;
NET "processing_system7_0_MIO[12]" LOC = C5;
NET "processing_system7_0_MIO[13]" LOC = A6;
NET "processing_system7_0_MIO[14]" LOC = B6;
NET "processing_system7_0_MIO[15]" LOC = E6;
NET "processing_system7_0_MIO[16]" LOC = D6;
NET "processing_system7_0_MIO[17]" LOC = E9;
NET "processing_system7_0_MIO[18]" LOC = A7;
NET "processing_system7_0_MIO[19]" LOC = E10;
NET "processing_system7_0_MIO[20]" LOC = A8;
NET "processing_system7_0_MIO[21]" LOC = F11;
NET "processing_system7_0_MIO[22]" LOC = A14;
NET "processing_system7_0_MIO[23]" LOC = E11;
NET "processing_system7_0_MIO[24]" LOC = B7;
NET "processing_system7_0_MIO[25]" LOC = F12;
NET "processing_system7_0_MIO[26]" LOC = A13;
NET "processing_system7_0_MIO[27]" LOC = D7;
NET "processing_system7_0_MIO[28]" LOC = A12;
NET "processing_system7_0_MIO[29]" LOC = E8;
NET "processing_system7_0_MIO[30]" LOC = A11;
NET "processing_system7_0_MIO[31]" LOC = F9;
NET "processing_system7_0_MIO[32]" LOC = C7;
NET "processing_system7_0_MIO[33]" LOC = G13;
NET "processing_system7_0_MIO[34]" LOC = B12;
NET "processing_system7_0_MIO[35]" LOC = F14;
NET "processing_system7_0_MIO[36]" LOC = A9;
NET "processing_system7_0_MIO[37]" LOC = B14;
NET "processing_system7_0_MIO[38]" LOC = F13;
NET "processing_system7_0_MIO[39]" LOC = C13;
NET "processing_system7_0_MIO[40]" LOC = E14;
NET "processing_system7_0_MIO[41]" LOC = C8;
NET "processing_system7_0_MIO[42]" LOC = D8;
NET "processing_system7_0_MIO[43]" LOC = B11;
NET "processing_system7_0_MIO[44]" LOC = E13;
NET "processing_system7_0_MIO[45]" LOC = B9;
NET "processing_system7_0_MIO[46]" LOC = D12;
NET "processing_system7_0_MIO[47]" LOC = B10;
NET "processing_system7_0_MIO[48]" LOC = D11;
NET "processing_system7_0_MIO[49]" LOC = C14;
NET "processing_system7_0_MIO[50]" LOC = D13;
NET "processing_system7_0_MIO[51]" LOC = C10;
NET "processing_system7_0_MIO[52]" LOC = D10;
NET "processing_system7_0_MIO[53]" LOC = C12;
NET "processing_system7_0_GPIO_pin[0]" LOC = T22;
NET "processing_system7_0_GPIO_pin[1]" LOC = T21;
NET "processing_system7_0_GPIO_pin[2]" LOC = U22;
NET "processing_system7_0_GPIO_pin[3]" LOC = U21;
NET "processing_system7_0_GPIO_pin[4]" LOC = V22;
NET "processing_system7_0_GPIO_pin[5]" LOC = W22;
NET "processing_system7_0_GPIO_pin[6]" LOC = U19;
NET "processing_system7_0_GPIO_pin[7]" LOC = U14;
NET "processing_system7_0_GPIO_pin[7]" IOSTANDARD = LVCMOS33;
NET "processing_system7_0_GPIO_pin[6]" IOSTANDARD = LVCMOS33;
NET "processing_system7_0_GPIO_pin[5]" IOSTANDARD = LVCMOS33;
NET "processing_system7_0_GPIO_pin[4]" IOSTANDARD = LVCMOS33;
NET "processing_system7_0_GPIO_pin[3]" IOSTANDARD = LVCMOS33;
NET "processing_system7_0_GPIO_pin[2]" IOSTANDARD = LVCMOS33;
NET "processing_system7_0_GPIO_pin[1]" IOSTANDARD = LVCMOS33;
NET "processing_system7_0_GPIO_pin[0]" IOSTANDARD = LVCMOS33;


如果对引脚的位置不太确定,可以参考我上传的资源:http://download.csdn.net/detail/kkk584520/5901617  里面有ZEDBoard原理图,其中有关LED的引脚如下图所示:

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第11张图片ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第12张图片

 

为了防止生成FPGA比特文件时报错,需要设置一下属性:

点菜单Flow->Bitstream Settings,设置More Options的值为-g UnconstrainedPins:Allow,点OK。

做完上面的内容,接着点击菜单Flow->Generate Bitstream。等大约5分钟(PC配置不同,时间有长有短),直到生成bitstream成功。这样就把FPGA逻辑设计部分工作做完了。

其实实际项目中,上述工作一般都是由逻辑开发工程师完成的,我们这个例子讲得如此详细是为了让ARM工程师对硬件有个较为深入的了解,这样后期调试时会更加得心应手。况且Xilinx把所有软件都集成在了PlanAhead中,ARM工程师不再像以前那样,直接用RealView MDK写代码,而是必须基于刚刚搭建的硬件环境用Xilinx的SDK开发工具完成软件设计。

下面将前面的硬件工程导出到SDK。

点击菜单File->Export->Export Hardware for SDK,弹出对话框,勾上Launch SDK,确认:

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第13张图片

经过一段时间的导出,进入了SDK开发界面,点击菜单File->New->Application Project,如下所示:

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第14张图片

名称随便起一个吧,我们取为led8,下一步,模板选择Hello World,这也是最基础的模板,后面我们大部分应用程序都基于这个模板。

 

打开helloworld.c,代码修改为:

/*
 * Copyright (c) 2009 Xilinx, Inc.  All rights reserved.
 *
 * Xilinx, Inc.
 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
 * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

/*
 * helloworld.c: simple test application
 */

#include 
#include "platform.h"
#define MIO_BASE 0xE000A000

#define DATA1_RO  0x64
#define DATA2		0x48
#define DATA2_RO	0x68
#define DIRM_2		0x284
#define OEN_2		0x288


void print(char *str);
void delay_1s(int i)
{
	int j;
	while(i--)
	{
		j=10000;
		while(j--)
		{
			__asm("NOP");
		}
	}
}
int main()
{
	int i;
    init_platform();
    *((volatile int*)(MIO_BASE+OEN_2)) = 0xff;
    *((volatile int*)(MIO_BASE+DIRM_2)) = 0xff;
    print("Hello world!\r\nThe Leds are flowing...\r\n");
    while(1)
    {
    	for(i = 0;i < 8; i++)
    	{
    		*((volatile int*)(MIO_BASE+DATA2)) = 0x01<


保存,程序会自动编译。如果控制台输出如下表示编译无错误出现。

arm-xilinx-eabi-size led8.elf  |tee "led8.elf.size"
   text	   data	    bss	    dec	    hex	filename
  22304	   1096	  29780	  53180	   cfbc	led8.elf
'Finished building: led8.elf.size'
' '

19:38:31 Build Finished (took 7s.342ms)


 

我们的LED流水灯程序马上就能跑了!别急,先做好运行准备。确保你的板子电源接好,MIO2~MIO6的短路帽都接地,USB-UART和USB-JTAG都连接到了电脑上,而且都已经安装相应驱动程序。打开电源开关,先下载bit流文件到FPGA,点击菜单Xilinx Tools->Launch Hardware Server,弹出一个黑框,不用管它(ISE14.2不需要这一步)。然后点击菜单Xilinx Tools->Program FPGA,确保bit文件位置正确(你可以亲自到相应目录下找到这个文件,看更新时间戳是不是正确),点Program,等待FPGA编程结束。成功编程后,板子上的LD12蓝灯会亮起。

 

接下来运行ARM端软件,右键点击工程浏览器中的led8,选择Run As->Launch on Hardware。打开电脑上的超级终端(Win7没有这个工具,我这里用的是SecureCRT),连接好,等待程序加载完成后,就能看到实验结果了,串口打印内容为:

ZED Board从入门到精通(三):从传统ARM开发到PS开发的转变_第15张图片

板子上的8个LED则会呈现出流水灯的效果。

最终效果视频地址为:http://v.youku.com/v_show/id_XNTk2ODg1ODU2.html

工程文件:http://download.csdn.net/detail/kkk584520/5961635

 

 总结:通过一个流水灯实验,我们基本上熟悉了Zynq开发需要的几个工具软件。步骤虽然很多,但有了一个清晰的方向,就不会迷失在各个软件的繁琐操作中。本博文不希望成为一个详细的傻瓜级教程(由于是第一个实验,步骤比较详细,后面的实验会非常简洁,所以不熟悉软件操作的童鞋要多加练习),也不想成为官方文档的简单堆砌和翻译,而是希望成为一个指路牌,告诉你在茫茫软件中何去何从。

ARM工程师关注的细节,应该是各类硬件寄存器,如GPIO,PLL,Timer,WDT,UART,SPI等等,这些寄存器可以从官方文档Zynq-7000-TRM中得到。经常查阅TRM是开发驱动、硬件接口必不可少的环节,如果需要移植操作系统,还需要查看ARM内核相应文档,如cortex_a9_mpcore_r4p1_trm,cortex_a9_neon_mpe_r4p1_trm等。一般来说,应用工程师需要熟悉相应的API,操作系统驱动工程师需要熟悉内核调用,裸机驱动工程师需要熟悉硬件协议。在一个项目中,需要所有工程师分工协作,这样才能高效地完成设计。

ARM工程师很多软件模块可以参考官方设计,在{ISE安装路径}\14.5\ISE_DS\EDK\sw\XilinxProcessorIPLib\drivers中有很多外设操作的例程,不需要从头开发。

在ARM之外,Zynq开发的另一个难点就是逻辑开发。下一节我们介绍如何利用ISE工具开发PL逻辑。

 

你可能感兴趣的:(FPGA,高性能计算——FPGA篇)