zoukankan      html  css  js  c++  java
  • ZYNQ FLASH+EMMC手动移植LINUX启动

    前言

    虽可使用Petalinux进行移植,简单方便,但为了更清楚明白的了解整个流程,还是尝试了一波手动移植。

    参考资料

    ZYNQ Linux 移植:包含petalinux移植和手动移植debian9

    ZYNQ #5 - 从vivado工程开始,从emmc启动Linux_里先森-CSDN博客

    流程

    对于手动移植,所需的文件为:

    BOOT.bin(FSBL+fpga_bit文件+u_boot.elf)、uImage、devicetree.dtb、uEnv.txt、文件系统

    文件放置位置说明:

    FLASH:BOOT.bin(FSBL+fpga_bit文件+u_boot.elf)

    EMMC:

    第一个分区放置:uImage、devicetree.dtb、uEnv.txt
    
    第二个分区放置:文件系统
    

    启动流程为:板子设置为QSPI启动模式,FSBL执行调u-boot执行,u-boot根据uEnv.txt调EMMC分区1中的内核执行,内核最后跳到分区二中的文件系统。

    FSBL、bit文件、uImage、文件系统都可复用SD卡移植模式下的内容:参考参考资料第一个链接。

    本文章主要讲述的重点在于:u-boot、设备树、uEnv.txt的更改部分

    板子主要信息说明:板子芯片:ZYNQ7035,板子的调试打印串口为PS0,板子上有SD卡(SD0)、EMMC(SD1),板子上有FLASH。其他外设不赘述。

    u-boot移植说明:

    1.下载u-boot源码:git clone [https://github.com/Xilinx/u-boot-xlnx.git](https://github.com/Xilinx/u-boot-xlnx.git)

    NOTE:u-boot xilinx-v2018.3版本的zynq-common.h跟xilinx-v2018.1版本的不一样,这里检出v2018.1版本使用。

    主要是CONFIG_EXTRA_ENV_SETTINGS 环境变量不一致。

    默认的如下所示:

    /* Default environment */
    #ifndef CONFIG_EXTRA_ENV_SETTINGS
    #define CONFIG_EXTRA_ENV_SETTINGS	
    	"ethaddr=00:0a:35:00:01:22"	
    	"kernel_image=uImage"	
    	"kernel_load_address=0x2080000" 
    	"ramdisk_image=uramdisk.image.gz"	
    	"ramdisk_load_address=0x4000000"	
    	"devicetree_image=devicetree.dtb"	
    	"devicetree_load_address=0x2000000"	
    	"bitstream_image=system.bit.bin"	
    	"boot_image=BOOT.bin"	
    	"loadbit_addr=0x100000"	
    	"loadbootenv_addr=0x2000000" 
    	"kernel_size=0x500000"	
    	"devicetree_size=0x20000"	
    	"ramdisk_size=0x5E0000"	
    	"boot_size=0xF00000"	
    	"fdt_high=0x20000000"	
    	"initrd_high=0x20000000"	
    	"bootenv=uEnv.txt" 
    	"loadbootenv=load mmc 0 ${loadbootenv_addr} ${bootenv}" 
    	"importbootenv=echo Importing environment from SD ...; " 
    		"env import -t ${loadbootenv_addr} $filesize" 
    	"sd_uEnvtxt_existence_test=test -e mmc 0 /uEnv.txt" 
    	"preboot=if test $modeboot = sdboot && env run sd_uEnvtxt_existence_test; " 
    			"then if env run loadbootenv; " 
    				"then env run importbootenv; " 
    			"fi; " 
    		"fi; " 
    	"mmc_loadbit=echo Loading bitstream from SD/MMC/eMMC to RAM.. && " 
    		"mmcinfo && " 
    		"load mmc 0 ${loadbit_addr} ${bitstream_image} && " 
    		"fpga load 0 ${loadbit_addr} ${filesize}" 
    	"norboot=echo Copying Linux from NOR flash to RAM... && " 
    		"cp.b 0xE2100000 ${kernel_load_address} ${kernel_size} && " 
    		"cp.b 0xE2600000 ${devicetree_load_address} ${devicetree_size} && " 
    		"echo Copying ramdisk... && " 
    		"cp.b 0xE2620000 ${ramdisk_load_address} ${ramdisk_size} && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"qspiboot=echo Copying Linux from QSPI flash to RAM... && " 
    		"sf probe 0 0 0 && " 
    		"sf read ${kernel_load_address} 0x100000 ${kernel_size} && " 
    		"sf read ${devicetree_load_address} 0x600000 ${devicetree_size} && " 
    		"echo Copying ramdisk... && " 
    		"sf read ${ramdisk_load_address} 0x620000 ${ramdisk_size} && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"uenvboot=" 
    		"if run loadbootenv; then " 
    			"echo Loaded environment from ${bootenv}; " 
    			"run importbootenv; " 
    		"fi; " 
    		"if test -n $uenvcmd; then " 
    			"echo Running uenvcmd ...; " 
    			"run uenvcmd; " 
    		"fi" 
    	"sdboot=if mmcinfo; then " 
    			"run uenvboot; " 
    			"echo Copying Linux from SD to RAM... && " 
    			"load mmc 0 ${kernel_load_address} ${kernel_image} && " 
    			"load mmc 0 ${devicetree_load_address} ${devicetree_image} && " 
    			"load mmc 0 ${ramdisk_load_address} ${ramdisk_image} && " 
    			"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; " 
    		"fi" 
    	"usbboot=if usb start; then " 
    			"run uenvboot; " 
    			"echo Copying Linux from USB to RAM... && " 
    			"load usb 0 ${kernel_load_address} ${kernel_image} && " 
    			"load usb 0 ${devicetree_load_address} ${devicetree_image} && " 
    			"load usb 0 ${ramdisk_load_address} ${ramdisk_image} && " 
    			"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; " 
    		"fi" 
    	"nandboot=echo Copying Linux from NAND flash to RAM... && " 
    		"nand read ${kernel_load_address} 0x100000 ${kernel_size} && " 
    		"nand read ${devicetree_load_address} 0x600000 ${devicetree_size} && " 
    		"echo Copying ramdisk... && " 
    		"nand read ${ramdisk_load_address} 0x620000 ${ramdisk_size} && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"jtagboot=echo TFTPing Linux to RAM... && " 
    		"tftpboot ${kernel_load_address} ${kernel_image} && " 
    		"tftpboot ${devicetree_load_address} ${devicetree_image} && " 
    		"tftpboot ${ramdisk_load_address} ${ramdisk_image} && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"rsa_norboot=echo Copying Image from NOR flash to RAM... && " 
    		"cp.b 0xE2100000 0x100000 ${boot_size} && " 
    		"zynqrsa 0x100000 && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"rsa_nandboot=echo Copying Image from NAND flash to RAM... && " 
    		"nand read 0x100000 0x0 ${boot_size} && " 
    		"zynqrsa 0x100000 && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"rsa_qspiboot=echo Copying Image from QSPI flash to RAM... && " 
    		"sf probe 0 0 0 && " 
    		"sf read 0x100000 0x0 ${boot_size} && " 
    		"zynqrsa 0x100000 && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"rsa_sdboot=echo Copying Image from SD to RAM... && " 
    		"load mmc 0 0x100000 ${boot_image} && " 
    		"zynqrsa 0x100000 && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    	"rsa_jtagboot=echo TFTPing Image to RAM... && " 
    		"tftpboot 0x100000 ${boot_image} && " 
    		"zynqrsa 0x100000 && " 
    		"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}" 
    		DFU_ALT_INFO 
    		BOOTENV
    #endif
    

    可以看到其上定义了一堆的东西及不同的启动指令。

    不同的启动指令由#define CONFIG_BOOTCOMMAND指定。

    这里想FLASH+EMMC启动,则可以选择sdboot,同时因为EMMC是SD1,所以上述的文件需要进行更改:更改uEnv.txt的存储位置为mmc 1;去掉sdboot中的ramdisk,及存储kernel、设备树位置为mmc 1;修改bootm参数。

    	"loadbootenv=load mmc 1 ${loadbootenv_addr} ${bootenv}" 
    	"importbootenv=echo Importing environment from SD ...; " 
    		"env import -t ${loadbootenv_addr} $filesize" 
    	"sd_uEnvtxt_existence_test=test -e mmc 1 /uEnv.txt" 
    
    "sdboot=if mmcinfo; then " 
    			"run uenvboot; " 
    			"echo Copying Linux from hahahah SD to RAM... && " 
    			"load mmc 1 ${kernel_load_address} ${kernel_image} && " 
    			"load mmc 1 ${devicetree_load_address} ${devicetree_image} && " 
    			"bootm ${kernel_load_address} - ${devicetree_load_address}; " 
    		"fi" 
    

    上述命令的执行逻辑为:u-boot启动后,执行sdboot指令:

    (1)装载uEnv.txt文件并运行;

    (2)装载内核、设备树;

    (3)运行;

    2.由于是自己做的板子,则可以基于类似的板子defconfig进行修改适配u-boot:这里使用zynq_zed_defconfig文件:

    (1)增加传统镜像文件支持:CONFIG_IMAGE_FORMAT_LEGACY=y

    (2)因为已经知道是从EMMC启动相关文件,则可直接指定:CONFIG_BOOTCOMMAND="mmc dev 1;run sdboot"

    mmc dev 1是为了避免u-boot死锁bug(移植petalinux中u-boot存在,为官方bug,这里加上,不知道有没有用);sdboot会直接调用执行zynq-common.h中的对应选项。

    (3)因为板子上串口使用的是PS0,修改:CONFIG_DEBUG_UART_BASE=0xe0000000(地址可在设备树中查看)

    文件参考:

    CONFIG_ARM=y
    CONFIG_ARCH_ZYNQ=y
    CONFIG_SYS_TEXT_BASE=0x4000000
    CONFIG_SPL_STACK_R_ADDR=0x200000
    CONFIG_DEFAULT_DEVICE_TREE="zynq-zed"
    CONFIG_DEBUG_UART=y
    CONFIG_DISTRO_DEFAULTS=y
    CONFIG_IMAGE_FORMAT_LEGACY=y
    CONFIG_FIT=y
    CONFIG_FIT_SIGNATURE=y
    CONFIG_FIT_VERBOSE=y
    CONFIG_BOOTCOMMAND="mmc dev 1;run sdboot"
    # CONFIG_DISPLAY_CPUINFO is not set
    CONFIG_SPL=y
    CONFIG_SPL_STACK_R=y
    CONFIG_SPL_OS_BOOT=y
    CONFIG_SYS_PROMPT="Zynq> "
    CONFIG_CMD_THOR_DOWNLOAD=y
    CONFIG_CMD_DFU=y
    # CONFIG_CMD_FLASH is not set
    CONFIG_CMD_FPGA_LOADBP=y
    CONFIG_CMD_FPGA_LOADFS=y
    CONFIG_CMD_FPGA_LOADMK=y
    CONFIG_CMD_FPGA_LOADP=y
    CONFIG_CMD_GPIO=y
    CONFIG_CMD_MMC=y
    CONFIG_CMD_SF=y
    CONFIG_CMD_USB=y
    # CONFIG_CMD_SETEXPR is not set
    CONFIG_CMD_TFTPPUT=y
    CONFIG_CMD_CACHE=y
    CONFIG_CMD_EXT4_WRITE=y
    CONFIG_OF_EMBED=y
    CONFIG_ENV_IS_IN_SPI_FLASH=y
    CONFIG_NET_RANDOM_ETHADDR=y
    CONFIG_SPL_DM_SEQ_ALIAS=y
    CONFIG_DFU_MMC=y
    CONFIG_DFU_RAM=y
    CONFIG_FPGA_XILINX=y
    CONFIG_DM_GPIO=y
    CONFIG_MMC_SDHCI=y
    CONFIG_MMC_SDHCI_ZYNQ=y
    CONFIG_SPI_FLASH=y
    CONFIG_SPI_FLASH_BAR=y
    CONFIG_SF_DUAL_FLASH=y
    CONFIG_SPI_FLASH_SPANSION=y
    CONFIG_SPI_FLASH_STMICRO=y
    CONFIG_SPI_FLASH_WINBOND=y
    CONFIG_PHY_MARVELL=y
    CONFIG_PHY_REALTEK=y
    CONFIG_PHY_XILINX=y
    CONFIG_ZYNQ_GEM=y
    CONFIG_DEBUG_UART_ZYNQ=y
    CONFIG_DEBUG_UART_BASE=0xe0000000
    CONFIG_DEBUG_UART_CLOCK=50000000
    CONFIG_ZYNQ_SERIAL=y
    CONFIG_ZYNQ_QSPI=y
    CONFIG_USB=y
    CONFIG_USB_EHCI_HCD=y
    CONFIG_USB_ULPI_VIEWPORT=y
    CONFIG_USB_ULPI=y
    CONFIG_USB_STORAGE=y
    CONFIG_USB_GADGET=y
    CONFIG_USB_GADGET_MANUFACTURER="Xilinx"
    CONFIG_USB_GADGET_VENDOR_NUM=0x03fd
    CONFIG_USB_GADGET_PRODUCT_NUM=0x0300
    CONFIG_CI_UDC=y
    CONFIG_USB_GADGET_DOWNLOAD=y
    

    3.修改u-boot的设备树:实际上u-boot也带了设备树,这里需要进行修改:

    (1)修改uart为uart0;

    (2)修改SD为mmc1;

    (3)去除QSPI中的分区表;

    文件参考:

    /*
     * Xilinx ZED board DTS
     *
     *  Copyright (C) 2011 - 2015 Xilinx
     *  Copyright (C) 2012 National Instruments Corp.
     *
     * SPDX-License-Identifier:	GPL-2.0+
     */
    /dts-v1/;
    #include "zynq-7000.dtsi"
    
    / {
    	model = "Zynq Zed Development Board";
    	compatible = "xlnx,zynq-zed", "xlnx,zynq-7000";
    
    	aliases {
    		ethernet0 = &gem0;
    		serial0 = &uart0;
    		spi0 = &qspi;
    		mmc1 = &sdhci1;
    	};
    
    	memory@0 {
    		device_type = "memory";
    		reg = <0x0 0x20000000>;
    	};
    
    	chosen {
    		bootargs = "";
    		stdout-path = "serial0:115200n8";
    	};
    
    	usb_phy0: phy0@e0002000 {
    		compatible = "ulpi-phy";
    		#phy-cells = <0>;
    		reg = <0xe0002000 0x1000>;
    		view-port = <0x0170>;
    		drv-vbus;
    	};
    };
    
    &clkc {
    	ps-clk-frequency = <33333333>;
    };
    
    &gem0 {
    	status = "okay";
    	phy-mode = "rgmii-id";
    	phy-handle = <&ethernet_phy>;
    
    	ethernet_phy: ethernet-phy@0 {
    		reg = <0>;
    		device_type = "ethernet-phy";
    	};
    };
    
    &qspi {
    	u-boot,dm-pre-reloc;
    	status = "okay";
    	is-dual = <0>;
    	num-cs = <1>;
    	flash@0 {
    		compatible = "n25q128a11";
    		reg = <0x0>;
    		spi-tx-bus-width = <1>;
    		spi-rx-bus-width = <4>;
    		spi-max-frequency = <50000000>;
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    	};
    };
    
    &sdhci1 {
    	u-boot,dm-pre-reloc;
    	status = "okay";
    };
    
    &uart0 {
    	u-boot,dm-pre-reloc;
    	status = "okay";
    };
    
    &usb0 {
    	status = "okay";
    	dr_mode = "host";
    	usb-phy = <&usb_phy0>;
    };
    
    1. 编译u-boot:

    清除中间编译:

    make distclean

    使用配置文件:

    make CROSS_COMPILE=arm-linux-gnueabihf- zynq_zed_defconfig

    通过下述指令可在界面中uboot进行进一步修改配置:改defconfig文件也可以,暂时默认即可

    make CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

    工具编译:

    make CROSS_COMPILE=arm-linux-gnueabihf- tools

    编译u-boot:

    make CROSS_COMPILE=arm-linux-gnueabihf-

    1. 修改总设备树的boottags:console=ttyPS0,115200n8 root=/dev/mmcblk1p2 rw noinitrd rootfstype=ext4 rootwait

    2. 修改uEnv.txt为:mmc 0修改为mmc 1;root=/dev/mmcblk1p2

    bootargs=console=ttyPS0,115200 root=/dev/mmcblk1p2 rw earlyprintk rootfstype=ext4 rootwait
    load_image=fatload mmc 1 ${kernel_load_address} ${kernel_image} && fatload mmc 1 ${devicetree_load_address} ${devicetree_image}
    uenvcmd=echo Copying Linux from SD to RAM... && mmcinfo &&  run load_image && bootm ${kernel_load_address} - ${devicetree_load_address}
    
    1. 组装BOOT.bin,不赘述。
    2. 烧录BOOT.bin到FLASH,对EMMC进行分区,EMMC分区一中放置uImage、devicetree.dtb、uEnv.txt,EMMC分区二中放置文件系统即可。
    3. 启动。
    U-Boot 2018.01-dirty (Jul 26 2021 - 20:05:00 +0800)
    
    Model: Zynq Zed Development Board
    Board: Xilinx Zynq
    Silicon: v3.1
    DRAM:  ECC disabled 512 MiB
    MMC:   sdhci_transfer_data: Error detected in status(0x208000)!
    sdhci@e0101000: 1 (eMMC)
    SF: Detected s25fl128s_64k with page size 256 Bytes, erase size 64 KiB, total 16 MiB
    *** Warning - bad CRC, using default environment
    
    In:    serial@e0000000
    Out:   serial@e0000000
    Err:   serial@e0000000
    Net:   ZYNQ GEM: e000b000, phyaddr 0, interface rgmii-id
    eth0: ethernet@e000b000
    Hit any key to stop autoboot:  0 
    sdhci_transfer_data: Error detected in status(0x208000)!
    switch to partitions #0, OK
    mmc1(part 0) is current device
    Device: sdhci@e0101000
    Manufacturer ID: 13
    OEM: 14e
    Name: Q2J55 
    Tran Speed: 25000000
    Rd Block Len: 512
    MMC version 5.0
    High Capacity: Yes
    Capacity: 7.1 GiB
    Bus Width: 4-bit
    Erase Group Size: 512 KiB
    HC WP Group Size: 8 MiB
    User Capacity: 7.1 GiB WRREL
    Boot Capacity: 16 MiB ENH
    RPMB Capacity: 4 MiB ENH
    reading uEnv.txt
    356 bytes read in 11 ms (31.3 KiB/s)
    Loaded environment from uEnv.txt
    Importing environment from SD ...
    Running uenvcmd ...
    Copying Linux from SD to RAM...
    Device: sdhci@e0101000
    Manufacturer ID: 13
    OEM: 14e
    Name: Q2J55 
    Tran Speed: 25000000
    Rd Block Len: 512
    MMC version 5.0
    High Capacity: Yes
    Capacity: 7.1 GiB
    Bus Width: 4-bit
    Erase Group Size: 512 KiB
    HC WP Group Size: 8 MiB
    User Capacity: 7.1 GiB WRREL
    Boot Capacity: 16 MiB ENH
    RPMB Capacity: 4 MiB ENH
    reading uImage
    4001616 bytes read in 377 ms (10.1 MiB/s)
    reading devicetree.dtb
    17052 bytes read in 18 ms (924.8 KiB/s)
    ## Booting kernel from Legacy Image at 02080000 ...
       Image Name:   Linux-4.14.0-xilinx
       Image Type:   ARM Linux Kernel Image (uncompressed)
       Data Size:    4001552 Bytes = 3.8 MiB
       Load Address: 00008000
       Entry Point:  00008000
       Verifying Checksum ... OK
    ## Flattened Device Tree blob at 02000000
       Booting using the fdt blob at 0x2000000
       Loading Kernel Image ... OK
       Loading Device Tree to 1eb12000, end 1eb1929b ... OK
    

    以上。

  • 相关阅读:
    末学者笔记--KVM虚拟化存储管理(3)
    离线安装docker-ce
    OpenStack各组件的常用命令
    docker容器的基本命令
    nfs samba文件共享服务
    kvm虚拟机管理(创建、连接)
    虚拟化kvm的搭建
    python(pymysql操作数据库)
    三大特征 封装 继承 多态
    面向对象
  • 原文地址:https://www.cnblogs.com/kingstacker/p/15064798.html
Copyright © 2011-2022 走看看