mirror of
https://github.com/MCKero6423/uv-k5-v3-emulator.git
synced 2026-10-02 03:15:36 +00:00
Finish the portability sweep: one firmware resolver, no author paths
The probe scripts, run.sh, trace_run.sh, webui.py and two emulator tests each named the same hardcoded firmware from a source tree that is not in this repository. They now resolve QEMU and the firmware the way tools/uvk5_testenv.py does -- environment, then PATH, then whatever the checkout has -- and skip with a reason when there is nothing. webui.py's --qemu and --elf lost their author defaults too: a bare qemu-system-arm through PATH, and no firmware until one is uploaded, which the page already reports.
This commit is contained in:
1 parent
ae8b48c85a
commit
542515d5ad
21 files changed
+133
-37
No files matched your search
@@ -114,7 +114,8 @@ keypresses silently stop working. Run the test after touching that code;
|
||||
uvk5_stream.py the MJPEG-style frame pump behind /stream
|
||||
uvk5_supervisor.py starts, stops and recovers the emulator process
|
||||
test_kill_emulator.sh cleanup never kills an unrelated process
|
||||
(plus ad-hoc probe scripts -- scan_trace.sh, gpio_watch.py and friends --
|
||||
uvk5_elf.sh where the probe scripts find a firmware (env, then the checkout)
|
||||
(plus ad-hoc probe scripts -- scan_trace.sh, gpio_watch.py and friends --
|
||||
kept because they are quick to reach for, not because they are polished)
|
||||
harness/, stubs/, shim/, tests/ host build of the CW timing chain (stage A)
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ VFO 重算了状态。在真机上你只看到"什么都没发生",在这里
|
||||
uvk5_stream.py /stream 背后的抓帧泵
|
||||
uvk5_supervisor.py 启动、停止、以及故障后恢复模拟器进程
|
||||
test_kill_emulator.sh 清理逻辑绝不会杀掉无关进程
|
||||
uvk5_elf.sh 探针脚本从哪里找固件(环境变量,然后本仓库)
|
||||
(另有一批临时探针脚本 —— scan_trace.sh、gpio_watch.py 等 ——
|
||||
留着是因为随手就能用,不是因为它们打磨过)
|
||||
harness/, stubs/, shim/, tests/ CW 时序链的宿主机构建(阶段 A)
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@
|
||||
# probe only read IDR, which cannot tell those two apart.
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
KEY="${1:-MENU}"
|
||||
BASE=0x50000400
|
||||
IDR=$((BASE + 0x10))
|
||||
|
||||
+3
-1
@@ -5,7 +5,9 @@
|
||||
# both twice gives the rate and an estimate of how long the delay will take.
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
GAP="${1:-4}"
|
||||
SCRIPT=$(mktemp --suffix=.gdb)
|
||||
trap 'rm -f "$SCRIPT"' EXIT
|
||||
|
||||
+3
-1
@@ -5,7 +5,9 @@
|
||||
# IDR 0x10, ODR 0x14.
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
BASE=0x50000400
|
||||
SCRIPT=$(mktemp --suffix=.gdb)
|
||||
trap 'rm -f "$SCRIPT"' EXIT
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@
|
||||
# the debounce in app.c accept it?
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
KEY="${1:-MENU}"
|
||||
|
||||
python3 - "$KEY" <<'PY'
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
# BSRR: low half sets a pin, high half resets it (py32f071xB.h).
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
KEY="${1:-MENU}"
|
||||
BASE=0x50000400
|
||||
BSRR=$((BASE + 0x18))
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
# in the matrix wiring or the debounce.
|
||||
set -uo pipefail
|
||||
|
||||
TOOLS="$HOME/uvk5-port/sim/tools"
|
||||
TOOLS="$(cd "$(dirname "$0")" && pwd)"
|
||||
KEY="${1:-MENU}"
|
||||
|
||||
python3 - "$KEY" <<'PY'
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@
|
||||
# (different PC, or r1 reset for a new call).
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
SAMPLES="${1:-6}"
|
||||
GAP="${2:-2}"
|
||||
SCRIPT=$(mktemp --suffix=.gdb)
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@
|
||||
# this only observes; the firmware does the driving.
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
KEY="${1:-MENU}"
|
||||
STEPS="${2:-400}"
|
||||
|
||||
|
||||
+7
-3
@@ -7,9 +7,13 @@
|
||||
# Usage: run.sh [firmware.elf]
|
||||
set -euo pipefail
|
||||
|
||||
QEMU="$HOME/qemu-build/qemu-7.2+dfsg/build/qemu-system-arm"
|
||||
ELF="${1:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
FLASH="$HOME/uvk5-port/sim/assets/flash.img"
|
||||
QEMU="${QEMU:-$(command -v qemu-system-arm || true)}"
|
||||
[ -n "$QEMU" ] || { echo "SKIP no qemu-system-arm; set QEMU or put it on PATH" >&2; exit 0; }
|
||||
ELF="${1:-}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
FLASH="${UVK5_FLASH_IMAGE:-$(cd "$(dirname "$0")/.." && pwd)/assets/flash.img}"
|
||||
QMP=/tmp/uvk5-qmp.sock
|
||||
|
||||
# Never `pkill -f 'M uv-k5-v3'` here: see tools/lib_kill_emulator.sh for why that
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@
|
||||
# the firmware looks, versus the rows going low but the debounce rejecting them.
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
KEY="${1:-MENU}"
|
||||
SAMPLES="${2:-10}"
|
||||
|
||||
|
||||
+3
-1
@@ -7,7 +7,9 @@
|
||||
# go low".
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
KEY="${1:-MENU}"
|
||||
HITS="${2:-12}"
|
||||
|
||||
|
||||
@@ -46,8 +46,9 @@ kill "$decoy" "$decoy2" 2>/dev/null || true
|
||||
wait 2>/dev/null || true
|
||||
|
||||
# And a real emulator must actually be terminated.
|
||||
QEMU="$HOME/qemu-build/qemu-7.2+dfsg/build/qemu-system-arm"
|
||||
ELF="$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf"
|
||||
QEMU="${QEMU:-$(command -v qemu-system-arm || true)}"
|
||||
. "$HERE/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf || true)
|
||||
IMG=$(mktemp /tmp/kill-test-XXXX.img)
|
||||
gzip -dc "$HERE/../assets/pristine/flash-pristine.img.gz" > "$IMG"
|
||||
|
||||
|
||||
@@ -18,18 +18,25 @@ import time
|
||||
|
||||
HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
SIM = os.path.dirname(HERE)
|
||||
QEMU = os.path.expanduser("~/qemu-build/qemu-7.2+dfsg/build/qemu-system-arm")
|
||||
ELF = os.path.expanduser("~/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf")
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
import uvk5_testenv
|
||||
|
||||
QEMU = uvk5_testenv.qemu()
|
||||
ELF = uvk5_testenv.firmware()
|
||||
FLASH = os.path.join(SIM, "assets", "flash.img")
|
||||
LOG = "/tmp/uvk5-serial-test.log"
|
||||
QMP = "/tmp/uvk5-serial-test.sock"
|
||||
|
||||
|
||||
def main():
|
||||
for path, what in ((QEMU, "QEMU binary"), (ELF, "firmware ELF"),
|
||||
(FLASH, "flash image")):
|
||||
if not os.path.exists(path):
|
||||
sys.exit(f"missing {what}: {path}")
|
||||
missing = uvk5_testenv.missing([
|
||||
(QEMU, "QEMU binary", "set QEMU=/path/to/qemu-system-arm, or put it on PATH"),
|
||||
(ELF, "firmware", "run tools/fetch_firmware.py, or set ELF=..."),
|
||||
(FLASH, "flash image", "run tools/make_flash.py"),
|
||||
])
|
||||
if missing:
|
||||
print("SKIP: %s" % missing)
|
||||
return 0
|
||||
if os.path.exists(QMP):
|
||||
os.unlink(QMP)
|
||||
|
||||
|
||||
@@ -25,8 +25,11 @@ HERE = os.path.dirname(os.path.abspath(__file__))
|
||||
SIM = os.path.dirname(HERE)
|
||||
sys.path.insert(0, HERE)
|
||||
|
||||
QEMU = os.path.expanduser("~/qemu-build/qemu-7.2+dfsg/build/qemu-system-arm")
|
||||
ELF = os.path.expanduser("~/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf")
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
import uvk5_testenv
|
||||
|
||||
QEMU = uvk5_testenv.qemu()
|
||||
ELF = uvk5_testenv.firmware()
|
||||
FLASH = os.path.join(SIM, "assets", "flash.img")
|
||||
QMP = "/tmp/uvk5-webui-e2e.sock"
|
||||
HTTP_PORT = 8099
|
||||
|
||||
+8
-4
@@ -6,9 +6,13 @@
|
||||
# - does the GPIO input callback run? (TRACE gpio... set_input)
|
||||
set -uo pipefail
|
||||
|
||||
QEMU="$HOME/qemu-build/qemu-7.2+dfsg/build/qemu-system-arm"
|
||||
ELF="${1:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
FLASH="$HOME/uvk5-port/sim/assets/flash.img"
|
||||
QEMU="${QEMU:-$(command -v qemu-system-arm || true)}"
|
||||
[ -n "$QEMU" ] || { echo "SKIP no qemu-system-arm; set QEMU or put it on PATH" >&2; exit 0; }
|
||||
ELF="${1:-}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
FLASH="${UVK5_FLASH_IMAGE:-$(cd "$(dirname "$0")/.." && pwd)/assets/flash.img}"
|
||||
LOG=/tmp/uvk5-trace.log
|
||||
QMP=/tmp/uvk5-qmp.sock
|
||||
|
||||
@@ -26,7 +30,7 @@ sleep 1
|
||||
-kernel "$ELF" -gdb tcp::1234 >"$LOG" 2>&1 &
|
||||
|
||||
sleep 12
|
||||
python3 "$HOME/uvk5-port/sim/tools/key.py" MENU >/dev/null 2>&1 || true
|
||||
python3 "$(dirname "$0")/key.py" MENU >/dev/null 2>&1 || true
|
||||
sleep 2
|
||||
|
||||
echo "== keypad row drives =="
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
# Where the firmware is, for the ad-hoc probe scripts.
|
||||
#
|
||||
# Every one of them used to name the same hardcoded path -- one developer's CW build --
|
||||
# so none of them ran on a machine that did not have that file. The order here matches
|
||||
# tools/uvk5_testenv.py, so the scripts and the tests agree about what is available.
|
||||
#
|
||||
# ELF, UVK5_FIRMWARE, UVK5_MULTIBOOT_IMAGE the environment wins
|
||||
# assets/firmware/*, work/* then whatever the checkout has
|
||||
#
|
||||
# Returns non-zero when there is nothing, so a caller can skip with a reason rather
|
||||
# than run against a path that does not exist.
|
||||
uvk5_find_elf() {
|
||||
local var value
|
||||
for var in ELF UVK5_FIRMWARE UVK5_MULTIBOOT_IMAGE; do
|
||||
eval "value=\${$var:-}"
|
||||
if [ -n "$value" ] && [ -e "$value" ]; then
|
||||
printf '%s' "$value"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
local root cand
|
||||
root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
for cand in "$root"/assets/firmware/*.elf "$root"/assets/firmware/*.bin \
|
||||
"$root"/work/*.elf "$root"/work/*.bin; do
|
||||
if [ -e "$cand" ]; then
|
||||
printf '%s' "$cand"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Where the emulator tests find a QEMU and a firmware, and what to say when they cannot.
|
||||
|
||||
The emulator tests used to name one developer's build directory:
|
||||
|
||||
QEMU = os.path.expanduser("~/qemu-build/qemu-7.2+dfsg/build/qemu-system-arm")
|
||||
ELF = os.path.expanduser("~/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf")
|
||||
The emulator tests used to name one developer's build directory -- a QEMU under their
|
||||
home, and one firmware build from a source tree outside this repository --
|
||||
|
||||
which is fine on the machine they were written on and useless anywhere else -- and a
|
||||
missing file used to be a hard failure, so a checkout without that build could never
|
||||
|
||||
+29
-4
@@ -1164,6 +1164,29 @@ pollFirmware();
|
||||
</body></html>"""
|
||||
|
||||
|
||||
def _default_qemu():
|
||||
"""A QEMU to spawn: the environment, then PATH. Never one developer's build dir."""
|
||||
try:
|
||||
import uvk5_testenv
|
||||
return str(uvk5_testenv.qemu() or "qemu-system-arm")
|
||||
except Exception:
|
||||
return "qemu-system-arm"
|
||||
|
||||
|
||||
def _default_firmware():
|
||||
"""Whatever firmware this checkout has, or nothing.
|
||||
|
||||
Nothing is the normal case now: a firmware can be uploaded from the page, and the page
|
||||
says when one is not loaded. tools/uvk5_testenv.py looks in assets/firmware and work.
|
||||
"""
|
||||
try:
|
||||
import uvk5_testenv
|
||||
firmware = uvk5_testenv.firmware()
|
||||
return str(firmware) if firmware else None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def main() -> int:
|
||||
ap = argparse.ArgumentParser(description=__doc__.splitlines()[0])
|
||||
ap.add_argument("--qmp", default="/tmp/uvk5-qmp.sock")
|
||||
@@ -1178,12 +1201,14 @@ def main() -> int:
|
||||
help="attach to an emulator started elsewhere (run.sh) "
|
||||
"instead of managing one. Off is then refused, since "
|
||||
"this server did not start that process.")
|
||||
ap.add_argument("--qemu", default=os.path.expanduser(
|
||||
"~/qemu-build/qemu-7.2+dfsg/build/qemu-system-arm"))
|
||||
# A path or a bare name: Popen resolves a bare name through PATH. The machine is
|
||||
# built from this checkout, not from one developer's build directory.
|
||||
ap.add_argument("--qemu", default=_default_qemu())
|
||||
# Named --elf for history; any .bin or .elf works, and its shape is read out
|
||||
# of the file rather than assumed. More can be uploaded from the page.
|
||||
ap.add_argument("--elf", "--firmware", dest="elf", default=os.path.expanduser(
|
||||
"~/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf"))
|
||||
# Nothing local by default: upload a firmware from the page, which says so when
|
||||
# none is loaded. tools/uvk5_testenv.py finds one in assets/firmware or work.
|
||||
ap.add_argument("--elf", "--firmware", dest="elf", default=_default_firmware())
|
||||
ap.add_argument("--flash", default=os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
|
||||
"assets", "flash.img"))
|
||||
|
||||
+3
-1
@@ -4,7 +4,9 @@
|
||||
# Usage: where.sh [samples]
|
||||
set -uo pipefail
|
||||
|
||||
ELF="${ELF:-$HOME/uvk5-port/uvk5-sat/build/CW/nr7y.cw.elf}"
|
||||
# shellcheck source=tools/uvk5_elf.sh
|
||||
. "$(dirname "$0")/uvk5_elf.sh"
|
||||
ELF=$(uvk5_find_elf) || { echo "SKIP no firmware found; set ELF or put one in assets/firmware" >&2; exit 0; }
|
||||
SAMPLES="${1:-1}"
|
||||
SCRIPT=$(mktemp --suffix=.gdb)
|
||||
trap 'rm -f "$SCRIPT"' EXIT
|
||||
|
||||
Reference in new issue
Block a user