88 lines
3.1 KiB
C
88 lines
3.1 KiB
C
/*
|
|
* OBL DFU loop entry points called from main.c's boot decision.
|
|
*
|
|
* Both run the same OBL middleware loop (OpenBootloader_Init +
|
|
* OpenBootloader_ProtocolDetection in a busy loop). They differ in how
|
|
* the DFU memory map is configured before the loop starts:
|
|
* - normal mode protects the OBL slot (advertise @External_Flash from
|
|
* nor0 0x100000 onwards — BF slot only);
|
|
* - recovery mode exposes nor0 from offset 0 so the host can rewrite
|
|
* OBL itself.
|
|
*
|
|
* The mode is communicated to USB_DFU_If_* in usbd_dfu_if.c via the
|
|
* obl_recovery_mode flag below — checked when DFU initialises its memory
|
|
* descriptor string.
|
|
*
|
|
* Once a host completes a DFU download, our patched usbd_dfu.c sets
|
|
* dfu_leave_pending; the loop below detaches USB and triggers a system
|
|
* reset so the freshly-flashed BF runs without manual NRST.
|
|
*/
|
|
|
|
#include "main.h"
|
|
#include "app_openbootloader.h"
|
|
#include "usbd_core.h"
|
|
|
|
#include "flash_iface.h"
|
|
|
|
bool obl_recovery_mode;
|
|
|
|
extern void obl_dfu_apply_mode(bool recovery);
|
|
extern volatile bool dfu_leave_pending;
|
|
extern volatile uint32_t dfu_last_write_tick;
|
|
extern USBD_HandleTypeDef hUsbDeviceFS;
|
|
|
|
/* Time for the host's final GET_STATUS to return dfuMANIFEST-WAIT-RESET
|
|
* before the device disappears off the bus. dfu-util prints a clean
|
|
* "File downloaded successfully" once the manifest poll loop completes
|
|
* within ~250 ms; 400 ms is generous. */
|
|
#define DFU_LEAVE_DRAIN_MS 400U
|
|
|
|
/* Auto-reboot after this many ms of write inactivity once at least one
|
|
* data block has landed. dfu-util without --reset finishes the download
|
|
* and exits without triggering manifest, so we infer "host is done" from
|
|
* a stretch of silence. 1500 ms is comfortably above the gap between
|
|
* dfu-util's per-block transfers (~ms) and below any reasonable interactive
|
|
* wait. */
|
|
#define DFU_IDLE_REBOOT_MS 1500U
|
|
|
|
static __attribute__((noreturn)) void run_obl_loop(bool recovery)
|
|
{
|
|
obl_recovery_mode = recovery;
|
|
/* Patch the DFU descriptor string before USB enumeration starts so
|
|
* the host sees the right memory geometry on first GET_DESCRIPTOR. */
|
|
obl_dfu_apply_mode(recovery);
|
|
|
|
OpenBootloader_Init();
|
|
|
|
/* IWDG is NOT started in DFU mode — host upload can take tens of
|
|
* seconds and the BF watchdog window (~30 s) is too tight for that.
|
|
* The watchdog is armed only when handing off to BF (iwdg_start in
|
|
* main.c). */
|
|
while (1) {
|
|
OpenBootloader_ProtocolDetection();
|
|
|
|
const bool leave_request = dfu_leave_pending;
|
|
const uint32_t last_tick = dfu_last_write_tick;
|
|
const bool idle_complete = (last_tick != 0U)
|
|
&& ((HAL_GetTick() - last_tick) >= DFU_IDLE_REBOOT_MS);
|
|
|
|
if (leave_request || idle_complete) {
|
|
HAL_Delay(DFU_LEAVE_DRAIN_MS);
|
|
(void)USBD_Stop(&hUsbDeviceFS);
|
|
(void)USBD_DeInit(&hUsbDeviceFS);
|
|
HAL_Delay(50U);
|
|
NVIC_SystemReset();
|
|
}
|
|
}
|
|
}
|
|
|
|
__attribute__((noreturn)) void OBL_run_dfu_normal(void)
|
|
{
|
|
run_obl_loop(false);
|
|
}
|
|
|
|
__attribute__((noreturn)) void OBL_run_dfu_recovery(void)
|
|
{
|
|
run_obl_loop(true);
|
|
}
|