แนวคิด — ฝั่ง LVGL poll ธงแทนถูกปลุก
lv_timer_create(ui_wifi_poll_timer_cb, UI_WIFI_POLL_MS=150, NULL) — ทุก 150 ms เรียก wifi_scan_service_process()
อ่าน+เคลียร์ scan_done_pending ใน critical section เดียวกัน ถ้าเสร็จค่อย render ใหม่
ข้อมูลข้าม thread ด้วย critical section, แจ้งเตือนข้าม thread ด้วยการ poll — คนละกลไกกับ lv_async_call() แต่ปลอดภัยเท่ากัน