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官方例程的网址为https://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软件(安装完成后,一般在桌面上会有快捷方式)。
单击“Create New Project ”,新建工程,为了方便叙述,连续点6次“Next”,直到出现下图:
左上框中选择“board”,在下面框中找到ZedBoard并选中,点Next,一直到Finish,结束。
在主面板左侧,点“Add Source”,添加一个嵌入式模块(这就是ARM核),选择如图所示。
Next,点“Create Sub-Design”
随便起个名吧,保留默认,OK,Finish。这个步骤主要功能是添加我们的ARM核心到万用板上,但是还没有连线。
这时PlanAhead会自动调用XPS,在XPS中,当有提问是否用BSB建立基本系统时,选“是”。OK,Next,出现下图:
把原先右侧的所有硬件都Remove掉,因为我们需要自己连线。点Finish。
看到了一个彩色的庞大系统,如下图所示。
主窗口显示的就是Zynq内部结构图,主窗口上面有四个标签,“Zynq”表示图形化显示,“Bus Interface”表示总线连接,“Ports”表示芯片外部IO连接,“Address”表示Zynq系统的地址映射。主窗口下有3个标签,有设计总结报告、系统组成显示、图形设计显示。默认用系统组成显示,另外两种可以在设计完成后观察。
我们点击Zynq系统组成框图中左上侧绿色的"I/O Peripherals“框,弹出IO口外设配置选项,展开最下侧的GPIO(点加号),勾上EMIO,并设置IO数目为8,如下图所示:
点关闭,然后从主窗口上面标签的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,如下图所示:
这时生成了顶层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”,如图所示
仍然点Create File,名称随便起,我们输入system,最后确认,回到主窗口。这时看到Project Manager中添加了system.ucf
双击该文件,添加内容如下:
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;
如果对引脚的位置不太确定,可以参考我上传的资源:https://download.csdn.net/detail/kkk584520/5901617 里面有ZEDBoard原理图,其中有关LED的引脚如下图所示:
为了防止生成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,确认:
经过一段时间的导出,进入了SDK开发界面,点击菜单File->New->Application Project,如下所示:
名称随便起一个吧,我们取为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 <stdio.h> #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<<i; delay_1s(1000); } } cleanup_platform(); return 0; }
保存,程序会自动编译。如果控制台输出如下表示编译无错误出现。
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),连接好,等待程序加载完成后,就能看到实验结果了,串口打印内容为:
板子上的8个LED则会呈现出流水灯的效果。
最终效果视频地址为:https://v.youku.com/v_show/id_XNTk2ODg1ODU2.html
工程文件:https://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逻辑。
最后更新:2017-04-03 16:48:57