zoukankan      html  css  js  c++  java
  • S04_CH01_搭建工程移植LINUX/测试EMMC/VGA

    S04_CH01_搭建工程移植LINUX/测试EMMC/VGA

    1.1概述:

    本章内容是在已经提供安装了VIVADO2015.4 的ubuntu系统下,进行。大家可以下周我们已经提供的虚拟机镜像,我们提供的虚拟机镜像是安装了VIVADO的ubuntu系统,系统版本是ubuntu14.04。

    主要完成的内容如下:

    1)、利用VIVADO搭建VDMA Frambuffer 工程 修改VTG IP模块 支持1024X600分辨率(主要考虑支持7寸HDMI液晶显示器)

    2)、产生FSBL文件

    3)、环境变量的批量设置

    4)、基于linux kernel部分zynq_zed.dts(miz702n需要使用到)/zynq_zybo(miz701n需要使用到) 修改设备树

    5)、修改kernel其他文件

    6)、通过menuconfig 向导配置 frambuffer驱动

    7)、编译kernel、编译uboot

    8)、测试显示器输出和串口打印信息

    9)、测试读EMMC内存、写EMMC内存、读写EMMC内存

    10)、测试frambuffer应用程序

    1.2 LINUX开发环境搭建

    1.2.1虚拟机环境配置(提供下载虚拟机已经完成)

    Step1:

    本例程的工作环境(包括 FPGA及嵌入式 Linux的开发)是在 ubuntu14.04 操作系统下完成,对于 其它 Linux操作系统可能需要解决相关包的依赖问题。

    Step2:

    例子放在/mnt/workspace/linux目录下,读者可以在该目录下正确编译、运行。而 /mnt/workspace/linux目录是为读者实验准备的。

    Step3:

    单击桌面上的控制台或者(ctrl+alt+T)即可打开命令行,然后输入 su,根据提示输入root密码即可切换到 root用 户。

    Step4:

    对于新安装的ubuntu操作系统需要命令行下运行一下scripts目录下的 fix_xilinx_deps.sh脚本, 该脚本主要是解决编译 u-boot、kernel源码等所需要的包依赖。而提供的虚拟机已经解决了这些问题。 # /mnt/workspace/linux/scripts/fix_xilinx_deps.sh

    注意:开机的时候可能系统会提示正在检查更新(如 ),此时可以打开图 示的有个勾的那个图标,然后点击 Install Updates,待其完成更新后再运行该脚本(如下图所示)。当 然,在平时的开发过程中,可以在打开虚拟机之前,禁止网络功能,提供的虚拟机已经禁止了。

    Step5:

    对于 Vivado开发工具的安装,将下载的压缩包解压后,从命令行进入该目录,执行 xsetup即可像在 Windows一样安装。注意:为减少虚拟机所占用硬盘空间,虚拟机里提供的开发套件是直接将本人PC中安装好的 Vivado和 SDK等复制到/mnt/workspace/toolchains目录中的,这里不提供全新安装 Vivado的步骤,若需要帮助的话,可以通过邮件联系我。

    Step6:

    本开发使用的是 Vivado开发套件里提供的交叉编译器,无须再安装其它交叉编译器。 Step7:

    整个开发过程主要使用脚本进行操作,故在每次开发前,需要执行如下图所示操作来设置好环境变量。如果需要支持新的开发板时,只需要建立新的目录(如 miz702等),然后把 scripts复制到新的目 录中,修改相关设置(如 uboot版本等),十分方便。

    1.2.2下载资源

    使用 get_xilinx_sources.sh脚本下载 uboot、kernel、device tree等源码及 ramdisk到 packages目录中,并 解压 uboot和 kernel等源码。若需要更改源码的版本,则打开 get_xilinx_sources.sh文件后,修改相应的 设置即可。当网络不是很好时,可以直接压缩包目录中的包复制到 packages目录下即可。

    1.3 VIVADO 工程的搭建

    计 FPGA 这部分相信读者已经相当熟悉了,这里只是对工程里的一些关键地方进行说明。在命令行下切换到/mnt/workspace/MIZ702N(工程目录读者可以自己指定)目录下,通过输入 vivado即可打开 vivado工具。

    此工程可以在WINDOWS或者LINUX下使用。建议初学者WINDOWS下使用。

    1.3.1 VIVADO 硬件工程构架

    MIZ701N

    wps35F0.tmp

    MIZ702/MIZ702N

    wps3620.tmp

    1.3.2 时钟设置

    Step1: 双击ZYNQ CPU IP 进行如下步骤设置:MIZ702和MIZ702N的输入时钟是333.333333MHZ

    wps3630.tmp

    Step2:MIZ701N PS的输入时钟是50MHZ

    wps3631.tmp

    Step3:PS的PLL提供本系统的时钟100MHZ

    wps3632.tmp

    Step4:MIZ702的开发板采用的是单片256MB的MT41K128M16JI-125

    wps3633.tmp

    Step5:MIZ701N和MIZ702N的内存型号一样,都是单片512MB的MT41K256M16RE-125

    wps3644.tmp

    Step6:启动1路HP接口,HP接口是ZYNQ个高速数据接口

    wps3645.tmp

    Step7:勾选PL到PS的中断资源(关于中断,在第二季的课程中有详细讲解,不熟悉的读者可以到第二季课程中温习一下)

    wps3646.tmp

    Step8:增加必要的外设,包括ENET0以太网接口、USB_0 USB接口、SD0 TF卡接口、SD1 EMMC接口、UART1串口。

    wps3657.tmp

    Step9:设置完成后单击OK

    Step10:双击VDMA IP 由于只使用了VDMA读通道设置如下:

    wps3658.tmp

    Step11:双击PLL时钟IP

    MIZ701N PLL时钟设置

    wps3659.tmp

    MIZ702/MIZ702N PLL时钟设置

    wps365A.tmp

    Step13:修改VTC 显示时序发生IP参数符合1024X600分辨率

    wps366A.tmp

    1.4 PS设置

    1.4.1 PS SDK测试显示器输出

    新建Display_VMDA_Test空的工程,为了测试在裸机下图形系统显示正确,编写SDK测试代码main.c函数以及其他必要函数。

    /*

    *南京米联电子科技有限公司

    *www.milinker.com

    *www.osrc.cn

    *test display

    Copyright (c) 2009-2012 Xilinx, Inc.  All rights reserved.

    */

    #include "xaxivdma.h"

    #include "xaxivdma_i.h"

    #include "sleep.h"

    #define DDR_BASEADDR        0x00000000

    #define VDMA_BASEADDR       XPAR_AXI_VDMA_0_BASEADDR

    #define H_STRIDE            1024

    #define H_ACTIVE            1024

    #define V_ACTIVE            600

    #define pi 3.14159265358

    #define COUNTS_PER_SECOND (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ)/64

    #define VIDEO_LENGTH  (H_STRIDE*V_ACTIVE)

    #define VIDEO_BASEADDR0 DDR_BASEADDR + 0x2000000

    #define VIDEO_BASEADDR1 DDR_BASEADDR + 0x3000000

    #define VIDEO_BASEADDR2 DDR_BASEADDR + 0x4000000

    u32 *BufferPtr[3];

    unsigned int srcBuffer = (XPAR_PS7_DDR_0_S_AXI_BASEADDR  + 0x1000000);

    int run_triple_frame_buffer(XAxiVdma* InstancePtr, int DeviceId, int hsize,

    int vsize, int buf_base_addr, int number_frame_count,

    int enable_frm_cnt_intr);

    //函数声明

    void Xil_DCacheFlush(void);

    // 所有数据格式 为 RGBA,低位的透明度暂不起作用

    extern const unsigned char gImage_beauty[1729536];

    extern const unsigned char gImage_mm[1228800];

    extern const unsigned char gImage_miz702[600000];

    extern const unsigned char gImage_miz702_rgba[600000];

    void show_img(u32 x, u32 y, u32 disp_base_addr, const unsigned char * addr, u32 size_x, u32 size_y)

    {

    //计算图片 左上角坐标

    u32 i=0;

    u32 j=0;

    u32 r,g,b;

    u32 start_addr=disp_base_addr;

    start_addr = disp_base_addr + 4*x + y*4*H_STRIDE;

    for(j=0;j<size_y;j++)

    {

    for(i=0;i<size_x;i++)

    {

    b = *(addr+(i+j*size_x)*4+1);

    g = *(addr+(i+j*size_x)*4+2);

    r = *(addr+(i+j*size_x)*4+3);

    Xil_Out32((start_addr+(i+j*H_STRIDE)*4),((r<<16)|(g<<8)|(b<<0)|0x0));

    }

    }

    Xil_DCacheFlush();

    }

    int main(void)

    {

    u32 i;

    //Xil_DCacheFlush();

    xil_printf("Starting the first VDMA ");

    //VDMA configurateAXI VDMA0

    /*****************往DDR写数据设置**********************/

    //Xil_Out32((VDMA_BASEADDR + 0x030), 0x00000003);// enable circular mode

    //Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0); // start address

    //Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1); // start address

    //Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2); // start address

    //Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*4)); // h offset (640 * 4) bytes

    //Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*4)); // h size (640 * 4) bytes

    //Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE); // v size (480)

    /*****************从DDR读数据设置**********************/

    Xil_Out32((VDMA_BASEADDR + 0x000), 0x00000003); // enable circular mode

    Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); // start address

    Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR0); // start address

    Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR0); // start address

    Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*4)); // h offset (640 * 4) bytes

    Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*4)); // h size (640 * 4) bytes

    Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); // v size (480)

        for(i=0;i<614400;i++)

        {

    Xil_Out32(VIDEO_BASEADDR0+i,0);

        }

    while(1)

    {

    show_img(0,0,VIDEO_BASEADDR0,&gImage_beauty[0],563,600);

    sleep(5);

    show_img(0,0,VIDEO_BASEADDR0,&gImage_miz702_rgba[0],375,400);

    sleep(5);

    }

        return 0;

    }

    1.4.2测试效果 缺图
    1.4.3 新建FSBL工程

    产生的fsbl.elf 后面将用于参数BOOT.BIN文件

    wps366B.tmp

    1.4.4产生设备树

    Step1:首先解压 device-tree-xlnx-xilinx-v2015.4.tar.gz,然后打开 Xilinx Tools→Repositories将刚 才解压的目录包含进来。

    wps367C.tmp

    wps367D.tmp

    Step2:打开 File→New→Board Support Package创建,其它弹出窗口按默认设置即可

    wps367E.tmp

    Step3:在该工程中,zynq-7000.dtsi文件是 Xilinx提供给所有 zynq-7000开发板使用的,只所有的 status都 设置为”disabled”,而 system.dts里根据板子上的具体实现,修改设备树使其可以正常工作。pl.dtsi文件 是 FPGA里使用的 IP对应的设备树。

    1.5编译 u-boot、kernel、设备树和文件系统

    1.5.1批处理文件

    这里使用 xilinx在 github上提供的 u-boot和 kernel源码,在 Wiki上提供的文件系统(当然,也可以直 接使用 buildroot自己匹配根文件系统,该方法简单快捷,不用再去解决什么依赖问题,但好像国内很 少有人这么干,他们都把 busybox等模块一个个搭建起来)。 1、配置 uboot和编译 uboot自带的工具,为编译 kernel提供 mkimage工具的支持。注意,由于编译新 版本的 uboot需要 openssl和 dtc的支持,这里呢,在系统里已经安装好了 openssl,而 dtc则利用 kernel 里自带的,所以这一步做完,我们将直接编译内核,等编译完内核后再来编译 uboot。注意: cfg_bootloader.sh可以在任意目录下使用,而 make tools只能在 bootloader目录下使用,bootloader就是 我们存放 uboot源码的地方。(注意:这部分仅在恢复配置文件至 Xilinx提供的配置时用,在自己修改完配置之后,除了需要恢复配置文件外,请谨慎使用这两条命令) 。

    Step1:运行setup_env.sh批处理文件(管理员模式下的密码为root)

    wps367F.tmp

    Step2:运行cfg_bootloader.sh批处理文件

    wps368F.tmp

    Step2:运行make tools处理命令(执行的是清理工作,重置配置时候使用)

    wps3690.tmp

    Step3:配置内核(注意:这部分仅在恢复配置文件至 Xilinx提供的配置时用,在自己修改完配置之后,除了需要恢复配 置文件外,请谨慎使用这条命令)

    wps3691.tmp

    1.5.2 修改设备树

    Step1:由于各种开发板可以参考zedboard的配置设备参数,因此我们可以修改已经存在的相关文件,来满足我们的自定义需求打开/mnt/workspace/linux/kernel/arch/arm/boot/dts/zynq-zed.dts

    Step2:修改 bootargs信息 启动参数 bootargs是传递给 kernel的参数。Console是一个输出系统管理信息的文本输出设备,这些信 息来自于内核,系统启动和系统用户,其中 console=ttyPS0,115200用来设置串口作为输出终端设备,是 这些信息可以通过串口在远程的终端上显示。而 console=tty0则是设置显示器作为输出终端。

    如果想屏幕永不休眠,则在启动参数 bootargs中增加  consoleblank=0,网络上大部分是讲修改内核源码, 但我觉得这种方法才是最方便,且符合一个内核适合多种产品的思想。 其它参数读者应该也知道是什么意思,这里也就不多讲了。

    wps36A2.tmp

    Step3:添加 vdma和 framebuffer设备树节点,注意:这里是添加到根节点。笔者觉得,arm linux引进设备树,比以前版本的做法好很多,只是驱动里需要设备树提供哪些参数, 在 Linux文档里没有很好的说明,或者是驱动里所需要的参数改变了,而文档又没有及时更新,这部分 是 linux的不足之处。所以,开发 Linux过程中,最好还是以源码为中心。设备树这部分是参考之前在 SDK里产生的设备树和内核里相关文档,在阅读 vdma等驱动源码后,修改而来的,并不是说 SDK里 产生的设备树直接搬来就可以正常使用。

    wps36A3.tmp

    Step4:修改 SD卡和 emmc设备树节点

    这部分直接将之前在 SDK里产生的设备树复制过来就可以正常使用。总的来说,对于 PS的外设,其 硬件是固定的,驱动也基本不会有太大的变化,故基本上是可以直接搬来就可以用,但也有例外,如果 USB,SDK里并不知道你要当 host或者 otg来使用,所以需要做些小修改。而对于 PL中使用的 IP,其 硬件和驱动经常有变化,SDK里产生的设备树不能直接拿来使用。

    wps36A4.tmp

    1.5.3 添加 framebuffer驱动

    Step1:把vdmafb.c文件复制到 /mnt/workspace/linux/kernel/drivers/video/fbdev 目录下,对于驱动这部分,主要还是要看源码,注意, 该驱动仅支持 640x480分辨率,若需要支持其它分辨率,需要修改和调试相关源码。

    Step2:打开/mnt/workspace/linux/kernel/drivers/video/fbdev目录下的 Makefile文件,当然也可以用其它 文本编辑器。

    找到 CONFIG_FB_XILINX,在其下方添加 obj-$(CONFIG_FB_VDMA)+= vdmafb.o。读者可以直接复制笔者提供的开发包中的修改好的文件。

    wps36A5.tmp

    Step3:打开/mnt/workspace/linux/kernel/drivers/video/fbdev目录下的 Kconfig文件:

    找到 FB_XILINX,在其下方添加以下信息。读者可以直接复制笔者提供的开发包中的修改好的文件。

    wps36B6.tmp

    Step4:打开/mnt/workspace/linux/kernel/drivers目录下的 Makefile文件,找到 obj-y += video/ 读者可以直接复制笔者提供的开发包中的修改好的文件。

    wps36B7.tmp

    把它剪切并粘贴到

    wps36B8.tmp

    Step5:回到 kernel目录下,执行 make menuconfig,配置 kernel。

    wps36C8.tmp

    按向下方向键找到 Device Drivers,按回车键进入

    wps36C9.tmp

    按向下方向键找到 Graphics support,按回车键进入

    wps36CA.tmp

    按向下方向键找到 Bootup logo,按空格键选择

    wps36CB.tmp

    按向上方向键找到 Frame buffer Devices,按回车键选择

    wps36DC.tmp

    至此已经完成 linux kernel的配置,按向左方向键至<Exit>,再按回车键返回上一级菜单

    wps36DD.tmp

    直到看到以下窗口,按<Yes>保存。

    wps36DE.tmp

    1.5.4执行mk_kernel.sh编译内核

    wps36EE.tmp

    1.5.5执行mk_bootloader.sh编译uboot

    wps36EF.tmp

    1.5.6制作UBOOT.BIN

    Step1:把system_wrapper.bit 和 fsbl.elf复制到 output/target/目录下。

    Step2:执行mk_sd_image.sh打包从 SD启动所需要的文件

    wps36F0.tmp

    Step3:至此系统部分已经完成,复制linux/image/sd_images文件下文件到TF卡测试移植好的LINUX系统。

    wps36F1.tmp

    1.6 EMMC 8GB内存测试(MIZ702不支持)

    Step1:从系统的启动信息可以看到,系统已经发现 mmc0(即 SD卡)和 mmc1(即 emmc),而且列出了 SD 卡为 7.41GB,而 emmc为 7.20GB

    wps3702.tmp

    Step2:给 eMMC分区 当然,如果只分为一个分区的话,其它也可以不分区。在命令行下运行 fdisk /dev/mmcblk1来对 emmc 进行分区。这里需要注意,确认有没有 SD卡插入,也就是说确认当前 eMMC是/dev/mmcblk1还是 /dev/mmcblk0,还有对于有多个分区的,可能存在/dev/mmcblk0p1、/dev/mmcblk0p2等等。

    wps3703.tmp

    Step3:将分区格式化为 ext2格式 能格式化为什么格式,如 ext2、ext3、nfts、fat32,这些都跟系统的定制有关

    wps3704.tmp

    Step4:测试 emmc的性能

    在 Linux下,既可以使用 dd命令来低格 U盘等,也可以用来复制文件(类似于 windows下的 ghost功 能),当然也可以用来测试硬盘等的性能,虽然没有专业软件的测试得准确,但用来对比性能已经足够 了。对于/dev/zero和/dev/null两个设备的说明,可以百度一下

    Step4.1写性能

    下面使用 dd命令将从/dev/zero设备中产生一个 1GB的文件写入到 emmc:

    wps3715.tmp

    Step4.2读性能

    下面使用 dd命令将 1GB的文件写入到/dev/null设备中:

    wps3716.tmp

    Step4.3读写性能

    下面使用 dd命令将 emmc中的一个 1GB的文件写入到 emmc的另外一个文件

    wps3717.tmp

    1.7 测试 framebuffer

    Step1:将虚拟机/mnt/workspace/linux/framebuffer目录下的测试程序(源代码也在该目录里)复制到 SD 卡上,然后给开发板上电。在 Windows下打开串口终端putty

    软件。

    Step2:切换到 sd卡目录下(比如 mount /dev/mmcblk0p1 /mnt, cd /mnt),然后运行./framebuffer,在串口终端 会显示 以下信息。

    wps3718.tmp

    Step3:在屏幕上会显示以下信息

  • 相关阅读:
    css颜色表示法&颜色表
    css单位
    DOM与BOM
    position定位
    grid layout
    Linux禁止Ping方法
    tracert(traceroute)与ping
    服务器负载均衡技术的原理
    Struts2与webx的比较
    SpringAOP的原理
  • 原文地址:https://www.cnblogs.com/milinker/p/6484502.html
Copyright © 2011-2022 走看看