wishbone-tool 0.7.3

A library and command line program to control a Wishbone bus of an embedded device
Documentation
# `wishbone-tool` - All-in-one Wishbone Binary and Library


`wishbone-tool` is useful for interacting with the internal Wishbone
bridge on a device.

Some of the things you can use `wishbone-tool` for:

-  Peeking and poking memory, similar to using `devmem2`
-  Testing memory and bridge link quality
-  Exposing a Wishbone bridge to Ethernet
-  Attaching a GDB server to a softcore

Currently-supported Wishbone bridges include:

-  **USB** - For use with Valentyusb such as on Fomu
-  **Serial** - Generic UART, nominally running at 115200 (but can be
   changed with ``--baud``)
-  **SPI** - Using 2-, 3-, or 4-wire SPI from
   [spibone](https://github.com/litex-hub/spibone)
-  **Ethernet** - Both TCP (e.g. a remote copy of `wishbone-tool`) or UDP (via Etherbone)
-  **PCI Express** - Using a PCIe softcore with the CSR register bank exposed

## Binaries

Precompiled versions of `wishbone-tool` can be found in the
[Releases](https://github.com/litex-hub/wishbone-utils/releases>)
section.

## Building

To build `wishbone-tool`:

1. Install Rust and Cargo. The easiest way to do this is to go to
   https://rustup.rs/ and follow the instructions.
2. Enter the ``wishbone-tool`` directory.
3. Run `cargo build` or `cargo build --release`

The `wishbone-tool` binary will be located under `target/debug/` or
`target/release/`.

## Usage

By default, `wishbone-tool` will communicate via USB, attempting to
open a device with PID `0x5bf0`. It will also run the `peek/poke` server
by default.

### USB Bridge

Simply run `wishbone-tool [ADDRESS]` to peek at a particular address.
To specify a particular vendor ID, pass `--vid [ID]`, for example `--vid 0xb0f1`.
To read from an area of memory (such as 0x10000000), run:

```
$ # Read from address 0x10000000 via USB
$ wishbone-tool 0x10000000
INFO [wishbone_tool::usb_bridge] waiting for target device
INFO [wishbone_tool::usb_bridge] opened USB device device 019 on bus 001
Value at 00000000: 6f80106f
$
```

To write a value to memory, add an additional parameter:

```sh
$ wishbone-tool 0x10000000 0x12345678
INFO [wishbone_tool::usb_bridge] opened USB device device 019 on bus 001
$ wishbone-tool 0x10000000
INFO [wishbone_tool::usb_bridge] opened USB device device 019 on bus 001
Value at 00000000: 12345678
$
```


### Serial Bridge

You can connect to a serial port by specifying the ``--serial``
argument:

```sh
$ wishbone-tool --serial COM4: 0x00000000
Value at 00000000: ffffffff
$ wishbone-tool --serial /dev/ttyUSB0 0x00000000
Value at 00000000: ffffffff
```

Ensure that you have write permission to the serial port. On some Linux
systems you may need to add your user to the `dialout` group.

### Ethernet Bridge

To connect to an Ethernet device, pass the `--ethernet-host` parameter:

```sh
$ wishbone-tool --ethernet 192.168.100.50 0x00000000
Value at 00000000: ffffffff
```

To connect to a different port, add `--ethernet-port PORT_NUMBER`. Finally,
if you would like to connect to another copy of `wishbone-tool` or to a copy of `lxserver`, add `--ethernet-tcp` to switch the connection from Etherbone to TCP.

### PCIe Bridge

If your device is connected via PCI Express, you can specify a PCIe BAR with `--pcie-bar FILE_PATH`. This will be a device under `/sys/bus`.

Note that when running in PCIe mode, only a small portion of the memory space
is exposed. This means that you may need to specify `--register-offset OFFSET`, because e.g. address 0 in the PCIe BAR may actually correspond to address 0xe0000000, and `wishbone-tool` needs to know how to perform the translation.

### SPI Bridge

If you specify `--spi-pins`, `wishbone-tool` will communicate with the target device via SPI. This is currently only supported on Raspberry Pi. Specify the physical Broadcom Pin numbers. Consult [Pinout.xyz](https://pinout.xyz/) for more details. For example, assume you want to connect COPI,CPIO,CLK, and CS_N to pins 3,5,7, and 12 on the Raspberry Pi header. If you consult that website, you'll see pin 3 is BCM2, pin 5 is BCM3, pin 7 is BCM4, and pin 12 is BCM18. Therefore, the argument you would provide to `wishbone-tool` is `--spi-pins 2,3,4,18`

## Crossover UART

If your bridge is over a UART, then that means your UART is already in use,
and isn't available for use as a console. Or if you're connecting via some
other medium and you only have a single cable connecting the two devices. LiteX supports creating a
"crossover" UART that `wishbone-tool` can interact with and present a
local terminal on.

To add a UART bridge and a crossover UART to your design, instantiate the
main SoC object with `uart_name="crossover"` and add a separate Wishbone
bridge.

```python
   class MySoC(SoCCore):
      def __init__(self, platform, sys_clk_freq):
         SoCCore.__init__(self, platform, sys_clk_freq, uart_name="crossover")

         # Add a bridge with the real UART pins
         self.submodules.uart_bridge = UARTWishboneBridge(
               platform.request("serial"),
               sys_clk_freq,
               baudrate=115200)
         self.add_wb_master(self.uart_bridge.wishbone)
```

Then, to interact with the terminal, run `wishbone-tool` and provide it
with the `csr.csv` file from your build, and add the `-s terminal` flag:

```
$ wishbone-tool -s terminal --csr-csv build/csr.csv
```

Note that you can run multiple `wishbone-tool` servers at the same time.
For example, to run the `gdb` server as well, run:

```
$ wishbone-tool -s gdb -s terminal --csr-csv build/csr.csv
```

To exit the session, press `Ctrl-C`.

## GDB Server

If your softcore has a Vexriscv CPU in it, you can enable debug mode
and use `wishbone-tool` to act as a gdbserver.

## Command line Auto-Completion

You can generate auto-completion for `wishbone-tool` with the `-c`
option. For example, to generate auto-completion for bash, run:

```
$ wishbone-tool -c bash > wishbone-tool.bash
$ . wishbone-tool.bash
$
```

Auto-completion is available for zsh, bash, fish, powershell, and
elvish.

## `wishbone-tool` as a Library

You can also use `wishbone-tool` as a library from within your own program.

For example, there is a kind of device that has a USB bridge with a small
random number generator at address 0xf001_7000. This device has a
simple API:

1. Write `1` to 0xf001_7000 to enable the device
2. When `0xf001_7008` is `1` there is data available
3. Read the data from `0xf001_7004`
4. Goto 2

We can turn this into a command that reads from this RNG and prints to stdout:

```rust
use std::io::{self, Write};
use wishbone_tool::{Bridge, BridgeError, BridgeKind, Config, UsbBridgeConfig};

fn main() -> Result<(), BridgeError> {
    let stdout = io::stdout();
    let mut handle = stdout.lock();

    // Create a configuration object with a USB bridge that
    // connects to a device with the product ID of 0x5bf0.
    let mut cfg = Config::default();
    cfg.bridge_kind = BridgeKind::UsbBridge(UsbBridgeConfig {
        pid: Some(0x5bf0),
        ..Default::default()
    });

    // Create the USB bridge and connect to it.
    let bridge = Bridge::new(&cfg)?;
    bridge.connect()?;

    // Enable the oscillator. Note that this address may change,
    // so consult the `csr.csv` for your device.
    bridge.poke(0xf001_7000, 1)?;

    loop {
        // Wait until the `Ready` flag is `1`
        while bridge.peek(0xf001_7008)? & 1 == 0 {}

        // Read the random word and write it to stdout
        handle
            .write_all(&bridge.peek(0xf001_7004)?.to_le_bytes())
            .unwrap();
    }
}
```