Files
firmware/config.env.example
T
Oleksandr Shyshatskyi 05b24f7c56 Moonraker and the camera yield to klippy
Stock ran neither moonraker nor nginx nor the streamer -- both lines are
commented out in FlashForge's own start.sh -- so klippy had this two-core
SoC to itself. The mod runs all of them. A host that misses Klipper's
step-generation deadlines does not print slowly, it stops: the MCU reports
"Timer too close" and shuts down mid-job.

So the services around klippy now start at a nice value instead of
competing with it on equal terms. NICE_MOONRAKER (5) and NICE_CAM (10) in
anvil.conf, baked in from config.env like the MOD_* switches and editable
on the printer afterwards; 0 restores the old behaviour exactly.

The two take different routes because they start differently. Moonraker
goes through svc_start_daemon, which now passes start-stop-daemon's -N when
SVC_NICE is set -- not a `nice` wrapper, because --exec is what
start-stop-daemon matches and records, and wrapping would put the nice
binary there instead of the program. The streamer is started by its own
respawn supervisor, so it takes the nice applet, re-applied per respawn.

Modest values, and deliberately so: this is insurance, not a fix. klippy is
already ahead on both counts -- klipper_pri.sh puts its main thread on
SCHED_FIFO 50, which outranks every nice value there is, and its serial
reader thread calls os.nice(-20) itself in serialhdl.py's _bg_thread
(FlashForge's own change, not upstream). These numbers only matter for
whatever klippy thread is neither of those, and for the case where the chrt
or the nice did not take -- which the log will say:

    grep -i nice /usr/data/logs/printer.log

Nothing here addresses memory or eMMC contention. This printer's busybox
has no ionice applet at all, so there is no knob for the second one.

case-priority.sh is the gate, and it rides along with the services one
because it is the same subject from the other side. It is not a grep for
"-N": whether the option is honoured is a property of THIS busybox (1.31.1,
and the missing ionice is why that is worth measuring), so every assertion
reads the nice value back out of /proc/<pid>/stat on the printer's own
shell. Verified there: -N 7 lands as 7, unset and 0 both land as 0.
2026-08-27 11:08:38 +03:00

122 lines
6.5 KiB
Bash

# creator5-fw-builder — build configuration
# Edit paths to match your machine, then run `make build`.
# ---- identity of the package you are building -------------------------------
MOD_NAME=anvil # goes into the .tgz filename
MOD_VER="" # empty = today's UTC date, e.g. 20260823.
# Pin it to rebuild an old release, or for a
# second release on the same day (20260823b).
# Version stamped on the software component. Empty = keep the stock number
# (recommended). The installer wipes every other version dir before renaming
# its temp dir, so a collision is not a problem; a suffix like 1.9.7-mod is
# only useful if you want to see at a glance that a machine is modded.
SW_VER=""
# ---- which printer is this for? --------------------------------------------
# Creator5Pro / 0029 or Creator5 / 0028
# Find it on the printer: Settings -> About, or in
# /usr/data/firmwareRes/config/general.json ("machineName").
#
# This MUST match the model the stock package was built for. A package's
# runFirmwareExe.sh carries its own MACHINE=/PID= gate and refuses to install
# on the other model, so a Pro cannot be recovered or modded with a non-Pro
# package (and vice versa).
TARGET_MACHINE=Creator5Pro
# Override for one command: MODEL=Creator5 make build
# Build both at once: make release
# ---- inputs (sources you already have on this machine) ----------------------
# Everything below is relative to this. Point it wherever you keep the
# firmware and the source repos; nothing here is committed (config.env is
# gitignored, this file is the template).
DESKTOP="$HOME/Desktop"
# Stock OTA packages, ONE PER MODEL. They are not interchangeable: each
# carries a different firmwareExe and refuses to install on the other model.
# The one matching TARGET_MACHINE (or MODEL=) is selected automatically.
STOCK_TGZ_CREATOR5PRO="$DESKTOP/Creator5-1.9.7-1.2.9-20260810/Creator5Pro-1.9.7-1.2.9-20260810.tgz"
STOCK_TGZ_CREATOR5="$DESKTOP/Creator5-1.9.7-1.2.9-20260810/Creator5-1.9.7-1.2.9-20260810.tgz"
# Set this only to force one specific package regardless of model.
STOCK_TGZ=""
# A local checkout of the Klipper fork (branch creator5), for working on the
# fork itself. LEAVE IT UNSET to build what a release builds: the commit
# pinned in versions.env, fetched into vendor/ by bin/fetch-assets.sh, with
# c_helper.so cross-compiled from those same sources by the pinned Ingenic
# toolchain. A checkout gets the same treatment -- its c_helper.so is rebuilt
# whenever it is missing or older than the chelper sources beside it.
#KLIPPER_FORK="$DESKTOP/klipper"
# The toolchanger mod (klippy-extras + configs + helixscreen db entry) used to
# be a TOOLCHANGE= path to a creator5-toolchange checkout. It now lives in this
# repo under payload/klipper/, so there is nothing to set. BUILD_TOOLCHANGE=0
# here still turns it off.
# Mainsail, the HelixScreen build for the Creator 5 (MIPS static) and Moonraker
# are NOT set here. They are downloaded on demand into vendor/ by
# bin/fetch-assets.sh, pinned by version and sha256 in versions.env, so the
# repo carries no binaries. Set any of these ONLY to build against your own
# local copy.
# NOTE: the path is still checksummed against versions.env, and on a mismatch
# fetch-assets.sh OVERWRITES it with the pinned release -- SKIP does not save
# you, it re-downloads too. To build against your own file, also put ITS
# sha256 in versions.env; only an exact match is left alone ("cached"):
#HELIX_TGZ="$DESKTOP/helixscreen-creator5-v0.99.115.tar.gz"
#MAINSAIL_ZIP="$DESKTOP/mainsail.zip"
#MOONRAKER_TGZ="$DESKTOP/moonraker-v0.9.3.tar.gz"
# Optional extras -- leave empty to skip that feature
BUSYBOX_BIN="$DESKTOP/creator5/busybox" # optional richer busybox
# ---- what the installed image does at boot (baked into anvil.conf) ----------
# RUNTIME switches: they are written into /usr/data/anvil/anvil.conf, which the
# printer re-reads at every boot, so they can be changed over ssh afterwards.
#
# The BUILD_* flags that decide what goes INTO a package (BUILD_KLIPPER,
# BUILD_MAINSAIL, BUILD_MOONRAKER, BUILD_HELIX, BUILD_TOOLCHANGE) are not set
# here: bin/common.sh defaults them to the full firmware, and setting one in
# this file overrides that. Only touch them if you want a piece left out.
MOD_WEB=1 # 1 = start nginx (Mainsail) + moonraker
MOD_CAM=1 # 1 = start mjpg-streamer on :8080 (firmwareExe used to)
MOD_UI=1 # 1 = start HelixScreen on the touchscreen
MOD_SSH=1 # build-time only: 1 = set a root password.
# ssh itself is stock S50dropbear, always up.
MOD_WIFI=1 # 1 = bring up wlan0 (firmwareExe used to do this)
# Nice values for the services that share the SoC with klippy: they yield to
# it, so a busy host is less likely to miss Klipper's step deadlines (which
# surfaces as an MCU "Timer too close" shutdown, not as slowness). Baked into
# anvil.conf, and editable on the printer afterwards. 0 = normal priority.
# See the long note in payload/anvil.conf before changing these: klippy is
# already SCHED_FIFO plus a nice -20 reader thread, so these are insurance.
NICE_MOONRAKER=5 # the print path -- keep it modest
NICE_CAM=10 # pure background; software JPEG encode is heavy
# ---- root login shipped in the image ---------------------------------------
# This is the whole "enable ssh" feature. The stock rootfs already runs
# dropbear from /etc/init.d/S50dropbear, so port 22 is ALREADY open on a
# stock printer -- there is simply no published root password.
#
# Empty = the INSTALLER picks a random password on the printer -- on the
# FIRST install only, updates keep the one the machine already has -- and
# writes it to anvil-password.txt on the USB stick you flashed from. Every
# machine gets a different one, which a hash baked into a shared package
# never could.
# Set one here to choose your own: make passwd
# (it prompts, and runs inside the build image -- the same python everywhere,
# where a host openssl may lack `passwd -6` entirely)
ROOT_PW_HASH=""
# ---- crypto (from /usr/prog/bin/unTar on the printer) -----------------------
FF_KEY='FFP0331&*%root'
# ---- the printer replica -----------------------------------------------------
# Nothing here. The replica's settings -- the factory image, the partition
# sizes, a prebuilt printer image -- live in test.env, because they exist only
# for the tests and must never reach a printer:
#
# cp test.env.example test.env