一,vivado到vitis流程
ZYNQ MPSoC芯片的特点是,需要fsbl来引导uboot。fsbl全称为First Stage Boot Loader,是用户可以接触到的最早的启动部分。我们使用 vitis 跑裸机代码的时候,fsbl 也发挥作用了,在程序运行前会打印 fsbl 的信息,引导裸机和引导系统都需要 fsbl 文件。
vitis会生成pmufw.elf和system_wrapper.bit这两个文件。pmufw.elf顾名思义就是pmu的管理程序,它负责了板级的电源管理。system_wrapper.bit文件则是PL端的配置文件,通过这个文件我们可以在linux启动时将vivado工程给一并配置至pl端,这样我们就能通过linux与PL端交互了。bit文件不仅会配置pl端,ps端也需要通过bit文件设置,要想让linux系统启动时配置好FPGA 端的逻辑,首先我们得先导出在vivado里设计好的硬件,然后用vitis把它汇编成机器可以识别的bit 文件,最后使用 linux下的工具包将其打包进BOOT.bin文件,也就是uboot。
二,vitis配置流程
1,从vivado2021导入PL端硬件到vitis。生成的硬件文件,以.xsa结尾
2,从桌面打开xilinx vitis 2021中填入路径
3,添加好后,开始新建工程,依次展开file – new – platform project:
点击Browse找到刚刚生成的xsa文件,再如图设置其他参数,点击finish完成设置
编译完毕,{工程位置}\zu_sdk\zu_base\hw\ 生成system_wrapper.bit。设备树也在里面。
{工程位置}\zu_sdk\zu_base\export\zu_base\sw\zu_base\boot\生成fsbl.elf。
把设备树zynqmp-mzux.dts分别复制到lab-xlnx/sources/uboot/arch/arm/dts和lab-xlnx/sources/kernel/arch/arm/boot/dts中,选择覆盖之前里面有的设备树文件。
将system_wrapper.bit、fsbl.elf 两个文件分别改名为system.bit、zynq_fsbl.elf,分别复制到/lab-xlnx/boards/mz7x/ubuntu/output/target中,有的话选择覆盖之前的文件。
三,虚拟机编译启动文件
1, source配置一些环境变量
2,编译uboot启动文件,执行make_uboot.sh
# => Setting The Development Environment Variables
if [ ! "${ZN_CONF_DONE}" ];then
printf "\033[31m[ERROR]\033[0m "
printf "Please source the settings-.sh script first.\n"
exit 1
fi
# => Filename of the running script
ZN_SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
# => Directory containing the running script
ZN_SCRIPT_DIR="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)"
# => Help and information
usage() {
echo "Purpose: build the u-boot and install the image after building."
echo "Usage : ${ZN_SCRIPT_NAME} [option]"
echo "options:"
echo "--help: Display this help message"
exit 0;
}
expr "$*" : ".*--help" > /dev/null && usage
# => The beginning
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Starting ${ZN_SCRIPT_NAME}\n"
# => Make sure the source is there
[[ "$(ls -A ${ZN_UBOOT_DIR})" = "" ]] && \
error_exit "Can't find the source code of u-boot."
# => Building the U-Boot bootloader is a part of the Xilinx design flow.
echo_info "Build U-Boot on the ${ZN_UBOOT_DIR}."
make -C ${ZN_UBOOT_DIR} ${MAKE_JOBS}
if [ $? -eq 0 ]; then
echo_info "Installing the U-Boot Image."
cp ${ZN_UBOOT_DIR}/u-boot ${ZN_TARGET_DIR}/u-boot.elf
else
error_exit "U-Boot - Build Failed"
fi
# => The end
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Finished ${ZN_SCRIPT_NAME}\n"
2,编译制作启动内核/驱动make_kernel.sh
# => Setting The Development Environment Variables
if [ ! "${ZN_CONF_DONE}" ];then
printf "\033[31m[ERROR]\033[0m "
printf "Please source the configs/.sh script first.\n"
exit 1
fi
# => Filename of the running script
ZN_SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
# => Directory containing the running script
ZN_SCRIPT_DIR="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)"
# => Help and information
usage() {
echo "Purpose: Compiling and Installing Linux kernel, Device Tree and module"
echo "Usage : ${ZN_SCRIPT_NAME} [option]"
echo "options:"
echo "--help: Display this help message"
exit 0;
}
expr "$*" : ".*--help" > /dev/null && usage
# => The beginning
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Starting ${ZN_SCRIPT_NAME}\n"
# => Make sure the source is there
[[ "$(ls -A ${ZN_KERNEL_DIR})" = "" ]] && \
error_exit "Can't find the source code of kernel."
# => Make sure the target directory is there
[[ ! "${ZN_TARGET_DIR}" ]] && error_exit "Can't find the target directory."
# => Compiling the Kernel
echo_info "Building the kernel image on the ${ZN_KERNEL_DIR}."
if [ ${ARCH} = arm64 ]; then
make -C ${ZN_KERNEL_DIR} ${MAKE_JOBS}
else
make -C ${ZN_KERNEL_DIR} ${MAKE_JOBS} UIMAGE_LOADADDR=0x8000 uImage
fi
if [ $? -eq 0 ]; then
echo_info "Installing the Kernel Image."
cp -a ${ZN_KERNEL_IMG} ${ZN_TARGET_DIR}
else
error_exit "Kernel Image - Build Failed."
fi
# => Compiling the Device Tree Binaries
echo_info "Building the Device Tree Binaries on the ${ZN_KERNEL_DIR}."
case ${ARCH} in
arm64)
cp ${ZN_DTB_DIR}/${ZN_DTB_NAME} ${ZN_TARGET_DIR}/system.dtb
;;
arm)
${ZN_DTC_DIR}/dtc -I dts -O dtb -o ${ZN_DTB_DIR}/${ZN_DTB_NAME} ${ZN_DTS_DIR}/${ZN_DTS_NAME}
if [ $? -eq 0 ]; then
echo_info "The Device Tree - Build OK"
else
error_exit "The Device Tree - Build Failed"
fi
cp ${ZN_DTB_DIR}/${ZN_DTB_NAME} ${ZN_TARGET_DIR}/devicetree.dtb
;;
*)
echo_error "Unsupported architecture!" && return 1
esac
# => Compiling the Kernel Modules
echo_info "Building the Kernel Modules on the ${ZN_KERNEL_DIR}"
make -C ${ZN_KERNEL_DIR} ${MAKE_JOBS} modules
if [ $? -eq 0 ]; then
echo_info "Installing the Kernel Modules"
ZN_ROOTFS_MOUNT_POINT=${ZN_OUTPUT_DIR}/rootfs
mkdir -p ${ZN_ROOTFS_MOUNT_POINT}
trap "sudo rm -rf ${ZN_ROOTFS_MOUNT_POINT}" EXIT
sudo tar zxf ${ZN_TARGET_DIR}/rootfs.tar.gz -C ${ZN_ROOTFS_MOUNT_POINT}
sudo rm -rf ${ZN_ROOTFS_MOUNT_POINT}/lib/modules/
sudo make -C ${ZN_KERNEL_DIR} ${MAKE_JOBS} \
INSTALL_MOD_PATH=${ZN_ROOTFS_MOUNT_POINT} modules_install
if [ $? -eq 0 ]; then
sudo rm ${ZN_TARGET_DIR}/rootfs.tar.gz
sudo tar zcf ${ZN_TARGET_DIR}/rootfs.tar.gz -C ${ZN_ROOTFS_MOUNT_POINT} .
else
error_exit "The Kernel Modules - Install Failed"
fi
else
error_exit "Kernel Modules - Build Failed"
fi
# => The end
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Finished ${ZN_SCRIPT_NAME}\n"
3,生成文件系统镜像:create_image.sh
# => Setting The Development Environment Variables
if [ ! "${ZN_CONF_DONE}" ];then
printf "\033[31m[ERROR]\033[0m "
printf "Please source the configs/.sh script first.\n"
exit 1
fi
# => Filename of the running script
ZN_SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
# => Directory containing the running script
ZN_SCRIPT_DIR="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)"
# => Help and information
usage() {
echo "Purpose: Building Debian/Ubuntu Image for SD card"
echo "Usage : ${ZN_SCRIPT_NAME} [option]"
echo "options:"
echo "--help: Display this help message"
exit 0;
}
expr "$*" : ".*--help" > /dev/null && usage
# => The beginning
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Starting ${ZN_SCRIPT_NAME}\n"
if [ ${ARCH} = arm64 ]; then
create_zynqmp_image.sh
else
create_zynq_image.sh
fi
# => The end
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Finished ${ZN_SCRIPT_NAME}\n"
五,SD卡分区和系统启动验证
1,格式化并分区 u 盘,先输入盘符,再输入确认:make_parted.sh
# => Setting The Development Environment Variables
if [ ! "${ZN_CONF_DONE}" ];then
printf "\033[31m[ERROR]\033[0m "
printf "Please source the configs/.sh script first.\n"
exit 1
fi
# => Filename of the running script
ZN_SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
# => Directory containing the running script
ZN_SCRIPT_DIR="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)"
# => Help and information
usage() {
echo "Purpose: Repartition SD Card"
echo "Usage : ${ZN_SCRIPT_NAME} [option]"
echo "options:"
echo "--help: Display this help message"
exit 0;
}
expr "$*" : ".*--help" > /dev/null && usage
# => The beginning
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Starting ${ZN_SCRIPT_NAME}\n"
# => Check for dependencies
if ! type parted > /dev/null 2>&1; then
echo_info "Installing parted..."
${SUDO} apt-get update && ${SUDO} apt-get --assume-yes install parted
echo_info "Done!"
fi
# 0、 Plug in your SD Card to your Linux machine.
# 1、Determine what device to use
DISKS=($( grep -Hv ^0$ /sys/block/*/removable | sed s/removable:.*$/device\\/uevent/ |
xargs grep -H ^DRIVER=sd | sed s/device.uevent.*$/size/ | xargs grep -Hv ^0$ |
cut -d / -f 4 ))
for i in "${!DISKS[@]}"; do DISKS[$i]="/dev/${DISKS[$i]}"; done
until [[ -b /dev/${DISK} && ${DISKS[@]/"/dev/${DISK}"/} != ${DISKS[@]} ]]; do
lsblk -d "${DISKS[@]}" -o NAME,RM,SIZE,TYPE,MODEL,SERIAL
print_info "Type device filename, or press to exit: " && read DISK
[[ -z ${DISK} ]] && exit 0
done
# 2. Remove All Existing Partitions
print_warn "ALL DATA ON ${DISK} WILL BE ERASED!!! DO YOU WANT TO CONTINUE [y/N]? " && read REPLY
case ${REPLY} in
y|Y)
echo_info "Umount All Mounted Partitions"
for part in $(lsblk /dev/${DISK} -o mountpoint --noheadings); do
${SUDO} umount ${part}
done
echo_info "Remove All Existing Partitions from ${DISK}"
for PARTITION in $(${SUDO} parted /dev/${DISK} print | awk '/^ /{print $1}'); do
${SUDO} parted -s /dev/${DISK} rm ${PARTITION}
done
echo_info "Choose the MBR Partitioning Standard"
${SUDO} parted -s /dev/${DISK} mklabel msdos
echo_info "Create the fat32 partition of 100MB and make it bootable"
${SUDO} parted -s /dev/${DISK} mkpart primary fat32 0% 100MiB && ${SUDO} parted -s /dev/${DISK} set 1 boot on
echo_info "Create the ext4 partition until end of device"
${SUDO} parted -s /dev/${DISK} mkpart primary ext4 100MiB 100%
echo_info "Re-read The Partition Table Without Rebooting Linux System"
${SUDO} partprobe /dev/${DISK} && sleep 1 && lsblk /dev/${DISK}
# Create a Filesystem on the New Partition
for PARTITION in $(lsblk -l /dev/${DISK} | grep part | awk '{print $1}'); do
PARTNUM=${PARTITION##*[[:alpha:]]}
case ${PARTNUM} in
1)
echo_info "To format a FAT32 filesystem on /dev/${PARTITION} with a 'BOOT' disk label"
${SUDO} mkfs.vfat -F 32 -n "BOOT" /dev/${PARTITION}
;;
2)
echo_info "To format an ext4 filesystem on /dev/${PARTITION} with a 'rootfs' disk label"
echo y | ${SUDO} mkfs.ext4 -L rootfs /dev/${PARTITION}
;;
*)
echo_warn "Extra unintended partition"
;;
esac
done
;;
*)
;;
esac
# => The end
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Finished ${ZN_SCRIPT_NAME}\n"
2,烧写启动文件与系统文件,输入盘符:deploy_image.sh
# => Setting The Development Environment Variables
if [ ! "${ZN_CONF_DONE}" ];then
printf "\033[31m[ERROR]\033[0m "
printf "Please source the configs/.sh script first.\n"
exit 1
fi
# => Filename of the running script
ZN_SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})"
# => Directory containing the running script
ZN_SCRIPT_DIR="$(cd "$(dirname ${BASH_SOURCE[0]})" && pwd)"
# => Help and information
usage() {
echo "Purpose: Deploying Debian/Ubuntu Image to SD card"
echo "Usage : ${ZN_SCRIPT_NAME} [option]"
echo "options:"
echo "--help: Display this help message"
exit 0;
}
expr "$*" : ".*--help" > /dev/null && usage
# => The beginning
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Starting ${ZN_SCRIPT_NAME}\n"
# 0、 Plug in your SD Card to your Linux machine.
# 1、Determine what device to use
DISKS=($( grep -Hv ^0$ /sys/block/*/removable | sed s/removable:.*$/device\\/uevent/ |
xargs grep -H ^DRIVER=sd | sed s/device.uevent.*$/size/ | xargs grep -Hv ^0$ |
cut -d / -f 4 ))
for i in "${!DISKS[@]}"; do DISKS[$i]="/dev/${DISKS[$i]}"; done
until [[ -b /dev/${DISK} && ${DISKS[@]/"/dev/${DISK}"/} != ${DISKS[@]} ]]; do
lsblk -d "${DISKS[@]}" -o NAME,RM,SIZE,TYPE,MODEL,SERIAL
print_info "Type device filename, or press to exit: " && read DISK
[[ -z ${DISK} ]] && exit 0
done
# 2、
echo_info "Umount All Mounted Partitions"
for PART in $(lsblk /dev/${DISK} -o mountpoint --noheadings); do
${SUDO} umount ${PART}
done
# 3、
SDCARD_MOUNT_POINT=${ZN_OUTPUT_DIR}/sdcard && mkdir -p ${SDCARD_MOUNT_POINT}
trap "sudo umount ${SDCARD_MOUNT_POINT} &> /dev/null; sudo rm -rf ${SDCARD_MOUNT_POINT}" EXIT
for PARTITION in $(lsblk -l /dev/$DISK | grep part | awk '{print $1}'); do
PARTNUM=${PARTITION##*[[:alpha:]]}
case ${PARTNUM} in
1)
[[ $(lsblk -no FSTYPE /dev/${PARTITION}) != 'vfat' ]] && \
error_exit "No bootable device found"
echo_info "Mount the boot partition to ${SDCARD_MOUNT_POINT}"
${SUDO} mount -t vfat /dev/${PARTITION} ${SDCARD_MOUNT_POINT}
echo_info "Install boot images to ${SDCARD_MOUNT_POINT}"
${SUDO} rsync -rv ${ZN_IMAGES_DIR}/boot/ ${SDCARD_MOUNT_POINT} && sync
echo_info "Umount the boot partition from ${SDCARD_MOUNT_POINT}"
${SUDO} umount ${SDCARD_MOUNT_POINT}
;;
2)
[[ $(lsblk -no FSTYPE /dev/${PARTITION}) != 'ext4' ]] && \
error_exit "No rootfs partition found"
echo_info "Mount the rootfs partition to ${SDCARD_MOUNT_POINT}"
${SUDO} mount -t ext4 /dev/${PARTITION} ${SDCARD_MOUNT_POINT}
if [ "$(ls -A ${SDCARD_MOUNT_POINT})" != "lost+found" ]; then
${SUDO} umount ${SDCARD_MOUNT_POINT}
error_exit "The ROOTFS partition is dirty, please clean it!"
fi
echo_info "Install rootfs images to ${SDCARD_MOUNT_POINT}"
${SUDO} tar zxmf ${ZN_IMAGES_DIR}/rootfs/rootfs.tar.gz -C ${SDCARD_MOUNT_POINT} && sync
if [ -d "${ZN_IMAGES_DIR}/custom" ];then
${SUDO} rsync -av ${ZN_IMAGES_DIR}/custom/ ${SDCARD_MOUNT_POINT} && sync
fi
if [ -d "${ZN_IMAGES_DIR}/recovery" ];then
${SUDO} rsync -av ${ZN_IMAGES_DIR}/recovery ${SDCARD_MOUNT_POINT} && sync
${SUDO} rsync -av ${ZN_IMAGES_DIR}/boot/ ${SDCARD_MOUNT_POINT}/recovery/boot && sync
${SUDO} rsync -av ${ZN_IMAGES_DIR}/custom/ ${SDCARD_MOUNT_POINT}/recovery/custom && sync
${SUDO} rsync -av ${ZN_IMAGES_DIR}/rootfs/ ${SDCARD_MOUNT_POINT}/recovery/rootfs && sync
fi
echo_info "umount the rootfs partition from ${SDCARD_MOUNT_POINT}"
${SUDO} umount ${SDCARD_MOUNT_POINT}
;;
*)
echo_warn "Extra unintended partition"
;;
esac
done
# => The end
print_info "[ $(date "+%Y/%m/%d %H:%M:%S") ] Finished ${ZN_SCRIPT_NAME}\n"
3,将模式开关拨至SD卡启动模式,再给ZYNQ上电验证