Skip to content

Unknown t41nq gc5603 work - #1285

Open
oskarirauta wants to merge 7 commits into
themactep:masterfrom
oskarirauta:unknown-t41nq-gc5603-work
Open

Unknown t41nq gc5603 work#1285
oskarirauta wants to merge 7 commits into
themactep:masterfrom
oskarirauta:unknown-t41nq-gc5603-work

Conversation

@oskarirauta

Copy link
Copy Markdown

Building a thingino image for the DML16-Z533 (T41NQ + GC5603 + RTL8733BU)

Step-by-step to reproduce this camera's working image from a clean thingino-firmware tree.
Board profile name: unknown_t41nq_gc5603_eth+rtl8733bu.

0. Prerequisites

  • A working thingino-firmware checkout that already builds some T41 camera.
  • The files in this package (patches/, config/).

1. Drop in the patches

cp patches/9999-t41-dml16-vendor-pad-init.patch         package/all-patches/uboot/2026.04/
cp patches/0002-rtl8733bu-no-poweroff-after-probe.patch package/all-patches/wifi-rtl8733bu/
cp patches/0002-gc5603-t41-mclk-clkname.patch           package/ingenic-sdk/   # package's OWN dir

(ingenic-sdk patches live in the package's own dir package/ingenic-sdk/*.patch,
NOT under package/all-patches/ingenic-sdk/ — that subdir does not exist. U-Boot
and wifi patches DO use package/all-patches/<pkg>/.)

2. Driver: CCV firmware flag (edit in place)

package/wifi-rtl8733bu/wifi-rtl8733bu.mk — add to WIFI_RTL8733BU_MODULE_MAKE_OPTS:

USER_EXTRA_CFLAGS=-DCONFIG_CCV_FW

3. U-Boot: enable the pad-init option

Add a U-Boot config fragment CONFIG_T41_VENDOR_PAD_INIT=y and reference it, e.g.:

mkdir -p user/unknown_t41nq_gc5603_eth+rtl8733bu
echo 'CONFIG_T41_VENDOR_PAD_INIT=y' > user/unknown_t41nq_gc5603_eth+rtl8733bu/uboot-vendor-pad.config
# in the board defconfig:
BR2_TARGET_UBOOT_CONFIG_FRAGMENT_FILES="/workspace/configs/uboot/layout/sfcnor.config /workspace/user/unknown_t41nq_gc5603_eth+rtl8733bu/uboot-vendor-pad.config"

4. Kernel config (button input; SADC optional)

board/ingenic/xburst2/kernel/4.4.94/t41.generic.config — append the gpio-keys / input
options so the reset button's /dev/input/event0 appears (see §9):

CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_GPIO=y

Optional: the SoC SADC (light-sensor) driver can be enabled, but it is not used for
day/night on this board — the LDR reads inverted and raptor's RIC can't invert, so the gain
trigger is used instead (see §8). If you still want to read the LDR by hand:

CONFIG_MFD_INGENIC_SADC_V13=y
CONFIG_MFD_INGENIC_SADC_AUX=y

(The sadc@10070000 DT node is already okay in t41.dtsi; no DTS change needed.)

5. Profile files

  • config/thingino.jsonconfigs/cameras/unknown_t41nq_gc5603_eth+rtl8733bu/thingino.json
  • Board DTS board/ingenic/dts/unknown_t41nq_gc5603.dts (see this package / README §6).
  • Defconfig: append the audio-gain, stream, and button lines
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_AUDIO_GAIN="31"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_AUDIO_VOLUME="92"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_SENSOR_FPS="30"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_STREAM0_FPS="30"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_STREAM0_BITRATE="3000000"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_STREAM1_WIDTH="1280"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_STREAM1_HEIGHT="720"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_STREAM1_FPS="30"
    BR2_PACKAGE_THINGINO_RAPTOR_CONF_STREAM1_BITRATE="768000"
    BR2_PACKAGE_THINGINO_BUTTON=y
    BR2_PACKAGE_WIRELESS_TOOLS=y
    BR2_PACKAGE_THINGINO_DEVSCRIPTS=y
    BR2_PACKAGE_THINGINO_DIAG=y
    
    (Do NOT add BR2_INGENIC_SDK_GPIO_USERKEYS — it is a no-op on 4.4.94, see §9.)
  • uenv: gpio_default=81o 82o
    (thingino auto-generates gpio_default from thingino.json without wlan; the old 61O
    was redundant — U-Boot's vendor-pad-init asserts WiFi power on PB29/GPIO61 — and is dropped.)

Overlay path mapping (IMPORTANT)

This board's rootfs is a read-only squashfs; / is an overlayfs with
upperdir=/overlay/root (the writable jffs2 DATA partition, mtd4). Therefore the
build staging dir user/<board>/overlay/root/ is the merged filesystem root /,
NOT /root. Consequences when placing files:

  • overlay/root/etc/init.d/S99runonce -> runtime /etc/init.d/S99runonce
  • overlay/root/root/foo -> runtime /root/foo (home dir)
  • overlay/root/foo -> runtime /foo (filesystem root)

So the shipped reference files belong in overlay/root/root/:

mkdir -p user/unknown_t41nq_gc5603_eth+rtl8733bu/overlay/root/root
mv user/.../overlay/root/unknown-t41nq-thingino-custom.zip \
   user/.../overlay/root/root/
mv user/.../overlay/root/raptor.conf \
   user/.../overlay/root/root/raptor.conf.sample

6. Build

make BOARD=unknown_t41nq_gc5603_eth+rtl8733bu br-uboot-dirclean
make BOARD=unknown_t41nq_gc5603_eth+rtl8733bu linux-reconfigure      # picks up appended kernel config
grep -E 'INPUT_EVDEV|KEYBOARD_GPIO' output/master/*/build/linux-*/.config   # verify =y (button)
make BOARD=unknown_t41nq_gc5603_eth+rtl8733bu

Output image: output/master/unknown_t41nq_gc5603_eth+rtl8733bu-4.4.94-uclibc/images/thingino-*.bin

If faac fails on install (libfaac.so already exists): make BOARD=... faac-dirclean then rebuild.

7. Flash

  • Fresh unit: full image via SD-card recovery or serial (the stock U-Boot on these is crippled;
    full-image via SD is the reliable path).
  • Kernel/rootfs only (already on our U-Boot): flashcp the relevant mtd from Linux.
  • Never flash U-Boot (mtd0) from the crippled stock U-Boot — it write-protects boot and can
    leave a half-erased SPL. Flash U-Boot from a running Linux (flashcp .../u-boot-with-spl-lzma.bin /dev/mtd0).

8. Per-camera day/night tuning (gain trigger)

Day/night on this board is driven by the sensor gain (raptor's RIC owns the IR-cut
relay), NOT by a light sensor — the LDR/SADC path is a dead end here (see README §7). Set in
/etc/raptor.conf:

[ircut]
trigger = gain
mode = auto            # or `day` for a fixed-day install until thresholds are tuned
day_threshold  = 390000
night_threshold = 490000

day_threshold / night_threshold are per-unit values on the sensor total_gain (tune
against your unit's lit/dark gain), then /etc/init.d/S31raptor restart. See
config/raptor.conf.sample. Because these vary per unit, the sample is shipped in /root
rather than baked hard into the image.

Do not run thingino-daynightd alongside raptor RIC. Its init script S97daynightd starts
the daemon unconditionally (ignores thingino.json daynight.enabled), so both systems fight
over the IR-cut. The overlay's S99runonce stops daynightd and removes its init script
(overlayfs whiteout) on first boot. See custom/community/UPSTREAM-NOTES.md finding #1.

9. Reset button (GPIO 59 / PB27) — native gpio-keys

The board's reset button is on GPIO 59 (PB27), active-low (reads 1 released via
internal pull-up, 0 pressed; bank gpb, so &gpb 27 in DTS). Found by diffing
/sys/kernel/debug/gpio snapshots while pressing.

It is handled the native way (no custom script): a DTS gpio-keys node in
board/ingenic/dts/unknown_t41nq_gc5603.dts maps PB27 to KEY_ENTER (linux,code = 28),
and the kernel is built with input support (appended to
board/ingenic/xburst2/kernel/4.4.94/t41.generic.config, see §4):

CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_GPIO=y

This makes /dev/input/event0 appear. The standard thingino-button daemon
(BR2_PACKAGE_THINGINO_BUTTON=y) then reads it and runs tap/timed actions.

Gotcha: thingino-button.conf ships DEVICE=auto, which fails to find the gpio-keys
node on this kernel. S99runonce fixes it on first boot:

sed -i 's|^DEVICE=auto|DEVICE=/dev/input/event0|' /etc/thingino-button.conf

then restarts the daemon. Confirmed working: keycode 28 detected, timed actions fire.

Actions (thingino-button defaults, confirmed on hardware):

  • short tap -> speaks/announces the IP
  • hold ~5 s -> wlan reset + reboot
  • hold ~20 s -> factory reset (firstboot -f)

Do not use gpio-userkeys / BR2_INGENIC_SDK_GPIO_USERKEYS — it is a no-op on 4.4.94
(module source only exists under 3.10.14 and depends on board-file symbols absent on a DT
kernel; UPSTREAM-NOTES.md #3). Do not reference thingino.json gpio.button_reset — jct
strips it and the DTS node owns the GPIO anyway (UPSTREAM-NOTES.md #2). The button needs no
custom init script beyond the S99runonce DEVICE fix (UPSTREAM-NOTES.md #4).

Note: a factory reset erases /overlay, which also removes the shipped reference files
(/root/*.zip, /root/raptor.conf.sample). Re-flash the full image to restore.

10. Image orientation / flip (gc5603, per-unit)

The image is flipped via the sensor shvflip mechanism, not the ISP. On this
tx-isp build the ISP-level runtime flip is blocked (raptorctl rvd set-vflip 1 ->
-4090, dmesg: "ISP and Sensor are prohibited from using mirror or flip together"),
and the [isp] hflip/vflip raptor.conf keys do nothing. The sensor driver already
has sensor_set_hvflip() (writes 0x022c + 0x0063, the latter preserves the Bayer
phase so colours stay correct) and assigns sensor->video.shvflip = shvflip; at
init. TWO patches are needed (one alone does nothing visible):

  • 0003-gc5603-t41-shvflip-module-param.patch makes shvflip a module_param
    (it was a plain static default 1, unsettable).
  • 0004-gc5603-t41-apply-shvflip-at-streamon.patch actually CALLS
    sensor_set_hvflip(sd, shvflip) once from sensor_s_stream() after stream-on.
    WITHOUT this the value is stored in video.shvflip but the ISP core never applies
    it for this sensor, so the image never flips regardless of the parameter value.

shvflip: 0=none, 1=mirror(hflip, driver default), 2=flip(vflip), 3=mirror+flip(180deg).

Apply (build machine). ingenic-sdk patches go in the package's OWN dir, and a plain
make BOARD=... only does a fast repack — build the package explicitly:

cp patches/0003-gc5603-t41-shvflip-module-param.patch      package/ingenic-sdk/
cp patches/0004-gc5603-t41-apply-shvflip-at-streamon.patch package/ingenic-sdk/
make BOARD=unknown_t41nq_gc5603_eth+rtl8733bu ingenic-sdk-dirclean
make BOARD=unknown_t41nq_gc5603_eth+rtl8733bu ingenic-sdk    # re-extract + patch + compile
grep -c 'sensor_set_hvflip(sd, shvflip)' output/master/*/build/ingenic-sdk-*/4.4.94/sensor-src/t41/gc5603.c  # expect 1
make BOARD=unknown_t41nq_gc5603_eth+rtl8733bu                 # repack image

Deploy without a full flash (safest on a mounted, wifi-only camera): /lib/modules
is on the overlayfs upper, so you can drop the freshly-built .ko in and it shadows
the squashfs copy:

KO=$(find output/master/*/per-package/ingenic-sdk/target -name sensor_gc5603_t41.ko | head -1)
scp "$KO" root@<camera>:/lib/modules/4.4.94/ingenic/sensor_gc5603_t41.ko
# on camera: set shvflip in /etc/modules.d/30-sensor (below) and reboot

Gotcha: a plain make BOARD=... is a fast repack that does NOT always regenerate
rootfs.squashfs from target/. After removing a package (e.g. go2rtc) delete the
installed files from output/master/*/target and rm images/rootfs.squashfs images/data.jffs2 images/thingino-*.bin before rebuilding, or the old rootfs ships.

Set per unit (these 3 cameras are mounted differently). The value lives in
/etc/modules.d/30-sensor; it is applied at module load, so reboot to apply
(no hot-reload — reloading the sensor under a running raptor oopses the ISP):

echo 'sensor_gc5603_t41 shvflip=3' > /etc/modules.d/30-sensor   # this "corridor" unit
reboot

And remove any ISP-side flip so the guard can't fire:

raptorctl config set isp hflip 0; raptorctl config set isp vflip 0; raptorctl config save

Because it is per-unit, ship it like the day/night thresholds (in /etc on the overlay),
not baked identically into the shared image. See config/modules.d-30-sensor.sample.

11. Streams (resolution / fps / bitrate)

Keep sensor fps = 30 and stream0 fps = 30 (native). The gc5603 2880×1620 mode is a
fixed 30 fps mode; other fps values recompute VTS and (before the vpll MCLK fix, README §4)
tripped the ISP AE fps-error freeze. Tune quality with bitrate (the WiFi-limited knob),
NOT resolution/fps. stream0 bitrate 3M is a good default (0.6M–6M all work on a good link).

Substream resolution must be divisible by 16 (H.264 macroblocks). 1280x720 works;
1440x810 / 960x540 / 1152x649 FAIL (colored boxes / broken substream). Ship
stream1 = 1280x720 @ 30 fps, bitrate 768k.

12. RTSP stability

Symptom: the stream appears to "drop" at a very regular ~58 s. Root cause is the RTSP session
timing out because the client's keepalive/RTCP is lost over WiFi (UDP) — not cron, not the
sensor. Fix on the client: use TCP RTSP transport.

  • VLC: --rtsp-tcp (or Live555 → "RTP over RTSP (TCP)")
  • Frigate / go2rtc: rtsp_transport: tcp

TCP also removes the intermittent grey/partial frames from UDP packet loss. Leave raptor
[rtsp] session_timeout at its 60 s default — do not set it to 0 (that backfires: rsd
closes sessions aggressively, ~15 s).

13. WiFi tuning

The overlay ships /etc/init.d/S95wifi-tune: after wlan0 comes up it sets the RTL8733BU
module knobs en_fwps=0 and dis_turboedca=1 (reduces stalls/latency on this chip), and
disables 802.11 station power-save with iwconfig wlan0 power off
— PS-on is the root cause
of the cameras dropping off the network (station dozes → AP ages it out). Note rtw_power_mgnt
is already 0 as the driver default yet PS is re-enabled at association, and iw is not in the
image, so iwconfig is the lever; the self-heal watchdog re-asserts it every minute. S95 also
supports restart (re-apply, used by self-heal after a reconnect). WiFi power (PB29/GPIO61) is
asserted by the U-Boot vendor-pad-init patch, so the profile uenv does not need 61O in
gpio_default — final uenv is gpio_default=81o 82o. See UPSTREAM-NOTES.md #10.

14. Self-healing watchdog

Ships overlay/root/sbin/selfheal.sh (→ /sbin/selfheal.sh) and
overlay/root/etc/init.d/S96selfheal. S96selfheal runs at boot, idempotently appending two
lines to /etc/cron/crontabs/root (a per-minute check and a 03:00 reboot-scheduled) and
HUP-ing crond — it does not touch thingino's own commented #0 3 * * * reboot -f line. No
runonce hook needed. The watchdog handles network recovery (gateway ping → soft reconnect →
reboot), raptor liveness, a staggered nightly reboot, and — critically — an anti-brick
inhibit that suppresses all reboots during a firmware flash (manual selfheal.sh pause
plus automatic detection of flash tools / any process holding an MTD device open). Full design
and the on-device facts it was built from: selfheal/SELFHEAL-DESIGN.md.

Known limitations (this board)

  • WiFi and Ethernet are one-at-a-time (hardware; same on stock).
  • Disturbing the Ethernet connector can cold-reset the camera (shared power lead in the harness).
  • IR/white LEDs not wired in thingino (weak/low-value on this unit).
  • Day/night uses the gain trigger (raptor RIC); the SADC/LDR path is unusable here (inverted).
  • Reset button: native gpio-keys + thingino-button (tap = announce IP, ~5 s = reboot, ~20 s = factory reset).
  • Image flip is sensor-side only (shvflip module param); ISP runtime/[isp] flip is blocked.

Document package is included.

unknown-t41nq-thingino-custom-final-r2.zip

Kernel/board:
- t41.generic.config: CONFIG_ERASE_SIZE_64K - fixes silent jffs2 overlay
  corruption (32K vs 64K erase-size mismatch)
- linux/4.4.94 0005: ingenic_adc_aux invert param (inverted-LDR day/night)
- DTS, thingino.json, defconfig: board profile

Overlay (user/.../overlay/root):
- S95wifi-tune: RTL8733BU fw-ps/turbo-edca off + 802.11 power-save off
  (root cause of the network drops)
- selfheal.sh + S96selfheal: self-heal watchdog - gateway recovery, raptor
  liveness, staggered 03:00 reboot, anti-brick flash inhibit
- S29invert-adc: enable ADC invert at boot
- S99runonce: daynight/button first-boot fixes + raptor.conf promotion
- raptor.conf(.sample), S12speaker-amp, per-unit tuning docs, docs bundle
…sbin symlink -> no /sbin/init -> init panic)
Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
Fix notes about overlay trap

Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
@themactep
themactep requested a review from gtxaspec July 27, 2026 22:50
oskarirauta and others added 2 commits July 29, 2026 14:29
CONFIG_T41_VENDOR_PAD_INIT exists in this tree but is default n and was
selected nowhere, so a build from a clean checkout produces a u-boot
whose RTL8733BU drops off the USB bus about two seconds after
enumeration and whose SD slot never completes ACMD41. u-boot itself
boots either way, which is what makes it easy to miss - the symptoms
land in Linux, a layer away from the cause.

configs/uboot/boards/<boardname>.config is the slot the makefiles
already look for; it just had no directory. The board is
isvp_t41nq_sfcnor.

Verified by disassembly rather than by running it: with the fragment in
place the SPL is byte-identical to the binary running on the camera
except for one header byte at 0x09, which is the checksum over the
compressed payload, and the pad-init writes land at the same four
offsets (0xa4c, 0xa80, 0xaa8, 0xc80). Without it they are absent.

Also in this fragment, and unrelated to the above:

AUTOBOOT_KEYED with ENTER as the stop string. With a one second
bootdelay, "press any key" means guessing when the window opens; a stop
string is held until it matches, so holding ENTER from power-on always
gets a prompt. On this camera the console is behind a metal case, so
each attempt is expensive and wants to work the first time.

CMD_TFTPPUT and CMD_FS_GENERIC, both for recovery over the network,
which is the only route in once the camera is assembled. tftpput reads
a partition back out to a server, so it can be saved before it is
overwritten rather than only after it is lost; fs_generic loads from an
SD card without knowing in advance how it was formatted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
Two changes to the same fragment, both about matching what an OpenIPC
user already knows.

The autoboot stop condition goes back to plain "hit any key", with a
two-second delay. The previous revision used AUTOBOOT_KEYED with ENTER as
a stop string, reasoning that a one-second window is hard to hit by
guessing. That is the better behaviour taken on its own and it is still
wrong here: the comparison that matters is OpenIPC/u-boot-gk7205v200, a
known-working OpenIPC bootloader, which has AUTOBOOT_KEYED off and
BOOTDELAY=2 - which is also why Ctrl-C works there, since any key does.
Two seconds of any key is easier to hit than one second of the right key,
so nothing is lost by matching. OpenIPC/u-boot-t41 was deliberately not
used as the reference: it is unfinished and flagged dangerous to flash,
so its choices are not evidence of anything.

NET_RANDOM_ETHADDR, because the environment deliberately carries no
ethaddr - a shared default would put the same MAC on every camera flashed
with this image. Without it u-boot has no address at all and tftp does
not run, which matters precisely when it is needed most: recovering a
board whose environment is blank. OpenIPC ships it on for the same
reason.

Signed-off-by: Oskari Rauta <oskari.rauta@gmail.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gtxaspec

Copy link
Copy Markdown
Collaborator

This is a big one! Will review and provide feedback for inclusion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants