09-27-2012 08:53 PM
Has anyone tried to use both cpu cores of zynq?
I did not find any example from Xilinx, only related information
in "Zynq-7000 EPP Technical Reference Manual UG585 (v1.2)".
It says that cpu0 must do these two things:
1. Write the address of the application for CPU1 to 0xFFFFFFF0.
2. Execute the SEV instruction to cause CPU1 to wake up and
jump to the application.
Found a "dual cpu demo" example on ARM web-site:
However, the attached source code doesn't do any of the
above two actions. How can the second cpu start then?
02-28-2013 06:02 AM
Thanks for your help. Zynq bare-metal/bare-metal AMP booting in JTAG mode is working fine.
When the Xilinx bare-metal/bare-metal refrence design like Linux/brare-metal(xapp1078) will avialable?
Also can you please advice me regarding, how to implement an Inter-Processor communication framwork between the Zynq cores in bare-metal/bare-metal AMP solution?
03-01-2013 07:10 AM
The bare-metal/ bare-metal xapp is going through the review process so it will still be a few weeks longer.
Regarding a communication framework, like the linux/bare-metal xapp, I just bit bash OCM memory. Cpu0 writes to, for example, 0xffff0000 and cpu1 reads/clears 0xffff0000 and cpu1 writes 0xffff0004 and cpu0 reads/clears 0xffff0004.
The trick with bare-metal/bare-metal is if cpu1 is servicing PPI interrupts, cpu0 first needs to initialize the ICD. Also, cpu0 needs to 'kick' cpu1 with an event in order to startup cpu1. I believe I posted the 'kicking' process either in this thread or another.
03-22-2013 08:35 AM
I am trying to make a standalone/standalone project.
I assigned the location 0x20000000 for cpu1, and in app0 I write this address to 0xfffffff0, and send the SEV instr.
When I boot from SD card, cpu0 prints Hello World, but cpu1 does not.
I made sure that the code of cpu1 was copied to mem (read the memory locations by cpu0 and sent them to UART)
can you please forward this example standalone/standalone project to me? I have been facing similar problems to what were mentioned in this forum.
My email is rida.jichi AT epfl.ch
Of course, I am aware that this example is not supported by Xilinx, and it will be on my own.
03-26-2013 03:12 AM
With the help of your XAPP1078, we can use AMP mode on ZC702 board. But we want to use this AMP mode on ZC706 board. So we converted the provided reference design using the following steps:
- Load the system.xmp using XPS 14.4
- Project->Project Options. Change device size to xc7z045
- Import -> ZC706 Board Template
- Regenerate bitstream
- Export design to SDK
Then followed the same steps described in the xapp1078, we are able to get a BOOT.BIN, boot and confirm that the CPU1 application is loaded in address 0x30000000. But "/mnt/rwmem.elf 0xfffffff0 0x30000000" does not seem to start app_cpu1 on CPU1, we can see that location 0xffff8000 is not incrementing, and no interrupt message with "/mnt/rwmem.elf 0x78600000 1" (we could see both happening on ZC702)
How do we get it to work on ZC706?
03-26-2013 08:21 PM
I have attached compressed project folder in some earlier post
in this same thread. I think it is on the first or second page.
04-04-2013 01:55 AM
Update on AMP on ZC706
In case anyone is facing the same issue, the workaround is to use XMD to start CPU1, like this:
XMD% connect arm hw -debugdevice cpunr 2
XMD% con 0x30000000
After this 0xffff8000 is being incremented as explained in xapp1078 (and as seen on ZC702 board). Poking around with xmd on ZC706, if we check state after just boot it says CPU is stopped. Wrote a small wrapper program to write "0x30000000" and then do a "SEV", it still had no effect (i.e.. CPU1 is not in WFE state). So only way to start CPU1 seems to be via xmd. I suspect that there seems to be a change in Boot ROM/FSBL or their behaviour on ZC706 which causes CPU1 to be not started
04-04-2013 05:50 PM
Sorry, I've had my head burried pretty deep the last while. The bare-metal/bare-metal xapp 1079 has just been released and is available here: http://www.xilinx.com/support/documentation/application_notes/xapp1079-amp-bare-metal-cortex-a9.pdf
Regarding startup of the second cpu, in early silicon (early versions of zc702), cpu1 is not correctly captured and relocated to 0xffffff00 if the config modes are set to jtag. The zc706 (newer silicon) is correctly captured and sent to 0xffffff00. WFE is part of the loop but in the case of running linux on cpu0, irqs are constantly happening causing cpu1 to be woken up.
Regarding zc702, if you have an older version of silicon, make sure you set the config mode to something like SD card and remove the card. When the bootrom tries to boot from the SD card and fails, it will correctly fallback to jtag mode and send cpu1 up to 0xffffff00.
04-05-2013 05:02 AM
johnmcd, I assume your reply is addressing my query on AMP on ZC706 (otherwise please ignore this)
I am wondering if you swapped zc702 and zc706? We have no problem running the xapp1078 design on zc702. The problem is on zc706.
Anyhow we have a work around right now (i.e. connect via xmd to cpu1 and do con 0x3....). Its not urgent, but I hope in due course we will have a solution where AMP can be triggered without xmd, like on zc702)
04-05-2013 08:17 AM
Hi Kanda and johnmcd,
I am using ZC706 to run the baremetal/linux AMP originally intended for ZC702. I did the adjustments as Kanda did and I am facing the same issue as it was described - Linux boots CPU0, CPU1 does not start after calling /mem/rwmem 0xfffffff0 0x30000000. In other words by calling /mem/rwmem 0xffff8000 the value is zero all the time.
Kanda, would be happy to share your XMD wrapper?
04-05-2013 11:39 PM
The steps to start via xmd are already there in my post., anyhow here they are in more detail:
- Start xmd via SDK: Xilinx_Tools > Launch_shell
- Or via command line <ISE Dir>/ISE_DS/EDK/bin/nt64 or <SDK dir>/SDK/SDK/bin/nt64 (or nt32)
- Just type following commands in XMD prompt
XMD% connect arm hw -debugdevice cpunr 2
XMD% con 0x30000000
The first command connects xmd to CPU1, the second command gets CPU1 to start (continue) execution from 0x30000000. After this you will see location 0xffff8000 incrementing (and work as explained in the xapp)
You can refer to Chapter 10, Xilinx Microprocessor Debugger (XMD)in Embedded System Tools Reference Manual (UG111) for more XMD commands to start, stop, reset, download .elf file, etc.
Hope this helps.
04-08-2013 01:42 AM
Thank you for your reply. I repeated the steps, however, I cannot see the location 0xffff8000 incrementing. I might have done sth. wrong in the previous steps, namely I did not import zc706 template in XPS, I only changed the settings of MIO manually. I will try to follow the way you did. I built the Linux kernel, bootloader and the device tree myself to target zc706. When building the device tree, I used http://www.wiki.xilinx.com/Build+Device+Tree+Blob, then changed the generated *.dts file accordingly and generated the dtb file. I downloaded the ram disk image from the Xilinx website. I guess this should not be a problem of the Linux (CPU0), should it?
04-08-2013 01:53 AM
When I launch app_cpu1 as debug config from the SDK and let it run with F8 hotkey, then request 0xffff8000, I got a kernel crash, see the attached picture.
04-08-2013 02:58 AM
Using the XMD commands responses so that everything seems ok:
Accepted a new TCLSock connection from 127.0.0.1 on port 38656
connect arm hw -debugdevice cpunr 2
JTAG chain configuration
Device ID Code IR Length Part Name
1 4ba00477 4 Cortex-A9
2 03731093 6 XC7Z045
CortexA9 Processor Configuration
No of PC Breakpoints................6
No of Addr/Data Watchpoints.........1
Connected to "arm" target. id = 65
Starting GDB server for "arm" target (id = 65) at TCP port no 1234
XMD% con 0x30000000
Launching ChipScope, I can see the signal EVENT_EVENT0 toggling, however, no iterrupt is captured either by the terminal, nor by the ChipScope after clicking on SyncOut.
04-08-2013 03:41 AM
I've got it! I made a mistake when not including the linker script for app_cpu1, after doing so I can see the memory location 0xffff8000 incrementing every second, iterrupts get generated using ChipScope's button or by writing 1 to location 0x78600000. Only, I cannot see the captured waveforms in ChipScope.
As well as Kanda, I would appreciate solution for triggering app_cpu1 directly from Linux in the future.
04-08-2013 07:32 AM
I've started to take a look at the linux/baremetal on the zc706. The zc706 uses a newer version of silicon. I've noticed two things
In order to fix #1, you can change the contents of the cpu1_bootvec.bin file. Using a hex editor, change the contents from "00 FF FF FF" to "2C FF FF FF".
04-08-2013 09:34 AM
The standalone/standalone programming is just what I need. I'm using EDK14.4, so would you please send me your example of standalone/standalone and the file of FSBL, BSP?
my email is: email@example.com
thank you very much!
04-09-2013 10:31 AM
Regarding running Linux/baremetal on zc706: as I previously mentioned, you need to change the cpu1_bootvec.bin file from containing 0xffffff00 to containing 0xFFFFFF2C in order to accomodate the wfe loop in the newer silicon.
Also, Linux resets the system when Linux boots. This action causes cpu1 to jump to the reset vec at 0x00000000. Linux has a different method of handling the startup of cpu1. A simple change in arch/arm/mach-zynq/platsmp.c will enable Linux to force cpu1 back to the wfe loop.
Change platsmp.c line 137 from
ret = zynq_cpu1_start(virt_to_phys(secondary_startup));
ret = zynq_cpu1_start(0xFFFFFF2C);
I hope that everyone using xapp1078 is compiling the kernel, but if not, reply to this thread and I will post a pre-compiled version of the kernel somewhere.
09-16-2013 05:47 AM
I try running baremetal on both cores (ZC702) based on xapp1079. I want to handle interrupts on both cores, e.g. CPU0 is running the lwip stack servicing the private timer interrupt (XPS_SCU_TMR_INT_ID). CPU1 ought to handle e.g. PL interrupts (XPS_IRQ_INT_ID).
Apparently setting up the ICD, enabling interrupts and register handlers on both cores is not the right way to do it.
CPU0 seems to run and service IRQs properly, but enabling IRQs on CPU1 seems to stall CPU1. It looks like, as if CPU1's IRQ handler is called once, but never returns.
From one of your preceding post:
If you plan on handling interrupts from the PL on only one cpu, you can bypass the ICD and just use that cpu's interrupt controller.
How can I bypass the ICD? And why?
Thanks a lot your your kind help!
09-19-2013 08:13 PM
Take a look at the TRD (ug585), figure 'Interrupt Controller Block Diagram'. Each cortex A9 has it's own Private Peripheral Interrupt (PPI) controller. The xapp uses interrupts in the PPI instead of the shared ICD.
If you are running baremetal on both cpus, you can still use just the ICD but make sure each cpu doesn't interfere with each other's resources within the ICD.
11-07-2013 04:38 PM
I've tried out XAPP1079 on the Zed board using the 14.4 suite and your posted 14.3 source files. In system.xmp, I changed the memory part and timing of the traces to match the Zed's design, otherwise I made no changes. Otherwise, I believe Zed and ZC702 are identical.
I was able to build system.bit, and the rest of the directions went smoothly until I actually tried the boot, which failed to display anything at all on the terminal.
I guess my question would be this: is there a version for which this works well? For example if I upgrade to 14.7 will your 14.5 design example files work, now that Xilinx allows a standard FSBL to run two programs on two CPUs without special modifications? Or is there likely something wrong on my end?
I also tried your pre-built images but imagine those are incorrect as the RAM is different between ZC702 and Zed.
Does anyone have a working example files for Zed Board? My goal is to run and examine this code so that I can port it to a custom, in house built board that utilizes the Zynq 7030. It will eventually run something much more complex, but I need to get a way to boot both CPU's and tweak examples, etc.
11-11-2013 04:49 PM
I am able to get xapp1078 to work on the ZC702 board ... but now we would like Linux to be able to force the baremetal app to restart (in case of a failure scenario, etc.).
I was able to pull the cpu1 app out of the boot image and load it manually from linux to 0x30000000, and then kick off the program by writing to 0xFFFFFFF0 just like the app note does (only now I am manually loading it instead of the FSBL doing it). This is so we can have a golden image bootloader image that will not need to get updated every time the cpu1 app gets updated.
However, when I force a reset from linux by writing to the control registers:
# Assert reset to CPU1
rwmem 0xF8000244 0x00000002
# Stop clock to CPU1
rwmem 0xF8000244 0x00000022
# Release reset to CPU1
rwmem 0xF8000244 0x00000020
# Start clock to CPU1
rwmem 0xF8000244 0x00000000
It seems to reset CPU1 to 0x00000000, rather than 0x30000000.
Any ideas on how to deal with SW resetting the 2nd core?
11-12-2013 12:18 PM
There is a working example of xapp1078 for the Zed board. I'm not aware of a port of xapp1079.
The primary difference between the Zed board and zc702 is the configuration of the PS which is all software and the configuration takes place by the FSBL. So at a mimimum, I would expect that you could create a new FSBL for the Zed board but use the original elf and bit files from version 14.5.
Take a look at the 14.5 files here: http://www.wiki.xilinx.com/XAPP1079+Latest+Information
11-12-2013 12:26 PM
You are describing the startup mechanism of Linux and how it grabs CPU1 (instead of using the wfe() loop).
Both CPUs use the same reset vector of 0x00000000. In the standalone BSP, you will notice code that checks if it is running on cpu0 or cpu1 and do the apropriate thing.
What Linux does is it temporarily replaces the reset vector with a different value, then resets cpu1, as you are describing, and then rewrites the original reset vector after cpu1 has been restarted.
You can take a look at the xapp1078 updates here: http://www.wiki.xilinx.com/XAPP1078+Latest+Information
11-12-2013 12:52 PM
Actually I am running baremetal on CPU1, and have restricted Linux to only use CPU0 in the devicetree startup command.
I want to be able to reset CPU1 and NOT reset CPU0 (say if CPU1 is stuck or otherwise fails), which now works after a good suggestion from Denis T at Xilinx (basically restrict Linux from the lower bytes and put an instruction at 0x00000000 to set CPU1's PC to the wfe loop).
I am manually loading and copying CPU1's code from Linux in a startup script, so a system reset is taken care of.
If we reset only CPU0 (with Linux on it), are you saying that it will also reset CPU1?
I put a printk statement into the function that is described by the wiki update page as you note, and it never appears to be getting called, I am guessing that is only if you let Linux manage both cores (we are not). Plus that mod is out of date from the trunk of the kernel source which uses zynq_cpun_start() instead of just cpu1.
11-14-2013 09:51 PM
The reason I pointed you to the wiki page was so that you could see how Linux manages the reset of CPU1 as an example of how to temporarily backup the value in 0x00000000, write it with the pointer to the wfe loop, reset CPU1, and then restore the original value back into 0x00000000. Basically what Denis mentioned to you.
Since you removed CPU1 from the devicetree, Linux will not try to manage it so CPU1 will not be reset if you reset only CPU0.
12-03-2013 08:45 AM
hi ,johnmcd, I've tried out XAPP1079 on the ZC702 board using the 14.6 suite and your posted 14.5 source files.So what should i do to update it ? the custom bsp standalone_v3_09_a couldnot match standalone_v3_10_a in 14.6 suite.