litex-hub / linux-on-litex-vexriscv

Linux on LiteX-VexRiscv
BSD 2-Clause "Simplified" License
551 stars 174 forks source link

Serial download with de0nano board: cannot communicate with FPGA #348

Closed fts-tmassey closed 10 months ago

fts-tmassey commented 10 months ago

Hello!

FPGA: Terasic DE0-Nano Host system: Debian 12.1 (Bookworm) FPGA Software: Quartus 22.1 Std (Free) linux-on-litex-vexriscv: Downloaded 2023/08/29.

I am following the Readme for linux-on-litex-vexriscv. I have successfully downloaded, built and run the project in the simulator. I am now trying to download it to the board.

I successfully compiled the package with:

./make.py --board=de0nano --cpu-count=1 --build

I seem to have successfully loaded the FPGA with:

./make.py --board=de0nano --cpu-count=1 --load

I get the LED's lighting up and turning off round-and-round, which I take to mean that the download was successful.

However, I cannot perform the next step: download the kernel, etc. via serial. The readme's next command is:

litex_term --images=images/boot.json /dev/ttyUSB0 --safe

but when I run that, nothing happens. When I type on the keyboard, I get a blinking LED on my USB serial adapter's TX LED, but nothing happens on the RX LED or shows up in the litex_term. If I use a jumper to connect TX and RX on the serial adapter, I do get both lights and the content is echoed on litex_term. So the litex_term command and the serial adapter seem to be working correctly, but I'm not getting any response from the FPGA.

Of course, I also don't know exactly where I'm supposed to connect the serial adapter to on the DE0-Nano board, either. I haven't found specific instructions for that. I've tried Googling extensively and I haven't found anything. The closest I could find was https://github.com/litex-hub/litex-boards/blob/master/litex_boards/platforms/terasic_de0nano.py where it seems to imply that (board) TX is JP1:10 and (board) RX is JP1:08. That seems to be confirmed by build/de0nano/gateware/de0nano.pin, which shows serial_rx as B4 and serial_tx as B5, which the Terasic DE0-Nano User Manual shows as GPIO-0 pins 8 and 10. I've tried that (and reversed TX/RX as well) to no effect. I'm using pins 29 and 30 for +3.3/Gnd.

I have successfully used Quartus to create, load and run a "Hello, world!" type program for the FPGA successfully, so it seems that my setup is working correctly. I've also tried to use litex_term via jtag, but that gives me an error (Error: unable to open ftdi device with description '', serial '' at bus location '*'), and I have not been able to pursue that any further. At this point, I'm out of ideas.

What do I need to do to be able to connect litex_term to a Terasic DE0-nano with linux-on-litex-vexriscv?

Thank you your time and attention. I appreciate any help you might be able to give me.

jeremy-heath commented 10 months ago

I had a similar problem with the default make.py and the litex_term for DE0-Nano. The baud rate did not match and it was slow for serial uploads. make.py use --uart-baudrate=1e6 litex_term use --speed=1e6

Also maybe reverse RX and TX on the serial connection.

josuah commented 10 months ago

Before getting linux-on-litex-vexriscv going, one way to get fewer to debug would be getting litex-vexriscv going without the linux-on- part:

The scripts on the https://github.com/litex-hub/litex-boards/ repo are used by linux-on-litex-vexriscv, but are also possible to be run stand-alone.

In these boards definitions, there are all the sources to build and load the bootloader, which would bring the idiomatic LiteX ascii art banner as well as a debug shell.

If you do not get this going, it is likely that linux-on-litex-vexriscv will stay stuck in the same state.

josuah commented 10 months ago

A quick glance at the DE0Nano target shows: https://github.com/litex-hub/litex-boards/blob/master/litex_boards/targets/terasic_de0nano.py#L10

josuah commented 10 months ago

And a quick glance at the DE0Nano platform shows: https://github.com/litex-hub/litex-boards/blob/master/litex_boards/platforms/terasic_de0nano.py#L37-L43

josuah commented 10 months ago

By running the script with --help:

~/litex/litex-boards/litex_boards$ targets/terasic_de0nano.py --help
usage: {'description': 'LiteX SoC on DE0-Nano.'} [-h] [--toolchain {quartus}] [--build] [--load]
...
  --uart-name UART_NAME
          UART type/name. (default: serial)
...

And here is some more hints about what can be supported for uart_name: https://github.com/enjoy-digital/litex/wiki/Load-Application-Code-To-CPU#serial-boot

In the end, accessing the console is a matter of bringing it to yourself the way you want it, rather than seeking how LiteX configures it for you: there is a command line flag that tells how the console is configured, and you are free to set it to anything supported for that board, whichever is easiest to get to work for yourself.

The --uart_name=serial (default) is likely using the pins in the "serial" pin definition (which should be working, unlike what you got :thinking:).

The --uart_name=jtag_uart uses the JTAG PHY to transfer serial data, with an example OpenOCD script for it as said on IRC (thanks for the tip!) and on the comment.

josuah commented 10 months ago

Now, onto getting that litex-board script working on linux-on-litex-vexriscv:

Here are the arguments passed from linux-on-litex-vexriscv to litex-boards, as if they were typed on the command line: https://github.com/litex-hub/linux-on-litex-vexriscv/blob/master/make.py#L626-L627

This means that by default there is not any command line argument for the UART set (like --uart_name). Not sure yet which one that would be for that board.

fts-tmassey commented 10 months ago

I had a similar problem with the default make.py and the litex_term for DE0-Nano. The baud rate did not match and it was slow for serial uploads.

Ding, ding, ding, we have a winner! :)

I redid the following with updated commands:

./make.py --uart-baudrate=1e6 --board=de0nano --cpu-count=1 --build ./make.py --uart-baudrate=1e6 --board=de0nano --cpu-count=1 --load litex_term --speed=1e6 --images=images/boot.json --safe /dev/ttyUSB0

And after pressing a few times and getting garbage, things got syncronized and I got a litex> prompt clear as day! Gave it a reboot command and got the litex boot screen! Then used serialboot and Image started to upload! I'm only 18% into that upload right now, so who knows if it will actually work... but that's not a serial communication issue and doesn't belong here anyway! :)

Also maybe reverse RX and TX on the serial connection.

Managed to have that correct. For reference: the pin labelled TxD (with an arrow out) on my serial adapter is attached to JP1 (the 4-pin header nearest the USB port) pin 8, and the pin labelled RxD (with an arrow in) on my serial adapter is attached to JP1 pin 10. (And Vin is attached to pin 29, and Gnd is attached to pin 30).

If I were to write up a detailed process for the DE0-Nano, would there be any interest in placing this somewhere where future users could find it? At least a future Google might find this issue...

As for the JTAG UART: sure, I would prefer just a single cable, and hopefully might be faster: I'm 20 minutes in and Image is only 40% downloaded... But for now, I have something, which is great. Right now, I'm at the follow-the-bouncing-ball stage, so I want to stay on the default path as much as possible, but that will likely be one of the first things I'll pursue once I'm ready to deviate. A DE0-Nano doesn't have a lot of options for high-speed I/O, so anything's probably better than RS-232... :)

Thank you both very much! If I have further issues with the JTAG UART, should I open a new issue or just use this one?

fts-tmassey commented 10 months ago

A brief followup:

As mentioned, the serial load for me was very slow. Like well over an hour for about 12MB of data. I gave a first pass at jtag_uart but continued to run into problems, so I focused on the one that worked, though slowly: the external UART. I did some experimenting to try to improve the performance.

First improvement: the FTDI interface seems to support up to 3Mb speed, so I updated the relevant baud parameters to 3e6 That helped, but only incrementally. Second improvement: I had been using the --safe parameter. In the project's defense, --safe was only mentioned not actually included directly, but I had added them. They may or may not improve safety, but they most certainly do make things orders of magnitude slower. Without them, and with the faster baudrate, it's now less than a minute to add the same 12MB of kernel and initrd. So until I see a problem, I'll stick with the external UART. For now, that's fast enough: I will worry about jtag_uart at a later time.

But while faster, it still didn't complete the boot. At that point, I completely wiped out my mangled installation and redid everything from the start, using the readme and my previous notes. This includes starting with the pre-built Linux image. Success! Everything worked as expected: I can build the FPGA code, download the pre-built Linux image data and boot it successfully -- just like the sim, but a LOT faster! :)

On to a custom buildroot! Thank you all again for your help.

I will close this ticket. Thank you very much for your help!