Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Valued Contributor III
1,681 Views

Guide for starting HPS FPGA bridges and general tips in baremetal C

If any of you have tried to use the FPGA bridges you might have ran in to a lot of problems with the CPU locking up, the JTAG interface locking up, Linux crashing or the Avalon bus in your FPGA doing sweet nothing as it waits for the waitreqest line to go low. If you fiddle around with rebuilding the preloader and uboot and all that stuff you might have struck lucky and got it to work eventually. But one should be able to just turn the thing on and use it. 

 

It has taken me some time to find all this stuff out and i would have found it very helpful if i had this information at day 1. So to save someone else from it here is a very basic guide to baremetal C and HPS FPGA bridges. 

 

1)the tools 

Install the latest Quartus and the Altera SoC EDS tools (Make sure you take the 30 day trial or get a license otherwise its unusable for baremetal C) 

 

2)making a baremetal project 

Open the ARM DS-5 eclipse environment and import "...\altera\14.0\embedded\examples\software\Altera-SoCFPGA-HelloWorld-Baremetal-ARMCC.tar.gz" Use this as your base for everything else (The folder also contains the most useful baremetal examples out there) To get acess to hardware registers you will also want to add the folder "...\altera\14.0\embedded\ip\altera\hps\altera_hps\hwlib\include" in to the include path of your project. the "socal" folder contains the register .h files. The directory also includes the hwlib library with ready made drivers for things(they can take a while to understand the documentation) 

Once you include the socal .h files you can define that register set with a name in this format: 

ALT_CLKMGR_raw_t *CLKGMRregs = (ALT_CLKMGR_raw_t*)ALT_CLKMGR_ADDR; ALT_SYSMGR_raw_t *SYSMGRregs = (ALT_SYSMGR_raw_t*)ALT_SYSMGR_ADDR; ALT_RSTMGR_raw_t *RSTMGRregs = (ALT_RSTMGR_raw_t*)ALT_RSTMGR_ADDR; ALT_GPIO_raw_t *GPIO0regs = (ALT_GPIO_raw_t*)ALT_GPIO0_ADDR; 

 

To acess individual parts of registers you also might want to put these in 

ALT_CLKMGR_t *CLKGMRbits = (ALT_CLKMGR_t*)ALT_CLKMGR_ADDR; ALT_SYSMGR_t *SYSMGRbits = (ALT_SYSMGR_t*)ALT_SYSMGR_ADDR; ALT_RSTMGR_t *RSTMGRbits = (ALT_RSTMGR_t*)ALT_RSTMGR_ADDR; ALT_GPIO_t *GPIO0bits = (ALT_GPIO_t*)ALT_GPIO0_ADDR; 

 

Then to use a regisster do this 

//GPIO Modules release from reset RSTMGRbits->permodrst.gpio0 = 0; //Write to GPIO pins GPIO0regs->gpio_swporta_dr = 0;  

 

3) the bridges and other peripherals 

When you got the dev board or SOM or whatever you didnt just buy it because it has a nice big FPGA in it, or because it has a fast 900MHz Dual core ARM in it. You bought it because it has BOTH in it and as a result can do some pretty cool stuff with the bridges... after you figure out how to acualy use them that is. 

 

If you do things wrong here the CPU or JTAG interface will likely lock up until you reset the chip or even have to power cycle it. This also happens when trying to acess registers of peripherals that are still in reset like the UART or SPI. This includes looking at the registers using JTAG in any way. If a peripheral you want to use is doing that then while connected to the chip via JTAG pause the CPU and click at the top Window->Show view-> Registers. In this useful register view open the Peripherals folder and look for "rstmgr" the bottom 5 registers in there control all the reset lines internal to the parts of the chip. If you set all 5 to zero every peripheral will be out of reset, including the FPGA bridges that are under rstmgr_brgmodrst. 

 

If you open the memory window (Window->Show view->Memory) and go to the adress 0xFF200000 (Lightweight HPS to FPGA) or 0xC0000000 (Regular HPS to FPGA) it will still lock up due to the bridge not running on the FPGA side. Go to quartus and load in the golden reference design or build your own if you like. For building your own all you need to do it start a new qsys system and add in "Processors and Peripherals->Hard Processor Systems-> Arria V/Cyclone V Hard Processor System". Leave the DDR3 settings and such alone and just set what you need. To make Qsys happy you will need to export the conduit called "memory", export it as whatever you want and simply dont assign it any pins in the pin planner, it will still be perfectly happy. To test it connect up some RAM to the buses or add a gpio block to toggle LEDs. Make sure it has a clock and is out of reset (I like to have a PLL in there and i export out the "locked" conduit out so a LED turns on when it has clock and is out of reset) once it is loaded in to the FPGA. 

 

I recommend doing this step before letting the hps bridge out of reset, but it also works the other way around. 

 

However for some reason a lot of the bridge related register groups will still lock everythyng up upon acessing them in the registry view window. Why this happens i dont know, but dont worry there are no important registers in there despite the name.But the adresses 0xFF200000 and 0xC0000000 should not lock up when you acess them trough the memory view and you should be able to modify the contents in that window. If you can write an area of your RAM located in Qsys and the number doesn't snap back to all 0s or Fs then it works. 

 

4)sdram bridge 

Okay fantastic everything works so now i am going to harness the amazing power of the bridges to acess the HPS side DDR memory from the FPGA fabric and make a kickass hardware accelerator for my ARM program. As you build your system and attempt to read/write trough the SDRAM bridge you might notice that nothing is happening or the waitreqest line in the avalon bus never goes to 0 to indicate its ready. The usual cause of that is located in the SDRAM controlers registers. Use the register window to go to "Peripherals->sdr" and look for the register "sdr_ctrlgrp_fpgaportrst" this contains aditional reset signals for the SDRAM bridge interfaces. This ports bits are inverse reset signals so to bring all the interfaces out of reset it needs to be set to 0x000003FFF. Aditionaly you might check the register "sdr_ctrlgrp_proportdefault" as it is capable of blocking memory acess from the fpga bridge. 

 

Also if the FPGA design you are loading in does not have valid DDR settings you may have to load the FPGA design in and afterwards press the warm reset button to run the preloader again and then launch your baremetal C code or mess about with JTAG. 

 

5)aditional tips 

If you are having difficulties trying to access the HPS to FPGA bridges you might also have a memory mapping or security problem. Check the registers "l3regs_remap" and "l3regs_secgrp_lwhps2fpgaregs" and similar to make sure the memory space is available to you (Note that you cannot see the contents over JTAG, only write to them due to some security reason). Also one thing to make sure is to check the clocks in "clkmgr" registers to make sure all l3 and l4 clocks are running, as the bridges run off them. 

 

For looking and writing to memory addresses in linux you can use the "memtool" command in the console for most images out there 

 

If nothing helps then also try to use a different preloaderor uboot version. 

 

 

I hope this quick guide helped you get started quickly and saved you time figuring all of this stuff out. I have seen a lot of people having problems with the HPS bridge on the forums so hopefully this solves most of them. If you happen to have any more useful tips on the topic do share them.
0 Kudos
3 Replies
Highlighted
Valued Contributor III
98 Views

I'll move this to the baremetal section of the forum and stick it.

0 Kudos
Highlighted
Valued Contributor III
98 Views

Berni, this looks like it may be rather helpful to me, so thank you. I gave up and moved onto other parts of the project now, but will eventually get back to trying to run a bare-metal C app.

0 Kudos
Highlighted
Beginner
61 Views

Hey thanks for these guide lines they helped me allot.
I have a question may be you can answer it for me.

i have a custom board and it has a CYCLONE V 5CSEBA5U23I7 on it.

on our custom board the HPS and the FPGA share the reset pin. both are getting the power on reset from the same source at the same time. e.g. when i switch on the FPGA boots from its own QSPI and the HPS loads the preloader from its own QSPI. both are power on independently.

i am not sure how to make the power on sequence.

the FPGA must need to boot first from the HPS if i am using H2F master and H2F lw bridge in the FPGA?

Here is what happens. when i power on my device i see that the H2F master and H2F lw bridges are not initialized automatically by the HPS. Although they exist in my QSYS project.

Then i manually initialize both bridges manually in the baremetal application in HPS firmware.

socfpga_bridge_setup(ALT_BRIDGE_LWH2F);

etc..

Now if i flash my program on the HPS and do a power on. the program on the HPS traps. and i think it traps because it does not see the H2F bridges.

but if i flash the *.sof on the FPGA and then start my HPS then every thing works perfect.

is there any one who can suggest me what should be the power on sequence required if i want to use the resources of the FPGA on the HPS?



many thanks.
0 Kudos