Zynq ZC702平台 Linux + Baremetal AMP实现(一)【快速启动CPU1】

Xilinx官方的Zynq AMP configure XAPP1078实现Linux+Baremetal方法有些麻烦,介绍一种可以通过在常规FSBL下来实现CPU0启动CPU1的方法。

预备知识:UG585, section 6.1.10 Starting Code on CPU 1

The steps for CPU 0 to start an application on CPU 1 are as follows:
1. Write the address of the application for CPU 1 to 0xFFFFFFF0.
2. Execute the SEV instruction to cause CPU 1 to wake up and jump to the application.

具体实现步骤:

Step1:通过Vivado建立CPU0的FSBL ,见下图,同时自动生成对应的BSP

Step2:在FSBL -> src -> main.c中最下方添加如下函数申明

/**************************************************************/
*
* This function Starting Code/Applications on CPU 1*
*
****************************************************************/
#define sev() __asm__("sev")
#define CPU1STARTADR 0xFFFFFFF0
#define CPU1STARTMEM 0x30000000

void StartCpu1(void)
{
    #if 1
    fsbl_printf(DEBUG_GENERAL,"FSBL: Write the address of the application for CPU 1 to 0xFFFFFFF0

");
    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

");
    sev();
    #endif
}

Step3:在FSBL -> src -> main.c 的int main(void)函数中,几乎最尾部,在Load boot image之后执行StartCpu1()

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

    fsbl_printf(DEBUG_INFO,"Handoff Address: 0x%08lx
",HandoffAddress);
    StartCpu1();   /*add starting cpu1*/

Step4: 建立CPU1的GPIO-LED点灯应用程序,对应的BSP中编译选项中设置-g -DUSE_AMP=1,

--直接打开给AMP工程建立FSBL时自动生成的对应的BSP中的system.mss,然后找到你想要的example程序,直接 Import Examples,见下图红色方框标识

  

 Step5::修改GPIO-LED下的lscripts.ld下的ddr内存空间: Base Address -> 0x30000000

--0x30000000,这个地址就是是FSBL将CPU1的应用程序helloworld搬运到ddr的内存起始地址0x30000000

--StartCpu1()中给地址0xFFFFFFF0写入的CPU1的应用程序起始地址,到现在就串起来了

 Step6: 修改devicetree:linux-xlnx-xilinx-v2017.1archarmootdts目录下复制zynq-zc702.dts,重命名zynq-zc702-amp.dts并编译生成zynq-zc702-amp.dtb,并更名为devicetree.dtb

--具体的修改内容:

1. 修改cpu0 的ddr空间为低0x00000000 - 0x30000000

  memory {
  device_type = "memory";
  reg = <0x00000000 0x30000000>;
  };

2. 注释/删除GPIO/LED相关的部分(根据你自己的情况修改不同的接口,由于是GPIO的例子,对应处理GPIO/LED的部分)

3. 修改bootargs参数

bootargs = "console=ttyPS0,115200 maxcpus=1 clk_ignore_unused root=/dev/ram rw ip=:::::eth0:dhcp earlyprintk";

 --说明一下:现在linux kernel在功耗管理者一块提升很大,新版本的kernel会将没有用的设备clock关掉,这样会导致CPU1用的外设无法访问而带来一系列问题,解决方法有2个:

a. 在bootargs中添加 clk_ignore_unused 参数,告诉linux内核不要关闭没有用的clock

https://www.kernel.org/doc/Documentation/clk.txt

=======================================
Disabling clock gating of unused clocks
=======================================

Sometimes during development it can be useful to be able to bypass the
default disabling of unused clocks. For example, if drivers aren't enabling
clocks properly but rely on them being on from the bootloader, bypassing
the disabling means that the driver will remain functional while the issues
are sorted out.

To bypass this disabling, include "clk_ignore_unused" in the bootargs to the
kernel.

b. 在make menuconfig中将power management option中uncheck,不同版本的名字可能会有差别,如果不在乎功耗,直接全部uncheck,或者自己读help,针对性的uncheck

Step6:正常编译uboot,kernel,并使用ramdisk文件,


Step7:在XSDK下用Xilinx tools -> Creat Boot Image, 将amp_fsbl.elf,app_cpu1_bsp_xgpiops_polled_example_1.elf,u-boot.elf生成BOOT.BIN

--Notes:生成BOOT.BIN的时候,add文件的顺序有一点小技巧,请按照 FSBL --> uboot.elf --> cpu1_app.elf的顺序,这样确保cpu0的linux正常启动。

Step8:将BOOT.BIN, uImage, uramdisk.image.gz, devicetree.dtb ,设置成SD启动

原文地址:https://www.cnblogs.com/kevin-heyongyuan/p/7471503.html