/* =============================================================================
 * main.c - SHT30 온습도 보드 펌웨어 진입점 (BOARD_SHT30)
 *
 * 부팅 순서 (RPi sht30_monitor.py 기동 대응):
 *   bsp_init()        : HAL/클럭(HSE 8MHz -> 168MHz)/공통 GPIO/LED
 *   applog_init()     : USART3 디버그 로그(PD8/PD9, 115200) — PA2 는 ETH_MDIO 전용
 *   watchdog_init()   : IWDG 활성화 (이후 헬스 태스크가 refresh)
 *   sht30_init()      : I2C 주변장치 + 센서 초기화
 *   net_init()        : ETH MAC + LAN8720 PHY(RMII) + LwIP
 *   tls_init()        : mbedTLS 엔트로피/DRBG 시드, 루트 CA 파싱
 *   app_sht30_start() : 측정 태스크 + 헬스 태스크 생성
 *   vTaskStartScheduler() : FreeRTOS 스케줄러 기동(반환하지 않음)
 *
 * 폐쇄망(air-gapped): 모든 의존성(HAL/CMSIS/FreeRTOS/lwip/mbedtls)은 third_party
 * 에 벤더링되어 있으며 런타임에 외부 네트워크를 사용하지 않는다(SNTP/HTTPS는
 * 사내 망 내부 서버 대상).
 * ===========================================================================*/
#include <stdint.h>

#include "FreeRTOS.h"
#include "task.h"

#include "app_config.h"     /* board_config.h + secrets.h 포함 */
#include "bsp.h"
#include "applog.h"
#include "watchdog.h"
#include "sht30.h"
#include "net.h"
#include "tls.h"

/* 이 펌웨어는 SHT30 보드 전용이다(CMake sht30_fw 타깃이 -DBOARD_SHT30 정의). */
#if !defined(BOARD_SHT30)
#error "board_sht30/main.c 는 -DBOARD_SHT30 로 빌드해야 합니다."
#endif

/* app_sht30.c 에서 정의 (전용 헤더 없이 모듈 내부 함수로 연결) */
extern void app_sht30_start(void);

int main(void)
{
    /* 1) 클럭/HAL/공통 주변장치. 가장 먼저 수행해야 이후 초기화가 유효하다. */
    bsp_init();

    /* 2) 디버그 로그 UART. 이후 단계의 진단 메시지를 위해 일찍 켠다. */
    applog_init();
    LOGI("=== SHT30 board boot ===");
    LOGI("device_id=%s sensor_id=%d ver=%s",
         BOARD_DEVICE_ID, BOARD_SENSOR_ID, APP_VERSION);
    LOGI("location=%s name=%s", BOARD_DEVICE_LOCATION, BOARD_SENSOR_NAME);

    /* 3) 독립 워치독(IWDG). 활성화 즉시 카운트다운이 시작되므로, 스케줄러 기동
     *    후 헬스 태스크가 첫 refresh 를 하기 전까지 타임아웃되지 않도록
     *    APP_WATCHDOG_TIMEOUT_MS 는 충분히 크게(20s) 설정되어 있다. */
    watchdog_init(APP_WATCHDOG_TIMEOUT_MS);

    /* 4) SHT30 센서(I2C). 실패해도 부팅은 계속한다: 측정 태스크가 매 주기
     *    재시도하므로(센서 일시 미연결 대비) 여기서 멈추지 않는다. */
    if (sht30_init() != 0) {
        LOGE("sht30_init failed (will retry in measure loop)");
    } else {
        LOGI("sht30 init ok (i2c addr=0x%02X)", APP_SHT30_I2C_ADDR);
    }

    /* 5) 네트워크 스택 초기화 (LwIP tcpip 스레드 포함). 링크 업 대기는
     *    측정 태스크에서 수행한다. */
    net_init();
    LOGI("net init ok");

    /* 6) TLS 전역 초기화 (엔트로피/DRBG, 임베드 루트 CA 파싱). 한 번만 수행. */
    if (tls_init() != 0) {
        /* TLS 가 없으면 서버 보고가 불가능하므로 치명적 오류로 처리.
         * (워치독이 결국 리셋하여 재기동을 시도) */
        bsp_fatal("tls_init failed");
    }
    LOGI("tls init ok");

    /* 7) 애플리케이션 태스크(측정 + 헬스) 생성. */
    app_sht30_start();
    LOGI("tasks created, starting scheduler");

    /* 8) 스케줄러 기동. 정상적으로는 반환하지 않는다. */
    vTaskStartScheduler();

    /* 여기에 도달했다면 힙 부족으로 스케줄러가 기동하지 못한 것이다. */
    bsp_fatal("scheduler returned (insufficient heap)");
    for (;;) {
        /* unreachable */
    }
}
