Document RG35XX Plus boot chain, reorganize device docs

Move device-specific content (hardware, software, libraries) from
TOOLCHAIN.md into new docs/rg35xx-plus.md. Add partition layout,
full boot chain trace (systemd → launcher.sh → loadapp.sh → dmenu_ln),
and sdlamp2 deployment instructions via dmenu_ln config toggle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Smith 2026-02-13 15:18:59 +01:00
parent 4f6d1de8e2
commit a5b04fcd08
3 changed files with 131 additions and 42 deletions

View File

@ -7,7 +7,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
SDLamp2 is a simple SDL2-based audio player written in C, designed for a child to use. It plays long m4a/mp3 files (fairy tale cassette rips) with a cassette-player-like UI: rewind, stop, play, fast-forward, next tape. Inspired by Winamp. SDLamp2 is a simple SDL2-based audio player written in C, designed for a child to use. It plays long m4a/mp3 files (fairy tale cassette rips) with a cassette-player-like UI: rewind, stop, play, fast-forward, next tape. Inspired by Winamp.
See `docs/sdlamp2-fsd.md` for the full functional specification and changelog. See `docs/sdlamp2-fsd.md` for the full functional specification and changelog.
See `docs/TOOLCHAIN.md` for target device details and the arm64 Docker build container. See `docs/TOOLCHAIN.md` for the arm64 Docker build container.
See `docs/rg35xx-plus.md` for target device details, boot chain, and deployment.
## Build and Run ## Build and Run

View File

@ -1,45 +1,6 @@
# Cross-Compilation Toolchain # Build Container
This document describes the target device and the arm64 Docker build container used to produce binaries for it. arm64 Docker build container for producing device binaries. For target device details see [`rg35xx-plus.md`](rg35xx-plus.md).
## Target Device
### Hardware
- **Device:** Anbernic RG35XX Plus
- **SoC:** Allwinner H700 — quad-core ARM Cortex-A53 @ 1.5 GHz (AArch64 / ARMv8-A)
- **GPU:** Mali G31 MP2
- **RAM:** 1 GB LPDDR4
- **Display:** 640×480 IPS
### Software
- **OS:** Ubuntu 22.04 LTS (Jammy Jellyfish) — [modified stock firmware](https://github.com/cbepx-me/Anbernic-H700-RG-xx-StockOS-Modification)
- **Kernel:** Linux 4.9.170 aarch64 (proprietary, no source released by Anbernic)
- **Architecture:** aarch64 / arm64 (confirmed via `dpkg --print-architecture`)
- **glibc:** 2.35
### Libraries on Device
All required shared libraries are pre-installed. Most are at `/usr/lib/`, some at `/usr/lib/aarch64-linux-gnu/` (Debian multiarch path):
| Library | Soname | Notes |
|---------|--------|-------|
| SDL2 | `libSDL2-2.0.so.0.12.0` | SDL 2.0.12 |
| SDL2_image | `libSDL2_image-2.0.so.0.900.0` | SDL2_image 2.0.9, at multiarch path |
| libavcodec | `libavcodec.so.58` | FFmpeg ~4.x |
| libavformat | `libavformat.so.58` | FFmpeg ~4.x |
| libavutil | `libavutil.so.56` | FFmpeg ~4.x |
| libswresample | `libswresample.so.3` | FFmpeg ~4.x |
### Implications for Cross-Compilation
- The device userland is Debian/Ubuntu-based (has `dpkg`, `apt-get`, `systemd`)
- Shared libraries are already present — no need to bundle or build them via Buildroot
- A native aarch64 compile (e.g. inside an arm64 Docker container) produces working binaries
- Must link against glibc ≤ 2.35 (use GCC ≤ 12 to avoid GLIBCXX version mismatches)
## Build Container
The `docker-arm64/` directory contains a Docker setup that runs an arm64 Ubuntu 22.04 container via QEMU user-mode emulation. This matches the target device exactly — same distro, same glibc 2.35, same library versions. The project's native `make` (using `pkg-config`) works as-is inside the container, no cross-compilation flags needed. The `docker-arm64/` directory contains a Docker setup that runs an arm64 Ubuntu 22.04 container via QEMU user-mode emulation. This matches the target device exactly — same distro, same glibc 2.35, same library versions. The project's native `make` (using `pkg-config`) works as-is inside the container, no cross-compilation flags needed.

127
docs/rg35xx-plus.md Normal file
View File

@ -0,0 +1,127 @@
# Anbernic RG35XX Plus
Device-specific reference for the target hardware. For build instructions see [`TOOLCHAIN.md`](TOOLCHAIN.md).
## Hardware
- **Device:** Anbernic RG35XX Plus
- **SoC:** Allwinner H700 — quad-core ARM Cortex-A53 @ 1.5 GHz (AArch64 / ARMv8-A)
- **GPU:** Mali G31 MP2
- **RAM:** 1 GB LPDDR4
- **Display:** 640×480 IPS
## Software
- **OS:** Ubuntu 22.04 LTS (Jammy Jellyfish) — [modified stock firmware](https://github.com/cbepx-me/Anbernic-H700-RG-xx-StockOS-Modification)
- **Kernel:** Linux 4.9.170 aarch64 (proprietary, no source released by Anbernic)
- **Architecture:** aarch64 / arm64 (confirmed via `dpkg --print-architecture`)
- **glibc:** 2.35
- **Userland:** Debian/Ubuntu-based (`dpkg`, `apt-get`, `systemd`)
## Libraries on Device
All required shared libraries are pre-installed. Most are at `/usr/lib/`, some at `/usr/lib/aarch64-linux-gnu/` (Debian multiarch path):
| Library | Soname | Notes |
|---------|--------|-------|
| SDL2 | `libSDL2-2.0.so.0.12.0` | SDL 2.0.12 |
| SDL2_image | `libSDL2_image-2.0.so.0.900.0` | SDL2_image 2.0.9, at multiarch path |
| libavcodec | `libavcodec.so.58` | FFmpeg ~4.x |
| libavformat | `libavformat.so.58` | FFmpeg ~4.x |
| libavutil | `libavutil.so.56` | FFmpeg ~4.x |
| libswresample | `libswresample.so.3` | FFmpeg ~4.x |
Shared libraries are already present — no need to bundle or build them. A native aarch64 compile (e.g. inside the arm64 Docker container) produces working binaries. Must link against glibc ≤ 2.35.
## Partition Layout
| Device | Mount point | Filesystem | Contents |
|--------|-------------|------------|----------|
| `/dev/mmcblk0p5` | `/` | ext4 | Root filesystem |
| `/dev/mmcblk0p6` | `/mnt/vendor` | ext4 | Firmware, apps, scripts |
| `/dev/mmcblk0p7` | `/mnt/data` | ext4 | User data |
| `/dev/mmcblk0p8` | `/mnt/mmc` | vfat | ROMs |
| SD card slot | `/mnt/sdcard` | (varies) | External storage |
## Boot Chain
The device uses systemd but boots its UI through a SysV init script that systemd auto-wraps via `systemd-sysv-generator`. The chain is intentionally layered: `launcher.sh` runs before partitions are mounted (hardware setup), `loadapp.sh` runs after mounts (filesystem/network setup + app restart loop), and `dmenu_ln` is the app dispatcher.
```
systemd (graphical.target)
└─ launcher.service (SysV → auto-generated by systemd-sysv-generator)
└─ /etc/init.d/launcher.sh start
├── mounts /mnt/vendor
├── starts brightCtrl.bin (backlight daemon) &
├── starts cexpert &
└── starts loadapp.sh &
├── resizes root partition (first boot only)
├── mounts /mnt/data, /mnt/mmc
├── charging mode: if boot_mode==1 → charger UI → poweroff
├── normal mode: starts NetworkManager, bluetooth, wifi
├── syncs RTC, loads kernel modules, mounts SD card
├── runs /mnt/mod/ctrl/autostart (if exists)
└── RESTART LOOP: runs /mnt/vendor/ctrl/dmenu_ln repeatedly
└─ /mnt/vendor/ctrl/dmenu_ln
├── selects binary (default: dmenu.bin)
├── config overrides: muos.ini → muos.bin, vpRun.ini → ...
├── runs binary via app_scheduling()
└── on exit: executes /tmp/.next (app dispatch for menu)
```
### Why the indirection?
- **`launcher.sh`** — Pre-mount hardware setup: mounts `/mnt/vendor`, starts backlight and system daemons. Runs as a SysV init script so it integrates with systemd's boot ordering.
- **`loadapp.sh`** — Post-mount filesystem/network setup: mounts data partitions, handles charging mode, starts networking, then enters the restart loop. Runs in the background (`&`) so `launcher.sh` can return.
- **`dmenu_ln`** — App dispatcher: selects which binary to run based on config files, wraps execution in `app_scheduling()` (which sleeps 30s on crash before retrying), and supports `/tmp/.next` for menu-driven app switching.
### `app_scheduling` behavior
The `app_scheduling` function in `dmenu_ln` runs the selected binary. If it exits with a non-zero status, it sleeps 30 seconds before returning, which prevents crash loops from consuming all CPU. The outer `while true` loop in `loadapp.sh` then re-invokes `dmenu_ln`, restarting the application.
## Deploying sdlamp2
### Overview
The `dmenu_ln` script already supports switching the startup binary via config files (e.g. `muos.ini``muos.bin`). We follow the same pattern to launch sdlamp2 instead of the default menu.
### Setup
1. **Copy the binary** to the device:
```sh
scp build/sdlamp2 root@<device>:/mnt/vendor/bin/sdlamp2
```
2. **Add the config check** to `/mnt/vendor/ctrl/dmenu_ln`. In the section where `CMD` overrides are checked (after the existing `muos.ini` / `vpRun.ini` checks, before the `app_scheduling` call), add:
```bash
if [ -f "/mnt/vendor/sdlamp2.ini" ];then
CMD="/mnt/vendor/bin/sdlamp2 /mnt/sdcard/Music"
fi
```
The unquoted `$CMD` in `app_scheduling` undergoes word splitting, so the path argument is passed correctly.
3. **Enable sdlamp2 on boot:**
```sh
touch /mnt/vendor/sdlamp2.ini
```
4. **Disable** (revert to normal menu):
```sh
rm /mnt/vendor/sdlamp2.ini
```
### What's preserved
Everything else in the boot chain continues to work:
- **Charging mode** — handled in `loadapp.sh` before the restart loop
- **LED/backlight control**`brightCtrl.bin` started by `launcher.sh`
- **Clean shutdown** — system shutdown scripts unaffected
- **Restart on exit** — if sdlamp2 exits cleanly (status 0), the restart loop in `loadapp.sh` re-launches it immediately
- **Crash recovery** — if sdlamp2 crashes (non-zero exit), `app_scheduling` sleeps 30s then the loop retries
- **Easy revert** — removing `sdlamp2.ini` restores the stock menu on next boot