Experiments with BX programmer and bootloader


#1

I am experimenting with changes to the BX programmer and bootloader, so that I can get one BX to program another BX over SPI.

I want to do that so that I can change the multiboot configuration of the BX for the menu for the tiny-fpga-bx-games-console. It needs to be able to load games from the SD card, write them to a new address in the flash memory and boot to that address. Currently I can only boot from 0x28000, so that means the menu program has to be overwritten.

Such a feature is also useful to restore the bootloader to a BX, if it gets corrupted, or if you have made your own BX board.

As a first step, I have added a feature to the BX programmer to allow if to read and image from flash memory.

So to read the user image at 0x28000, you do

tinyprog -r test.bin

TinyProg CLI
------------
Using device id 1d50:6130
Only one board with active bootloader, using it.
Reading image from address 163840 size 135100 to file test.bin
Reading: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 135k/135k [00:00<00:00, 362kB/s]

To read the bootloader, you do:

tinyprog -a 0xa0 -r test.bin

TinyProg CLI
------------
Using device id 1d50:6130
Only one board with active bootloader, using it.
Reading image from address 160 size 135100 to file test.bin
Reading: 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 135k/135k [00:00<00:00, 362kB/s]

To read the multiboot table in the first 160 bytes, you do:

tinyprog -a 0 -s 160 -b test.bin

Here is a hex dump of the the multiboot table:

000000 7eaa 997e 9200 0044 0300 00a0 8200 0001
000010 0800 0000 0000 0000 0000 0000 0000 0000
000020 7eaa 997e 9200 0044 0300 00a0 8200 0001
000030 0800 0000 0000 0000 0000 0000 0000 0000
000040 7eaa 997e 9200 0044 0302 8000 8200 0001
000050 0800 0000 0000 0000 0000 0000 0000 0000
000060 7eaa 997e 9200 0044 0300 00a0 8200 0001
000070 0800 0000 0000 0000 0000 0000 0000 0000

You can see that all 32-byte entries other than the third specify boot to address 0x0000a0 (bytes 9-11) , and the third (used to warm boot to the user image) specifies address 0x028000.

The next thing I plan to do is to rebuild the bootloader with different pins for the 4 SPI flash signals. I can then solder wires to the flash SPI pins on the underside of a second BX, connect them to the changed SPI pins on the first BX and use the first BX to program the second.

I can start by reading the flash memory of the second BX, to check that this works.

Here is the code for the modified programmer:


#2

I changed the SPI pins on the bootloader to pins 1-4 and changed the Makefile to allow 4 warm boot addresses, so if I write this multiboot configuration to a BX, I should be able to boot to 0x50000 or 0x78000 as well as 0x28000.

> icemulti -v -o fw.bin -a15 -p0 bootloader_0.bin bootloader_1.bin bootloader_2.bin bootloader_3.bin
> Place image 0 at 0000a0 .. 028000 (`bootloader_0.bin')
> Place image 1 at 028000 .. 050000 (`bootloader_1.bin')
> Place image 2 at 050000 .. 078000 (`bootloader_2.bin')
> Place image 3 at 078000 .. 0a0000 (`bootloader_3.bin')

Here is one BX programming another:

The second BX needs to be running a design that does not access the SPI flash pins, so I have it running blinky. So far I have just shown that I can read the metadata from the second BX. I have not worked up the courage to write the new multiboot configuration to it yet.


#3

I have now sucessfully written the new multiboot configuration to one of the Bx, and it is not bricked!

Here is the new multiboot configuration:

000000 7eaa 997e 9200 0044 0300 00a0 8200 0001
000010 0800 0000 0000 0000 0000 0000 0000 0000
000020 7eaa 997e 9200 0044 0300 00a0 8200 0001
000030 0800 0000 0000 0000 0000 0000 0000 0000
000040 7eaa 997e 9200 0044 0302 8000 8200 0001
000050 0800 0000 0000 0000 0000 0000 0000 0000
000060 7eaa 997e 9200 0044 0305 0000 8200 0001
000070 0800 0000 0000 0000 0000 0000 0000 0000
000080 7eaa 997e 9200 0044 0307 8000 8200 0001
000090 0800 0000 0000 0000 0000 0000 0000 0000

If anyone else does this, you need to change the Makefile and build the new multiboot configuration and save it, before changing the SPI pins, or you will build a multiboot that can only program another BX, not itself.


#4

Hi,

I was thinking. the SD functionality is not that useful (in general) but the programming is more. Changing the SPI pins is trivial so. Can you not modify the existing bootloader to allow to use different pins (over a usb message)? … That would me me very happy :stuck_out_tongue:


#5

Isn’t that what I have done :confused:

If you change the pins like I did, and build the bootloader then it will use the new pins when you send it a message over usb. That is how I programmed the new 4 configuration multiboot for my BX.

To use that bootloader, you just do tinyprog -p bootloader.bin.

It is then a bit confusing as you have a bootloader with the internal SPI pins at address a0 and and a bootloader with external SPI pins (pins 1 - 4) at address 0x28000.

After doing tinyprog -p bootloader.bin, the bootloader using pins 1-4 will be running and you will be able to program another BX or even another board such as a B2. After pressing reset or switching the BX off and on, the standard bootloader at address a0 with the internal SPI pins will be running.

I take no responsibility for people bricking their devices if they get this wrong.

If I were to use this to program a B2 board, I would use the read capability I added to the programmer to read the contents of an existing B2 board first as I am not familiar with them. I believe they need a multiboot configuration like the BX does. I don’t know if they contain the metadata like the BX board does. The tinyprog programmer uses that metadata to find the address to write the user image and user data to. I believe the user image is at address 0x30000 on the B2 not 0x28000 like the BX, but you could change that if you were putting a new multiboot configuration on it.


#6

Hi,

I was more thinking of adding a command to the bootloader e.g. CMD_SPI_MODE = (INT|EXT) to change the pins to use in the real bootloader. e.g. somewhere near


#7

I have just experimented with changing that code to toggle an LED - see USB Communication


#8

Yes, you could do that. Presumably you would switch between two sets of SPI pins, the existing internal set, and another external set (such as pins 1-4).

You would then have to write the new booloader to the BX. So you would need to create a new multiboot binary that includes it and write that to address 0. This is what I did to my BX to support my changed multiboot configuration.

You can do that by rebuilding the bootloader and then doing:

tinyprog -a 0 -p fw.bin

You then bravely ignore the dire warning message and type β€œyes”. That should either write your new multiboot loader with your new SPI mode command to the BX, or brick your device. If it fails or you get anything wrong you will need to reprogram the BX by soldering wires to the SPI pins on the underside, like I did.


#9

Or as you are only changing the bootloader, you could equivalently do:

tinyprog -a 0xa0 -p bootloader.bin

Although I am not sure I would recommend that as I have not tried it and it only works if the multiboot table is already in the first 160 bytes of flash memory, so it won’t work for a new board.

Also, it requires the programmer to read the first 4k of data, modify it, erase it and write it back. There is code in tinyprog for that but I doubt if it has been used much and there seems to be a bug in that general area. So I would stick with writing the multiboot binary at address 0.