FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6529 Discussions

custom Nios bootloader

Altera_Forum
Honored Contributor II
2,390 Views

Hello, 

I have a very small board containing ethernet phy, sdram and cyclone III fpga only. The fpga upload is done from another board, which has microcontroller on it, using passive serial mode. The .sof upload is easy, I enable TTF file generation in Quartus and give that generated code to the microcontroller.  

 

Now the difficult part is Nios upload. I don't have neither EPCS nor CFI flash, but I have 8bit interface with microcontroller with some control signals, so I need other methods to upload Nios .elf file to the system, instead of epcs and cfi methods described in manual. 

One of the ideas would be to place reset vector into onchip memory where I would place a small program, that copies software into sdram, but I am not sure if the option enabling memory initialization from .hex is directly compiled into the .sof or not. Are there any solutions? 

 

Thanks.
0 Kudos
15 Replies
Altera_Forum
Honored Contributor II
1,380 Views

Yes if you specify on the on-chip ram block to use a specified .hex file, it will be included in the .sof configuration and will be available as soon as the FPGA switches to user mode. 

Just be sure that your software is compiled into the correct .hex file, and that you compile the Quartus project after the .hex file has been updated. If the Quartus project is already compile, you should only need to run the assembler to update a .sof when you change the contents of the .hex file.
0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

So I should put the reset vector to the on-chip ram, then it should start the bootloader where I copy the data to sdram and jump to the start address?

0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

Yes, exactly. Just ensure that your bootloader software project is configured to place the code in the on-chip ram. application note 458 (http://www.altera.com/literature/an/an458.pdf) is about designing custom boot loaders and could help you in this task.

0 Kudos
Altera_Forum
Honored Contributor II
1,379 Views

Right, but now the interesting question: what if Nios received reset? It'll jump to bootloader which will wait for a new binary file then?

0 Kudos
Altera_Forum
Honored Contributor II
1,379 Views

Yes. All the bootloaders I know re-load the application on reset. 

In theory you could change the bootloader code so that it detects a reset condition and chooses to directly jump to the application instead of waiting for a new binary file. You should be vary careful with this though, as all the static variables with initialization will keep the value they had before reset instead of being reinitialized to their default value. This could break your code (or some drivers).
0 Kudos
Altera_Forum
Honored Contributor II
1,379 Views

In this case, I can't reuse the on-chip ram after program start, because bootloader will be corrupted and a whole new reconfiguration is needed.

0 Kudos
Altera_Forum
Honored Contributor II
1,379 Views

It depends on how you write your bootloader. If you don't use statically initialized variables but initialize everything in your code (in the bootloader, the code and the drivers) it could work. But I admit it isn't the usual way embedded applications boot.

0 Kudos
Altera_Forum
Honored Contributor II
1,379 Views

I would consider writing an Avalon master driven from the external micro via the 8bit interface. You'll need to do multiple cycles to setup the 32bit address and read/write data register prior to/after requesting the actual cycle (and maybe polling for cycle completion). 

Expose the nios soft reset lines to an avalon slave as well (I did a 32bit wide register with separate write-to-set and write-to-clear addresses, with a mask and then ored to interrupt the external host...) 

 

This all has the advantage that you can use the same interface to dump out the memory (and io registers) while the system is running. Continuous displays (well every 100ms or longer will do) are useful for debug. 

 

You can then quite probably load directly from the elf program file using the 'program headers'. 

 

I actually extract the nios code/data blocks and convert them into ppc data objects which then get linked into a ppc linux application! The app is also linked with the symbol table from the nios image. 

(We do have a PCIe slave, but I used a pio->avalon master block when testing the code on some alternate hardware.)
0 Kudos
Altera_Forum
Honored Contributor II
1,379 Views

Sorry for taking an old thread up, but I am stuck on some interesting place. 

 

Now I am trying to do a bootloader, which gets data through SPI. The bootloader reset vector is in on-chip memory, which is at 0x01000000. The exception vector is placed on SDRAM, which is at 0x00800020 (SDRAM component address is 0x00800000). Now when I try to write the binary data to SDRAM_BASE (0x00800000) or to exception address (0x00800020), then the data is written up to a certain address (e.g. writes up to 0x00800864) and the cpu hangs. If I begin to write from 0x008F0000, then all the binary data is written fine. 

 

The question: where do I have begin to to write the binary data? To SDRAM_BASE, to exception address or other address?
0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

I've never written a bootloader so I have no experience in this, but just as an idea, it is possible that an exception occurs while you are writing the data in the SDRam. If you have written the exception instruction at the exception address but not the actual exception code yet, if an exception occurs it can hang the CPU. It could be a good idea to write the text data first, without the exceptions and finish by writing the exceptions themselves and the reset code. Or be sure the exceptions are entirely disabled before you start writing. I don't know what the default bootloader does, but here are my ideas...

0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

Well, that's actually strange, because I am writing data from 0x00800000, which is SDRAM_BASE. It always stops writing at 0x00800864. I am also using SPI interrupt to get byte and then write it to SDRAM.

0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

How can you be using the SPI interrupt in the bootloader, when the interrupt vector address is in SDRAM - where you are loading the code to. 

 

I'd have thought you'd need to run the boot loader with interrupts disabled (polling for status). 

 

Also, where is your bootloader's stack (if the code actually uses one). If that is in SDRAM you might be writing over the stack. 

 

It ought to be possible to write a bootloader (in C) that has almost no memory accesses. I couldn't stop the function prologue saving registers - they are the only references to %sp in my entire hdlc and mtp2 engines. 

(gcc would need a rebuild to let me use %sp as a general register!)
0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

Hm, I've set all the vectors to on_chip ram except the exception one. Just a minute ago, I've managed to run the bootloader using SPI status register polling. Now I'll try to use interrupts if possible.

0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

Why bother using interrupts? 

The processor isn't doing anything else is it?
0 Kudos
Altera_Forum
Honored Contributor II
1,380 Views

Using interrupts is elegant solution :) but anyway, it doesn't work as You've said. I've left the bootloader to poll bytes from SPI.

0 Kudos
Reply