zynq 7000 通常有2个cpu (arm A9),咱们通常都用一个cpu0,本实验让2个cpu 都运行起来,cpu0 运行操做系统petalinux 2018.2, cpu1: 裸机流水灯。同时经过共享内存的方式,实现2个核之间的交互。linux
关于zynq 双核运行的官方文档有以下3篇:编程
xapp1078-amp-linux-bare-metal.pdfubuntu
xapp1079-amp-bare-metal-cortex-a9.pdfwindows
ug1186-zynq-openamp-gsg.pdfapp
咱们这个实验对应xapp1078, 但文档对应petalinux2014 的版本,有点太老了,而个人实验是在petalinux2018.2 上完成的。工具
前提条件
1:会作petalinux 2018.2 或其余版本的启动制做。若是不会请看:petalinux 2018.2 在ubuntu 16 下的工程制做并启动实验测试
2:熟悉 zynq 7000 AMP模式 双裸核CPU同时运行,由于这个比较简单,能够做为本实验的热身。ui
硬件平台的创建
硬件工程的创建是在Vivado2018.2 上完成的。其实要求很简单,符合linux下流水灯实验的要求便可,固然还须要挂接上SD卡。个人硬件就用的那个流水灯实验的工程,如有不清楚,请参考:spa
zynq 7000 petalinux 2018.2下的流水灯实验操作系统
裸机流水灯工程的准备和验证
这个流水灯工程是创建运行在cpu1上的,存放地址在0x1e00_0000,工程的创建请看:zynq 7000 AMP模式 双裸核CPU同时运行。连接里的工程创建的存放地址是0x1000_0000,但咱们这里cpu0 要运行petalinux2018.2 ,因此设置得比较高。
程序的代码作了适当修改以下:
cpu1的led.c
#include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "xparameters.h" #include "xil_io.h" #include "sleep.h" #define MY_IP 0x41200000 #include "xil_mmu.h" #define COM_VAL (*(volatile unsigned int*)(0xffff0000)) #define COM_VAL1 (*(volatile unsigned int*)(0xffff0004)) #define COM_VAL2 (*(volatile unsigned int*)(0xffff0008)) int main() { u32 Ledwidth; u32 count; Xil_SetTlbAttributes(0xffff0000,0x14de2); COM_VAL=0; COM_VAL1=0; count=0; while (1) { for (Ledwidth = 0x0; Ledwidth < 4; Ledwidth++) { Xil_Out32(MY_IP,1 << Ledwidth); COM_VAL1=1<<Ledwidth; count++; COM_VAL2=count; //printf("led=%x, cpu0 count1=%d cpu1=%d\n\r",1<<Ledwidth,COM_VAL,COM_VAL2); sleep(1); } } return 0; }
cpu0 的验证程序 helloworld.c
#include <stdio.h> #include "xil_printf.h" #include "sleep.h" #include "xil_mmu.h" #define COM_VAL (*(volatile unsigned int*)(0xffff0000)) #define COM_VAL1 (*(volatile unsigned int*)(0xffff0004)) #define COM_VAL2 (*(volatile unsigned int*)(0xffff0008)) int main() { int i=0; Xil_SetTlbAttributes(0xffff0000,0x14de2); COM_VAL=0; COM_VAL1=0; while (1) { i++; COM_VAL=i; printf("%d: Hello led=%d cpu1=%d\n\r",i,COM_VAL1,COM_VAL2); sleep(2); } return 0; }
验证程序必定要看到程序正常运行,而且复制到sd卡运行。特别是那个cpu1地址改成了0x1e00_0000,在fsbl 里的那个CPUSTARTMEM 记得改成0x1e000000。看到SD卡启动后能正常运行。有流水灯,还有helloworld显示。led 的显示被关闭了。
我开始没有好好验证,发现linux 下没有流水灯,只好返回验证才发现其中的一些错误。
petalinux 2018.2 工程的创建
利用相同的hdf 文件创建一个SD卡上运行的petalinux。能够先不作修改制做BOOT.BIN 和image.ub ,复制到SD卡,测试petalinux 可以正常启动。能够参考:petalinux 2018.2 在ubuntu 16 下的工程制做并启动实验
而后咱们在petalinux 里作2个地方的修改。
1:须要保留cpu1 流水灯裸机所占用的DDR空间
修改的文件名是system-user.dtsi , 文件的目录是~/alinx/cnc7a/project-spec/meta-user/recipes-bsp/device-tree/files
个人工程目录是~/alinx/cnc7a/,因此你的应该是:工程目录/project-spec/meta-user/recipes-bsp/device-tree/files
文件内容以下,就是添加保留ddr,或者叫reserved-memory。
/include/ "system-conf.dtsi" / { reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; reserved: buffer@0x1e000000 { no-map; reg = <0x1e000000 0x00400000>; }; }; reserved-driver@0 { compatible = "xlnx,reserved-memory"; memory-region = <&reserved>; }; };
若是不保留这个空间,linux 就会冲掉咱们的cpu1的裸机流水灯程序
作了这个修改,来测试下咱们的系统作得怎么样了,能够双核启动了吗。
petalinux-build 成功后,咱们须要更改咱们的打包方案了,咱们须要把cpu1led 流水灯裸机程序加上去,而且启动流水灯程序。
直接用petalinux 下的打包程序,我不知道怎么启动流水灯程序,因此我转到sdk 下的打包程序。
打包程序包括流水灯程序
其实很简单,linux 下须要的是system.bit, u-boot.elf, image.ub。 把这几个文件经过共享的方式,复制到windows 的共享目录下。若是不会共享,能够看看:虚拟机VMware时,如何在Windows和Ubuntu之间共享文件夹。
而后咱们继续使用双核裸机的打包流程,只是把cpu0 部分替换成llinux下造成的u-boot.elf。流文件也用linux 下的,其实应该也能够用sdk 下的,我这个没测试。
看看打包的界面以下:
这样就造成了BOOT.BIN。把这个BOOT.BIN和image.ub复制到SD卡,而后测试启动。
看到流水程序启动了,而后linux 启动了。但linux 启动的时候,流水灯就不流了。
2:设置linux 为 单核
正常状况下,linux 为双核运行。上面的内存保留没有冲掉程序,但linux启动时占用了cpu1,因此流水灯被停掉了。查找xapp1078,page 21/34 上这样写的:
Creating Linux Device Tree
Refer to the wiki pages at http://wiki.xilinx.com for instructions to compile the device tree. The
device tree needs to be changed to instruct Linux SMP to only use one CPU and to decrease
the amount of memory available to Linux. A copy of the modified devicetree.dts and
compiled devicetree.dtb is included at design\generated_files\boot.
The commands used are listed here:
1. Copy the zynq-zc702.dts device tree included with the downloaded linux kernel to a
new location:
cp arch/arm/boot/dts/zynq-zc702.dts <somewhere>
2. Modify the copied device tree to reduce the memory. The memory entry should be:
memory {
device_type = "memory";
reg = <0x00000000 0x30000000>;
};
3. Set the maximum number of CPUs to 1 by adding maxcpus=1 to the bootargs assignment:
bootargs = "console=ttyPS0,115200 maxcpus=1 root=/dev/ram rw
ip=:::::eth0:dhcp earlyprintk";
4. Compile the new devicetree.dts to create devicetree.dtb as described in the wiki
scripts/dtc/dtc -I dts -O dtb -o <somewhere>/devicetree.dtb
<somewhere>/zynq-zc702.dts.
把maxcpus=1 设置进设备树就成了关键,xapp1078 这么写了,我殊不知怎么作,困惑了我好几天。我在xilinx 论坛上问到了。下面是问题连接:
https://forums.xilinx.com/t5/Embedded-Linux/how-to-add-maxcpus-1-to-dt/m-p/1127901#M43760
知道了,其实很简单,不是去修改设备树,以下操做就能够。
petalinux-config
界面出现后,选择 DTG Setting ----->
在出现的子界面里选择 Kernel Bootargs ----->
取消那个generate boot args automatically,转到下行回车,或者直接出现输入界面
在这个界面里添加 maxcpus=1, 以下图
这样操做保存后后,再petalinux-build ,按上面打包方法打包,在petalinux 2018.2 启动后, 流水灯在继续运行。
这说明cpu0 核运行petalinux2018.2 ,cpu1 运行裸机流水灯成功了。
petalinux 核和裸机流水灯核的交互
在上面的流水灯代码里,
COM_VAL1=1<<Ledwidth; count++; COM_VAL2=count;
每隔1秒延迟,COM_VAL2 会+1, 而COM_VAL1 则保存灯控命令,1,2,4,8。
在linux 里编程读取到这些值,就完成了咱们的交互实验。linux 里能读到裸机程序的变量。
linux 里有个io口测试的程序,就是说不用编程就有,叫作devmem。个人博客里有他源代码分析,能够查看 Linux驱动开发经常使用调试工具 devmem之代码分析
在petalinux 终端输入 devmem 0xffff0008,能够看到计数值不断增长,能够不断重复上个命令,反正隔几秒就加几。
在petalinux 终端输入 devmem 0xffff0004 ,就能够看到灯控命令1,2,4,8中之一。
为何是0xffff0008,这是咱们共享宏定义里肯定的,也能够看看 ZYNQ 7000 AMP模式双裸核运行 双方共享内存交互,这文介绍得比较详细。
这就说明数据的交互彻底成功。
介绍到此,但愿对你有用。