- Add ota.h / ota.c: ota_enter_dfu() (armed guard, writes BKP15R, resets), ota_fw_crc32() using STM32F7 hardware CRC peripheral (CRC-32/MPEG-2, 512 KB) - Add JLINK_CMD_DFU_ENTER (0x06) and dfu_req flag to jlink.h / jlink.c - Handle dfu_req in main loop: calls ota_enter_dfu(is_armed) — no-op if armed - Update usbd_cdc_if.c: move DFU magic from BKP0R to BKP15R (OTA_DFU_BKP_IDX) resolving BKP register conflict with BNO055 calibration (BKP0R–6R, PR #150) - Add scripts/flash_firmware.py: CRC-32/MPEG-2 + ISO-HDLC verification, dfu-util flash, host-side backup/rollback, --trigger-dfu JLink serial path - Add test/test_ota.py: 42 tests passing (CRC-32/MPEG-2, CRC-16/XMODEM, DFU_ENTER frame structure, BKP register safety, flash constants) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
58 lines
1.5 KiB
C
58 lines
1.5 KiB
C
#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;
|
||
}
|