#include "ota.h"
#include "stm32f7xx_hal.h"

/* ---- ota_enter_dfu() ---- */
bool ota_enter_dfu(bool is_armed)
{
    if (is_armed) return false;

    /* Enable backup domain access */
    __HAL_RCC_PWR_CLK_ENABLE();
    HAL_PWR_EnableBkUpAccess();
    __HAL_RCC_RTC_ENABLE();

    /*
     * Write DFU magic to BKP15R.
     * checkForBootloader() runs on next boot and jumps to the ST system
     * bootloader at 0x1FF00000 when it finds this magic in BKP15R.
     * BKP15R avoids the BNO055 calibration range (BKP0R–BKP6R).
     *
     * RTC->BKP0R through BKP31R are laid out consecutively in memory,
     * so (&RTC->BKP0R)[OTA_DFU_BKP_IDX] reaches BKP15R.
     */
    (&RTC->BKP0R)[OTA_DFU_BKP_IDX] = OTA_DFU_MAGIC;

    __disable_irq();
    NVIC_SystemReset();

    return true; /* never reached */
}

/* ---- ota_fw_crc32() ---- */
uint32_t ota_fw_crc32(void)
{
    /*
     * STM32F7 hardware CRC unit:
     *   Polynomial : 0x04C11DB7 (CRC-32/MPEG-2)
     *   Initial    : 0xFFFFFFFF  (CRC_INIT register default)
     *   Width      : 32 bits
     *   Reflection : none
     *
     * The unit processes one 32-bit word at a time.  Feeding the full
     * 512 KB flash (128 K words) takes ~0.5 ms at 216 MHz.
     */
    __HAL_RCC_CRC_CLK_ENABLE();

    /* Reset CRC state; keep default 32-bit polynomial and no reversal */
    CRC->CR = CRC_CR_RESET;

    const uint32_t *p     = (const uint32_t *)OTA_FLASH_BASE;
    uint32_t        words = OTA_FLASH_SIZE / 4u;

    while (words--) {
        CRC->DR = *p++;
    }

    return CRC->DR;
}
