tools: Switch to pyfu-usb for flashing

Add Gonk tools usage to //tools/README.md

Change-Id: Ifb7ea0b7c4bc886d8b22dd5152283b98d484b83c
Reviewed-on: https://pigweed-review.googlesource.com/c/gonk/+/208951
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com>
Pigweed-Auto-Submit: Anthony DiGirolamo <tonymd@google.com>
Reviewed-by: Eric Holland <hollande@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index ecd7a90..87ea61d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -152,4 +152,7 @@
     ":gonk_firmware",
     ":gonk_python_tools",
   ]
+
+  # Add the tools README to the zipfile.
+  inputs = [ "//tools/README.md > /README.md" ]
 }
diff --git a/README.md b/README.md
index 08757e4..a4f2e7b 100644
--- a/README.md
+++ b/README.md
@@ -74,11 +74,11 @@
 
 Flash the stm32f7 and launch the `write_fpga.py` script on a bitstream file.
 
-### Flash with dfu-util
+### Flash via DFU
 
 1. Unplug gonk from USB and replug with MODE button held down.
 
-1. Run `gonk-flash` on the MCU binary. This uses `dfu-util`.
+1. Run `gonk-flash` on the MCU binary. This uses `pyfu-usb`.
 
    ```sh
    gonk-flash ./out/gn/arduino_size_optimized/obj/applications/fpga_config/fpga_config.bin
diff --git a/tools/README.md b/tools/README.md
new file mode 100644
index 0000000..cad95cc
--- /dev/null
+++ b/tools/README.md
@@ -0,0 +1,168 @@
+# Gonk Python Tools Bundle
+
+Unzip and install the bundle.
+
+```sh
+unzip gonk_bundle.zip
+cd gonk_bundle
+./setup.sh
+```
+
+## Flash a Gonk for the first time:
+
+```sh
+. ./python-venv/bin/activate
+gonk-flash
+```
+
+or without activating the Python virtualenv:
+
+```sh
+./python-venv/bin/gonk-flash
+```
+
+## Log ADC measurements
+
+### Logging
+
+By default two log files are created:
+
+- Host log messages are set to: `--logfile gonk-logs.txt`
+- Device (logs from Gonk) are set to: `--device-logfile gonk-device-logs.txt`
+
+You can add ADC json output with the `--json-logfile gonk-device-logs.json`
+option.
+
+That will produce a json lines file with each line corresponding to one ADC
+measurement event. For example:
+
+```
+{
+  "message": "host_time: 20240507 12:47:41.308278 size: 40 delta_microseconds: 204 vbus: 3,2,3,2,2 vshunt: 0,0,0,69,0",
+  "levelno": 20,
+  "levelname": "\u001b[35m\u001b[1mINF\u001b[0m",
+  "args": [
+    "20240507 12:47:41.308278",
+    "40",
+    "204",
+    "3,2,3,2,2",
+    "0,0,0,69,0"
+  ],
+  "time": "1715111261.308351",
+  "time_string": "2024-05-07T12:47:41",
+  "py_file": "gonk_log_stream.py:213",
+  "py_logger": "gonk",
+  "fields": {
+    "host_time": "20240507 12:47:41.308278",
+    "packet_size": "40",
+    "delta_micros": "204",
+    "vbus_values": "[0, 0, 0, 69, 0]",
+    "vshunt_values": "[3, 2, 3, 2, 2]"
+  }
+}
+```
+
+### Start Logging ADC Measurements
+
+```sh
+./python-venv/bin/gonk --log-to-stderr --bitstream-file DEFAULT
+```
+
+This will provision the FPGA and begin logging ADC measurements.
+
+1. The FPGA bitstream file is sent over serial first:
+
+```
+20240507 12:35:32 [gonk] INF Waiting for bitstream -- lib/fpga_control/fpga_control.cc:53
+20240507 12:35:33 [gonk] INF Waiting for bitstream -- lib/fpga_control/fpga_control.cc:53
+20240507 12:35:34 [host] INF Sending bitstream...
+20240507 12:35:34 [gonk] INF Waiting for bitstream -- lib/fpga_control/fpga_control.cc:53
+20240507 12:35:34 [gonk] INF Discard byte: 1 -- lib/fpga_control/fpga_control.cc:65
+20240507 12:35:34 [gonk] INF Discard byte: 2 -- lib/fpga_control/fpga_control.cc:65
+20240507 12:35:34 [gonk] INF Discard byte: 3 -- lib/fpga_control/fpga_control.cc:65
+20240507 12:35:34 [gonk] INF Discard byte: 4 -- lib/fpga_control/fpga_control.cc:65
+20240507 12:35:34 [gonk] INF Start Sequence found. -- lib/fpga_control/fpga_control.cc:71
+20240507 12:35:35 [gonk] INF Got bytes: 4096 -- lib/fpga_control/fpga_control.cc:84
+...
+20240507 12:35:36 [gonk] INF Got bytes: 4096 -- lib/fpga_control/fpga_control.cc:84
+20240507 12:35:36 [host] INF Done sending bitstream. Wrote 135100
+20240507 12:35:37 [gonk] INF Got bytes: 4024 -- lib/fpga_control/fpga_control.cc:84
+20240507 12:35:37 [gonk] INF All 135100 bytes recieved. -- lib/fpga_control/fpga_control.cc:92
+20240507 12:35:37 [gonk] INF File ready: 135096 -- lib/fpga_control/fpga_control.cc:102
+20240507 12:35:37 [gonk] INF First 12 bytes -- lib/fpga_control/fpga_control.cc:104
+...
+20240507 12:35:37 [gonk] INF Last 12 bytes -- lib/fpga_control/fpga_control.cc:109
+...
+20240507 12:35:37 [gonk] INF Sending bitstream file to the FPGA. -- lib/fpga_control/fpga_control.cc:118
+20240507 12:35:37 [gonk] INF FPGA Config Success. -- lib/fpga_control/fpga_control.cc:162
+```
+
+2. SPI Flash and ADC communication is tested.
+
+```
+20240507 12:35:37 [gonk] INF Checking SPI Flash -- applications/fpga_config/main.cc:153
+20240507 12:35:37 [gonk] INF SPI Flash JEDEC ID: 1f 84 1 -- applications/fpga_config/main.cc:158
+20240507 12:35:37 [gonk] INF Init ADCs -- lib/adc/adc.cc:543
+20240507 12:35:37 [gonk] INF ADC #01: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #01: VSHUNT = 00 00 00 = 3 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #01: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #02: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #02: VSHUNT = 00 00 20 = 2 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #02: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #03: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #03: VSHUNT = 00 00 30 = 3 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #03: VBUS   = 00 04 70 = 71 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #04: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #04: VSHUNT = 00 00 20 = 2 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #04: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #05: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #05: VSHUNT = 00 00 20 = 2 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #05: VBUS   = 00 04 60 = 70 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #06: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #06: VSHUNT = 00 04 f0 = 79 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #06: VBUS   = 00 04 70 = 71 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #07: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #07: VSHUNT = 00 00 30 = 3 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #07: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #08: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #08: VSHUNT = 00 00 20 = 2 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #08: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #09: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #09: VSHUNT = 00 00 30 = 3 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #09: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #10: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #10: VSHUNT = 00 00 30 = 3 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #10: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF ADC #11: ADC Config = b000 -- lib/adc/adc.cc:578
+20240507 12:35:37 [gonk] INF ADC #11: VSHUNT = 00 00 20 = 2 -- lib/adc/adc.cc:502
+20240507 12:35:37 [gonk] INF ADC #11: VBUS   = 00 00 00 = 0 -- lib/adc/adc.cc:517
+20240507 12:35:37 [gonk] INF Selected ADC count: 5 -- lib/adc/adc.cc:224
+```
+
+3. ADC measurements begin logging.
+
+```
+20240507 12:35:37 [gonk] INF host_time: 20240507 12:35:37.585414 size: 70 delta_microseconds: 351574012 vbus: 3,-74,-74,-73,2 vshunt: 0,0,0,0,0
+20240507 12:35:37 [gonk] INF host_time: 20240507 12:35:37.586015 size: 40 delta_microseconds: 226 vbus: 3,2,3,2,2 vshunt: 0,0,0,0,0
+...
+20240507 12:35:40 [gonk] INF host_time: 20240507 12:35:40.156319 size: 40 delta_microseconds: 194 vbus: 3,2,3,79,79 vshunt: 0,0,0,0,0
+```
+
+Measurements can be stopped by pressing Enter. This text should appear in the terminal:
+
+```
+ [Send: '\n']
+```
+
+Followed shortly by a message from Gonk stopping continuous reading:
+
+```
+20240507 12:35:40 [gonk] INF Stopping ADC Continuous Reads. -- applications/fpga_config/main.cc:134
+20240507 12:35:41 [gonk] INF ADC Idle -- applications/fpga_config/main.cc:114
+20240507 12:35:42 [gonk] INF ADC Idle -- applications/fpga_config/main.cc:114
+20240507 12:35:43 [gonk] INF ADC Idle -- applications/fpga_config/main.cc:114
+```
+
+Pressing Enter again will resume continuous reading.
+Ctrl-C will exit the gonk app.
+
diff --git a/tools/gonk_tools/flash.py b/tools/gonk_tools/flash.py
index 1fa188e..6ccf7a8 100644
--- a/tools/gonk_tools/flash.py
+++ b/tools/gonk_tools/flash.py
@@ -11,7 +11,7 @@
 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 # License for the specific language governing permissions and limitations under
 # the License.
-"""Flash Gonk via dfu-util."""
+"""Flash Gonk via DFU."""
 
 import argparse
 from pathlib import Path
@@ -27,34 +27,26 @@
 
 _COLOR = pw_cli.color.colors()
 
-DFU_SERIAL_STRING = 'STM32FxSTM32'
-
 
 def _parse_args():
     parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument(
-        '--dfu-serial-string',
-        default=DFU_SERIAL_STRING,
-        help=f'Serial string to pass to dfu-util. Default: {DFU_SERIAL_STRING}',
-    )
 
     parser.add_argument(
         '--bin-file',
-        help='Binary to flash with dfu-util',
+        help='Binary to flash',
         type=Path,
     )
     return parser.parse_args()
 
 
 def main(
-    dfu_serial_string: str,
-    bin_file: Optional[Path],
+    bin_file: Optional[Path] = None,
 ) -> int:
-    """Flash Gonk via dfu-util."""
+    """Flash Gonk via pyfu-usb."""
 
-    dfu_util_binary = shutil.which('dfu-util')
+    dfu_util_binary = shutil.which('pyfu-usb')
     if not dfu_util_binary or not Path(dfu_util_binary).is_file():
-        raise FileNotFoundError('Unable to find "dfu-util"')
+        raise FileNotFoundError('Unable to find "pyfu-usb"')
 
     if not bin_file:
         bin_file = bundled_bin_path()
@@ -66,14 +58,11 @@
 
     dfu_flash_args = [
         dfu_util_binary,
+        '--verbose',
         '--device',
         '0483:df11',
-        '--dfuse-address',
-        '0x08000000:leave',
-        '--serial',
-        dfu_serial_string,
-        '--alt',
-        '0',
+        '--address',
+        '0x08000000',
         '--download',
         str(bin_file),
     ]
@@ -83,7 +72,7 @@
         ' '.join(dfu_flash_args),
     )
 
-    # Ignore Ctrl-C to allow dfu-util to handle normally.
+    # Ignore Ctrl-C to allow pyfu-usb to handle normally.
     signal.signal(signal.SIGINT, signal.SIG_IGN)
     return subprocess.run(dfu_flash_args, check=False).returncode
 
diff --git a/tools/gonk_tools/write_fpga.py b/tools/gonk_tools/write_fpga.py
index 21cef39..28c3b7e 100644
--- a/tools/gonk_tools/write_fpga.py
+++ b/tools/gonk_tools/write_fpga.py
@@ -108,6 +108,7 @@
             'Default log file. This will contain host side '
             'log messages only unles the '
             '--merge-device-and-host-logs argument is used.'
+            'Default: "gonk-logs.txt"'
         ),
     )
     parser.add_argument(
@@ -141,7 +142,7 @@
         '--device-logfile',
         type=Path,
         default=Path('gonk-device-logs.txt'),
-        help='Device only log file.',
+        help='Device only log file. Default: "gonk-device-logs.txt"',
     )
     parser.add_argument(
         '--json-logfile',
diff --git a/tools/setup.cfg b/tools/setup.cfg
index a196307..9aef744 100644
--- a/tools/setup.cfg
+++ b/tools/setup.cfg
@@ -22,6 +22,8 @@
 packages = find:
 zip_safe = False
 install_requires =
+    pyfu-usb
+    pyserial
 
 [options.entry_points]
 console_scripts =