ps端例程学习

Linux系统制作

在制作Linux系统时,需要准备如下文件:

  • system.bit:FPGA端的配置文件,是用来配置FPGA的逻辑部分。
  • zynqmp_fsbl.elf:fsbl全称为First Stage Boot Loader,用来引导uboot。
  • pmufw.elf:底层电源和平台管理相关固件。
  • zynqmp-mzux.dts:设备树文件,告诉Linux这块板子的硬件长什么样。

其中前三个文件由vits导出,而设备树文件zynqmp-mzux.dts由米联客提供。 vits导出步骤如下:将准备好的.xsa硬件文件导入到vits中,编译完成后即可在下图路径中找到相应文件。

alt text

这里需要将system_wrapper.bitfsbl.elf两个文件改为system.bitzynqmp_fsbl.elf文件,否则编译内核的脚本会无法识别。

在准备完所需要的文件后,我们需要在已经配置好的开发环境中制作kernel。具体开发环境部署详见https://www.limfx.pro/ReadArticle/4409/ps-duan-kai-fa-huan-jing-bu-shu 。这里不做赘述。

将vits导出的三个文件(system.bitzynqmp_fsbl.elfpmufw.elf)拷贝进./uisrc-labxlnx/boards/mzux/ubuntu/output/target;将设备树文件zynqmp-mzux.dts分别拷贝进./uisrc-lab-xlnx/sources/uboot/arch/arm/dts./uisrc-lab-xlnx/sources/kernel/arch/arm64/boot/dts/Xilinx

之后在./uisrc-lab-xlnx中打开的终端,一次运行以下指令:

source scripts/mzuxcfg.sh //加载工程配置和环境变量
make_uboot.sh //制作 U-Boot 引导程序
make_kernel.sh //编译 Linux 内核
create_image.sh //把前面生成的启动文件、内核、设备树等内容打包成系统镜像

在制作完系统镜像后,插入SD卡。

make_parted.sh //格式化并分区 SD 卡
deploy_image.sh //把前面制作好的系统内容,真正拷贝到 SD 卡里

这样,就制作好了一个Linux系统,将SD卡插入到FPGA板卡上,上电启动即可。

字符设备驱动与应用

这里以例程hello world进行了字符设备驱动的学习。一般进行开发时,需要准备以下三个文件:

  • KernelPrint.c:驱动程序,是硬件和操作系统之间的桥梁。
  • KernelPrintApp.c:应用层程序,是用户与系统交互的接口。
  • Makefile:编译文件,负责将驱动程序编译为.ko文件,将应用层程序编译为可执行文件。

对于字符设备的驱动,大都围绕着四个函数:openreadwriterelease

//驱动文件描述集合
static struct file_operations drive_fops = {
	.owner = THIS_MODULE,
	.open = KernelPrint_open,
	.read = KernelPrint_read,
	.write = KernelPrint_write,
	.release = KernelPrint_release,
};

同时,在驱动中,必须有init函数和exit函数。这两个函数就相当于应用程序中的main函数,在驱动装载时执行init函数,驱动卸载时执行exit函数。一般会声明装载和卸载接口,然后再去编写装载入口函数和卸载入口函数。

//申明装载入口函数和卸载入口函数
module_init(KernelPrint_init);
module_exit(KernelPrint_exit);

init函数中,一般有以下几个步骤:注册字符设备register_chrdev、创建设备类class_create和创建设备节点device_create。然后在exit函数中,对应的也是依次删除设备device_destroy、删除类class_destroy、注销主设备号unregister_chrdev

在应用程序部分就是通过 open、read、write、close 调用到驱动内部对应的函数,从而实现具体功能的实现。

makefile文件就是自动编译脚本,只需一个make指令就可以进行编译,最终通过编译可以得到KernelPrint.ko和KernelPrintApp可执行文件。具体内容如下:

KERNEL_DIR = /home/uisrc/uisrc-lab-xlnx/sources/kernel #Linux 内核源码目录位置

export ARCH=arm64 #编译给 ARM64 平台使用,这里是进行了交叉编译
export CROSS_COMPILE=aarch64-linux-gnu- #使用 ARM64 的交叉编译工具链

#当前路径
CURRENT_DIR = $(shell pwd)

MODULE = KernelPrint #驱动模块
APP = KernelPrintApp #驱动模块

all : 
#进入并调用内核源码目录中Makefile的规则, 将当前的目录中的源码编译成模块
	make -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules 
	rm -rf *.symvers *.order *.o *.mod.o *.mod.c

ifneq ($(APP), )
	$(CROSS_COMPILE)gcc $(APP).c -o $(APP)
endif

clean : 
	make -C $(KERNEL_DIR) M=$(CURRENT_DIR) clean
	rm $(APP)

#指定编译哪个文件
obj-m += $(MODULE).o

具体操作过程及上板测试

在准备好了驱动、应用以及makefile文件后,可以将其拷贝到已经配置好的开发环境中(装有Ubuntu系统的虚拟机),然后输入make指令进行编译。得到KernelPrint.ko和KernelPrintApp可执行文件后,可以将其拷贝到windows电脑上,以便后续串口或者ssh将该文件传输到板卡上。

这里我选择使用putty进行传输。

putty并不支持rz和sz命令,需要手动去添加。具体可参考https://blog.csdn.net/TragueZw/article/details/127727882 alt text alt text

然后可以通过串口,去输入一些指令,就类似终端一样。

ls #查看文件是否传输成功
su #进入root模式
insmod KernelPrint.ko #安装驱动
lsmod #查看当前安装的驱动
ls /dev #找到对应的设备
chmod 777 KernelPrintApp #改变 “KernelPrintApp”的权限。这里的777分别代表owner/group/others的权限,7=4(r)+2)(w)+1(x),也就是说owner/group/others三者的权限都是可读可写可执行。
./KernelPrintApp /dev/KernelPrint_0 r #测试read
./KernelPrintApp /dev/KernelPrint_0 w "Just do it!" #测试write
dmesg | tail #查看是否成功写入

本文章使用limfx的vscode插件快速发布