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 \n\r");

//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:在屏幕上会显示以下信息

posted on 2017-03-01 15:27  米联客小号  阅读(4472)  评论(0编辑  收藏  举报