嵌入式应用程序是本项目的核心,其入口点为 main/main.c。它负责初始化系统、驱动UI、并在一个主循环中处理所有事件。其设计核心是平台无关性,通过CMake和C预处理器宏,实现了PC与ARM平台的代码复用。

应用程序启动流程

程序启动后,严格遵循以下初始化顺序:

  1. LVGL核心初始化:

    • lv_init(): 初始化LVGL库。
    • lv_log_register_print_cb(): 注册日志回调,以便在 printf 中看到LVGL的内部日志。
    • lv_fs_posix_init(): 初始化基于Posix的文件系统接口,供LVGL使用。
  2. 平台特定初始化 (Platform-Specific Init):

    • 时间同步 (仅ARM): 在ARM平台上,会调用 sync_time_on_startup() 函数,通过执行 ntpd 等shell命令来同步网络时间并更新硬件时钟(RTC)。
    • HAL初始化 (hal_init): 这是平台适配的关键。内部通过 #if USE_SDL 宏来判断:
      • PC平台: 调用 sdl_init() 并注册SDL的显示和输入(鼠标、键盘)驱动。
      • ARM平台: 调用 fbdev_init()evdev_init() 并注册Linux Framebuffer显示驱动和evdev触摸/鼠标输入驱动。
  3. 服务与模块初始化 (Services & Modules Init):

    • lv_png_init(): 初始化LVGL的PNG图片解码器。
    • hardware_init(): 初始化硬件抽象层,打开 /dev/Led 等设备文件。
    • restore_persisted_states(): 关键步骤。调用state_store模块的load函数,读取上次保存的状态,并立即通过 control_led/buzzer 函数将硬件恢复到该状态。
    • mqtt_client_start(): 启动MQTT客户端,使其在后台线程开始连接并处理网络消息。
  4. UI加载与主循环:

    • demo_dashboard(): 调用此函数来创建并显示初始界面(仪表盘)。
    • 进入主循环: 程序进入 while(1) 无限循环,在循环中以5毫秒的间隔不断调用 lv_timer_handler()。这是LVGL的心跳,负责驱动所有UI渲染、动画和事件处理。