USB CDC TX works alone, breaks when icm42688_init() is added — needs bisect #9

Closed
opened 2026-02-28 13:04:37 -05:00 by seb · 0 comments
Owner

Confirmed Facts

Working firmware (tested, data streams at 10Hz):

int main(void) {
    SCB_EnableICache();
    HAL_Init();
    SystemClock_Config();
    USBD_Init/RegisterClass/CDC/Start;
    HAL_Delay(3000);
    // NO peripheral inits
    while (1) {
        snprintf(buf, ..., "{\"hello\":%lu}\n", count++);
        CDC_Transmit(buf, len);
        HAL_Delay(100);
    }
}

This produces data. Confirmed via pyserial on macOS.

Broken firmware (no data, port enumerates but TX is silent):

Same as above but add icm42688_init() before the loop. icm42688_init() does:

  1. Enable GPIOA clock (for SPI CS on PA4)
  2. Configure PA4 as GPIO output (CS)
  3. Call SCB_DisableDCache()this is inside icm42688.c
  4. Init SPI1 (PA5=SCK, PA6=MISO, PA7=MOSI)
  5. SPI transactions to read WHO_AM_I

Key Clue

SCB_DisableDCache() is called INSIDE icm42688_init(), which runs AFTER USB has started. Disabling DCache after USB OTG FS is running likely corrupts USB DMA state.

What We Tried (all failed)

  • Moving SCB_DisableDCache() before HAL_Init()USB port never enumerates (boot crash)
  • Moving SCB_DisableDCache() after SystemClock_Config() before USBD_Init()USB port never enumerates
  • Removing SCB_DisableDCache() entirely + using SCB_CleanDCache_by_Addr() on TX buffer → port enumerates, no data
  • memcpy to static buffer before TX → no effect
  • TxState busy recovery counter → no effect

What PR #6 Got Wrong

PR #6 DCache fix was on the right track but the PR was incomplete (missing mpu6000.c) and the SCB_DisableDCache() before HAL_Init() crashed USB enumeration entirely.

What Needs To Happen

  1. Flash the working hello firmware (commit the test main.c, verify it works on hardware)
  2. Add ONLY icm42688_init() and confirm it breaks
  3. Remove SCB_DisableDCache() from icm42688.c and test — does SPI still work without it?
  4. If SPI needs DCache disabled: disable it BEFORE USBD_Init() and figure out why that crashes enumeration
  5. Alternative: use cache-safe SPI buffers (aligned + clean/invalidate) instead of disabling DCache globally

Hardware Access

  • FC connected via USB to mbpm4 (192.168.87.40, user seb)
  • Flash via DFU: pio run --target upload (must hold BOOT button on FC)
  • Read serial: python3 -c "import serial; s=serial.Serial('/dev/cu.usbmodemSALTY0011', 115200, timeout=3); ...
  • 3 second HAL_Delay after USBD_Start is required for USB host to enumerate before first TX

Files

  • src/icm42688.c — line with SCB_DisableDCache() is the prime suspect
  • lib/USB_CDC/src/usbd_cdc_if.c — CDC_Transmit
  • src/main.c — needs to be the simple test version for bisecting
## Confirmed Facts ### Working firmware (tested, data streams at 10Hz): ```c int main(void) { SCB_EnableICache(); HAL_Init(); SystemClock_Config(); USBD_Init/RegisterClass/CDC/Start; HAL_Delay(3000); // NO peripheral inits while (1) { snprintf(buf, ..., "{\"hello\":%lu}\n", count++); CDC_Transmit(buf, len); HAL_Delay(100); } } ``` This produces data. Confirmed via pyserial on macOS. ### Broken firmware (no data, port enumerates but TX is silent): Same as above but add `icm42688_init()` before the loop. icm42688_init() does: 1. Enable GPIOA clock (for SPI CS on PA4) 2. Configure PA4 as GPIO output (CS) 3. Call `SCB_DisableDCache()` ← **this is inside icm42688.c** 4. Init SPI1 (PA5=SCK, PA6=MISO, PA7=MOSI) 5. SPI transactions to read WHO_AM_I ## Key Clue `SCB_DisableDCache()` is called INSIDE `icm42688_init()`, which runs AFTER USB has started. Disabling DCache after USB OTG FS is running likely corrupts USB DMA state. ## What We Tried (all failed) - Moving `SCB_DisableDCache()` before `HAL_Init()` → **USB port never enumerates** (boot crash) - Moving `SCB_DisableDCache()` after `SystemClock_Config()` before `USBD_Init()` → **USB port never enumerates** - Removing `SCB_DisableDCache()` entirely + using `SCB_CleanDCache_by_Addr()` on TX buffer → **port enumerates, no data** - `memcpy` to static buffer before TX → no effect - TxState busy recovery counter → no effect ## What PR #6 Got Wrong PR #6 DCache fix was on the right track but the PR was incomplete (missing mpu6000.c) and the `SCB_DisableDCache()` before `HAL_Init()` crashed USB enumeration entirely. ## What Needs To Happen 1. **Flash the working hello firmware** (commit the test main.c, verify it works on hardware) 2. **Add ONLY `icm42688_init()`** and confirm it breaks 3. **Remove `SCB_DisableDCache()` from icm42688.c** and test — does SPI still work without it? 4. If SPI needs DCache disabled: disable it BEFORE `USBD_Init()` and figure out why that crashes enumeration 5. Alternative: use cache-safe SPI buffers (aligned + clean/invalidate) instead of disabling DCache globally ## Hardware Access - FC connected via USB to mbpm4 (192.168.87.40, user seb) - Flash via DFU: `pio run --target upload` (must hold BOOT button on FC) - Read serial: `python3 -c "import serial; s=serial.Serial('/dev/cu.usbmodemSALTY0011', 115200, timeout=3); ...` - **3 second HAL_Delay after USBD_Start is required** for USB host to enumerate before first TX ## Files - `src/icm42688.c` — line with `SCB_DisableDCache()` is the prime suspect - `lib/USB_CDC/src/usbd_cdc_if.c` — CDC_Transmit - `src/main.c` — needs to be the simple test version for bisecting
sl-firmware was assigned by seb 2026-02-28 13:04:37 -05:00
seb closed this issue 2026-02-28 17:41:37 -05:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: seb/saltylab-firmware#9
No description provided.