ZYNQ UltraScale 双核裸跑 / 裸跑 + Linux

# 1 背景提出
    某项目对中断延迟有很高的要求,客户的构架为:PPC+ Vxworks,延迟时间大概:10us.(因硬件设计原因, 还可以更小)。我们在Linu系统下测试中断延迟大概几百us, 而且这是在CPU很空闲情况下的测试结果。Linux非实时性操作系统,延迟参数不可预估。所以,想采用裸跑+Linux的方案。

# 2 开发平台
    硬件平台:ZYNQ7020、ZYNQ Ultascale + MPSOC XCZU19EGFFVC1760-2-I
    软件版本:Vivado 2019.1 SDK Petalinux 2019.1

# 4 双核裸跑
    0.新建FSBL.
    1.新建app工程0,    选择cpu_0,修改应用程序,见源码。

    int i;
    init_platform();

    while(1){
        for(i = 0; i < 0xffffff; i++);
        print("Hello World run at cpu 0! \n\r");
    }

    cleanup_platform();

    2.新建app工程1,选择cpu_1,修改应用程序,见源码。

    int i;
    init_platform();

    while(1){
        for(i = 0; i < 0xffffff; i++);
        print("Hello World run at cpu 1! \n\r");
    }

    cleanup_platform();

    3.选择app工程1的BSP包,打开Board Support Package Settings, dirvers->ps_cortex9_1->extra_compiler_flag添加:-DUSE_AMP=1
    4.修改cpu0、cpu1的app工程连脚本文件:lscript.ld的DDR配置
                                base address                            size
        CPU0:        ps_ddr_0    0x00100000                            0x1FE00000
        CPU1:        ps_ddr_0    0x20100000                            0x20000000
    5.打开FSBL->src->src->main.c,添加定义:
        #define sev() __asm__("sev")
        #define CPU1STARTADR      0xFFFFFFF0
        #define CPU1STARTMEM     0x20100000 //该参数为CPU1应用程序的起始地址
        定义函数:
        void StartCpu1(void)
        {
            #if 1
            Xil_Out32(CPU1STARTADR, CPU1STARTMEM);
            dmb(); //waits until write has finished
            sev();
            #endif
        }
    6.在HandoffAddress = LoadBootImage();函数后添加自定义函数
        //kuens
        StartCpu1();
    7.制作BOOT.BIN,烧写启动
    8. 终端输出信息 

        Hello World run at cpu 1!
        Hello World run at cpu 0!
        Hello World run at cpu 1!
        Hello World run at cpu 0!
        Hello World run at cpu 1!
        Hello World run at cpu 0!
        Hello World run at cpu 0!
        Hello World run at cpu 1!


注1:为验证启动双核应用程序的正确性,可在SDK中分别新建CPU0、CPU1的应用程序,在SDK中分别Debug到相应的CPU上运行起来,如运行成功,再进行添加引导CPU1、程序固化等工作。

注2:在ZYNQ Ultrascale下不需要修改启动代码,只需要修改应用程序脚本中的DDR参数,SDK中直接制作BOOT.BIN启动文件即可。

# 5 Baremetal +Linux

## 5.1 ZYNQ 平台
    0.新建FSBL.
    1.新建app工程1,选择cpu_1,修改应用程序,见源码,本例程为: LED MIO 0闪烁。

int main()
{
    int i,Status;
    XGpioPs_Config *ConfigPtr;
    Output_Pin = 0;

    init_platform();
    ConfigPtr = XGpioPs_LookupConfig(GPIO_DEVICE_ID);
    Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
                        ConfigPtr->BaseAddr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
    XGpioPs_SetDirectionPin(&Gpio, Output_Pin, 1);
    XGpioPs_SetOutputEnablePin(&Gpio, Output_Pin, 1);

    /* Set the GPIO output to be low. */


    while(1){
        for(i = 0; i < 0xffffff; i++);
        XGpioPs_WritePin(&Gpio, Output_Pin, 0x1);

        for(i = 0; i < 0xffffff; i++);
        XGpioPs_WritePin(&Gpio, Output_Pin, 0x0);
    }

    cleanup_platform();
    return 0;
}

    3.选择app工程1的BSP包,打开Board Support Package Settings, dirvers->ps_cortex9_1->extra_compiler_flag添加:-DUSE_AMP=1

ZYNQ UltraScale 双核裸跑 / 裸跑 + Linux_第1张图片
    4.修改 cpu1的app工程连脚本文件:lscript.ld的DDR配置
                                base address            size
        CPU0:        ps_ddr_0    0x00100000            0x1FE00000     //Linux
        CPU1:        ps_ddr_1    0x20100000            0x20000000    //Baremetal

CPU0:

ZYNQ UltraScale 双核裸跑 / 裸跑 + Linux_第2张图片

CPU1:

ZYNQ UltraScale 双核裸跑 / 裸跑 + Linux_第3张图片


    5.打开FSBL->src->main.c,添加定义:

ZYNQ UltraScale 双核裸跑 / 裸跑 + Linux_第4张图片
        #define sev() __asm__("sev")
        #define CPU1STARTADR      0xFFFFFFF0
        #define CPU1STARTMEM     0x20100000    //cpu_1应用程序的链接地址
        定义函数:
        void StartCpu1(void)
        {
            #if 1
            Xil_Out32(CPU1STARTADR, CPU1STARTMEM);
            dmb(); //waits until write has finished
            sev();
            #endif
        }
    6. 在main函数中,找到的HandoffAddress = LoadBootImage(),该函数后添加自定义函数
        //kuens
        StartCpu1();
    7.修改设备树:
        在bootargs 中添加 maxcpus=1 mem=512M@0x0;    //根据实际情况修改
        例如:
            chosen {
                bootargs = "console=ttyPS0,115200 maxcpus=1 mem=384M@0x0 clk_ingore_unused earlyprintk";
                stdout-path = "serial0:115200n8";
            };
        在设备树重写memory节点:
        memory {
            device_type = "memory";
            //reg = <0x0 0x40000000>;
            reg = <0x0 0x20000000>;
        };

    8.使用petalinux命令制作BOOT.BIN(SD卡启动)
        petalinux-package --boot --fsbl ./images/linux/FSBL.elf --fpga --u-boot --add ./images/linux/world.elf --force
        (--add 的骚操作,一般人我不告诉他!)
    9.启动:
        在kernel启动前,CPU1运行正常。kernel启动后,CPU1停止运行。
       原因分析:FSBL、Uboot阶段,CPU1 运行正常,Kernel启动后由于gpiolib 对IO资源的统一管理,使得CPU1 不能获取相关硬件资源。(个人分析)
    10.登陆linux系统
        cd /sys/class/gpio906 //LED使用 MIO 0
        echo 906 > export
        运行正常

注:如平台是UltraScale+MPSoc平台,上述步骤有出入:

1.1  新建FSBL,无需修改源码

1.2  链接脚本,设备树,启动参数需要修改。

1.3  BOOT.BIN打包参考UG209.PDF(Page70)

kuens@ubtu:~/Desktop/zcu_106/vpx$ petalinux-package --boot --fsbl  --fpga --add ./images/linux/cpu1.elf --u-boot --force
INFO: File in BOOT BIN: "/home/kuens/Desktop/zcu_106/vpx/images/linux/zynqmp_fsbl.elf"
INFO: File in BOOT BIN: "/home/kuens/Desktop/zcu_106/vpx/images/linux/pmufw.elf"
INFO: File in BOOT BIN: "/home/kuens/Desktop/zcu_106/vpx/project-spec/hw-description/design_1_wrapper.bit"
INFO: File in BOOT BIN: "/home/kuens/Desktop/zcu_106/vpx/images/linux/bl31.elf"
INFO: File in BOOT BIN: "/home/kuens/Desktop/zcu_106/vpx/images/linux/u-boot.elf"
INFO: File in BOOT BIN: "/home/kuens/Desktop/zcu_106/vpx/images/linux/cpu1.elf"
INFO: Generating zynqmp binary package BOOT.BIN...

该命令打包不可行,参考本文可执行文件添加顺序,在SDK中手动制作BOOT.BIN.注意:Exception Level参数设置。与UG1209.PDF一致即可。

Ref:
        xapp1078-amp-linux-bare-metal(2018-11-20 17.04.24).pdf
        xapp1078-amp-linux-bare-metal.pdf

        Zynq UltraScale MPSoC Embedded Design Tutorial (UG1209).pdf
QQ:810871522

你可能感兴趣的:(ZYNQ开发,ZYNQ,Ultrascale,+,MPSoc)