Difficulties with BCC2 mkprom-hello example

I’m trying to get acquainted with the toolchains for LEON3 and following the README in bcc2/src/examples/mkprom-hello, but I am unable to get it to work.

From the instructions:

  • hello.prom contains the boot loader and a compressed version of hello.elf. It is linked for storage in non-volatile memory, typically on address 0x00000000.

I can get hello.elf running from RAM successfully.

My target is a LEON3 on a Digilent Arty A7 board. I flash the example from grlib/designs/leon3-digilent-arty-a7 unmodified. From the README I understand that I need to make sure that the binary ends up at 0x400000, because the lower portion of the flash is reserved for the FPGA bitstream (relevant quote at the end). Hence, I compiled the example with (0x400000 = 4194304):

$ make CFLAGS="-mcpu=leon3 -msoft-float" MKPROMOPT="-leon3 -freq 81 -baud 38352 -rstaddr 4194304"

Verify the start address:

$ sparc-gaisler-elf-objdump -x hello.prom 

hello.prom:     file format elf32-sparc
architecture: sparc, flags 0x00000012:
start address 0x00400000

Flash it to ROM:

grmon3> spim flash load hello.prom
            400000 .text             46.3kB /  46.3kB   [===============>] 100%
  Total size: 46.31kB (821.49bit/s)
  Entry point 0x00400000
  Image /.../examples/mkprom-hello/hello.prom loaded

Trying to run it:

grmon3> reset

grmon3> run
  Exception (tt = 0x02, illegal instruction)
  0x00400000: ffffffff  unknown opcode: 0xffffffff

I don’t see anything on /dev/ttyUSB1 either (using screen). Checking the first few instructions:

grmon3> mem 0
  0x00000000  88100000  09001000  81c120b0  01000000    .......... .....
  0x00000010  a1480000  a7500000  10800177  ac102001    .H...P.....w.. .
  0x00000020  91d02000  01000000  01000000  01000000    .. .............
  0x00000030  91d02000  01000000  01000000  01000000    .. .............
grmon3> dis 0 4
       0x00000000: 88100000  clr  %g4                 
       0x00000004: 09001000  sethi  %hi(0x400000), %g4
       0x00000008: 81c120b0  jmp  %g4 + 0xb0          
       0x0000000c: 01000000  nop        

What am I missing?

From README in designs/leon3-digilent-arty-a7:

Typically the lower part of the SPI flash device will hold the configuration bitstream for the FPGA. The SPIMCTRL core is configured with an offset value that will be added to the incoming AHB address
before the address is propagated to the SPI flash device. The default offset is 0x00400000 (this value is set via xconfig and the constant is called CFG_SPIMCTRL_OFFSET). When the processor starts after power-up it will read address 0x0, this will be translated by SPIMCTRL to 0x00400000.

SPIMCTRL can only add this offset to accesses made via the core’s memory area. For accesses made via the register interface the offset must be taken into account. This means that if we want to program the Flash with an application which is linked to address 0x0 (our typical bootloader) then we need to add the offset 0x00400000 before programming the file with GRMON. We load the Flash with our application starting at 0x00400000 and SPIMCTRL will then translate accesses from AMBA address 0x0 + n to Flash address 0x00400000 + n.


You can use objcopy to change the load address of all the sections. Remove the -rstaddr option to mkrprom2 so the application is linked to address 0x0. Then you will load data to 0x400000 but run the application from 0x0.

sparc-gaisler-elf-objcopy --change-section-lma *+0x400000 hello.prom hello.spim

Thanks @arvid , but unfortunately, that doesn’t seems to change much. The error goes away, but now GRMON complains: “No entry point set!”:

grmon3> reset
grmon3> run
  No entry point set!

The second instruction is different now (sethi(0) instead of sethi(0x400000)) and matches with the example in the MKPROM manual:

grmon3> dis 0 4
       0x00000000: 88100000  clr  %g4          
       0x00000004: 09000000  sethi  %hi(0), %g4
       0x00000008: 81c120b0  jmp  %g4 + 0xb0   
       0x0000000c: 01000000  nop      

I guess I have some debugging to do, but ideas are welcome in the meantime…!

Uet the command “ep 0” to set the entry point manually, or add it to the run command “run 0”

grmon3> reset
grmon3> run 0
  Error mode  (tt = 0x04, fp disabled)
  0x000005f4: 91d02000  ta  0

Different error than before… I guess my next learning goal is to attach the debugger.

I think I got a bit further. The trap lead me to finding out that the out-of-the-box design had SVT enabled. So I recompiled with -qsvt:

make CFLAGS="-mcpu=leon3 -msoft-float -qsvt" MKPROMOPT="-leon3 -qsvt -freq 81 -baud 38425"

Unfortunately, that didn’t change anything:

grmon3> run
  Error mode  (tt = 0x04, fp disabled)
  0x0000063c: 91d02000  ta  0  <_prom_srmmu_fault+0>

I see that the design also has the MMU disabled, but I can’t directly identify a flag for MKPROM related to it. Or is _prom_srmmu_fault a red herring?

It looks like you have used “info mkprom2” in GRMON. That output is a suggestion, you should sanity check the values. For example the baudrate should probably be the standard 38400. And the frequency seem to be a bit odd (should it be 80MHz?), note that GRMON detects the wrong frequency sometimes (in which case you should provide the correct frequency to GRMON with the commandline flag -freq ).

It error indicates that you trying to use the floating-point unit, but its turned of or missing. You can verify this by looking at the instruction trace (“inst 1000” in GRMON), and you should see either a floating point instruction issued or a floating point register being used.

You need to provide -msoft-float to mkprom2 as well.

It’s probably a good idea to go through the commandline options of mkprom2 in the manual to see if you are missing anything else.

@arvid thanks so much! I can’t believe I forgot to add -msoft-float to the options for MKPROM, it’s even the first one in the list in the manual… Adding that flag and setting the baudrate to 38400 solved it and the example is working as expected.

As an aside: I was wondering about how to sanity check the baud rate. I noticed that subsequent calls to info mkprom2 would give different values for frequency and baudrate. The frequency I can cross-check with the design files (83 MHz is set there), but while the baudrate didn’t make sense initially, I also couldn’t find a way how to check it.