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

2023-05-16

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

罗宾老师
嵌入式教师、码峰社QQ群541931432
48 人 赞同了该文章

当初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);
}

接下来是实作录屏。





本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ZYNQ有两个CPU?(一)——AMP搭建 的相关文章

  • 最全面的shsh备份及恢复教程,已更新Win版小雨伞4.33.00

    转自 xff1a http bbs weiphone com read htm tid 2017752 html 很多小白不知道如何备份shsh xff0c 论坛有很多关于备份shsh的帖子 xff0c 但大多都不全面 xff0c 本贴把s
  • C++查看大端序小端序的一些思考

    首先明确一个概念 xff0c 无论是大段序还是小端序 类型指针指向的地址都是该类型所占内存的低地址 明确了这个 xff0c 就好判断大端序和小端序了 这是大端序小端序的介绍链接 下边的是验证系统是大端序还是小端序的程序 span class

随机推荐

  • 设计模式书籍推荐

    1 名称 xff1a Head First Design Patterns 语言 xff1a java 评论 xff1a Jolt大奖得主 xff0c 介绍了常见的十几种模式 我认为最好的模式入门书籍 xff0c 内容生动 xff0c 风格
  • C#如何调用linux so库

    testlib c中的内容 xff1a include lt stdio h gt int sum int a int b return a 43 b int minus int a int b return a b main cs中的内容
  • 电机KV值

    电机 KV 值 xff1a 电机的转速 xff08 空载 xff09 61 KV 值 X 电压 xff1b 例如 KV1000 的电机在 10V 电压下它的转速 xff08 空载 xff09 就是 10000 转 分钟 电机的 KV 值越高
  • 用DD命令制作硬盘镜像

    用DD命令制作硬盘镜像 本文参考http serverfault com questions 4906 using dd for disk cloning写出 xff0c 转载时请说明出处 以下的说明都是针对备份整个硬盘 xff0c 而不是
  • 什么是PID 算法

    PID是工业控制上的一种控制算法 xff0c 其中P表示比例 xff0c I表示积分 xff0c D表示微分 以温度控制的PID程序为例 xff1a P xff08 比例 xff09 表示在温度设定值上下多少度的范围内做比例动作 xff0c
  • html代码向左居右对齐

    刚才居然忘了 现在写出来 lt div align 61 right gt 居右对齐 lt div gt left左 xff0c center中 xff0c right右
  • 出现java.lang.IllegalArgumentException: No configs match configSpec

    模拟器不支持OpenGL ES 2 0 是因为android模拟器不支持OpenGL ES 2 0 xff0c 解决办法 xff1a 创建模拟器时 xff1a GPU emulation选yes xff0c 需要android 4 0以上的
  • [005] [ARM-Cortex-M3/4] 大小端存储

  • Android使用java调用C的方法

    Android使用java调用C的方法 xff1a 要将C语言写的算法需要集成到安卓端 xff0c 因此学习如何从安卓java调用C JNI 1 JNI 提示 Android NDK Android Developers google cn
  • STM32之USART-串口通信(含串口实验详细解析)

    STM32之串口通信 USART xff08 含串口实验详细解析 xff09 开发环境 xff1a Window 10开发工具 xff1a Keil uVision5 MDK硬件 xff1a STM32F103 资料参考 xff1a 正点原
  • 昆仑镜Air530 GPS串口输出

    原理图 Air724UG硬件手册说明 Air724UG模块硬件手册 实际开机后并不是默认打开 pmd手册 LDO VMMC level范围0 15 其中0表示关闭其余值满足下面公式 step 61 9 level 当step大于127时为1
  • 常用bat代码

    清除空文件夹 清理空文件夹 删除空文件夹 64 echo off for f 34 tokens 61 34 i in 39 dir s b ad sort r 39 do rd 34 i 34
  • 如何快速的翻译并阅读外文文献

    本文适用一些想要快速了解文献内容的童鞋 在进行查找文献时 不可避免要查找外文文献 其中以英文居多 当然也有可能涉及到其他语言 像楼主这样学了十几年英语 然而听说读写弱鸡的人 面对英语时 会头痛 要是查到其他语言的文献时 估计要死的心都有了
  • [c/c++ ]字节序与大小端转换

    注明 xff1a 以下内容均为学习内容整理 xff0c 记录 xff0c 便于自己学习 xff0c 并非完全意义上的自产 xff0c 如有感到不适 xff0c 请联系我 一 多字节值及字节序 1 brief 现在有一个数字 65430 xf
  • 5V升压8.4V芯片电路图,5V充电7.4V电池

    两节锂电池串联 xff0c 串联电压相加 xff0c 一般锂电池标称电压3 7V xff0c 3 7V 43 3 7V 61 7 4V xff0c 7 4V锂电池 xff0c 充电充满电压饱和是8 4V 7 4V锂电池放电电压一般是6V 8
  • 浅谈资源加载 -AssetBundleSystem

    AssetBundleSystem Ps 稍微抽点时间写一下这个 xff0c 这个小项目完成度80 左右 xff0c 在年初2月份的时候就完成的差不多了 xff0c 因为各种原因处于半搁浅的阶段 xff0c 现在官方出了Addressabl
  • 地形转网格工具(Terrain2Mesh)

    在游戏开发的制作中可能需要制作地形 xff0c 需要制作的相关的地形工具 xff0c 绝大部分情况下并不会使用unity的terrain xff0c 因为其在移动平台上的表现很差 xff0c 相同顶点甚至更多的mesh性能也比其优秀很多 x
  • Unity-EmojiUI更新

    项目中可能会用到emoji表情 xff0c 所以这几天针对这个模块进行了制作和整理 首先 xff0c 在网上进行简单的搜索查找现成方案 xff0c 主要搜索结果为textmeshpro和github上的一些emoji项目 xff0c 因为闭
  • ZYNQ UltraScale 双核裸跑 / 裸跑 + Linux

    1 背景提出 某项目对中断延迟有很高的要求 xff0c 客户的构架为 xff1a PPC 43 Vxworks 延迟时间大概 xff1a 10us 因硬件设计原因 xff0c 还可以更小 我们在Linu系统下测试中断延迟大概几百us 而且这
  • ZYNQ有两个CPU?(一)——AMP搭建

    ZYNQ有两个CPU xff1f xff08 一 xff09 AMP搭建 罗宾老师 嵌入式教师 码峰社QQ群541931432