summaryrefslogtreecommitdiff
path: root/README.md
blob: de909d303e78f562a18533e72484874dfa75c2ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<!--
  README.md - Description of sbc-harness

  Copyright (C) 2024-2025  Luke T. Shumaker <lukeshu@lukeshu.com>
  SPDX-License-Identifier: AGPL-3.0-or-later
-->

# Building

Building requires CMake, GNU Make, an "arm-none-eabi" toolchain
(including newlib), and picotool (including the `.cmake` files;
e.g. `/usr/lib/cmake/picotool/*.cmake`).

At the time of this writing, on Parabola GNU/Linux-libre that means:

 - make 4.4.1-2
 - cmake 3.30.3-1
 - arm-none-eabi-binutils 2.42-1
 - arm-none-eabi-gcc 14.1.0-1
 - arm-none-eabi-newlib 4.4.0.20231231-1
 - picotool 2.1.1-1

Then, simply run `make`.  This will create
`build/rp2040-*/cmd/sbc_harness/sbc_harness.{elf,bin,hex,uf2}` files:

 - The `.elf` is the firmware image plus debugger symbols and
   relocation data.
 - The `.bin` file is the raw firmware image (`objcopy -Obinary
   INFILE.elf OUTFILE.bin`).
 - The `.hex` file is the raw firmware image, encoded in the [Intel
   HEX](https://archive.org/details/IntelHEXStandard) format (`objcopy
   -Oihex INFILE.elf OUTFILE.hex`).  Note that unlike the `.bin`, the
   `.hex` may contain gaps/holes; holes are filled with 0x00-bytes in
   the `.bin`, but tools for working with the `.hex` may fill them
   with other data, causing minor differences when comparing the
   `.bin` and `.hex`.  (Yes, the `.hex` is expected to be about 2.8
   times the size of the `.bin`; twice for being ASCII-encoded hex,
   plus another 13 bytes overhead for every 16 bytes of input.)
 - The `.uf2` file is the `.bin` wrapped into a [USB Flashing Format
   (UF2)](https://github.com/microsoft/uf2) container that can be used
   with the bootrom flasher.  (Yes, the `.uf2` is expected to be about
   twice the size of the `.bin`; each 128-byte block of input is
   wrapped in a 256-byte UF2 block.)

There are several ways of putting this firmware file onto the harness:

 1. bootrom flasher: Hold the "BOOTSEL" button when powering on.  The
    harness will appear to a host PC as a USB storage device.  Simply
    mount the device and copy the `.uf2` file to the device.  It will
    automatically reboot into the new firmware image.
 2. debug port: Using OpenOCD (see `HACKING.md`), run the OpenOCD command
    `program /path/to/sbc_harness.elf reset`.

    If OpenOCD is not already running:
    ```
    openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "program $PWD/build/rp2040-Debug/cmd/sbc_harness/sbc_harness.elf reset exit"`
    ```

    If OpenOCD is already running:
    ```
    socat STDIO TCP:localhost:4444 <<<"program $PWD/build/rp2040-Debug/cmd/sbc_harness/sbc_harness.elf reset"
    ```
 3. Use `flashprog` or `flashrom` and a SOIC-8 clip to directly
    program the flash chip.  I'm not sure why you would do this
    instead of one of the above.

# Usage

The harness uses DHCP to acquire an IPv4 address, then serves the 9P
protocol over TCP:

 - TCP port: 564
 - Supported protocol versions:
   - `9P2000` (base protocol): Yes
   - `9P2000.u` (Unix extension): Yes, with Linux kernel
     architecture-"generic" errnos.  This will match the Linux kernel
     errnos on most architectures (but, as of Linux v6.7, not on
     Alpha, MIPS, PA-RISC, PowerPC, or SPARC; I am unsure whether on
     these platforms the kernel's v9fs filesystem driver will map the
     "generic" errnos to the architecture-specific errnos for you).
   - `9P2000.L` (Linux extension): No, it's an abomination and
     unlikely to ever be supported
   - `9P2000.e` (Erlang extension): No, but if you want it and ask
     nicely I'd be happy to add it (I'm not sure why you'd want it
     though).
 - Authentication: None

There are lots of 9P clients that you can use.  9P is a filesystem
protocol; and you can mount it directly with the the Linux kernel's
v9fs filesystem driver, with plan9port's `9pfuse`; or interact with it
without mounting it using the shell commands `9p` (from plan9port),
`wmiir`, or `ixpc`; or interact with it without mounting it by using a
library for your programming language of choice.

Some notes on choosing a client:
 - On x86-32, the Linux kernel v9fs driver is known to drop entries
   from directory listings; I advise using 9pfuse instead if you want
   to mount it on 32-bit systems.
 - I generally like mounting it as a real filesystem, but this means
   that you only get errno errors, and the more-helpful error strings
   are discarded.
 - The sbc-harness only supports 7 concurrent connections to the 9P
   server, so while shell commands are handy for poking around, for
   real use where you're doing things in parallel you'll likely want
   to mount it or use a library that can reuse existing connections.

# Bugs/Limitations

 - Only supports 7 concurrent TCP connectsions to the 9P server (due
   to limitations in the W5500 TCP-offload chip; TODO: investigate
   using a software TCP/IP stack with the W5500 in MAC-raw mode)
 - Only supports 2 concurrent 9P requests per connection (I wanted a
   static limit, and 2 seemed reasonable)
 - Only supports IPv4, not IPv6 (due to limitations in the W5500
   TCP-offload chip; TODO: investigate upgrading to the W6100 or using
   a software TCP/IP stack with the W5500 in MAC-raw mode)