zynq linux开发笔记

Zynq linux开发笔记

1 petalinux

1.1 petalinux命令

1.1.1 工程创建

创建工程:
petalinux-create -t project -n vanjee --template zynq

导入/配置工程硬件信息:
petalinux-config --get-hw-description ../linux_base.sdk

1.1.2 组件配置

配置全部:
petalinux-config

配置uboot:
petalinux-config -c u-boot

配置设备树:
petalinux-config -c device-tree

配置内核:
petalinux-config -c kernel

配置rootfs:
petalinux-config -c rootfs

1.1.3 组件编译

编译全部:
petalinux-build

编译uboot:
petalinux-build -c u-boot

编译设备树:
petalinux-build -c device-tree
[注]:如果不是第一次编译设备树,即使修改了设备树执行上述命令也不会生成dtb文件,这时应先执行:
petalinux-build -c device-tree -x cleansstate 
清理编译状态后再编译设备树。

编译内核:
petalinux-build -c kernel

编译根文件系统:
petalinux-build -c rootfs

编译工具链,可以独立编译应用:
petalinux-build -c meta-toolchain
或者使用:
petalinux-build --sdk,petalinux-package --sysroot
命令编译出交叉编译工具链,这样只会在 images/linux/sdk文件夹下就生成了编译工具和sysroot。

如果编译过程中出现异常 , 下一次编译的时候可以用:
petalinux-build -x mrproper 
清除之后重新编译

1.1.4 生成BOOT文件

仅打包fsbl、pl的bit流、u-boot:
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga --u-boot --force

仅打包fsbl、pl的bit流、u-boot和kernel:
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga --u-boot --kernel --force

如需将根文件系统一起打包:
petalinux-package --boot --u-boot --kernel --add images/linux/rootfs.jffs2 --offset <partition offset given for jffs2>
例如:
petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --fpga --u-boot --kernel --add images/linux/rootfs.jffs2 --offset 0x00fa0000 --force

1.1.5 常见错误

1.1.5.1 bb.data_smart.ExpansionError: Failure expanding variable do_compile[file-checksums]

【错误截图】:
image

【错误原因】
petalinux 2018.3编译时由于某种原因(尚未可知),删除了<project_root-path>/build/downloads目录,导致编译时找不到git版本库,查看<project_root-path>/build/bitbake-cookerdaemon.log,可以证实:
image

【解决办法】
重新建立个测试工程,编译之后将其<project_root-path>/build/downloads拷贝到目标工程对应的文件夹<project_root-path>/build/下,再重新编译目标工程即可。

1.1.6 petalinux常用配置

1.1.6.1 源码保留

petalinux 2018.3 编译完成自动删除,如果想保留,可以在<project_root-path>/project-spec/meta-user/conf/petalinuxbsp.conf中添加以下内容,重新config并build工程即可:

RM_WORK_EXCLUDE += "linux-xlnx"
RM_WORK_EXCLUDE += "u-boot-xlnx"
1.1.6.2 自定义bootargs和root设备

如需在uboot启动时自定义bootargs,则需在petalinux-config时使能设备树自动生成并取消bootargs的自动生成,如下所示:
image

image
然后输入自定义的bootargs即可。

若需在uboot启动时自定义root设备,则需在则需在petalinux-config时选择Root filesystem type为other,如下图所示:
image

常用bootargs:

从flash启动:
setenv bootargs "console=ttyPS0,115200 earlyprintk rootfstype=jffs2 root=/dev/mtdblock3 rw rootwait"

从SD卡(单分区)启动:
setenv bootargs "console=ttyPS0,115200 earlyprintk root=/dev/mmcblk0 rw rootwait"

从initramfs(内核中含initramfs)启动:
setenv bootargs "console=ttyPS0,115200 earlyprintk" 

1.2 常用文件路径

设备树:
<project_root-path>/components/plnx_workspace/device-tree/device-tree/

system-user.dtsi:
<project_root-path>/project-spec/meta-user/recipes-bsp/device-tree/files

uboot源码:
<project_root-path>/build/tmp/work/plnx_zynq7-xilinx-linux-gnueabi/u-boot-xlnx/v2018.01-xilinx-v2018.3+gitAUTOINC+d8fc4b3b70-r0/git

uboot配置文件.config:
<project_root-path>/build/tmp/work/plnx_zynq7-xilinx-linux-gnueabi/u-boot-xlnx/v2018.01-xilinx-v2018.3+gitAUTOINC+d8fc4b3b70-r0/build/.config
eg:
cp ~/disk/zynq/board/tst/tst/build/tmp/work/plnx_zynq7-xilinx-linux-gnueabi/u-boot-xlnx/v2018.01-xilinx-v2018.3+gitAUTOINC+d8fc4b3b70-r0/build/.config ~/disk/zynq/board/alinx/alinx/build/tmp/work/plnx_zynq7-xilinx-linux-gnueabi/u-boot-xlnx/v2018.01-xilinx-v2018.3+git999-r0/u-boot-xlnx-v2018.01-xilinx-v2018.3+git999/

内核源码:
<project_root-path>/build/tmp/work-shared/plnx-zynq7/kernel-source

1.3 uboot快捷命令

1.3.1 快捷指令1

setenv ipaddr 192.168.8.138
setenv serverip 192.168.8.177
setenv bootargs "console=ttyPS0,115200 earlyprintk rootfstype=jffs2 root=/dev/mtdblock3 rw rootwait"
setenv update_all "tftpboot 0x10000000 BOOT.BIN && sf probe 0 0 && sf erase 0 0x2000000 && sf write 0x10000000 0 0x2000000"
setenv update_boot "tftpboot 0x10000000 BOOT.BIN && sf probe 0 0 && sf erase 0 0x1E0000 && sf write 0x10000000 0 0x1E0000"
setenv update_rfs "tftpboot 0x10000000 rootfs.jffs2 && sf probe 0 0 && sf erase 0x700000 0x01900000 && sf write 0x10000000 0x700000 0x01900000"
setenv update_core "tftpboot 0x10000000 image.ub && sf probe 0 0 && sf erase 0x200000 0xA00000 && sf write 0x10000000 0x200000 0xA00000"
setenv pri_dtb "tftpboot 0x10000000 system.dtb && fdt addr 0x10000000 && fdt print"
setenv tst_core "tftpboot 0x10000000 image.ub && tftpboot 0x12000000 system.dtb && bootm 0x10000000 - 0x12000000"
setenv tst_corez "tftpboot 0x10000000 zImage && tftpboot 0x12000000 system.dtb && bootz 0x10000000 - 0x12000000"
saveenv

1.3.2 其它指令

1.3.2.1 uboot查看设备树指令
tftp加载设备树到内存地址0x10000000:
tftpboot 0x10000000 system.dtb

设置fdt地址为0x10000000:
fdt addr 0x10000000

查看设备树:
仅查看当前层:fdt list <path> [<prop>] - Print one level starting at <path>
查看当前层及子目录:fdt print <path> [<prop>] - Recursive print starting at <path>
例如:
fdt list /amba/spi@e000d000
fdt print /amba/spi@e000d000

2 zinux_cc

2.1 相关脚本

2.1.1 newproj.sh

功能:创建项目
代码:

#!/bin/sh

#0 参数合法性校验
#eg:./newproj.sh design_1_wrapper.hdf
if [ "$#" != 1 ];then
    echo "Invalid input params!Eg:./newproj.sh design_1_wrapper.hdf" 
    exit -1
fi

echo "[HDF FILE]:$1"

#1 相关变量定义
LIB_PATH=/home/zynq/zynq_lib
MAKE_PATH=/usr/bin/make

#2 获取当前路径
cd ..
ROOT_PATH=$(pwd)
echo "[ROOT PATH]:$ROOT_PATH"

#3 检查相关组件和库是否正确安装
if [ ! -f $LIB_PATH/device-tree-xlnx-xilinx-v2018.3.tar.gz ];then
    echo "Can not find device-tree-xlnx-xilinx-v2018.3.tar.gz in $LIB_PATH"
    exit -1
fi

if [ ! -f $LIB_PATH/embeddedsw-xilinx-v2018.3.tar.gz ];then
    echo "Can not find embeddedsw-xilinx-v2018.3.tar.gz in $LIB_PATH"
    exit -1
fi

if [ ! -f $LIB_PATH/u-boot-xlnx-xilinx-v2018.3.tar.gz ];then
    echo "Can not find u-boot-xlnx-xilinx-v2018.3.tar.gz in $LIB_PATH"
    exit -1
fi

if [ ! -f $LIB_PATH/linux-xlnx-xilinx-v2018.3.tar.gz ];then
    echo "Can not find linux-xlnx-xilinx-v2018.3.tar.gz in $LIB_PATH"
    exit -1
fi

[ -f /usr/bin/gmake ] || sudo ln -s $MAKE_PATH /usr/bin/gmake
[ -d $LIB_PATH/device-tree-xlnx-xilinx-v2018.3 ] || tar xvf $LIB_PATH/device-tree-xlnx-xilinx-v2018.3.tar.gz -C $LIB_PATH
[ -d $LIB_PATH/embeddedsw-xilinx-v2018.3 ] || tar xvf $LIB_PATH/embeddedsw-xilinx-v2018.3.tar.gz -C $LIB_PATH
[ -d $ROOT_PATH/u-boot-xlnx-xilinx-v2018.3 ] || tar xvf $LIB_PATH/u-boot-xlnx-xilinx-v2018.3.tar.gz -C $ROOT_PATH
[ -d $ROOT_PATH/linux-xlnx-xilinx-v2018.3 ] || tar xvf $LIB_PATH/linux-xlnx-xilinx-v2018.3.tar.gz -C $ROOT_PATH

#4 根据hdf文件($1)生成bit流和ps端初始化的c和h文件 && 生成设备树
[ -d $ROOT_PATH/ps_init ] && rm -rf $ROOT_PATH/ps_init 
mkdir $ROOT_PATH/ps_init


cd $ROOT_PATH/ps_init

cp $ROOT_PATH/proj/$1 system.hdf

xsct $ROOT_PATH/proj/initproj.tcl

#5 u-boot和kernel添加设备树
cp $ROOT_PATH/ps_init/dts/pcw.dtsi dts/pl.dtsi $ROOT_PATH/ps_init/dts/system-top.dts dts/zynq-7000.dtsi $ROOT_PATH/u-boot-xlnx-xilinx-v2018.3/arch/arm/dts
cp $ROOT_PATH/ps_init/dts/pcw.dtsi dts/pl.dtsi $ROOT_PATH/ps_init/dts/system-top.dts dts/zynq-7000.dtsi $ROOT_PATH/linux-xlnx-xilinx-v2018.3/arch/arm/boot/dts

#6 拷贝用户文件
if [ -f $ROOT_PATH/user/list ];then
    while read line
    do
        src=`echo $line | awk -F " " '{print $1}'` 
        dst=`echo $line | awk -F " " '{print $2}'`
        echo "copy ROOT_PATH/user/$src to ROOT_PATH/$dst"
        cp $ROOT_PATH/user/$src $ROOT_PATH/$dst
    done <$ROOT_PATH/user/list
fi
#n 清理相关编译中间文件
cd $ROOT_PATH/ps_init/fsbl && cp executable.elf zynq_fsbl.elf && make clean

2.1.2 initproj.tcl

功能:根据hdf文件创建设备树和bit流文件以及ps初始化的c和h文件
代码:

#!/usr/bin/tclsh

#1 generate pl bit stream file & ps init c & h file 
hsi::open_hw_design system.hdf

#2 generate device tree
hsi::set_repo_path /home/zynq/zynq_lib/device-tree-xlnx-xilinx-v2018.3
hsi::create_sw_design device-tree -os device_tree -proc ps7_cortexa9_0
hsi::generate_target -dir ./dts

#3 generate fsbl.elf
hsi::set_repo_path /home/zynq/zynq_lib/embeddedsw-xilinx-v2018.3
hsi::generate_app -hw design_1_wrapper -os standalone -proc ps7_cortexa9_0 -app zynq_fsbl -compile -sw fsbl -dir ./fsbl

2.1.3 pack.sh

功能:用于编译之后打包镜像
代码:

#!/bin/sh

#1 记录root目录
cd ..
ROOT_PATH=$(pwd)

#2 检查相关文件是否准备就绪
if [ ! -f $ROOT_PATH/linux-xlnx-xilinx-v2018.3/arch/arm/boot/zImage ];then
    echo "can not find zImage!"
    exit -1
fi

if [ ! -f $ROOT_PATH/linux-xlnx-xilinx-v2018.3/arch/arm/boot/dts/system-top.dtb ];then
    echo "can not find system-top.dtb!"
    exit -1
fi

if [ ! -f $ROOT_PATH/ps_init/design_1_wrapper.bit ];then
    echo "can not find design_1_wrapper.bit!"
    exit -1
fi

if [ ! -f $ROOT_PATH/ps_init/fsbl/zynq_fsbl.elf ];then
    echo "can not find zynq_fsbl.elf!"
    exit -1
fi

if [ ! -f $ROOT_PATH/u-boot-xlnx-xilinx-v2018.3/u-boot ];then
    echo "can not find u-boot!"
    exit -1
fi

#3 进入image文件夹
[ -d image ] || mkdir image
cd image
[ "$(ls -A .)" ] && rm ./*

#4 合成BOOT.BIN
cp $ROOT_PATH/u-boot-xlnx-xilinx-v2018.3/u-boot u-boot.elf
cp $ROOT_PATH/ps_init/fsbl/zynq_fsbl.elf .
bootgen -image $ROOT_PATH/proj/boot.bif -o BOOT.bin -w on
rm u-boot.elf zynq_fsbl.elf

#5 拷贝文件到image文件夹
cp $ROOT_PATH/ps_init/design_1_wrapper.bit system.bit
cp $ROOT_PATH/linux-xlnx-xilinx-v2018.3/arch/arm/boot/dts/system-top.dtb system.dtb
cp $ROOT_PATH/linux-xlnx-xilinx-v2018.3/arch/arm/boot/zImage .

echo "pack success!"

2.1.4 boot.bif

功能:用于配置bootgen生成BOOT.bin
源码:

the_ROM_image:
{
[bootloader]zynq_fsbl.elf
u-boot.elf
}

2.1.5 list

功能:位于根目录user目录下,用于在执行newproj.sh创建项目时,将用户指定的自定义文件拷贝或者替换至自动生成的源码文件
格式:
[user下对应文件夹]/[源文件名] [目的文件夹/目的文件]

文件内容:

dts/system-top.dts	u-boot-xlnx-xilinx-v2018.3/arch/arm/dts
dts/system-top.dts	linux-xlnx-xilinx-v2018.3/arch/arm/boot/dts
boot/.config		u-boot-xlnx-xilinx-v2018.3/
boot/Makefile		u-boot-xlnx-xilinx-v2018.3/arch/arm/dts
boot/zynq-common.h	u-boot-xlnx-xilinx-v2018.3/include/configs
boot/zynq_zc70x.h	u-boot-xlnx-xilinx-v2018.3/include/configs
kernel/Makefile		linux-xlnx-xilinx-v2018.3/arch/arm/boot/dts

2.2 启动指令

2.2.1 TFTP网络启动内核

setenv serverip 192.168.8.139
setenv ipaddr 192.168.8.168
setenv bitstream_load_address 0x100000
setenv kernel_load_address 0x2080000
setenv devicetree_load_address 0x2000000
setenv bitstream_image system.bit
setenv bitstream_size 0x300000
setenv kernel_image zImage
setenv devicetree_image system.dtb
setenv netboot 'tftpboot ${bitstream_load_address} ${bitstream_image} && fpga loadb 0 ${bitstream_load_address} ${bitstream_size} && tftpboot ${kernel_load_address} ${kernel_image} && tftpboot ${devicetree_load_address} ${devicetree_image} && bootz ${kernel_load_address} - ${devicetree_load_address}'

2.2.2 SD启动指令

setenv bitstream_load_address 0x100000
setenv kernel_load_address 0x2080000
setenv devicetree_load_address 0x2000000
setenv bitstream_image system.bit
setenv bitstream_size 0x300000
setenv kernel_image zImage
setenv devicetree_image system.dtb
setenv sdboot 'if mmcinfo; then run uenvboot; echo Copying Linux from SD to RAM... && load mmc 0 ${bitstream_load_address} ${bitstream_image} && fpga loadb 0 ${bitstream_load_address} ${bitstream_size} && load mmc 0 ${kernel_load_address} ${kernel_image} && load mmc 0 ${devicetree_load_address} ${devicetree_image} && bootz ${kernel_load_address} - ${devicetree_load_address}; fi'
setenv pri_dtb "load mmc 0 ${devicetree_load_address} ${devicetree_image} && fdt addr ${devicetree_load_address} && fdt print"

2.2.3 eMMC启动指令

setenv bitstream_load_address 0x100000
setenv kernel_load_address 0x2080000
setenv devicetree_load_address 0x2000000
setenv bitstream_image system.bit
setenv bitstream_size 0x300000
setenv kernel_image zImage
setenv devicetree_image system.dtb
setenv emmcboot 'if mmc dev 1 && mmcinfo; then run uenvboot; echo Copying Linux from eMMC to RAM... && load mmc 1 ${bitstream_load_address} ${bitstream_image} && fpga loadb 0 ${bitstream_load_address} ${bitstream_size} && load mmc 1 ${kernel_load_address} ${kernel_image} && load mmc 1 ${devicetree_load_address} ${devicetree_image} && bootz ${kernel_load_address} - ${devicetree_load_address}; fi'
setenv pri_dtb "load mmc 1 ${devicetree_load_address} ${devicetree_image} && fdt addr ${devicetree_load_address} && fdt print"
setenv bootcmd 'run emmcboot'

2.3 bootargs配置

2.3.1 NFS启动bootargs

 启动bootargs如下设置:

setenv bootargs 'console=ttyPS0,115200 earlyprintk rootfstype=nfsroot root=/dev/nfs rw nfsroot=192.168.8.139:/home/bear/nfsroot/rootfs,proto=tcp,nfsvers=3,nolock ip=192.168.8.168:192.168.8.139:192.168.8.1:255.255.255.0::eth0:off uio_pdrv_genirq.of_id=generic-uio'

 若启动时提示以下错误:
image
 需要将rootfs目录所有者设置为root.

2.3.2 SD启动bootargs

setenv bootargs 'console=ttyPS0,115200 earlyprintk root=/dev/mmcblk0p2 rw rootwait uio_pdrv_genirq.of_id=generic-uio'

2.3.3 eMMC启动bootargs

setenv bootargs 'console=ttyPS0,115200 earlyprintk root=/dev/mmcblk1p2 rw rootwait uio_pdrv_genirq.of_id=generic-uio'

3 QSPI Flash启动

3.1 petalinux配置

3.2 内核flash错误修改

 内核启动时,出现以下错误:

m25p80 spi0.0: found w25q256, expected n25q512a
m25p80 spi0.0: failed to read ear reg
m25p80 spi0.0: w25q256 (32768 Kbytes)

 第一行错误是因为,petaLinux默认设备树中的flash为n25q512a,修改系统设备树system-conf.dtsi为w25q256即可,如下图所示:
image
 或者我们可以修改system-user.dtsi,修改后内容如下:

/include/ "system-conf.dtsi"
/ {
};

&flash0 {
	compatible = "w25q256";
};

 第二行的错误是因为,Zynq QSPI flash 控制器只支持3字节的地址,因此只支持最大128Mbit的QSPI flash。 如果要支持更大的flash,需要使用QSPI flash中的bank寄存器。
 而函数read_ear则正是为了读取bank/扩展地址寄存器,如下所示:

/**
 * read_ear - Get the extended/bank address register value
 * @nor:	Pointer to the flash control structure
 *
 * This routine reads the Extended/bank address register value
 *
 * Return:	Negative if error occured.
 */
static int read_ear(struct spi_nor *nor, struct flash_info *info)
{
	int ret;
	u8 val;
	u8 code;

	/* This is actually Spansion */
	if (JEDEC_MFR(info) == CFI_MFR_AMD)
		code = SPINOR_OP_BRRD;
	/* This is actually Micron */
	else if (JEDEC_MFR(info) == CFI_MFR_ST ||
		 JEDEC_MFR(info) == CFI_MFR_MACRONIX ||
		 JEDEC_MFR(info) == SNOR_MFR_ISSI)
		code = SPINOR_OP_RDEAR;
	else
		return -EINVAL;

	ret = nor->read_reg(nor, code, &val, 1);
	if (ret < 0)
		return ret;

	return val;
}

 对应w25q256的数据手册如下:
image
 但是在read_ear函数中未对winbond进行支持,以至于其返回的值为-EINVAL,而winbond应该返回的值为SPINOR_OP_RDEAR(0xC8),故修改代码如下:

/* This is actually Spansion */
if (JEDEC_MFR(info) == CFI_MFR_AMD)
	code = SPINOR_OP_BRRD;
/* This is actually Micron */
else if (JEDEC_MFR(info) == CFI_MFR_ST ||
	 JEDEC_MFR(info) == CFI_MFR_MACRONIX ||
	 JEDEC_MFR(info) == CFI_MFR_ISSI ||
	 JEDEC_MFR(info) == SNOR_MFR_WINBOND)
	code = SPINOR_OP_RDEAR;
else
	return -EINVAL;

 如此再对内核代码进行编译,则无上述错误提示。

4 UIO相关

4.1 linux的中断

4.1.1 GPIO编号

 Zynq7020的GPIO包括:54个MIO和192个EMIO(64个输入和128个输出),其中MIO是PS这边的,而EMIO是PL这边的,不过EMIO内部和PS端相连,而MIO是能直接拉出到外部引脚上。
 从UG585中可以看到,Zynq7020的GPIO分为了4组,其中BANK0和BANK1是MIO,共有54个,编号为0~53;BANK2和BANK3是EMIO,共有64个,编号为54 ~ 117。
 进入到/sys/class/gpio目录下可以看到只有一个gpiochip906,代表它的第一个gpio是从906开始的,前面54个为MIO,如果要操作EMIO的第一个引脚,则文件描述符计算为:906+54=960。

4.1.2 Zynq7020的中断

4.1.2.1 中断总体结构

 Zynq7020的GIC控制器结构如图所示:
image
 上图中间部分为GIC,也即中断控制器,用于对中断进行使能、关闭、掩码、设置优先等。Zynq中断大致可分为三个部分:SGI,软件生成的中断,共16个端口;PPI,CPU私有外设中断,有5个;SPI,共享外设中断,来自于44个PS端的IO外设以及16个PL端的中断。
 具体中断 IRQ ID如下表所示:
image
image
image
image

4.1.2.2 设备树interrupts属性

 在设备树⾥⾯,中断使⽤interrupts来描述。interrupts属性后⾯,会有不同的参数,一般是三个,有时是两个。
三个的时候:
第⼀个参数表⽰中断类型:0 则代表了SPI类型 ,1代表PPI类型
第⼆个参数表⽰:中断号,表示是第⼀个中断类型⾥⾯的第⼏个中断
第三个参数表⽰:中断触发方式:上升沿、下降沿、电平等

中断类型:
IPI:inter-processer interrupt 中断号0~15
PPI:per processor interrupts 中断号16~31
SPI:shared processor interrupts 中断号 32 ~32+224
SGI:software generated interrupts (SGI).
中断触发方式:
#define IRQ_TYPE_NONE 0
#define IRQ_TYPE_EDGE_RISING 1
#define IRQ_TYPE_EDGE_FALLING 2
#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
#define IRQ_TYPE_LEVEL_HIGH 4
#define IRQ_TYPE_LEVEL_LOW 8

 实例如下:

gpio0: gpio@e000a000 {
	compatible = "xlnx,zynq-gpio-1.0";
	#gpio-cells = <2>;
	clocks = <&clkc 42>;
	gpio-controller;
	interrupt-controller;
	#interrupt-cells = <2>;
	interrupt-parent = <&intc>;
	interrupts = <0 20 4>;
	reg = <0xe000a000 0x1000>;
};

 interrupt-controller;是一个没有值的属性,用以表明这个节点描述的是一个中断控制器。
 #interrupt-cells = <2>;表示:该节点的所有子节点的interrupts属性含两个参数。
 interrupts = <0 20 4>;表示:中断类型为SPI;中断号为SPI里面的第20个(SPI中断号从32开始,故该中断号为32+20=52);中断触发方式为高电平触发。

 两个的时候⼀般是这样出现:

touchscreen@0 {
	interrupt-parent = <&gpio0>;
	interrupts = <10 4>; /* MIO10, level high */
};

 上述表示:中断控制器是gpio0;使⽤中断控制器gpio0的10号中断(这⾥的10号,对应MIO10号引脚);4是指触发的⽅式为高电平触发。

 另外ZynqMP和Zynq的一个区别需要注意,ZynqMP的interrupt-parent指向的是&gic, 而Zynq指向了&intc。其实可以再看看其他的dtsi文件,可以发现,intc其实也是指向了CPU的gic,所以说实际上是一样的,并没有使用PL侧的INTC IP核中断。

 UIO机制中虽然包含四种中断方式(高电平、低电平、上升沿、下降沿),但在zynq中只支持2种(高电平、上升沿)。

4.1.2.3 Zynq7020 MIO/EMIO中断号列表

引脚号 全局中断号 设备树中断号 备注 实例
MIO0~53 共用gpio0中断号:52 0~53 中断控制器为gpio0 MIO10中断配置:interrupt-parent = <&gpio0>;interrupts = <10 4>;
EMIO0~7 61~68 29~36 中断控制器为intc,ZynqMP为gic,中断类型为0:SPI,实际中断号需减去SPI中断偏移32 EMIO3中断配置:interrupt-parent = <&intc>;interrupts = <0 32 4>;
EMIO8~15 84~91 52~59 中断控制器为intc,ZynqMP为gic,中断类型为0:SPI,实际中断号需减去SPI中断偏移32 EMIO9中断配置:interrupt-parent = <&intc>;interrupts = <0 53 4>;

4.2 坑人的问题

 原计划PS端与PL端利用UIO进行交互,利用UIO实现内存的访问和中断的获取,设备树配置如下:

reserved-memory {
	#address-cells = <1>;
	#size-cells = <1>;
	ranges;

	reserved: buffer@0x10000000 {
	    //no-map;
	    reg = <0x10000000 0x200000>;
	};
};

shared-ddr {
	compatible = "generic-uio";
	linux,uio-name = "ps-pl-ddr";
	reg = <0x10000000 0x200000>;
};

pl2ps-irq0 {
	compatible = "generic-uio";
	status = "okay";
	interrupt-controller;
	interrupt-parent = <&gpio0>;
	interrupts = <11 3>;//MIO11
};

pl2ps-irq1 {
	compatible = "generic-uio";
	status = "okay";
	interrupt-controller;
	interrupt-parent = <&gpio0>;
	interrupts = <12 3>;//MIO12		
};

 上述设备树中,内存的读写已经实现。UIO中断通过MIO上的按键去模拟,但是中断始终无法触发!!!!遍访google,百度,yandex!!!花了整整10天时间,未能解决!!追踪过内核代码,各种修改设备树,均已失败告终!!按键都快按坏。
 尝试通过devmem去写寄存器控制MIO,但是发现devmem无法操作MIO的寄存器,再次百度得知:“由于新内核中启用了电源管理机制,内核默认将设备处于暂停状态,从而使用devmem读写寄存器失败,关闭电源管理机制后能解决该问题”。参考链接如下:https://blog.csdn.net/zhaoxinfan/article/details/94048340
 将下面图中红框的选项取消:
image
image
 然后重新编译内核,烧写。
 发现此时devmem已能够读写寄存器!同时UIO中断已经能够触发了!

5 设备挂载initramfs根文件系统

5.1 内核的配置

image

image

image

 第三张截图中 Default number of RAM disks 一般设置为8,最小设置为1;Default RAM disk size设置为ramdisk镜像的大小,此处设置为32M,若要增加ramdisk镜像的空间,此处要对应修改。

5.2 ramdisk镜像的制作

#!/bin/sh

[ -f ramdisk.gz ] && rm ramdisk.gz
[ -f ramdisk.gz_test ] && rm ramdisk.gz_test
[ -f uramdisk.img.gz ] && rm uramdisk.img.gz

sudo dd if=/dev/zero of=ramdisk bs=1024 count=32768
sudo mke2fs -F -m0 ramdisk #格式化,-F强制,-m0不为管理员预留空间
sudo mount -t ext2 ramdisk ramfs
cd ramfs
sudo cp /home/bear/nfsroot/rootfs/* ./ -afR
cd -
sudo umount ramfs
gzip -v9 ramdisk   #生成ramdisk.gz

mkimage -n 'Ramdisk Image'  -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz ramdisk.gz_test

cp ramdisk.gz_test  uramdisk.image.gz

mv uramdisk.image.gz /home/bear/tftpboot/

5.3 uboot启动参数配置

5.3.1 bootargs设置为initramfs启动

setenv bootargs 'console=ttyPS0,115200 earlyprintk root=/dev/ram0 rw rootwait uio_pdrv_genirq.of_id=generic-uio'

5.3.2 boot命令

5.3.2.1 网络启动内核及initramfs
setenv serverip 192.168.8.139
setenv ipaddr 192.168.8.168
setenv kernel_load_address 0x2080000
setenv devicetree_load_address 0x2000000
setenv ramdisk_load_address 0x4000000
setenv kernel_image zImage
setenv devicetree_image system.dtb
setenv ramdisk_image uramdisk.image.gz
setenv netboot_ramfs 'tftpboot ${kernel_load_address} ${kernel_image} && tftpboot ${devicetree_load_address} ${devicetree_image} && tftpboot ${ramdisk_load_address} ${ramdisk_image} && bootz ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}'
5.3.2.2 emmc启动
setenv emmcboot_ramfs 'if mmc dev 1 && mmcinfo; then run uenvboot; echo Copying Linux from eMMC to RAM... && load mmc 1 ${kernel_load_address} ${kernel_image} && load mmc 1 ${devicetree_load_address} ${devicetree_image} && load mmc 1 ${ramdisk_load_address} ${ramdisk_image} && bootz ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}; fi'

5.4 linux烧写PL bit流文件

5.4.1 bit流bin文件制作

5.4.1.1 bit_bin.bif文件
all:
{
        system.bit
}
5.4.1.2 生成system.bit.bin
bootgen -image $ROOT_PATH/proj/bit_bin.bif -arch zynq -process_bitstream bin

5.4.2 烧写脚本

mkdir -p /lib/firmware
cd /lib/firmware/
cp /run/media/mmcblk1p1/system.bit.bin .
echo system.bit.bin > /sys/class/fpga_manager/fpga0/firmware

6 内核崩溃分析

6.1 core 文件产生

6.1.1 方式1

 设置系统最大产生20480(kB)的core文件,默认值为0,表示未开启

ulimit -c 20480

 事实上,上述命令写在开机启动脚本中并未生效,故采用方式2。

6.1.2 方式2

 修改/etc/security/limits.conf文件

#<domain>      <type>  <item>         <value>
#

*               soft    core            20480
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#@student        -       maxlogins       4

6.1.3 core文件设置路径和名称

echo "/home/root/.lidar/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

6.2 core文件分析

image

6.3 参考链接

https://blog.csdn.net/luronggui/article/details/118111897
https://jason--liu.github.io/2018/01/23/gdbdebug/
https://blog.csdn.net/u014213012/article/details/111593778

posted @ 2022-09-15 13:39  玩呀熊熊  阅读(976)  评论(0编辑  收藏  举报