查看: 86|回复: 0

ZedBoard学习手记(四)为使用Linux系统做准备——建立Bootloader及设备树

[复制链接]

主题

好友

3932

积分

版主

  • TA的每日心情
    无聊
    2015-8-17 09:38
  • 签到天数: 361 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2013-12-23 18:28:28 |显示全部楼层
    在上一篇博文中,我已经介绍了建立AXI总线自定义外设的全过程,包括Verilog逻辑部分,和裸机软件部分。裸机控制外设是非常简单的,与普通的单片机并无二异,但仅仅有裸奔代码还远远无法发挥Cortex-A9硬核的作用,毕竟Zynq芯片集成了一颗最高能跑到1GHz的双核CPU(ZedBoard上的XC7Z020只能到800MHz)。并且ZedBoard上配备了Gigabit Ethernet、HDMI和USB OTG接口,不运行操作系统岂不浪费。
    有朋友想要在ZedBoard上做WinCE,但这方面的资料极为稀缺,而WinCE又是体积庞大、版权成本很高的操作系统,于是开源有小巧的嵌入式Linux就成了首选。之前兔子为了做出图形界面,还致力于移植桌面型的Linaro Ubuntu系统,不过ADI给出的参考例子未经优化奇卡无比,Xillinux正式版迟迟未现又只支持色彩度很低的简易VGA接口(ZedBoard上的VGA甚至到不了16位色),于是兔子不得不放弃之前的工作,重新启用ZedBoard出厂默认的轻量级Linux上。这个系统没有图形桌面,但已包含了网卡、HDMI驱动和其他基本功能,足够使用了。
    想要在Linux下控制外设,最重要的一环就是驱动了,但在动手写驱动之前,先要做些准备工作。为了减少工作量,我们就直接修改ZedBoard的出厂Demo,加入之前完成的my_gpio外设,并通过U-Boot实现Bootloader功能。这个Demo的源工程可以在Digilent网站的ZedBoard页面找到:
    https://digilentinc.com/Products/Detail.cfm?NavPath=2,400,1028&Prod=ZEDBOARD
    点击下面的Download,可以下载到ZedBoard_OOB_Design.zip文件,这个压缩包里包含了XPS工程、U-Boot文件、Linux内核配置文件、DeviceTree源文件、rootfs等。README.txt中有相近的操作说明,建议通读一遍。

    ZedBoard上默认的XPS系统工程位于hwxps_proj文件夹下,双击system.xmp打开工程,按照之前所说的方法,将my_gpio外设IP核导入到工程中。
    传送门:ZedBoard学习手记(二) 开发自定义AXI总线外设IP核——以LED和开关为例
    之后,查看一下XPS是否为我们的外设分配了地址空间,如果没有,就需要手动设置一个地址,这里我们设成0x75C80000,空间大小为AXI设备统一的64K。

    按照ZedBoard学习手记(二)中的方法设置总线连接,结果如下图:

    修改xps_projdatasystem.ucf文件,为my_gpio外设分配外部引脚(ucf约束文件中的引脚名称和Ports中的一定要相同,已经有不少网友在这里出过问题了)。另外我们分配的引脚占用了原来ARM的GPIO 引脚位置,应在XPS的Port列表里将processing_system7_0_GPIO数量设为[0:6]或干禁用,以除后患。

    完成后先单击Generate BitStream生成配置数据,再点击Export Design,选Export & Launch SDK将硬件信息导出到SDK中。


    在SDK里,新建一个C工程,不同于裸机的HelloWorld,这次要建立的是Bootloader,因此选择FSBL工程,即First Stage Bootloader,用实现U-Boot之前的初始化和启动工作。其他选项默认即可。

    编译一下工程,完成后SDK会生成FSBL的elf文件,另外加上从XPS导出的System.bit,以及我们在第一篇文章中编译生成的u-boot.elf,就可以生成用来实现SD卡启动系统的完整Bootloader文件了。
    u-boot.elf在ZedBoard_OOB_Design中包含,不过这个兔子没试过,通过Xilinx U-Boot编译生成u-boot.elf的方法请见:ZedBoard学习手记(一) First Step——建立Xilinx交叉编译环境
    集齐这三个文件之后,点击Xilinx Tools→Create Boot Image,添加到列表中,选择一个输出路径,就可以创建Bootloader了。


    SDK会在输出路劲生成u-boot.bin文件,将其改为BOOT.bin,拷贝到SD卡中,为ZedBoard板配置合适的跳线。这时再打开ZedBoard电源,Bootloader会初始化PS,用BitStream配置PL(包含了我们创建的my_gpio外设),并将操作权移交给U-Boot。U-Boot会自动加载Device Tree、Linux内核镜像和RootFS,最终启动Linux。
    ZedBoard出场时SD中还带有zImage、devicetree和rootfs文件,这些文件都可以采用原有的,直接用Xilinx交叉编译工具编译写好的C语言驱动就可以在这个系统上运行并控制外设了。
    当然,如果你想自己编译内核,或者不想采用静态物理地址的方式调用外设,就需要再往下进行一步,注意这一步对于Linux下控制AXI总线自定义外设并非必要。
    为了给有兴趣的朋友继续深入研究做个铺垫,这里兔子就讲一下编译ZedBoard上运行的Linux内核和设备树吧。当然这个方法也详细记录在ZedBoard_OOB_Design的README文件中。
    在PC的Linux环境下(兔子这里是Ubuntu)通过Git指令下载Digilent Linux内核源码:

    git clone git://github.com/Digilent/linux-3.3-digilent.git
    切换到ZedBoard Branch:
    cd linux-3.3-digilent

    git checkout -b zedboard_oob v3.3.0-digilent-12.07-zed-beta

    将ZedBoard_OOB_Design中的.config文件拷贝到源码目录下,然后编译内核(指的是ZedBoard_OOB_Design所在目录):
    cp /linux/.config ./.config

    make
    生成的内核镜像zImage 位于/arch/arm/boot/文件夹下。
    之后修改devicetree_ramdisk.dts文件,加入my_gpio外设信息。
    /******* LED & Swtich Controller ******/
    my_gpio@75c80000 {

    compatible = "xlnx,my_gpio-1.00.a";

    reg = <0x75c80000 0x10000>;

    xlnx,dphase-timeout = <0x8>;

    xlnx,family = "virtex6";

    xlnx,c_num_reg = <0x1>;

    xlnx,c_num_mem = <0x1>;

    xlnx,s-axi-min-size = <0x1ff>;

    xlnx,c_slv_awidth = <0x20>;

    xlnx,c_slv_dwidth = <0x20>;

    xlnx,use-wstrb = <0x0>;

    };
    通过下面指令生成设备树,同样Copy到SD卡中:
    ./scripts/dtc/dtc -O dtb –I dts –o ./devicetree_ramdisk.dtb  /linux/devicetree_ramdisk.dts
    这个设备树文件有网友说是将驱动加入到内核中用的,但兔子以为不然。如果不想通过静态设备物理地址(上面的0x75c80000)来加载驱动,就可以根据这个设备树信息(具体是通过xlnx,my_gpio-1.00.a字串)来动态识别设备。
    具体的方法有兴趣的童鞋可以一试,下次我们就要开始正式编写my_gpio外设的Linux驱动了。窗外还在下着雨,今天哪儿也去不了了,眼看周日和同事去箭扣长城的计划也要泡汤……话说这两天貌似不止北京在降温,大家可要注意保暖啊:D。
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    关闭

    站长推荐上一条 /5 下一条

    手机版|电路城

    GMT+8, 2019-9-17 13:50 , Processed in 0.157268 second(s), 13 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz!

    返回顶部