Hi,
I'm new to this game,being mostly a (French) software dev doing backend Node.js.
Recently I bought a 21.5" Android kiosk display from Beelta, the T2100AA, to build a custom kiosk for my company. The Android build is bloated, so I wanted something cleaner.
I started looking into porting Armbian to this display. Inside there's an SBC identified as a Shimeta AIoT-3568A. There's no Linux support for this board, and the manufacturer wasn't willing to provide any documentation.
I started digging with Claude and worked through most of the blockers in under a day. Here's what I found — and possibly a path forward for other Shimeta-based boards too (more on that below).
Hardware
SoC: Rockchip RK3568 (quad Cortex-A55, Mali-G52, unused 0.8 TOPS NPU)
Based on the reference rockchip,rk3568-evb1-ddr4-v10 design; the stock firmware actually bundles several board variants (EVB1/3568HV/3568S/3568ST/3568WP) selected at boot via androidboot.dtb_idx
DDR4, DDR init confirmed working with the stock rk3568_ddr_1560MHz idbloader (MiniLoaderAll.bin)
PMIC: RK809 (i2c 0x20) with integrated audio codec
21.5" Full HD (1920×1080) touch panel — this is an all-in-one panel/SBC unit, not a bare dev board
Analysis method
Full generic Android firmware image extracted (RKFW→RKAF) plus a live dump (via adb root) from a unit actually running in production, giving both /sys/firmware/fdt and the real boot/dtbo/vbmeta partitions to cross-check against.
Display pipeline — the core blocker
RK3568 DSI0 → GM8775C (DSI-to-dual-channel-LVDS bridge, "CORPRO") → dual-LVDS → 21.5" FHD panel
RK3568 has no native dual-channel LVDS output (needed above ~1440×900), hence the GM8775C bridge chip on the PCB. It's configured purely through generic DSI commands from the RK3568 (no separate I2C control) — the full init sequence has been extracted from the vendor DTB (panel-init-sequence). Timing is confirmed stable at 1920×1080@60 (148.5 MHz pixel clock).
Everything else is straightforward / mainline-ready
Backlight: standard pwm-backlight, PWM + GPIO enable, nothing to write
Touch: pure USB, ILITEK controller, standard HID multitouch — zero driver work
Ethernet: dual GMAC with RTL8211F PHY, mature mainline support
WiFi/BT: AW-NM43438 (Broadcom/AmpaK BCM43438/AP6212 rebrand) — just needs the correct firmware/nvram blobs pulled from the vendor partition, brcmfmac/hci_bcm handle the rest
Power button, headset jack, IR receiver: all standard or non-blocking
Getting a working base
The Odroid M1 mainline image worked out of the box for HDMI, USB, etc., but had no LVDS output and no networking. With Claude's help, I:
Overwrote the Odroid idbloader with the one from the stock Android install
Built a DTB for the AIoT-3568A to get networking working, which let me switch to SSH over Ethernet for much faster iteration
Wrote (well, Claude wrote...) the MIPI-DSI-to-LVDS bridge driver for the Corpro GM8775C, plus the LVDS panel config — resulting in a fully working panel with backlight
Reboot issue and solution
Board freezes completely and power-cycles (not a clean reboot, not a kernel panic) roughly 10 minutes after power-on, regardless of load, distro, or kernel config. Confirmed independently by another user on the same board family in the youyeetoo forum back in 2023 — including a report that it happens even while stuck in U-Boot, before Linux ever runs.
What we ruled out (with evidence, on Armbian mainline kernel 6.18)
SoC-internal software watchdog (dw_wdt): disabled, masked, or actively fed via ftrace-confirmed kicks right up to the crash — innocent either way
Thermal: never critical (43–58 °C)
CPU/RAM/storage stress in isolation (stress-ng): all pass
Two different SD cards, freshly reformatted: same symptom
systemd timers (fstrim/tmpfiles/hwclock): masked, no effect
Main DC input power, scoped on a Rigol DP832: no anomalous current draw correlated with the crash
Ethernet fully unplugged, WiFi/BT unloaded: no effect
PMIC (RK809) regulator config: confirmed exact match against the live vendor DTB, node by node
ext4 commit interval: tested multiple values, inconclusive
Decisive test:
powered on, then issued a software reboot at ~5 min uptime. The board still crashed at ~10 min from the original power-on, not restarted from the software reboot. This proves the timer is driven by something external to Linux, tied to physical power, not the OS.
Root cause: undocumented external supervisor MCU
These boards carry a secondary microcontroller separate from the RK3568/RK3588/RK3399 main SoC — an STM8S00K3, shown in the vendor device tree as:
dts
mcuinf@62 {
compatible = "smdtmcu,STM8S00K3"; status = "okay"; reg = <0x62>;
};
Sitting on an I2C bus (i2c5 @ 0x62 on the 3568A), invisible to any mainline Linux driver. ShiMeta's own product documentation confirms its purpose: "Watchdog Timer Configuration: To ensure 24/7 autonomous uptime, the MCU runs a hardware watchdog. If the main Android system freezes, the MCU automatically forces a hard reset to recover the device."
Reverse-engineered by tracing I2C traffic (ftrace events/i2c) on the stock Android vendor image, where a kernel thread literally named mcu proc (kthread, PPID 2 — not killable from userspace) talks to the MCU continuously:
I2C transactionFrequencyPurpose
None of this exists in mainline Linux, so on any custom OS (Armbian, or any non-vendor image) the MCU eventually decides the AP never booted / has hung, and fires the hardware reset it's designed to perform.
What actually fixes it:
Write reg 0x51 = 0x33, read back via 0xD1 → 0x33 (once, ~25s after power-on (triggered by vendor binary /system/bin/mcu_tool notify_power_on) : Tells the MCU "AP booted successfully" — disarms the initial boot-timeout
Write 0x80, read 1 byte (every 3.04s, continuous) : Status poll (0x00 = nominal, 0xAA = observed once feeding stops)
Write [0x33, 0xAB] (2 bytes) (every 11.15s, continuous) : Periodic heartbeat/feed from the AP
This script fixes sends the correct frames:
# one-shot, early in boot
i2cset -y 5 0x62 0x51 0x33
# then, forever, two independent loops:
while true; do i2cget -y 5 0x62 0x80 >/dev/null; sleep 3; done &
while true; do i2cset -y 5 0x62 0x33 0xAB >/dev/null; sleep 10; done &
Thomas.