ZYNQ UltraScale 双核裸跑 / 裸跑 + Linux

本文介绍在ZYNQ平台上实现双核裸金属运行及与Linux共存的具体步骤,包括修改应用程序、配置内存区域、启动代码编写等关键技术点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

# 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


    4.修改 cpu1的app工程连脚本文件:lscript.ld的DDR配置
                                base address            size
        CPU0:        ps_ddr_0    0x00100000            0x1FE00000     //Linux
        CPU1:        ps_ddr_1    0x20100000            0x20000000    //Baremetal

CPU0:

CPU1:


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


        #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 UltraScale+ MPSoC 的 AMP 架构细节与实现 Zynq UltraScale+ MPSoC 是一种高度集成的多处理器片上系统(MPSoC),支持异步多处理(Asymmetric Multiprocessing, AMP)模式。这种架构允许不同的处理器核运行独立的操作系统或机程序,从而满足多种应用需求。 #### 处理器配置 Zynq UltraScale+ MPSoC 配备了一个四核 ARM Cortex-A53 和两个双核 ARM Cortex-R5F 处理器集群[^1]。这些核心可以被分配到不同类型的计算任务中,其中 AMP 模式利用了这一特性来分离工作负载。具体来说: - **ARM Cortex-A53**:通常用于运行通用操作系统(如 Linux 或 Android)。它适合执行复杂的应用层功能。 - **ARM Cortex-R5F**:设计为实时控制单元的核心,适用于需要高可靠性和低延迟的任务。 #### 软硬件分区 在 AMP 架构下,软件和硬件资源可以根据特定的需求进行灵活划分。例如,在某些工业控制系统中,可能让一个 R5 核心专门负责电机驱动逻辑,而 A53 则承担图形界面显示和其他管理职责。 #### 实现机制 为了有效地实施 AMP 结构,Xilinx 提供了一系列工具和技术帮助开发者完成如下几个方面的工作: - **引导加载程序定制**: 开发者可以通过修改 BootROM 来定义哪些 CPU 将启动并进入何种状态(等待命令还是立即开始执行指定代码). - **通信接口设置**: 使用共享内存区域或者专用外设作为跨域通讯手段之一;另外还有 Mailbox 和 Event Signaling Unit 这样的组件促进安全高效的进程间消息传递. 以下是简单的初始化伪代码展示如何针对不同子系统设定初始参数: ```c // Example of initializing cores in an AMP configuration on Zynq US+ MPSoC. void initialize_amps(void){ configure_core(A53_CORE0, RUN_LINUX); configure_core(R5F_CORE0, EXECUTE_BAREMETAL_APP); } ``` 上述函数调用了 `configure_core` 方法分别指定了A53的第一个核心应加载Linux环境以及R5第一个实例直接机应用程序.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值