cuter

Zynq启动过程探讨--进入main函数前我不了解的事

0
阅读(9225)

写在前面:

  • 本人纯属菜鸟,不敢保证自己的观点正确,各位看官多指教。
  • 本文讨论的主题是zynq启动过程。
  • 阅读本文要对Zyna EPP有那么一点点了解,最好使用过Xilinx的PlanAhead、EDK、XPS、SDK开发工具,我用的版本是14.2。
  • 建议阅读本文前先看一下pkilllo前辈的一篇文章《ZEDBOARD入手体验------ZYNQ "HELLO,WORLD!"背后的故事》,链接为:http://blog.chinaaet.com/detail/30143.html
  • 文章最后有文中提到的文档的下载链接。
  • 这篇博文没有编辑格式,附件给出word版本下载。

接触zc702和ZedBoard也有一阵子了,最大的感触就是开发工具做的工作实在太多。以前都是用Altera的片子,用Quartus II,从来没有用过Xilinx的东西,是一个不折不扣的新手,刚接触Xilinx就是他们最新产品Zynq,结果可想而知:相当摸不到头脑。

ChinaAET上几位前辈做了简单的测试之后,都已经开始做比较大的方案,这对于我这个还没有入门的人跳跃太大,所以在打算将自己规划的学习过程记录下来,希望对和我同样是门外汉的人有所帮助。

 

跟着官方的教程一直next,超级终端就能打印出“HelloWorld”,测试串口发送的目的是达到了,可是自己除了知道去点哪些菜单之外,对整个平台到底在做什么真的是一无所知!

为了让自己不那么白痴,只能硬着头皮肯官方文档。那时候我还不知道ChinaAET上开展了ZedBoard体验的活动,一直在闭门造车的研究Xilinx和ZedBoard的官方英文文档,直到昨天才在ChinaAET上发现很多有用的资料。其中pkilllo前辈的一篇文章《ZEDBOARD入手体验------ZYNQ "HELLO,WORLD!"背后的故事》跟我正在研究的东西很类似,令我受益匪浅,但是我觉得这篇文章对Zynq的启动过程分析稍微缺了一部分,故将自己的心得写下来。

 

废话不多说了,直奔主题。

首先提一下Xilinx官方提供的文档《Zynq-7000 Extensible Processing Platform Technical Reference Manual(ug585)》,这篇文档总共有1700左右,可想而知它的信息量有多丰富,可以说是搞Zynq离不开的资料。这篇文档第6章Boot and Configuration对Zynq的启动过程进行了描述。文中指出:

------------------------------------------------翻译并引用原文-------------------------------------------------

配置Zynq-7000系列可扩展器件需要多个步骤,最少要2个阶段,通常需要3个阶段,如下:

Stage0:称为BootROM,这一阶段控制最初的器件启动,BootROM是不可改动的可执行代码,处理器在上电复位和热重启之后执行。

Stage1:通常称为第一阶段引导程序(First Stage Boot Loader,FSBL),它可以是任何用户可控的代码。关于FSBL的细节请参考UG821:《Zynq-7000 EPP Software Developers Guide》。

Stage2:该阶段通常开始执行用户所设计的处理系统,但是它也可以是第二阶段引导程序(Second Stage Boot Loader,SSBL)。这一阶段完全在用户的控制之下,本章并不予以详述。请参考UG821:《Zynq-7000 EPP Software Developers Guide》了解FSBL和Stage 2 images。

-----------------------------------------------------引用结束-----------------------------------------------------

由上述描述可以看出,Zynq上电后最先执行的是BootROM启动,由于它不可更改,所以我们可以跳到Stage1,FSBL。查阅ug821相关章节:

------------------------------------------------翻译并引用原文-------------------------------------------------

第一阶段引导程序(FSBL)在启动后开始。它由BootROM加载到OCM(On Chip Memory)或者在BootROM header所指明的加密位置执行。

FSBL负责:

  • 利用XPS提供的PS配置数据进行初始化。(见Zynq PS 配置)
  • 将比特流(bitstream)下载到PL。将第二阶段引导程序(SSBL)或者是“裸奔”应用代码加载到内存。
  • 开始执行SSBL或是“裸奔”应用程序。

……

查看SDK提供的FSBL代码可以了解FSBL如何初始化CPU和FSBL所用到的外设,以及它如何使用一个简单的C run-time library。

……

Zynq PS 配置

利用Zynq配置UI,XPS生成MIO和SLCR寄存器的初始化代码。这些文件在XPS工程文件夹下:

  • Ps7_init.c和ps7_init.h,用于初始化CLK,DDR和MIO。Ps7_init.tcl完成的初始化和ps7_init.c代码完成的初始化是相同的。
  • Ps7_init.tcl文件,可以用来初始化CLK,DDR和MIO。它所完成的初始化和ps7_init.c代码完成的初始化是相同的。

注意:当使用XMD调试应用程序的时候tcl文件是很有用的。例如,你可以执行Ps7_init.tcl文件然后将应用程序加载到DDR中并调试。在这种情况下,就不需要进行FSBL的全过程。

  • Ps7_init.html,描述了初始化数据。

重要:在将来的版本中,可以改变PS初始化数据的位置和形式。

注意:XPS保持PL比特流和这些初始化数据的同步。不建议手动更改这些设置。

-----------------------------------------------------引用结束-----------------------------------------------------

相信大家看了上面两段引文,对Zynq的启动过程已经有了大致的了解。另外,还可以看出,FSBL阶段不仅调用了pkilllo前辈提到的BSP提供的ARM启动代码,而且使用ps7_init.c中的代码对设备进行了初始化工作。这两部分的初始化又是哪个在前,哪个在后呢?

从理论上来讲,假设先后改动这两部分对串口波特率的初始化数据,如果改动之后波特率发生变化,那么就可以知道被改动的部分是后执行的。但是正如pkilllo前辈所说的,这只是理论上的想法,在改动BSP提供的源文件时发现一旦重新build,SDK又会重新生成源码,而不会编译改动后的文件;另外,在改动ps7_init.c和ps7_init.tcl后,波特率也没有发生变化,我想这是由于这些初始化数据是由XPS生成,并且和bitstream同步,应该是PFGA内部硬件连线实现的初始化,所以我手动更改也是无效的。不过,按照ug821的说法,在以后的版本中或许可以在XPS中对初始化数据进行设置。

闹了这半天,到头来发现你考虑的这些玩意目前只能由开发工具完成,想随心所欲八成是没戏的,但如果能够自己开发BSP的话,应该可以按照自己的想法做一些事情。对于我这个菜鸟来说,BSP还太遥远,目前只能利用SDK提供的源码学习如果操作各种外设。

经过一番周折,虽然没有能够改变串口通信的波特率,但回过头来再看,我对开发工具到底做了哪些工作已经有所了解,这让我的思路清晰了不少。我打算在下一篇文章结合利用PS在串口打印“Hello ZedBoard!”的工程,讲一下自己对Xilinx一些列开发工具所做工作的理解。

 

UG585 Zynq-7000 Extensible Processing Platform Technical Reference Manual 下载链接:

http://china.xilinx.com/support/documentation/user_guides/ug585-Zynq-7000-TRM.pdf

UG821 Zynq-7000 EPP Software Developers Guide 下载链接:

http://china.xilinx.com/support/documentation/user_guides/ug821-zynq-7000-swdg.pdf