TinyFPGA-BX Won't Program Anymore


#1

My TinyFPGA BX board was working, but now gives me a python error when trying communicating to the board. Here’s the error when using tinyprog -m:

C:\Users\Cathy>tinyprog -m
Traceback (most recent call last):
File “c:\users\cathy\appdata\local\programs\python\python36\lib\runpy.py”, line 193, in run_module_as_main
main”, mod_spec)
File “c:\users\cathy\appdata\local\programs\python\python36\lib\runpy.py”, line 85, in run_code
exec(code, run_globals)
File "C:\Users\Cathy\AppData\Local\Programs\Python\Python36\Scripts\tinyprog.exe_main
.py", line 9, in
File "c:\users\cathy\appdata\local\programs\python\python36\lib\site-packages\tinyprog_main
.py", line 257, in main
m[“port”] = str(port)
TypeError: ‘int’ object does not support item assignment

I get a similar error with tinyprog -p.

I have tried a different WIndows 10 PC, uninstalling, reinstalling, and updating tinyprog. The current blinking program that I wrote still works (I can see the LED blinking).

Also when I try to update the bootloader I get “all active boards are up to date!”
C:\Users\Cathy>tinyprog --update-bootloader

TinyProg CLI
------------
Using device id 1d50:6130
Only one board with active bootloader, using it.
All connected and active boards are up to date!

Any hints or help will be greatly appreciated. Thanks.


#2

Hi, the code in question does the following

if args.meta:
    meta = []
    for port in active_boards:
        with port:
            p = TinyProg(port)
            m = p.meta.root
            m["port"] = str(port)
            meta.append(m)
    print(json.dumps(meta, indent=2))
    sys.exit(0)

it looks like your meta data might be wrong. Can you paste the output of tinyprog -m

tinyprog -m

[
  {
    "boardmeta": {
      "name": "TinyFPGA BX",
      "fpga": "ice40lp8k-cm81",
      "hver": "1.0.0",
      "uuid": "8617ef5d-babe-beef-eeee-ff1487b963dc"
    },
    "bootmeta": {
      "bootloader": "TinyFPGA USB Bootloader",
      "bver": "1.0.1",
      "update": "https://tinyfpga.com/update/tinyfpga-bx",
      "addrmap": {
        "bootloader": "0x000a0-0x28000",
        "userimage": "0x28000-0x50000",
        "userdata": "0x50000-0x100000"
      }
    },
    "port": "/dev/ttyACM0"
  }
]

#3

Hi! I am interested to hear the responses to this thread. I am experiencing the same thing and the metadata is wrong or missing. I get the same response on Windows 7 and MacOS using tinyprog.


#4

Very interesting. It appears the metadata is not coming back. I’ll make a metadata utility to rewrite the metadata. It could be another issue still, but that will be a good thing to try.


#5

Thanks Luke! I hope the metadata utility fixes it. Also, the error that I posted earlier was for getting the metadata, not for programming the .bin file (I didn’t have a program on that computer at the time).


#6

Hi Aaron, can you try dumping the raw data (before the error occurs?)


#7

Hi,
I also have the same issue.

tinyprog -l

    TinyProg CLI
    ------------
    Using device id 1d50:6130
    Only one board with active bootloader, using it.
    Boards with active bootloaders:

        COM10: No metadata

and when i try to program it:

tinyprog -c COM10 --program hardware.bin

    TinyProg CLI
    ------------
    Using device id 1d50:6130
    Programming COM10 with hardware.bin
Traceback (most recent call last):
  File "c:\users\hfranca\appdata\local\programs\python\python36\lib\runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "c:\users\hfranca\appdata\local\programs\python\python36\lib\runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "C:\Users\hfranca\AppData\Local\Programs\Python\Python36\Scripts\tinyprog.exe\__main__.py", line 9, in <module>
  File "c:\users\hfranca\appdata\local\programs\python\python36\lib\site-packages\tinyprog\__main__.py", line 334, in main
    addr = fpga.meta.userimage_addr_range()[0]
  File "c:\users\hfranca\appdata\local\programs\python\python36\lib\site-packages\tinyprog\__init__.py", line 182, in userimage_addr_range
    return self._get_addr_range(u"userimage")
  File "c:\users\hfranca\appdata\local\programs\python\python36\lib\site-packages\tinyprog\__init__.py", line 188, in _get_addr_range
    addr_str = self.root[u"bootmeta"][u"addrmap"][name]
TypeError: 'int' object is not subscriptable

It was working fine just a few minutes before.
Now I’m stuck…
I would appreciate very much some help!


#8

Ok…I’ve been thinking about this some more. This is very strange. The metadata is written to special security pages in the SPI flash. The first page contains the unique device ID along with the board name and hardware revision. The second page contains the address map.

The first page is write-protected. It can’t be overwritten, erased, or modified in any way. The second page is not write-protected…it can be modified.

I think I’ll make a utility that will both read out and write back the correct metadata. Time is tight, but it should be able to get done this week.


#9

It would be extremely useful to have that utility!


#10

I have been thinking about what I might have done to cause this issue. I was wondering if pushing the button on the board while the board is being programmed might have caused some of the metadata to be overwritten.

This is just a theory, but I hope it may help you figuring this out.


#11

Your theory can make sense.
I don’t think that I’ve done exactly that, but it is possible that I have started tinyprog before releasing the reset button.


#12

Hi Luke,
I refresh this page every couple of hours to see if the utility to re-write the metadata is available.
I hope you will find some spare time to write it.
Cheers!


#13

Hi,

Perhaps we can try to fix this as community. It should be not be very hard and will empower us!
-There is a tool to read the data
-There is a tool to write (generic) data
-We can try and figure out the small changed needed for this.


#14

I did start having a look at this. I previously made some changes to tinyprog to allow it to read data - see Experiments with BX programmer and bootloader

I was thinking of adding to that, the ability to read and dump the metadata to a file. That would be useful in diagnosing the problem as the -m flag only currently works when the metadata is valid json. It would also help in developing the utility.

To do that looks easy - it would be like the --read_image flag I added, but would use read_security_register_page rather than read.

There are already erase_security_register_page and and program_security_register_page methods in init.py.

So adding a --write_metadata flag to tinyprog shouldn’t be too hard. We would need to format the json and write it to the three security pages. There seems to be optional metadata in normal pages as well, but I am not sure that that is used.

Most of the metadata is fixed, other than a uuid and the version numbers.


#15

So, I implemented the flag (-z, --read_security_image) to dump the security data, see -

And here is the result:

python __main__.py -ztest.bin

TinyProg CLI
------------
Using device id 1d50:6130
Only one board with active bootloader, using it.
Reading security page image to file test.bin

od -Ax -c test.bin

000000 { " b o a r d m e t a " : { " n
000010 a m e " : " T i n y F P G A B
000020 X " , " f p g a " : " i c e 4 0
000030 l p 8 k - c m 8 1 " , " h v e r
000040 " : " 1 . 0 . 0 " , " u u i d "
000050 : " 5 e 2 0 5 4 0 7 - 2 f 6 d -
000060 4 a 7 a - b 7 d f - 1 b 1 d 2 2
000070 8 6 f a 8 d " } } \0
000080
*
0000f0 {
000100 " b o o t m e t a " : { " b o o
000110 t l o a d e r " : " T i n y F P
000120 G A U S B B o o t l o a d e
000130 r " , " b v e r " : " 1 . 0 . 1
000140 " , " u p d a t e " : " h t t p
000150 s : / / t i n y f p g a . c o m
000160 / u p d a t e / t i n y f p g a
000170 - b x " , " a d d r m a p " : {
000180 " b o o t l o a d e r " : " 0 x
000190 0 0 0 a 0 - 0 x 2 8 0 0 0 " , "
0001a0 u s e r i m a g e " : " 0 x 2 8
0001b0 0 0 0 - 0 x 5 0 0 0 0 " , " u s
0001c0 e r d a t a " : " 0 x 5 0 0 0 0
0001d0 - 0 x 1 0 0 0 0 0 " } } } \0
0001e0
0001f0 377 377
000200 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377 377
*
0002f0 377 377 377 377 377 377 377 377 377 377 377 377 377
0002fd


#16

It looks like just security register pages 1 and 2 are used and are filled with binary zero after the json data. The opening “{” for the second page is at address 0x100 not 0xf0 (i.e the stat of the second page) as you can see if you read the pages one by one. The third page is filled with 0xff, possibly because it has never been written.

I don’t know how the uuid is formed.


#17

Another solution that should work is to change tinyprog so that if it fails to read the metadata, it returns default metadata. That should make the device usable without writing to it, and would be at least a temporary solution until @lukevalenty writes the metadata utility.


#18

I have investigated this a bit more and I don’t think the problem is the metadata in the security pages.

As the update process does not touch the security pages, it seemed unlikely that that was the problem.

The code to get the metadata does:

    > meta_roots = (
        [self._parse_json(self.prog.read_security_register_page(p).replace(b"\x00", b"").replace(b"\xff", b"")) for p in [1, 2, 3]] +
        [self._parse_json(self.prog.read(int(math.pow(2, p) - (4 * 1024)), (4 * 1024)).replace(b"\x00", b"").replace(b"\xff", b"")) for p in [17, 18, 19, 20, 21, 22, 23, 24]]
    )

This concatenates roots from security pages and normal pages. As the normal pages are not currently used, they are not needed and you can comment them out like:

      > meta_roots = (
        [self._parse_json(self.prog.read_security_register_page(p).replace(b"\x00", b"").replace(b"\xff", b"")) for p in [1, 2, 3]] # +
       # [self._parse_json(self.prog.read(int(math.pow(2, p) - (4 * 1024)), (4 * 1024)).replace(b"\x00", b"").replace(b"\xff", b"")) for p in [17, 18, 19, 20, 21, 22, 23, 24]]
    )roots = (
        [self._parse_json(self.prog.read_security_register_page(p).replace(b"\x00", b"").replace(b"\xff", b"")) for p in [1, 2, 3]] +
        [self._parse_json(self.prog.read(int(math.pow(2, p) - (4 * 1024)), (4 * 1024)).replace(b"\x00", b"").replace(b"\xff", b"")) for p in [17, 18, 19, 20, 21, 22, 23, 24]]
    )

and metadata is still returned fine.

However if any of those pages have numeric data that is not 0x00 or 0xff, you will get the error you reported. You can test this by just inserting " + [0] ", and you get the error you reported.

So it looks like one of those pages got data written to it during the failed update. If you comment out the read of those normal pages, as above, you should avoid the error and it should return metadata, unless your failed update caused other problems.


#19

Hi Lawrie,

Thank you for the info.
However, I’m still not able to bring back to life my TinyFPGA BX.
I’m using the tinyprog from windows.
If I use the tinyfpgab script, it returns “No port was specified and no active bootloaders found”, and if I use it with the “-c” option it returns “No active bootloaders found”.
Also, I cannot find where the the lines of code that you propose to comment are.


#20

I did not think tinyfpgab worked with the BX.

The code I mentioned is at https://github.com/lawrie/TinyFPGA-Bootloader/blob/master/programmer/tinyprog/__init__.py

You should be add to run that on Windows. Put __init__.py in a directory called tinyprog and comment out the code as shown. Put main.py in the directory above tinyprog and then run:

python __main__.py -m