summaryrefslogtreecommitdiff
path: root/HACKING.md
blob: d522034341df7177d253a77fa3bed6f62d6f300f (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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
<!--
  HACKING.md - Description of sbc-harness sources

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

# Source Layout

Our own "flavor" of C: GNU C plus `-fplan9-extensions`, making use of:

 - `libobj/`: For Go-like object-oriented programming
 - `libmisc/`: Low-level C programming utilities; sort of an augmented
   "libc"

Our own tiny cooperative-multitasking OS:

 - `libcr/`: The kernel (a simple coroutine library)
 - `libcr_ipc/`: IPC primatives (semaphores, mutexes, channels, ...)
   for libcr
 - `libhw/`: The hardware drivers
 - `libhw_generic/`: The hardware abstraction layer

Libraries for generic parts of what the harness is doing:

 - `lib9p/`: a 9P network filesystem server library
 - `lib9p_util/`: Utilities for use with lib9p
 - `libdhcp/`: A DHCP client
 - `libusb/`: Wrapper and utilities for TinyUSB

 - `cmd/sbc_harness/`: The main firmware image
 - `3rd-party/`: Sources from third parties; some definitions of
   things (USB language codes, Linux kernel errnos), and the Pico-SDK
   (for the RP2040 CPU, and its included TinyUSB).  Does not include
   newlib, which you need to have installed separately.
 - `build-aux/`: Build-system files

# Debugging

There are 2 "debug" connectors on the harness:

## UART (Universal Asynchronous Receiver/Transmitter) logging

Baud rate: 115200

Pinout:
| RPi Pico | RP2040 | Use                                    |
|----------|--------|----------------------------------------|
| pin1     | gpio0  | TX (so connect it to your FTDI's RX)   |
| pin2     | gpio1  | RX (so connect it to your FTDI's TX)   |
| pin3     |        | gnd (so connect it to your FTDI's GND) |

Example use:

> I use `picocom` (because it's small and Parabola GNU/Linux-libre
> has it), but other programs such as GNU Screen or minicom work
> as well.
>
> I sometimes use a Rasberry Pi Debug Probe (see below) as my
> UART-to-USB adapter because it's convenient because I'm using it
> anyway for ARM SWD.  I sometimes use a FTDI-brand adapter because it
> seems to be more reliable; the Debug Probe can sometimes get
> messed-up byte boundaries.
>
> Depending on your UART adapter, on GNU/Linux the device may be
> named either `/dev/ttyUSB{n}` or `/dev/ttyACM{n}`.
>
> - `picocom --baud=115200 /dev/ttyUSB0`
> - `picocom --baud=115200 /dev/ttyACM0`

## ARM SWD (Serial Wire Debug)

Pinout: Separate from the main 40-pin layout of the RPi Pico, there
are 3 separate ARM SWD pins; they may have a [Raspberry Pi 3-pin Debug
Connector][#raspberry-pi-3-pin-debug-connector] socket soldered to
them, or may just be regular pin headers.
| Pin # | ARM SW-DP (Single-Wire Debug-Port) |
|-------|------------------------------------|
| 1     | SC/SWCLK (serial clock)            |
| 2     | GND                                |
| 3     | SD/SWDIO (bidi serial data)        |
| N/C   | SWO (optional: serial wire output) |

The RP2040 CPU speaks the ADIv5 SWD protocol on this port; you need a
separate USB device to translate this to the ARM CMSIS-DAP protocol (a
USB-based protocol), and then a piece of software on your PC  to talk
CMSIS-DAP; likely [OpenOCD](https://openocd.org/) to bridge to the GNU
Debugger (GDB):

```
┌─[Host PC]─────────────────────────┐
│              ┌─────┐              │
│              │ GDB │              │
│              └─────┘              │
│                 ⇑                 │
│                 ║ GDB Remote Serial Protocol on localhost:3333
│                 ⇓                 │
│            ┌─────────┐            │
│            │ OpenOCD │            │
│            └─────────┘            │
│                 ⇑                 │
└─────────────────║─────────────────┘
                USB-A
                  ║ ARM CMSIS-DAP protocol (a USB-based protocol)
            (micro)USB-B
       ┌─[Debug Probe]───────┐
       │          ⇓          │
       │  ┌────────────────┐ │
       │  │     ARM's      │ │
       │  │   reference    │ │
       │  │   CMSIS-DAP    │ │
       │  │ implementation │ │
       │  └────────────────┘ │
       │          ⇑          │
       └──────────║──────────┘
         SW-DP (3-pin JST-SH)
                  ║ ADIv5 SWD protocol
        SW-DP (3 .1" headers)
┌─[SBC-Harness]───║─────────────────┐
│ ╔═══════════════╝                 │
│ ║  ┌────────────────────────────┐ │
│ ║  │ Cortex-M0+ (core 0)        │ │
│ ║  │ ┌────────────────────────┐ │ │
│ ╠═══⇒│ CoreSight ADIv5 module │ │ │
│ ║  │ └────────────────────────┘ │ │
│ ║  └────────────────────────────┘ │
│ ║  ┌────────────────────────────┐ │
│ ║  │ Cortex-M0+ (core 1)        │ │
│ ║  │ ┌────────────────────────┐ │ │
│ ╚═══⇒│ CoreSight ADIv5 module │ │ │
│    │ └────────────────────────┘ │ │
│    └────────────────────────────┘ │
└───────────────────────────────────┘
```

Example use:

> For the device that translates from ADIv5 SWD to CMSIS-DAP, I use
> the [Raspberry Pi Debug
> Probe](https://www.raspberrypi.com/products/debug-probe/) because it
> is cheap, runs Free Software, and is also a UART-to-USB adapter, so
> I can use it for both ports with less clutter on my desk ([source
> code](https://github.com/raspberrypi/debugprobe),
> [tutorial](https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html).
> Another freedom-friendly option is the
> https://oshwlab.com/wagiminator/samd11c-swd-programmer which uses
> https://github.com/ataradov/free-dap instead of ARM's reference
> CMSIS implementation; but I have not tried it.
>
> I use OpenOCD for talking CMSIS-DAP from my laptop, but pyOCD is
> another option.
>
> In one terminal:
> - `openocd -f interface/cmsis-dap.cfg -c 'set USE_CORE 0' -f target/rp2040.cfg -c "adapter speed 5000"`
>   (Explanation of `USE_CORE`: https://github.com/raspberrypi/debugprobe/issues/45)
> In another terminal:
> - `arm-none-eabi-gdb ./build/rp2040-Debug/cmd/sbc_harness/sbc_harness.elf`
>   ```
>   target extended-remote localhost:3333
>   monitor reset init
>   continue
>   ```
>   See https://openocd.org/doc/html/General-Commands.html for
>   documentation on the commands that you can send from GDB to
>   OpenOCD with `monitor`.

References:
- https://developer.arm.com/documentation/101761/1-0/Debug-and-trace-interface/Serial-Wire-Debug-signals
- https://developer.arm.com/documentation/ihi0031/a/The-Serial-Wire-Debug-Port--SW-DP-/Introduction-to-the-ARM-Serial-Wire-Debug--SWD--protocol
- https://arm-software.github.io/CMSIS-DAP/latest/index.html
- ADIv5: https://developer.arm.com/documentation/ihi0031/g/
- ADIv6: https://developer.arm.com/documentation/ihi0074/e/

# Other references

## Raspberry Pi 3-pin Debug Connector

- https://datasheets.raspberrypi.com/debug/debug-connector-specification.pdf

| Pin # | UART                 | ARM SW-DP                          | cJTAG (IEEE 1149.7)              |
|-------|----------------------|------------------------------------|----------------------------------|
| 1     | RX (target←debugger) | SC/SWCLK (serial clock)            | TMSC - Test Clock Control        |
| 2     | GND                  | GND                                | GND                              |
| 3     | TX (target→debugger) | SD/SWDIO (bidi serial data)        | TCKC - Test Master/Slave Control |
|       |                      | SWO (optional: serial wire output) |                                  |

Note that the RP2040 chip has a pure SW-DP (just speaks SWD), not a
JTAG-DP (just speaks JTAG) nor a SWJ-DP (can speak either SWD or
JTAG).

The Raspberry Pi Debug Probe has 2 debug connectors on it; one to
connect to the UART (labeled "U"), one to connect to the SWD (labeled
"D").