AMP模式 双核CPU同时运行

转自:https://blog.csdn.net/long_fly/article/details/79335025

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]}]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

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
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

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

    /*
     * Load boot image
     */
    HandoffAddress = LoadBootImage();

    fsbl_printf(DEBUG_INFO,"Handoff Address: 0x%08lx\r\n",HandoffAddress);
    StartCpu1();   /*add starting cpu1*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

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

猜你喜欢

转载自blog.csdn.net/liuzq/article/details/80489040