Jump to content

Recommended Posts

Posted

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.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines