**

ZYNQ有两个CPU?(一)——AMP搭建

**
本文转载自:https://zhuanlan.zhihu.com/p/30336605

当初Xilinx技术支持忽悠我用ZYNQ的时候这双核就是其中一条广告词,可回想起来在Standalone下面我还真没好好用过双核所以在这里跟大家分享一下在Standalone下面如何搭建AMP分几个阶段进行,从最简单的做起。

至于什么是AMP和SMP我找了个链接就不做解释了:

多核处理器基础SMP&AMP&BMP - zamely - 博客园

今天要做的事情是先在两个CPU上跑出两个完全并行的程序,相互之间没有交集。然后在把程序下载到Flash中让CPU0唤醒CPU1实现真正的AMP。在这个过程中我们还会分析和解决遇到的问题。

当然做事情之前得查资料,搜索一下文档浏览器以后找到了两篇XAPP1078和XAPP1079:一篇是双裸机,一篇是裸机+Linux。根据需求我选了后者,进去之后就发现自己被坑了。这篇文章是在ISE+XPS的古老环境中实现的,而我自己用的是VIVADO,这就悲剧了!

不过我还是把文档和参考设计down下来了。


在文档中心用AMP做关键字搜到的XAPP1079


接下来是到Xilinx官网下载资料


下载后解压毕竟C代码还是有参考价值的。文档只有32页,跳过ISE和XPS的部分直接看SDK的内容。

看完后我就自己关注的内容总结了一下:

hw_platform不需要对AMP进行设置,主要工作都在SDK上。


需要分别建立两个CPU的APP项目,其中CPU1的向导中要注意处理器选项选择CPU1。


CPU1的BSP SETTING需增加-DUSE_AMP=1。


每个CPU的APP项目的src目录中按照自己预想的存储器分配方案修改lscript.ld文件中的内容,千万注意不要让两个CPU的DDR地址重合,因为你APP的ELF文件是加载到DDR中执行的。由于没有OS,ELF肯定是加载到每个CPU的DDR起始地址。如果有重合那么一个CPU的ELF会覆盖另一个的,别问我是怎么知道的。


我在VIVADO中把开发板上的8位LED灯和七段数码管的24位驱动引脚做到了一个axi_gpio的两个通道上。在两个CPU上分别访问一个通道。


写完两个CPU的APP后,分别debug在各自的CPU上run起来,结果如下图:


然后当我把这个设计固化到flash里后发现只有CPU0跑起来了,为啥啊?这才想起自己down下来的代码,对比代码又查询了UG585才知道原因:即使fsbl已经把CPU1的ELF加载到位,但CPU1是处于waiting状态的。需要CPU发出WFE指令才能唤醒CPU1。而CPU1被唤醒后首先就是从地址0XFFFFFFF0读取地址进行跳转。因此CPU0在发出WFE指令前要在0XFFFFFFF0存入CPU1的DDR起始地址。而0XFFFFFFF0属于OCM的地址范围,所以需要去掉OCM这块儿的Cache属性。下面的代码需要包含库文件"xil_io.h"。

    //Disable cache on OCM
    Xil_SetTlbAttributes(0xFFFF0000,0x14de2);           // S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0
    Xil_Out32(CPU1_START_UP_REG, CPU1STARTADR); //CPU1STARTADR=0xFFFFFFF0, CPU1STARTADR=0x20000000);
    dmb(); //waits until write has finished
    print("CPU0: sending the SEV to wake up CPU1\n\r");__asm__("sev");dmb(); //waits until write has finished

修改完成烧写flash成功,运行成功。这是我LED.c的源代码

/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xgpio.h"
#include "xil_printf.h"
#include "xil_io.h"
/************************** Constant Definitions *****************************/
#define LED 0x01   /* Assumes bit 0 of GPIO is connected to an LED  */
/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define GPIO_EXAMPLE_DEVICE_ID  XPAR_GPIO_LEDS_DEVICE_ID

/*
 * The following constant is used to wait after an LED is turned on to make
 * sure that it is visible to the human eye.  This constant might need to be
 * tuned for faster or slower processor speeds.
 */
#define LED_DELAY     10000000

/*
 * The following constant is used to determine which channel of the GPIO is
 * used for the LED if there are 2 channels supported.
 */
#define LED_CHANNEL 2
#define CPU1_START_UP_REG 0xFFFFFFF0
#define CPU1STARTADR 0x20000000
/************************** Variable Definitions *****************************/
/*
 * The following are declared globally so they are zeroed and so they are
 * easily accessible from a debugger
 */
XGpio Gpio; /* The Instance of the GPIO Driver */
/*****************************************************************************/
/**
*
* The purpose of this function is to illustrate how to use the GPIO
* driver to turn on and off an LED.
*
* @param   None
*
* @return  XST_FAILURE to indicate that the GPIO Initialization had
*       failed.
*
* @note        This function will not return if the test is running.
*
******************************************************************************/
int main(void)
{int Status;volatile int Delay;int i;//Disable cache on OCM
    Xil_SetTlbAttributes(0xFFFF0000,0x14de2);           // S=b1 TEX=b100 AP=b11, Domain=b1111, C=b0, B=b0
    Xil_Out32(CPU1_START_UP_REG, CPU1STARTADR); //CPU1STARTADR=0xFFFFFFF0, CPU1STARTADR=0x20000000);
    dmb(); //waits until write has finished
    print("CPU0: sending the SEV to wake up CPU1\n\r");__asm__("sev");dmb(); //waits until write has finished
    xil_printf("Start to light the leds\r\n");/* Initialize the GPIO driver */Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);if (Status != XST_SUCCESS) {xil_printf("Gpio Initialization Failed\r\n");return XST_FAILURE;}/* Set the direction for all signals as inputs except the LED output */XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0);//set all pins as output
    /* Loop forever blinking the LED */while (1){for (i=0;i<8;i++){/* Set one LED light each time */XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, ~(LED<<i));
      <span class="cm">/* Wait a small amount of time so the LED is visible */</span><span class="k">for</span> <span class="p">(</span><span class="n">Delay</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">Delay</span> <span class="o">&lt;</span> <span class="n">LED_DELAY</span><span class="p">;</span> <span class="n">Delay</span><span class="o">++</span><span class="p">);</span><span class="p">}</span>
<span class="p">}</span>
<span class="c1">//xil_printf("Successfully ran Gpio Example\r\n");

return XST_SUCCESS;
}

下面是SEG7_LEDS.c的源代码:

/***************************** Include Files /
#include “xparameters.h”
#include “xgpio.h”
#include “xil_printf.h”
/ Constant Definitions /
/
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 /
#define GPIO_EXAMPLE_DEVICE_ID  XPAR_GPIO_LEDS_DEVICE_ID

/
 * The following constant is used to wait after an LED is turned on to make
 * sure that it is visible to the human eye.  This constant might need to be
 * tuned for faster or slower processor speeds.
 /
#define LED_DELAY     100000
/
 * The following constant is used to determine which channel of the GPIO is
 * used for the LED if there are 2 channels supported.
 /
#define LED_CHANNEL 1
const   unsigned   int   Display_Code[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
const   unsigned   int   Selected_Code[4]={0xEE,0xDD,0xBB,0x77};
/ Function Prototypes /
static int emerge_ledbus(int ledbus0,int ledbus1,int ledsel);
/ Variable Definitions /
/
 * The following are declared globally so they are zeroed and so they are
 * easily accessible from a debugger
 /
XGpio Gpio; / The Instance of the GPIO Driver /
/*************************************/
/

 The purpose of this function is to illustrate how to use the GPIO
 driver to turn on and off an LED.
*
* @param   None
*
* @return  XST_FAILURE to indicate that the GPIO Initialization had
*       failed.
*
* @note        This function will not return if the test is running.
*
*****************************************************************************/
int main(void)
{
int Status;
int led_bus0,led_bus1,led_sel;
volatile int Delay;
int i;
xil_printf(“Start to light the leds\r\n”);
/ Initialize the GPIO driver /
Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf(“Gpio Initialization Failed\r\n”);
return XST_FAILURE;
}
/ Set the direction for all signals as inputs except the LED output /
XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0);//set all pins as output
    / Loop forever blinking the LED */
while (1) {
  <span class="k">for</span><span class="p">(</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span><span class="n">i</span><span class="o">&lt;</span><span class="mi">4</span><span class="p">;</span><span class="n">i</span><span class="o">++</span><span class="p">)</span><span class="p">{</span><span class="c1">//XGpioPs_Write(&amp;Gpio, LED_BANK, emerge_ledbus(0,0,0xFF));//Close all LEDS

led_bus0=Display_Code[i];
led_bus1=Display_Code[i+4];
led_sel= Selected_Code[i];
XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, emerge_ledbus(led_bus0,led_bus1,led_sel));
for (Delay = 0; Delay < LED_DELAY; Delay++);
}
}

<span class="c1">//xil_printf("Successfully ran Gpio Example\r\n");

return XST_SUCCESS;
}

//emerge 3 8bits bus into a 24bits bus
/
static int emerge_ledbus(int ledbus0,int ledbus1,int ledsel)
{
return ledbus0+(ledbus1<<8)+(ledsel<<16);

ZYNQ有两个CPU?(一)——AMP搭建相关推荐

  1. ZYNQ有两个CPU?(三)——SGI异步通信

    ZYNQ有两个CPU?(三)--SGI异步通信 罗宾老师 嵌入式教师.码峰社QQ群541931432 19 人 赞同了该文章 前面两篇文章中我分享了ZYNQ上在Standalone环境下搭建AMP和用 ...

  2. ZYNQ有两个CPU?(二)——OCM共享内存

    在上一篇文章中,我们搭建了一个AMP的环境,而且在CPU0和CPU1上分别跑了两个没有交集的线程.这篇文章中我们需要让两个CPU之间能够进行通信.而传递数据采用了共享内存,我们将共享内存设置在OCM( ...

  3. 【转帖】龙芯将两款 CPU 核开源,这意味着什么?

    龙芯将两款 CPU 核开源,这意味着什么? https://www.oschina.net/news/78316/loongson-open-source-two-cpu-core 文章挺不错的也讲了 ...

  4. 龙芯将两款 CPU 核开源,这意味着什么?

    10月21日,教育部计算机类教学指导委员会.中国计算机学会教育专委会将2016 CNCC期间在山西太原举办"面向计算机系统能力培养的龙芯CPU高校开源计划"活动,在活动中,龙芯中科 ...

  5. 服务器2颗cpu的性能,DIY从入门到放弃:两颗CPU性能更强吗?

    如果DIY让你觉得头疼,说明你的思路是正确的. 两根内存组双通道性能更强,两块硬盘组RAID速度提升,那你肯定想过,给主板多开一个CPU插槽组成双CPU平台,性能岂不是会更强吗? 这个问题问得好 来来 ...

  6. 服务器主板最多能装几个cpu,主板装两颗CPU:性能会更强吗?

    如果DIY让你觉得头疼,说明你的思路是正确的. 两根内存组双通道性能更强,两块硬盘组RAID速度提升,那你肯定想过,给主板多开一个CPU插槽组成双CPU平台,性能岂不是会更强吗? 来来来快坐下,我理解 ...

  7. 松下PLC编程 FP-XH 10轴定位 松下PLC项目实例,两台CPU间通过RS485通讯

    松下PLC编程 FP-XH 10轴定位 松下PLC项目实例,两台CPU间通过RS485通讯,10轴定位控制. 轴控制程序采用FB,直观可靠,可以重复使用,使用时只需要对fb接口赋值即可,内部已经对系统 ...

  8. 撕裂者cpu三代文件服务器,AMD 两年 CPU 线路图曝出,10月发第三代线程撕裂者

    AMD 两年 CPU 线路图曝出,10月发第三代线程撕裂者 2019-07-22 14:20:24 26点赞 38收藏 47评论 AMD现在已经发布了锐龙3000系列处理器,接下来就是第二代EYPC服 ...

  9. 行业:海信发布中国首颗全自研8K AI画质芯片,集成两路CPU

    1月11日下午,海信发布了中国首颗全自研8K AI画质芯片,这是海信第五代画质芯片,也是海信研发芯片以来集成度最高.功能最丰富的一代芯片,核心技术全部自主研发,号称画质芯片处理能力天花板,内部集成了两 ...

最新文章

  1. 部署LyncServer2013之一 前期准备
  2. php childnodes,小tips:HTML DOM中的children和childNodes属性
  3. Android init.rc执行顺序
  4. 面试官:缓存穿透、缓存雪崩和缓存击穿是什么?
  5. Session一致性的解决方案
  6. zstack 第一个例子
  7. mvc 两个控制器session 丢失_用纯 JavaScript 撸一个 MVC 程序
  8. 软件工程网络15个人阅读作业2(201521123111 陈伟泽)
  9. 脉冲耦合神经网络(PCNN)-pulse coupled neural network
  10. 如何深入Delphi编程
  11. 麦克风声源定位原理_关于基于麦克风阵列的声源被动定位系统的设计
  12. java实现有限自动机_Java 实现一个非确定性有限自动机(NFA)
  13. 解决能登录微信却登不上网页的问题
  14. 1005打印任务取消不了 hp_HP打印机打印时任务打印不了时无法取消
  15. rpa项目poc_RPA POC概述
  16. IIS应用程序池自动停止,报503错误解决方法
  17. Java面向对象的知识(二)
  18. 算法思考题-三只老鼠找8瓶毒药思路(个人思考+收集)
  19. 为什么说中小学编程教育是创新思维体操
  20. Android:短信的接收

热门文章

  1. vulhub中漏洞复现1
  2. Win10上如何分配硬盘空间
  3. 快速了解实用新型专利申请的流程及费用
  4. [SRS+docker]实现直播服务器 8 云产商直播服务
  5. Python快速学习- 文件类型(*.py/*.pyc/*.pyo)
  6. Python selenium模拟淘宝登陆
  7. IO流处理2022-11-11
  8. CPU性能排查篇——CPU平均负载
  9. C++ 简易弹球游戏(分块解释、源码、注释)
  10. 天津大学计算机保研面试经验,师哥保研经验谈:如何准备推免面试?