每一个环境变量字符串之间都是用"\0"分割,这是cmdline的格式要求。由于语句太长,为了便于阅读,在定义时,分成了多行的形式,并用行拼接符""来强制拼接。
在C语言中,多个字符串在同一个语句中时,会被预处理,进行合并。所以,虽然代码上看到有很多行字符串,并且分别用"“表示,但是在预处理时,这些字符串由于被”“强制拼接了,所以他们视为一行,属于同一个语句,所以,所有的”“最终将被合并成只有一个”"。
zynq_common.h中定义了这个宏。看看每个变量定义了什么。
为了作为对比,看看zynq_test.h做了哪些修改。
**
以下语句,是zynq_common.h和zynq_test.h一样的。
**
“ethaddr=00:0a:35:00:01:22\0”
定义了以太网MAC地址。
“kernel_image=uImage\0”
定义了内核文件名
“ramdisk_image=uramdisk.image.gz\0”
定义了RAMDISK的文件名。
“devicetree_image=devicetree.dtb\0”
定义了设备树BIN文件的文件名。
“bitstream_image=system.bit.bin\0”
定义了PL侧BIT文件的文件名。
“boot_image=BOOT.bin\0”
定义了BOOT.bin的文件名
“loadbit_addr=0x100000\0”
定义了加载BIT文件到DDR的基地址。可以看到,从1MBytes的位置开始的。
“loadbootenv_addr=0x2000000\0”
定义了读取BOOTENV文件的数据到DDR的基地址。可以看到,从20MBytes的位置开始的。
“fdt_high=0x20000000\0”
定义了FDT的高地址,可以看到,从200MBytes的位置开始的。
“initrd_high=0x20000000\0”
定义了INITRD的高地址,可以看到,也是从200MBytes的位置开始的。
“bootenv=uEnv.txt\0”
定义了BOOTENV文件的文件名。注意大小写。
“loadbootenv=fatload mmc 0 ${loadbootenv_addr} ${bootenv}\0”
定义了LOADBOOTENV命令的具体操作,表示从SD卡读取uEnv.txt文件的内容,放到0x2000000的位置。这是Bootargs的内存地址位置。所以,uEnv.txt存放的,其实是kernel需要的bootargs。
"importbootenv=echo Importing environment from SD …; " \
“env import -t ${loadbootenv_addr} $filesize\0”
定义了IMPORTBOOTENV命令的具体操作,首先echo提示信息,然后import环境变量。从环境变量loadbootenv_addr指定的地址和fatload返回的filesize大小开始import。
“uenvboot=” \
"if run loadbootenv; then " \
"echo Loaded environment from ${bootenv}; " \
"run importbootenv; " \
"fi; " \
"if test -n $uenvcmd; then " \
"echo Running uenvcmd …; " \
"run uenvcmd; " \
“fi\0”
定义了UENVBOOT命令的具体操作。
首先run loadbootenv,从环境变量loadbootenv提取命令行运行,如果返回结果SUCCESS,即能够从uEnv.txt加载bootargs,那么echo,然后把从uEnv.txt加载的内容import到Bootargs数据段。
如果定义了uenvcmd变量,那么就run uenvcmd。
**
以下语句,是zynq_test.h添加的。
**
“kernel_load_address=0x2080000\0”
“ramdisk_load_address=0x4000000\0”
“devicetree_load_address=0x2000000\0”
定义了KERNEL,RAMDISK,DTB的加载地址。
“qboot_addr=0x000000\0”
“qbootenv_addr=0x080000\0”
“qbootenv_size=0x020000\0”
定义了QSPI启动时,BOOT地址,BOOTENV地址,BOOTENV_SIZE。
“qkernel_addr=0x500000\0”
“qramdisk_addr=0x990000\0”
“qdevtree_addr=0x980000\0”
定义了QSPI启动时,KERNEL,RAMDISK,DTB在QFLASH里的存放地址。
**
以下语句,是zynq_common.h和zynq_test.h不同的。
**
以下是zynq_common.h定义的内核,设备树,RAMDISK,BOOTARGS的大小。
“kernel_size=0x500000\0”
“devicetree_size=0x20000\0”
“ramdisk_size=0x5E0000\0”
“boot_size=0xF00000\0”
以下是zynq_test.h定义的内核,设备树,RAMDISK,BOOTSIZE的大小。
“kernel_size=0x480000\0”
“devicetree_size=0x010000\0”
“ramdisk_size=0x600000\0”
“boot_size=0x080000\0”
以下是zynq_common.h定义的MMC_LOADBIT_FAT命令.
"mmc_loadbit_fat=echo Loading bitstream from SD/MMC/eMMC to RAM… && " \
"mmcinfo && " \
"fatload mmc 0 ${loadbit_addr} ${bitstream_image} && " \
“fpga load 0 ${loadbit_addr} ${filesize}\0”
首先echo,并且mmcinfo,获取mmc信息,
然后将system.bit.bin文件的数据,从SD卡加载到0x100000的位置。
如果成功则继续,
将0x100000位置的BIT文件,用FPGA_LOAD命令加载到PL。
以下是zynq_test.h定义的MMC_LOADBIT_FAT命令.
"mmc_loadbit_fat=echo Loading bitstream from SD/MMC/eMMC to RAM… && " \
"get_bitstream_name && mmcinfo && " \
"fatload mmc 0 ${loadbit_addr} ${bitstream_image} && " \
“fpga loadb 0 ${loadbit_addr} ${filesize}\0”
首先echo,并且mmcinfo,获取mmc信息,
然后获取BIT文件名称,用到的命令是GET_BITSTREAM_NAME。该命令将重新定义bitstream_image的值。
然后将文件的数据,从SD卡加载到0x100000的位置。
如果成功则继续,
将0x100000位置的BIT文件,用FPGA_LOADB命令加载到PL。
以下是zynq_common.h定义的NORBOOT命令。
"norboot=echo Copying Linux from NOR flash to RAM… && " \
"cp.b 0xE2100000 0x3000000 ${kernel_size} && " \
"cp.b 0xE2600000 0x2A00000 ${devicetree_size} && " \
"echo Copying ramdisk… && " \
"cp.b 0xE2620000 0x2000000 ${ramdisk_size} && " \
“bootm 0x3000000 0x2000000 0x2A00000\0”
首先echo,
然后从FLASH中拷贝kernel到0x3000000,
然后从FLASH中拷贝devicetree到0x2A00000,
然后echo,
然后从FLASH中拷贝RAMDISH到0x2000000,
然后执行BOOTM命令,启动内核。
以下是zynq_test.h定义的NORBOOT命令。
"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}\0”
首先echo,
然后从FLASH中拷贝kernel到kernel_load_address变量定义的地址,
然后从FLASH中拷贝devicetree到devicetree_load_address变量定义的地址,
然后echo,
然后从FLASH中拷贝RAMDISH到ramdisk_load_address变量定义的地址,
然后执行BOOTM命令,启动内核。
对比可以看出,ZED和zynq_test在这两个命令上的区别,在于ZED加载内核到绝对地址,而zynq_test加载地址由环境变量定义。
以下是zynq_common.h定义的QSPIBOOT命令。
"qspiboot=echo Copying Linux from QSPI flash to RAM… && " \
"sf probe 0 0 0 && " \
"sf read 0x3000000 0x100000 ${kernel_size} && " \
"sf read 0x2A00000 0x600000 ${devicetree_size} && " \
"echo Copying ramdisk… && " \
"sf read 0x2000000 0x620000 ${ramdisk_size} && " \
“bootm 0x3000000 0x2000000 0x2A00000\0”
首先echo,
然后SF_PROBE,探测FLASH,
然后SF_READ,从0x100000处,读取kernel到DDR的0x3000000处,
然后SF_READ,从0x600000 处,读取DTB到DDR的0x2A00000处,
然后echo,
然后然后SF_READ,从0x620000处,读取RAMDISK到DDR的0x2000000处,
然后bootm,启动KERNEL。
以下是zynq_test.h定义的QSPIBOOT命令
"qspiboot=echo Copying Linux from QSPI flash to RAM… && " \
"sf probe 0 0 0 && " \
"qspi_get_bitsize 0x0A0000 && " \
"sf read ${loadbit_addr} 0x0A0004 ${bitsize} && " \
"fpga loadb 0 ${loadbit_addr} ${bitsize} && " \
"sf read ${kernel_load_address} ${qkernel_addr} ${kernel_size} && " \
"sf ${devicetree_load_address} ${qdevtree_addr} ${devicetree_size} && " \
"echo Copying ramdisk… && " \
"sf read ${ramdisk_load_address} ${qramdisk_addr} ${ramdisk_size} && " \
“bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}\0”
区别在于,qspi_get_bitsize命令,从0xA0000处读了4个Bytes的头,并将值传给了bitsize环境变量。
之后,由SF_READ读取BIT文件,加载到loadbit_addr定义的DDR位置,
然后FPGA_LOADB命令下载到PL。
之后的操作,和ZED一样,唯一的区别是,ZED使用绝对地址,zynq_test使用环境变量定义的地址。
以下是zynq_common.h定义的SDBOOT命令。
"sdboot=if mmcinfo; then " \
"run uenvboot; " \
"echo Copying Linux from SD to RAM… && " \
"fatload mmc 0 0x3000000 ${kernel_image} && " \
"fatload mmc 0 0x2A00000 ${devicetree_image} && " \
"fatload mmc 0 0x2000000 ${ramdisk_image} && " \
"bootm 0x3000000 0x2000000 0x2A00000; " \
“fi\0”
首先执行MMCINFO命令,如果成功则继续,
执行uenvboot定义的命令行,
然后echo,
然后FATLOAD,找到对应的文件名,加载kernel到0x3000000,
然后FATLOAD,找到对应的文件名,加载DTB到0x2A00000,
然后FATLOAD,找到对应的文件名,加载RAMDISK到0x2000000,
然后bootm,启动KERNEL。
对于ZED,该命令执行的是,loadbootenv命令行,也就是找到uEnv.txt,并加载BOOTENV。
以下是zynq_test.h定义的SDBOOT命令
"sdboot=if mmcinfo; then " \
"run uenvboot; " \
"get_bitstream_name && " \
"echo - load ${bitname} to PL… && " \
"fatload mmc 0 0x200000 ${bitname} && " \
"fpga loadb 0 0x200000 ${filesize} && " \
"echo Copying Linux from SD to RAM… && " \
"fatload mmc 0 ${kernel_load_address} ${kernel_image} && " \
"fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && " \
"fatload mmc 0 ${ramdisk_load_address} ${ramdisk_image} && " \
"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; " \
“fi\0”
首先和ZED一样,知道uEnv.txt并加载,
然后,区别在于,zynq_test通过GET_BITSTREAM_NAME命令,设置了bitname变量的值,
然后,FATLOAD这个BITNAME文件到0x200000位置,并设置filesize变量,
然后,FPGA_LOADB,加载到PL,
之后的操作,和ZED一样,区别在于,ZED使用绝对地址,zynq_test使用环境变量定义的地址。
以下是zynq_common.h定义的NANDBOOT命令。
"nandboot=echo Copying Linux from NAND flash to RAM… && "
"nand read 0x3000000 0x100000 ${kernel_size} && "
"nand read 0x2A00000 0x600000 ${devicetree_size} && "
"echo Copying ramdisk… && "
"nand read 0x2000000 0x620000 ${ramdisk_size} && "
“bootm 0x3000000 0x2000000 0x2A00000\0”
不再分析。
以下是zynq_test.h定义的SDBOOT命令。
"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}\0”
不再分析。和ZED一样,区别在于,ZED使用绝对地址,zynq_test使用环境变量定义的地址。
以下是zynq_common.h定义的JTAGBOOT命令。
"jtagboot=echo TFTPing Linux to RAM… && "
"tftp 0x3000000 ${kernel_image} && "
"tftp 0x2A00000 ${devicetree_image} && "
"tftp 0x2000000 ${ramdisk_image} && "
“bootm 0x3000000 0x2000000 0x2A00000\0”
不再分析。
以下是zynq_test.h定义的JTAGBOOT命令。
"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}\0”
不再分析。和ZED一样,区别在于,ZED使用绝对地址,zynq_test使用环境变量定义的地址。
以下是zynq_common.h定义的RSA*BOOT命令。
"rsa_norboot=echo Copying Image from NOR flash to RAM… && "
"cp.b 0xE2100000 0x100000 ${boot_size} && "
"zynqrsa 0x100000 && "
“bootm 0x3000000 0x2000000 0x2A00000\0”
"rsa_nandboot=echo Copying Image from NAND flash to RAM… && "
"nand read 0x100000 0x0 ${boot_size} && "
"zynqrsa 0x100000 && "
“bootm 0x3000000 0x2000000 0x2A00000\0”
"rsa_qspiboot=echo Copying Image from QSPI flash to RAM… && "
"sf probe 0 0 0 && "
"sf read 0x100000 0x0 ${boot_size} && "
"zynqrsa 0x100000 && "
“bootm 0x3000000 0x2000000 0x2A00000\0”
"rsa_sdboot=echo Copying Image from SD to RAM… && "
"fatload mmc 0 0x100000 ${boot_image} && "
"zynqrsa 0x100000 && "
“bootm 0x3000000 0x2000000 0x2A00000\0”
"rsa_jtagboot=echo TFTPing Image to RAM… && "
"tftp 0x100000 ${boot_image} && "
"zynqrsa 0x100000 && "
“bootm 0x3000000 0x2000000 0x2A00000\0”
不再分析。
以下是zynq_test.h定义的RSA*BOOT命令。
"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}\0”
"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}\0”
"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}\0”
"rsa_sdboot=echo Copying Image from SD to RAM… && "
"fatload mmc 0 0x100000 ${boot_image} && "
"zynqrsa 0x100000 && "
“bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}\0”
"rsa_jtagboot=echo TFTPing Image to RAM… && "
"tftpboot 0x100000 ${boot_image} && "
"zynqrsa 0x100000 && "
“bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}\0”
不再分析。和ZED一样,区别在于,ZED使用绝对地址,zynq_test使用环境变量定义的地址。
**
以下是zynq_test添加的BOOT方式。
**
"usbboot=if usb start; then "
"run uenvboot; "
"echo Copying Linux from USB to RAM… && "
"fatload usb 0 ${kernel_load_address} ${kernel_image} && "
"fatload usb 0 ${devicetree_load_address} ${devicetree_image} && "
"fatload usb 0 ${ramdisk_load_address} ${ramdisk_image} && "
"bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; "
“fi\0”
配置USB加载方式。暂时不用。
"qspiupdate=echo Update qspi images from sd card… && "
"echo - Init mmc… && mmc rescan && "
"echo - Init qspi flash… && sf probe 0 0 0 && "
"echo - Write boot.bin… && "
"fatload mmc 0 0x200000 boot.bin && "
"sf erase ${qboot_addr} ${boot_size} && "
"sf erase ${qbootenv_addr} ${qbootenv_size} && "
"sf write 0x200000 0 ${filesize} && "
"get_bitstream_name && "
"echo - Write ${bitstream_image}… && "
"fatload mmc 0 0x200000 ${bitstream_image} && "
"sf erase 0x0A0000 0x460000 && "
"mw.l 0x100000 ${filesize} && "
"sf write 0x100000 0x0A0000 4 && "
"sf write 0x200000 0x0A0004 ${filesize} && "
"echo - Write uImage… && "
"fatload mmc 0 0x200000 uImage && "
"sf erase ${qkernel_addr} ${kernel_size} && "
"sf write 0x200000 ${qkernel_addr} ${filesize} && "
"echo - Write device tree… && "
"fatload mmc 0 0x200000 devicetree.dtb && "
"sf erase ${qdevtree_addr} ${devicetree_size} && "
"sf write 0x200000 ${qdevtree_addr} ${filesize} && "
"echo - Write Ramdisk… && "
"fatload mmc 0 0x200000 uramdisk.image.gz && "
"sf erase ${qramdisk_addr} ${ramdisk_size} && "
"sf write 0x200000 ${qramdisk_addr} ${filesize} && "
“echo - Done.\0”
利用SD卡更新QSPI的文件。
首先echo,并MMC_RESCAN,获取MMC信息,
然后echo,并SF_PROBE,探测QFLASH,
然后echo,并FATLOAD,找到文件名boot.bin,并加载到DDR的0x200000的位置,FATLOAD会设置filesize变量。
然后SF_ERASE,之后SF_WRITE刚加载的boot.bin到QFLASH中。
然后GET_BITSTREAM_NAME,设置bitstream_image的值。
然后echo,并FATLOAD,找到文件名,并加载到DDR的0x200000的位置,FATLOAD会设置filesize变量。
然后SF_ERASE,先MWL,把filesize写到0x100000的一个DWORD,之后SF_WRITE,这个DWORD,之后再SF_WRITE之前加载的BIT文件,
然后echo,并FATLOAD,找到文件名uImage,并加载到DDR的0x200000的位置,FATLOAD会设置filesize变量。
然后SF_ERASE,之后SF_WRITE刚才加载的文件uImage。
然后echo,并FATLOAD,找到文件名devicetree.dtb,并加载到DDR的0x200000的位置,FATLOAD会设置filesize变量。
然后SF_ERASE,之后SF_WRITE刚才加载的文件devicetree.dtb,
然后echo,并FATLOAD,找到文件名uramdisk.image.gz,并加载到DDR的0x200000的位置,FATLOAD会设置filesize变量。
然后SF_ERASE,之后SF_WRITE刚才加载的文件uramdisk.image.gz。
最后echo, DONE.