ZYNQ基础系列(五) AMP模式 双裸核CPU同时运行

xiaoxiao2021-02-28  77

AMP模式 双核CPU同时运行


从软件的角度来看,多核处理器的运行模式有三种: AMP(非对称多进程):多个核心相对独立的运行不同的任务,每个核心可能运行不同的操作系统或裸机程序,但是有一个主要核心,用来控制整个系统以及其它从核心 SMP(对称多进程):一个操作系统同等的管理各个内核,例如PC机 BMP(受约束多进程):与SMP类似,但开发者可以指定将某个任务仅在某个指定内核上执行 默认情况下,ZYNQ仅运行一个CPU,这里主要研究AMP模式下,两个CPU同时运行


实验目的

使用ZYNQ7010完成 1> CPU0在裸核下运行helloworld,CPU1在裸核下运行流水灯 2> CPU0在linux下运行helloworld,CPU1在裸核下运行流水灯

硬件环境

硬件环境过于简单,这里只文字描述 1.创建原理图,添加PS核,双击进入PS的配置界面 2.peripheral I/O pin里开启串口和EMIO和SD卡 3.在MIO configuration中,配置EMIO宽度为4 4.在clock configuration和DDR configuration中,设置对应的时钟频率和DDR型号 5.关闭配置界面,原理图如下 6.右击原理图,生成输出文件 7.右击原理图,生成顶层文件 8.对LED进行引脚约束

set_property PACKAGE_PIN N15 [get_ports {LED_tri_io[0]}] set_property PACKAGE_PIN N16 [get_ports {LED_tri_io[1]}] set_property PACKAGE_PIN M19 [get_ports {LED_tri_io[2]}] set_property PACKAGE_PIN M20 [get_ports {LED_tri_io[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED_tri_io[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED_tri_io[1]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED_tri_io[2]}] set_property IOSTANDARD LVCMOS33 [get_ports {LED_tri_io[3]}]

9.综合、实现、生成bit文件,并导出硬件,运行SDK

SDK环境

AMP模式的使用,重点在SDK上 1.创建CPU0工程,选择生成helloworld例程,内容为:

#include <stdio.h> #include "platform.h" #include "xil_printf.h" #include "sleep.h" int main() { init_platform(); while (1) { print("Hello World\n\r"); sleep(2); } cleanup_platform(); return 0; }

2.创建CPU1工程 注意选择核1,创建led.c为主函数,内容为:

#include "xgpiops.h" #include "sleep.h" int main() { static XGpioPs psGpioInstancePtr; XGpioPs_Config* GpioConfigPtr; int xStatus; GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID); if(GpioConfigPtr == NULL) return XST_FAILURE; xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr->BaseAddr); if(XST_SUCCESS != xStatus) return -1; XGpioPs_SetDirectionPin(&psGpioInstancePtr, 54,1); XGpioPs_SetDirectionPin(&psGpioInstancePtr, 55,1); XGpioPs_SetDirectionPin(&psGpioInstancePtr, 56,1); XGpioPs_SetDirectionPin(&psGpioInstancePtr, 57,1); XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 54,1); XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 55,1); XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 56,1); XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, 57,1); while(1) { XGpioPs_WritePin(&psGpioInstancePtr, 54, 1); sleep(1); XGpioPs_WritePin(&psGpioInstancePtr, 54, 0); XGpioPs_WritePin(&psGpioInstancePtr, 55, 1); sleep(1); XGpioPs_WritePin(&psGpioInstancePtr, 55, 0); XGpioPs_WritePin(&psGpioInstancePtr, 56, 1); sleep(1); XGpioPs_WritePin(&psGpioInstancePtr, 56, 0); XGpioPs_WritePin(&psGpioInstancePtr, 57, 1); sleep(1); XGpioPs_WritePin(&psGpioInstancePtr, 57, 0); sleep(1); } return 0; }

3.工程结构为:

4.CPU1的BSP SETTING中添加 -DUSE_AMP=1

5.DDR空间分配 通过修改lscript.ld文件中的内容,可以改变在存储器中的执行位置, 因为ELF文件是加载到DDR中执行的,所以两个DDR地址不能重合 CPU0: CPU1:

6.运行debug 两个CPU都运行起来了,且不相互干扰

7.固化到SD卡中启动 再创建一个FSBL的工程,在FSBL的src中找到main.c文件打开,在里面添加下面一段代码,用于启动CPU1:

#define sev() __asm__("sev") #define CPU1STARTADR 0xFFFFFFF0 #define CPU1STARTMEM 0x20000000 void StartCpu1(void) { #if 1 fsbl_printf(DEBUG_GENERAL,"FSBL: Write the address of the application for CPU 1 to 0xFFFFFFF0\n\r"); Xil_Out32(CPU1STARTADR, CPU1STARTMEM); dmb(); //waits until write has finished fsbl_printf(DEBUG_GENERAL,"FSBL: Execute the SEV instruction to cause CPU 1 to wake up and jump to the application\n\r"); sev(); #endif }

前面添加的是CPU1的启动函数,再找到Load boot image的位置,将CPU1的启动函数,放置于此位置,改动后的代码段如下:

/* * Load boot image */ HandoffAddress = LoadBootImage(); fsbl_printf(DEBUG_INFO,"Handoff Address: 0xlx\r\n",HandoffAddress); StartCpu1(); /*add starting cpu1*/

将上述文件合并为BIN文件,并放入SD卡中,ZYNQ启动模式要为SD启动,正常情况下将正常工作 注—-若是没出现正常的现象,则可能是: 1>SD卡的bank电压及引脚速度选择错误 2>CPU0和CPU1的DDR地址冲突 3>未在FSBL的main.c中加入StartCpu1函数

那么,双裸核实验到此结束


分界线:下面是linux+裸核的实验,但是CPU1只能短暂工作,即实验暂时失败,之后有需要再研究,下面是失败案例,不要看


双核分别跑不同的系统

接下来,将在已有的双核基础上,实现双核的linux+裸核工作 CPU0的linux系统将通过petalinux方式移植,CPU1则按照上述的方式照旧 linux具体的移植方式参考:petalinux方式移植linux

硬件上:

在之前的硬件基础上,添加TTC: 重新生成的PS核: 更新输出文件后,重新综合、实现、生成bit文件、导出硬件,上述工作完成后,可以在/(工程文件夹)/(工程名).sdk这个文件夹下找到.hdf后缀的文件,待用

开启linux虚拟机:

在普通用户(非超级用户)模式下:

#工作目录 cd PRO #定位编译链 source /home/hlf/mnt/petalinux/settings.sh #创建工程并命名 petalinux-create --type project --template zynq --name h2_amp #进入工程目录 cd h2_amp #将.hdf文件拷到文件夹中,并引用硬件描述文件,遇到配置界面做如下修改后,直接save并exit,等待默认配置 petalinux-config --get-hw-description=/home/hlf/PRO/h2_amp

Subsystem AUTO Hardware Settings —> Memory Settings —>

#获取文件夹权限(工程文件夹和petalinux的安装文件夹),否则编译的时候,会发生错误 sudo chmod -R 777 /home/hlf #编译u-boot,直接save为u-boot.config,并exit petalinux-config -c u-boot #编译kernel,操作同上(save为kernel.config) petalinux-config -c kernel #编译rootfs,操作同上(save为默认即可) petalinux-config -c rootfs

设备树配置:在工程文件夹下,Ctr+F搜索.dts就可以找到相关文件 打开设备树文件,修改DDR地址,还是注意与petalinux-config时的设置值一致,不要和CPU1的DDR地址重叠

#一切就绪后,编译工程 petalinux-build

编译完成后:进入(工程目录)/image/linux目录,将u-boot.elf和image.ub文件拷贝出来 打开SDK:新建CPU1的工程,和之前例子里的配置相同(主要注意修改BSP和DDR地址),然后新建一个FSBL的工程,其步骤也是和之前一样的(添加CPU1的启动函数),然后按照顺序FSBL.elf — xxx.bit — u-boot.elf — CPU1_APP.elf 的顺序制作BOOT.bin文件,将BOOT.bin和image.ub拷贝到SD卡中,开机

#现象:linux系统正常运行,但是流水灯正常运行一段时间后停止运行,卡在某一个灯,可能是linux的运行影响了CPU1的工作

转载请注明原文地址: https://www.6miu.com/read-2625420.html

最新回复(0)