Test and debug.
Embedded debugging is mostly about restoring the thing you take for granted everywhere else: being able to see what your program is doing. Deploying got easy in Booster v2.3.0. Seeing inside a running microfirmware did not, and this is how you get it back.
Printf, but over a wire
The C half prints diagnostics with DPRINTF. There is no console attached to a
microcontroller, so that output goes out of the serial port, and you need something at the
other end of it.
That something is the Raspberry Pi Debug Probe ,
wired to the board's UART pins: TX, RX, ground. Once connected, open the serial port on
your computer and your DPRINTF lines appear as your app runs. Its
documentation covers the wiring and the UART bridge.
Without it you are inferring behaviour from what appears on the Atari's screen. With it you have a log. If you have been putting off buying the probe, this is the step where it pays for itself.
Remember to build with debug rather than release while you are
working. That is the second argument to build.sh, and it is what keeps the
diagnostics in.
The probe and the Wi-Fi deploy API solve different problems, and they work together well. Deploy over Wi-Fi so you never unplug anything, and keep the probe attached the whole time for the log. See DEPLOY-API.md for the deploy side.
Stepping through code in VS Code
The templates ship a .vscode/ directory with a launch.json set
up for Cortex-Debug, which drives the probe through OpenOCD. With the
extension installed in step 3 and the probe connected, you get real breakpoints, stepping
and variable inspection on the microcontroller.
This is where the two environment variables step 3 told you to skip finally matter. Set them now:
ARM_GDB_PATH # your ARM toolchain, for arm-none-eabi-gdb
PICO_OPENOCD_PATH # OpenOCD's tcl directory
If the debugger fails to launch, these are the first thing to check. The error messages are not helpful about it. Raspberry Pi's C/C++ SDK guide is where both the toolchain and OpenOCD come from, so it is the place to go if either is missing.
Halting at a breakpoint stops the microcontroller answering the Atari's bus reads. The
Atari does not pause politely and wait, so expect the host machine to misbehave while
you are stopped. This is normal, and it is why DPRINTF logging is often
more useful than breakpoints for anything involving the emulation path.
Without a probe
You can still make progress, just more slowly:
- Put state on the Atari's screen. Crude, but it is a display you already control.
- Bisect by building. Comment out half of what you added, rebuild, reload. Slow, but it always converges.
- The SELECT button on the board is a physical input you can read, useful as a manual trigger when you cannot type.
- Hold SHIFT at boot to skip straight to GEMDOS. This is your way back when a build hangs the machine.
When the screen stays black
Work down this list in order. It is roughly sorted by how often each one is the answer.
| Check | Why |
|---|---|
| Does the unmodified template still run? | Reflash the step 6 build. If that fails too, the problem is the board or Booster rather than your code, and you have just saved yourself hours. |
| Are you blocking in the main loop? | Anything that stops chandler_loop() stops the Atari being
answered. A machine that appears frozen is usually this. |
| Did the deploy actually happen? | picotool or curl reporting success and the board
running your new code are two different claims. Add a DPRINTF at
startup and look for it. |
| Is the Atari-side code over budget? | userfw.s has 6 KB. Overrunning it produces failures that look
nothing like a size problem. |
| Is the microSD card present and readable? | Code that assumes a mounted filesystem fails early and silently when it is not there. |
| Is Booster still installed? | Flashing certain images over it will replace it. Reinstall from step 4, and check troubleshooting and the FAQ for symptoms that are not about your code. |
Where emulators fit
Hatari and STEEM emulate the Atari ST. They do not emulate the SidecarTridge board, so they cannot run your microfirmware. What they are good for is Atari-side logic you can exercise independently: screen layout, keyboard handling, anything that does not depend on the board answering.
Treat them as a fast side-loop for a narrow class of problem, not as a development environment. Everything that matters still has to be tested on hardware.
"It does not work" gets you guesses. Give it the shape of the system and the evidence:
My SidecarTridge microfirmware <what it does wrong> on real hardware.
What I changed since it last worked:
<the diff, or a description>
DPRINTF output over the debug probe:
<paste it, including where it stops>
Already ruled out:
- the unmodified template still runs correctly
- <anything else you have checked>
Remember the main loop must never block, the Atari side has 6 KB and
cannot use Atari RAM, and commands are polled rather than interrupt
driven. Which of my changes is most likely responsible, and what should
I instrument next?
The "already ruled out" section is what stops it re-suggesting things you have done.