AI generated issue-ticket
Problem
CLI AutoComplete builder intermittently stalls with double "Building AutoComplete Cache..." messages on HELIOSPRING (HESP), STRIXF10 (SX10), and MODE2FLUX (FLUX) boards, requiring USB unplug/replug to recover.
Behavior:
- Works reliably (~70-90% success rate) if user waits and low system activity
- Fails when switching tabs rapidly or during high background activity (OSD rendering, telemetry, blackbox)
- Stall manifests as: double build text, configurator 3s watchdog timeout, sync loss
Root Cause
USB VCP write starvation under scheduler load on boards with USE_DMA_SPI_DEVICE + USE_GYRO_IMUF9001:
- Gyro EXTI interrupt fires at NVIC priority 0 (highest), reading IMUF data at 8–32 kHz
- USB OTG interrupt runs at priority 2 (lower)
- During CLI
dump command (~100 USB flushes of 64-byte buffer):
- Each flush calls
CDC_Send_DATA() with 50ms timeout
- Gyro EXTI constantly preempts USB interrupt
- Under scheduler load, USB endpoint can't drain before timeout expires
- Bytes silently dropped → sentinel echoes lost → watchdog fires → stall
Affected boards:
- HELIOSPRING (STM32F405 + STM32F3,
dma_spi.c)
- STRIXF10 (STM32F7x2RE,
dma_spi_hal.c)
- MODE2FLUX (STM32F405,
dma_spi.c)
All three use USE_DMA_SPI_DEVICE + USE_GYRO_IMUF9001 + MSP_OVER_CLI.
Solution
Disable gyro EXTI interrupt during CLI mode (FC is arming-disabled anyway; IMUF keeps running independently):
File: src/main/interface/cli.c
In cliEnter():
void cliEnter(serialPort_t *serialPort) {
cliMode = 1;
cliPort = serialPort;
setPrintfSerialPort(cliPort);
cliWriter = bufWriterInit(cliWriteBuffer, sizeof(cliWriteBuffer), (bufWrite_t)serialWriteBufShim, serialPort);
#ifdef USE_DMA_SPI_DEVICE
// Disable gyro EXTI during CLI to prevent preemption of USB writes
EXTIEnable(IOGetByTag(IO_TAG(MPU_INT_EXTI)), false);
#endif
// ...rest of cliEnter()
}
In cliExit():
static void cliExit(char *cmdline) {
UNUSED(cmdline);
cliPrintHashLine("leaving CLI mode, unsaved changes lost");
bufWriterFlush(cliWriter);
*cliBuffer = '\0';
bufferIndex = 0;
cliMode = 0;
mixerResetDisarmedMotors();
#ifdef USE_DMA_SPI_DEVICE
// Re-enable gyro EXTI before reboot
EXTIEnable(IOGetByTag(IO_TAG(MPU_INT_EXTI)), true);
#endif
cliReboot();
cliWriter = NULL;
}
In cliRebootEx():
static void cliRebootEx(bool bootloader) {
UNUSED(bootloader);
cliPrintHashLine("rebooting");
bufWriterFlush(cliWriter);
*cliBuffer = '\0';
bufferIndex = 0;
cliMode = 0;
mixerResetDisarmedMotors();
#ifdef USE_DMA_SPI_DEVICE
// Re-enable gyro EXTI before reboot
EXTIEnable(IOGetByTag(IO_TAG(MPU_INT_EXTI)), true);
#endif
// ...rest of cliRebootEx()
}
Why This Works
- ✅ USB drains cleanly (no preemption from gyro EXTI during CLI output)
- ✅ IMUF version query still works (uses blocking SPI, not EXTI)
- ✅ Flight unaffected (EXTI re-enabled on CLI exit)
- ✅ IMUF safe (continues filtering internally; FC just stops reading data-ready signal)
- ✅ Resource cost negligible (~10 bytes code, zero SRAM)
Testing
- Enter CLI immediately after USB connect (no manual wait)
- Rapid tab switching before/during autocomplete build (repeat 10× → should work 100%)
- Verify
# version returns IMUF version correctly
- Exit CLI, fly 30-second hover, verify gyro response is smooth
- Test on HELIOSPRING, STRIXF10, MODE2FLUX
- Verify no impact on boards without
USE_DMA_SPI_DEVICE
AI generated issue-ticket
Problem
CLI AutoComplete builder intermittently stalls with double "Building AutoComplete Cache..." messages on HELIOSPRING (HESP), STRIXF10 (SX10), and MODE2FLUX (FLUX) boards, requiring USB unplug/replug to recover.
Behavior:
Root Cause
USB VCP write starvation under scheduler load on boards with
USE_DMA_SPI_DEVICE+USE_GYRO_IMUF9001:dumpcommand (~100 USB flushes of 64-byte buffer):CDC_Send_DATA()with 50ms timeoutAffected boards:
dma_spi.c)dma_spi_hal.c)dma_spi.c)All three use
USE_DMA_SPI_DEVICE+USE_GYRO_IMUF9001+MSP_OVER_CLI.Solution
Disable gyro EXTI interrupt during CLI mode (FC is arming-disabled anyway; IMUF keeps running independently):
File:
src/main/interface/cli.cIn
cliEnter():In
cliExit():In
cliRebootEx():Why This Works
Testing
# versionreturns IMUF version correctlyUSE_DMA_SPI_DEVICE