Skip to content

steami: Stabilize config zone firmware (I2C IRQ race condition). #5

@nedseb

Description

@nedseb

Context

The config zone commands (READ_CONFIG 0x31, WRITE_CONFIG 0x30, CLEAR_CONFIG 0x32) using the STM32F103 internal flash work correctly after a clean build, but the initial investigation revealed a race condition in the I2C interrupt handler.

Root cause identified

Two combined factors:

  1. Flash timing incompatible with 30ms hook — W25Q64JV sector erase takes 400ms typical (up to 2s max per datasheet p.76). During this time, the flash rejects all SPI commands except Read Status.

  2. I2C IRQ race condition — The I2C callback (HAL_I2C_SlaveRxCpltCallback) runs in interrupt context with priority 0 (highest) and directly modifies shared state (current_task, task_rx, task_rx_len, tx_i2c_data) without critical sections or memory barriers.

Corrections needed

Firmware side

  1. Add __disable_irq() / __enable_irq() around current_task modifications in on_I2C_receive_command() (IRQ context) and process_task() (thread context)
  2. Make config operations non-blocking (state machine like WRITE_DATA): TASK_CLEAR_CONFIG → send erase → TASK_WAIT_FLASH_BUSY → poll w25q64_is_busy()
  3. Use TASK_WAIT_FLASH_BUSY after WRITE_CONFIG and CLEAR_CONFIG

MicroPython side

  1. Increase polling delay to 50ms instead of 5ms to reduce I2C pressure
  2. Add sleep after write/erase operations before starting status polling

Current state

The internal flash config zone (PR #4, merged) works correctly. This issue tracks the stabilization of the external W25Q64 flash operations for potential future use.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions