zynq双核交互(1)之zynq双核的启动
- zynq双核交互相关的官方相关资料如下:
- ug585-Zynq-7000-TRM.pdf
- 第6.1.10章节。
- xapp1078-amp-linux-bare-metal.pdf
- 本文档还描述了如何创建可启动的解决方案以及如何调试两个cpu。
- xapp1079-amp-bare-metal-cortex-a9.pdf
- ug585-Zynq-7000-TRM.pdf
Zynq-7000 AP SoC提供两个Cortex-A9处理器,共享公共内存和外围设备。
双核使用的一种方式是非对称多处理(AMP)机制,它允许两个处理器运行各自的操作系统或裸机应用程序,并且可以通过共享资源对这些应用程序进行松散耦合。难点是需要注意防止cpu在共享硬件资源上发生冲突。
双核启动流程理论步骤
zynq在启动时,总是先启动cpu0.然后用cpu0来启动cpu1.在zynq启动时,BootROM(zynq内部的启动程序,对用户不可见)将CPU1置于等待事件模式让cpu1就一直等待cpu0来触发启动自己。
那么cpu0如何触发启动cpu1呢,步骤如下:
- cpu0向地址
0xFFFFFFF0
写入cpu1的程序起始地址。说白了就是告诉cpu1要你运行的程序在那个地方。- 注意:写入
0xFFFFFFF0
的地址必须是四字节对齐的。
- 注意:写入
- cpu0发送SEV事件。说白了它就是那个触发cpu1运行的事件。
- 然后cpu1就自己跑起来了。
对程序编译不太熟悉的人可能在cpu1的程序起始地址
是多少以及如何设置这这个问题上卡住。这儿就拿不带mmu的裸机程序(当然RTOS的程序在这儿可以当裸机程序理解)来说。
- 用sdk建立cpu1的裸机应用程序。
- 建立完应用程序后会发现程序种会有一个
lscript.ld
的链接文件,我们就是要在这个文件中设置和更改cpu1应用程序的起始运行地址。也就是向地址0xFFFFFFF0
要写入的地址。修改图如下: - 这个地址值设置为多少合适了?这就要涉及到自己的DDR以及OCM的内存的运行分配了。简单的说就是运行内存不重叠就行。但如何做到不重叠了?这就要涉及到
fsbl
程序、cpu0应用程序、cpu1应用程序三个程序的运行内存分配问题了。- cpu1程序的运行内存不能跟
fsbl
程序的运行内存重叠。说白了,就是他俩中.ld
文件中的上图说的那么地址范围不能重叠。 - cpu1程序的运行内存不能跟cpu0的应用程序的运行内存重叠。如果cpu0的应用程序也是裸机程序,那就和比较
fsbl
程序的方式一致。但如果是linux,那就可以在设备树中修改ddr的地址。 - 注意,上面说的
fsbl
程序和cpu0应用程序都是运行在cpu0上的。
- cpu1程序的运行内存不能跟
启动程序如下,将它加入fsbl
程序或者cpu0应用程序中,都可以启动cpu1。笔者将它放在了fsbl
程序main函数中的HandoffAddress = LoadBootImage();
后面。
void StartCpu1(void)
{
/* cpu1运行起始地址 */
#define CPU1_START_ADDR 0x10000000
/* 触发事件 */
#define sev() __asm__("sev")
/* 1. 向地址0xFFFFFFF0写入cpu1运行地址 */
Xil_Out32(0xFFFFFFF0,CPU1_START_ADDR);
dmb();/* 等待写完成 */
fsbl_printf(DEBUG_GENERAL,"cpu1 start \n\r");
/* 2. cpu0发送SEV事件 */
sev();
}
双核启动实践步骤
- sdk中创建cpu0应用程序。
- sdk中创建cpu1应用程序。
- sdk中创建fsbl启动程序。
- 按照上面所说的修改cpu1的
lscript.ld
链接文件中的起始运行地址。 - 在fsbl程序中添加上面所说的启动程序。
- 生成
Boot.bin
.添加顺序如图: - 下载。看效果。笔者的双核启动测试程序链接。环境是sdk2018.3.
成Boot.bin
.添加顺序如图: - 下载。看效果。笔者的双核启动测试程序链接。环境是sdk2018.3.
关于技术交流
此处后的文字已经和题目内容无关,可以不看。
qq群:825695030
微信公众号:嵌入式的日常
如果上面的文章对你有用,欢迎打赏、点赞、评论。