欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

ZYNQ 双核运行并交互,一个linux,一个裸核

程序员文章站 2022-05-20 17:46:16
zynq 7000 一般有2个cpu (arm A9),我们一般都用一个cpu0,本实验让2个cpu 都运行起来,cpu0 运行操作系统petalinux 2018.2, cpu1: 裸机流水灯。同时通过共享内存的方式,实现2个核之间的交互。...

zynq 7000 一般有2个cpu (arm A9),我们一般都用一个cpu0,本实验让2个cpu 都运行起来,cpu0 运行操作系统petalinux 2018.2, cpu1: 裸机流水灯。同时通过共享内存的方式,实现2个核之间的交互。

关于zynq 双核运行的官方文档有如下3篇:

xapp1078-amp-linux-bare-metal.pdf

xapp1079-amp-bare-metal-cortex-a9.pdf

ug1186-zynq-openamp-gsg.pdf

我们这个实验对应xapp1078, 但文档对应petalinux2014 的版本,有点太老了,而我的实验是在petalinux2018.2 上完成的。

前提条件

1:会做petalinux 2018.2 或其他版本的启动制作。如果不会请看:petalinux 2018.2 在ubuntu 16 下的工程制作并启动实验

2:熟悉 zynq 7000 AMP模式 双裸核CPU同时运行,因为这个比较简单,可以作为本实验的热身。

硬件平台的建立

硬件工程的建立是在Vivado2018.2 上完成的。其实要求很简单,符合linux下流水灯实验的要求即可,当然还需要挂接上SD卡。我的硬件就用的那个流水灯实验的工程,若有不清楚,请参考:

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 下的,我这个没测试。

看看打包的界面如下:

ZYNQ 双核运行并交互,一个linux,一个裸核

这样就形成了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,转到下行回车,或者直接出现输入界面

ZYNQ 双核运行并交互,一个linux,一个裸核

在这个界面里添加 maxcpus=1, 如下图

ZYNQ 双核运行并交互,一个linux,一个裸核

这样操作保存后后,再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模式双裸核运行 双方共享内存交互,这文介绍得比较详细。

这就说明数据的交互完全成功。

介绍到此,希望对你有用。

 

本文地址:https://blog.csdn.net/leon_zeng0/article/details/107351335