cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
jimmimarquart
Observer
Observer
488 Views
Registered: ‎12-11-2018

zynqMP dual core app

Jump to solution

Hi,

I am using Xilinx Zynq UltraScale+ ZU4CG on a Trenz MPSoC Module.
TL;DR
I am trying to boot cpu1 from cpu0, hence i am looking for a section similar to section 6.1.10 Starting Code on CPU 1 from UG585 Zynq-7000 SoC for the ZynqMP ultrascale. I cant seem to find anything similar in UG1085.
And if there is something similar to XAPP1079 for ZynqMP it would be great.

U-boot, what I want to achieve
I have a simple uboot.elf which is compiled together with prebuilts from trenz (fsbl.elf, test_board.bit) together with a modified uboot.elf and the applications for cpu0 and cpu1.
I want to transfer cpu0.bin and cpu1.bin with kermit (or xmodem) "loadb <ram_addr>" to the RAM and store it QPSI (sf erasesf write), and then boot from QSPI and auto load (sf read) the bin files into ram and then "go <app_cpu0_ram_addr>" and then cpu0 should be responsible for booting up cpu1.

It seems straight forward if you specify which destination_cpu in the .bif file. However it seems that the FSBL is responsible for booting cpu1 using this method.

Code idea
I just want to achieve that cpu0 and cpu1 prints to the terminal based on a single address in DDR (when cpu0 successfully booted cpu1).

Searching the forums i have seen methods that reboots cpu1 from cpu0, could that be done the following way?:

#define XPAR_PSU_CRF_APB_S_AXI_BASEADDR 0xFD1A0000 //xparameters.h
#define XRESETPS_CRF_APB_BASE     (XPAR_PSU_CRF_APB_S_AXI_BASEADDR)
#define XRESETPS_CRF_APB_RST_FPD_APU ((XRESETPS_CRF_APB_BASE) + ((u32)0X00000104U))
#define ACPU1_PWRON_RESET_MASK    ((u32)0X00000800U)
#define ACPU0_PWRON_RESET_MASK    ((u32)0X00000400U)
#define ACPU1_RESET_MASK          ((u32)0X00000002U)
#define ACPU0_RESET_MASK          ((u32)0X00000001U)

void boot_cpu1() {
    u32 regVal;
    regVal = Xil_In32(XRESETPS_CRF_APB_RST_FPD_APU);
    regVal &= ~(ACPU1_RESET_MASK | ACPU1_PWRON_RESET_MASK); 
    Xil_Out32(XRESETPS_CRF_APB_RST_FPD_APU, regVal);
}

 

Further, from UG585 section 6.1.10 and XAPP1079, I tried something similar for zynqMP but it did not seem to work. (I have included multiple header files as well)
CPU0 code:

#define CPU1_APP_ADDRESS  0x2000000
#define CPU1STARTADR 0xfffffff0
#define sev() __asm__("sev")

void set_cpu1_addr() {
    Xil_Out32(CPU1STARTADR, CPU1_APP_ADDRESS);
    dmb(); // waits until write has finished
    //Xil_DCacheFlushLine(CPU1STARTADR); //disable cache instead
    sev();
}

int main() {
    init_platform();
    Xil_DCacheDisable();
    xil_printf("cpu0: hello\r\n");
    Xil_Out32(0x8000000, 0x0);
    
    boot_cpu1();
    set_cpu1_addr();

    while(1){
        xil_printf("CPU0: Hello World CPU 0\n\r");
        sleep(1);
        Xil_Out32(0x8000000, 0x1);
        while(0x1 == Xil_In32(0x8000000)){};
    }
    cleanup_platform();
    return 0;
}

  CPU1 code:

int main() {
    init_platform();
    Xil_DCacheDisable();
    xil_printf("cpu1: hello\r\n");

    while(1) {
        while(0x0 == Xil_In32(0x8000000)){};
        xil_printf("CPU1: Hello World CPU 1\n\r");
        sleep(1);
        Xil_Out32(0x8000000, 0x0);
    }
    cleanup_platform();
    return 0;
}

 

I also tried to run set_cpu1_addr() before boot_cpu() but that did not work either.

If boot_cpu() and set_cpu1_addr() is commented out, and set destination_cpu for both applications in the bif file, together with FSBL it will run fine when the boot.bin is placed in the QSPI.

Finally theres the linker-script and i have tried multiple sizes and offsets, both overlapping and non-overlapping but did not give any successful results.


I hope somebody is able to help.

Kind regards

 

0 Kudos
Reply
1 Solution

Accepted Solutions
ericv
Scholar
Scholar
346 Views
Registered: ‎04-13-2015

@jimmimarquart here's the info on how to get core#1 started at a specific address. Refer to the register reference:

https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html

From core #0:

1 - Reset  core #1 through the RST_FPF_APU register.

2 - Set the jump address of core #1 in its RVBAR register

3 - Release core # 1 from reset (RST_FPF_APU register again)

 

 

 

View solution in original post

2 Replies
ericv
Scholar
Scholar
347 Views
Registered: ‎04-13-2015

@jimmimarquart here's the info on how to get core#1 started at a specific address. Refer to the register reference:

https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html

From core #0:

1 - Reset  core #1 through the RST_FPF_APU register.

2 - Set the jump address of core #1 in its RVBAR register

3 - Release core # 1 from reset (RST_FPF_APU register again)

 

 

 

View solution in original post

jimmimarquart
Observer
Observer
306 Views
Registered: ‎12-11-2018
Thank you, I already figured it out, but I didnt have the time to write the solution my self. I was missing the RVBAR register. I do not think it seems obvious from the zynqmp manual or from the register reference, at least at first glance.
0 Kudos
Reply