riscv-rust/longan-nano

Unable to flash with dfu-util

eiskasten opened this issue · 34 comments

I wanted to test the display example. But it does not seem to work.

Steps to reproduce:

cargo build --release --example display --features=lcd

output:

   Compiling semver-parser v0.7.0
   Compiling proc-macro2 v0.4.30
   Compiling unicode-xid v0.1.0
   Compiling syn v0.15.44
   Compiling riscv v0.5.4
   Compiling bit_field v0.9.0
   Compiling autocfg v1.0.0
   Compiling num-derive v0.2.5
   Compiling nb v0.1.2
   Compiling rand_core v0.4.2
   Compiling void v1.0.2
   Compiling vcell v0.1.2
   Compiling gd32vf103xx-hal v0.2.1
   Compiling st7735-lcd v0.6.2
   Compiling longan-nano v0.1.1 (/tmp/longan-nano)
   Compiling embedded-graphics v0.5.2
   Compiling riscv-rt v0.6.1
   Compiling r0 v0.2.2
   Compiling panic-halt v0.2.0
   Compiling semver v0.9.0
   Compiling embedded-hal v0.2.3
   Compiling rand_core v0.3.1
   Compiling rand v0.5.6
   Compiling rustc_version v0.2.3
   Compiling num-traits v0.2.11
   Compiling quote v0.6.13
   Compiling bare-metal v0.2.5
   Compiling cast v0.2.3
   Compiling gd32vf103-pac v0.2.0
   Compiling riscv-rt-macros v0.1.6
   Finished release [optimized] target(s) in 23.93s

As I have connected the Sipeed Longan Nano via USB-C, I had to dfu-util to flash the binary which must be converted before:

riscv-sifive-elf-objcopy -O binary target/riscv32imac-unknown-none-elf/release/examples/display display.bin

A file with ~23K size is the result. The next step was to put the Sipeed Longan Nano into flash mode and flash the bin file:

sudo dfu-util -s 0x08000000:leave -D display.bin

which outputs:

dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 28e9:0189
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 2048
DfuSe interface name: "Internal Flash  "
Downloading to address = 0x08000000, size = 22888
Download	[=========================] 100%        22888 bytes
Download done.
File downloaded successfully
dfu-util: Error during download get_status

When completed, the Sipeed Longan Nano resets and is not in flashmode anymore.

During the whole process including flashmode, flashing and running the program, the red led next to the boot button is on and the backlight of the display too but all pixels remain black and never change their color which is not expected as it should display Hello Rust! when the program is running.

I do not use openocd as I do not know how to use it as I do not own a JTAG adapter. I only own a USB UART adapter but I think it is not possible to use that instead.

That's strange. Have you already flashed different examples with this dfu-util method? Did it work?

Hmm, using dfu-util from the Archlinux repo results in a half-broken firmware: every other block has mismatched data. I think that one needs a gd32-specific dfu-util to flash this chip correctly.

I tried blinky too but I was not sure if an actual led should blink or just a pin. If a led on the board itself should blink, then it has the exact same broken behavior as display.

Hmm, using dfu-util from the Archlinux repo results in a half-broken firmware: every other block has mismatched data. I think that one needs a gd32-specific dfu-util to flash this chip correctly.

That is interesting. I use the one from the Archlinux Repo. But I used it two days ago with another Rust code (not from this repo, I cannot remember from where it was) and it worked flawlessly.

Try this one: https://github.com/riscv-mcu/gd32-dfu-utils

This one has (from the master branch) the same result but has a slightly different output (both, display and blinky)

dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 28e9:0189
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 2048
GD32 flash memory access detected
Device model: GD32VF103CB
Memory segment (0x08000000 - 0801ffff)(rew)
Erase size 1024, page count 128
Downloading to address = 0x08000000, size = 22888
Download	[=========================] 100%        22888 bytes
Download done.
File downloaded successfully
dfu-util: Error during download get_status

The lines with the Device Model does not appear in the Arch's one.

Maybe the outputs of riscv-sifive-elf-objdump -Cd target/riscv32imac-unknown-none-elf/release/examples/display | head and riscv-sifive-elf-objdump -Cd target/riscv32imac-unknown-none-elf/release/examples/blinky | head are interesting?

target/riscv32imac-unknown-none-elf/release/examples/display:     file format elf32-littleriscv


Disassembly of section .text:

08000000 <_start>:
 8000000:	30405073          	csrwi	mie,0
 8000004:	34405073          	csrwi	mip,0
 8000008:	4081                	li	ra,0
target/riscv32imac-unknown-none-elf/release/examples/blinky:     file format elf32-littleriscv


Disassembly of section .text:

08000000 <_start>:
 8000000:	30405073          	csrwi	mie,0
 8000004:	34405073          	csrwi	mip,0
 8000008:	4081                	li	ra,0

Try getting your firmware back with the --upload option and compare with the original firmware binary with dhex or something.

I have uploaded it without the -s 0x08000000:leave option, I hope this was correct and they match exactly until including 0x7ff. The uploaded one is a bit smaller (16K instead of 23K but I think that is due to the -s 0x08000000:leave in the download command and the size would match).

I've just built https://github.com/riscv-mcu/gd32-dfu-utils from master and
/path/to/gd32-dfu-utils-dist/bin/dfu-util --alt 0 -s 0x08000000:leave -D display.bin works for me.
I don't know why dfu-util doesn't ask for --alt option from you, on my pc both Arch and gd32-specific dfu-util fail with the following error:
dfu-util: More than one DFU capable USB device found! Try `--list' and specify the serial number or disconnect all but one device

And

% dfu-util --list                                                
dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Found DFU: [28e9:0189] ver=1000, devnum=10, cfg=1, intf=0, path="2-4.2", alt=1, name="@Option Bytes  /0x1FFFF800/01*016 g", serial="??"
Found DFU: [28e9:0189] ver=1000, devnum=10, cfg=1, intf=0, path="2-4.2", alt=0, name="@Internal Flash  /0x08000000/512*002Kg", serial="??"

I have GD32VF103C8 on my board though, not GD32VF103CB.

That is because in my case dfu-util only lists "Internal Flash":

dfu-util 0.9

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2016 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to http://sourceforge.net/p/dfu-util/tickets/

Found DFU: [28e9:0189] ver=0100, devnum=24, cfg=1, intf=0, path="2-12", alt=0, name="@Internal Flash  /0x08000000/128*001Kg", serial="3CBJ"

This is the output from dfu-util compiled by myself. The Arch's one has the exact same output except the serial which is "??" as seen in your output.

I own five of the Longan Nano, I tried a second one which has the exact behavior (including every step of this issue) and just has devnum=25 if that is device specific.

I can confirm that on my longan nano, with the dfu-util from:
http://dl.sipeed.com/LONGAN/platformio/dl-packages/tool-gd32vflash-v0.1.0-linux.tar.gz
the display example works just fine.

Ok that is strange. Which board do you exactly have? What prints dfu-util --list? Which (exact) OS do you use?

I have a longan nano (GD32VF103CBT6).

I run dfu-util --list, with the dfu-util package I linked above:

dfu-util: Cannot open DFU device 28e9:0189

However, flashing works perfectly so far.

DFU Device ID: 28e9:0189
Run-time device DFU version 011a

OS: Manjaro Linux 5.4.18-1, same tools worked on windows 10.

Do you use the GD32 dfu-utils?

You have to run that as root. Yeah but I compiles them for myself as mentioned above.

doh. Of course. It says:

Found DFU: [28e9:0189] ver=1000, devnum=16, cfg=1, intf=0, path="3-4", alt=1, name="@option Bytes /0x1FFFF800/01016 g", serial="3CBJ"
Found DFU: [28e9:0189] ver=1000, devnum=16, cfg=1, intf=0, path="3-4", alt=0, name="@internal Flash /0x08000000/512
002Kg", serial="3CBJ"

What happens when you try the official compiled utils? Is the point of this issue that it does not work with your custom compiled dfu-util?

I see one major difference with the @eiskasten's board

8c8,9
< Found DFU: [28e9:0189] ver=0100, devnum=24, cfg=1, intf=0, path="2-12", alt=0, name="@Internal Flash  /0x08000000/128*001Kg", serial="3CBJ"
---
> Found DFU: [28e9:0189] ver=1000, devnum=17, cfg=1, intf=0, path="2-4.1.3", alt=1, name="@Option Bytes  /0x1FFFF800/01*016 g", serial="3CBJ"
> Found DFU: [28e9:0189] ver=1000, devnum=17, cfg=1, intf=0, path="2-4.1.3", alt=0, name="@Internal Flash  /0x08000000/512*002Kg", serial="3CBJ"

That board reports ver=0100. This field is extracted from the USB device descriptor (field bcdDevice). I think this board has different USB DFU code in the system memory, maybe even old-and-buggy code.

DaQue commented

Question, I have two of the Longan nano boards [purchased the week Seeedstudio first started selling them. Can the bootloader be updated, should I just buy some new ones and save me the trouble.

@DaQue if you have the same problem, I'd recommend getting a cheap JTAG adapter / FTDI breakout board.

Also there is a thread on Sipeed forums about this problem.

Why is @optionFlash missing on my boards? I have bought five of them, I have tested two and none of them has @optionFlash. Since I have successfully used Rust code on them in the past (sadly, I do not know how I have archived that) I do not think that the dfu-util is the problem.

Actually, I think maybe you use a wrong RISC-V GNU Toolchain (riscv-none-embed-objcopy), and this works for me which comes from NUCLEI (Official GD32 Core Designer)

https://www.nucleisys.com/download.php

riscv-none-embed-objcopy -O binary target/riscv32imac-unknown-none-elf/release/examples/display display.bin

I've tried it today, it does not make any difference.

Btw, does anybody now know how to fix that?:

Why is @optionFlash missing on my boards? I have bought five of them, I have tested two and none of them has @optionFlash. Since I have successfully used Rust code on them in the past (sadly, I do not know how I have archived that) I do not think that the dfu-util is the problem.

@eiskasten I'm not sure that you can fix this. Looks like you have a different bootloader which doesn't support @optionFlash and also has some bugs that prevent dfu-util from working properly. I believe dfu-util could be fixed to support these chips too. I can still recommend you to get a JTAG probe and use it instead.

Obtaining a JTAG adapter is a little bit compilcated as my country is locked down due to COVID-19, maybe it is possible to order one online.

Now I have tried https://github.com/WRansohoff/GD32VF103_templates (but it is in C instead of Rust) and the hello_led example works for me, although I had to replace every riscv32-unknown occurrence to riscv-sifive and I used it with the dfu-util from the Arch repo. However, the hello_display example does not work for me but it that is better than nothing.

@eiskasten as an alternative, you can use Windows flashing tool from Nuclei. I don't know the details, but people reported that it works for these chips.

Ok I will look for an Windows machine, but isn't my linked repo the proof that that is no flashing problem?

This example can fit in the first ~512 bytes and work because of that. Try flashing a bigger one.

So you think that this problem is bootloader/size related? Do you think this might help? https://mecrisp-stellaris-folkdoc.sourceforge.io/gd32vf103.html#flashing-the-mecrisp-quintus-binary

Hmm, it could help. Worth a try!

Hello, just to add one more datapoint:

I'm having the same problem with my longan-nano, which also reports only the @INTERNALflash section.

I'm not having any trouble downloading & running the rust example from https://github.com/pcein/rust-sipeed-longan-nano with either dfu-util, but when I try to download the examples from this repository it fails.

I can confirm that when uploading and diffing the small binary from that repository, there are no differences.

Uploading and diffing the bigger binaries from this repository here, I do get differences.

Using the patched dfu-util from https://github.com/riscv-mcu/gd32-dfu-utils does not help for me.

You are most likely to have the GD32VF103CB instead of the GD32VF103C8 device too, which nearly nobody seems to own. However, I found this guy on reddit which has the same problem too but unfortunately, this bug in the bootloader does not seem to be get ever fixed and according to Seeed, it is not possible to patch the bootloader.

I also have only differences when using bigger binaries and the patched version does not make any difference to this behavior.

@eiskasten Correct, I do have the GD32VF103CB.

But I just got the display example to work!

a) The most recent upstream version of dfu-utils (as of May 2nd 2020) contains a workaround for the buggy bootloader (https://sourceforge.net/p/dfu-util/dfu-util/ci/master/tree/).

Down- and uploading binaries still gives me a dfu-util: Error during download get_status , but there are no differences anymore after doing a round-trip (besides of old stuff at the end).

b) Now I realised that the binary I was writing started with a bunch of 0x00 at 0x8000000 -- which seemed odd. I tried different *-objcopy binaries and riscv-nuclei-elf-objcopy -O binary ... gave be a binary that actually started with something reasonable.

Downloading that then actually worked! I do see a "Hello Rust!" with green background on my display now!

Update: I was using rust-objcopy from rust llvm-tools before.

Confirmed! Works without problems now (beside the get_status error message)! Thank you very much I was quite desperate. I have tried it with riscv-sifive-elf-objcopy.

Since the problem is kinda solved and described in README, I think we can close the issue.