Skip to content

I2CDeviceScanning

Rob Dobson edited this page Feb 21, 2026 · 3 revisions

I2C Device Scanning

Overview

The I2C bus scanning system automatically detects devices connected to the I2C bus, including devices connected through bus multiplexers. Scanning is distinct from polling: scanning detects which devices are present and determines their type, while polling retrieves data from known online devices.

The scanning process is sophisticated, using priority-based address ordering rather than simple linear scanning, and handles complex scenarios including bus stuck conditions, and hot-swapping of devices.

Scan vs Poll

It's important to understand the distinction between these two operations:

Operation Purpose Frequency Target
Scanning Detect device presence and identify device type Variable (fast initially, then slow periodic) All potential I2C addresses
Polling Retrieve data from known devices Regular intervals (device-specific) Only identified, online devices

Scanning discovers what devices are present; polling retrieves data from those devices.

Scan Modes

The scanner operates in different modes that progress through the initialization and steady-state operation:

Scan Mode Progression

IDLE
  ↓
MAIN_BUS_MUX_ONLY  (Detect bus multiplexers on main bus)
  ↓
MAIN_BUS          (Scan all addresses on main bus)
  ↓
SCAN_FAST         (Fast scanning of all addresses including slots)
  ↓
SCAN_SLOW         (Periodic slow scanning)

Mode Descriptions

Mode Purpose Duration Slot Scanning
IDLE Initial state before scanning starts Momentary No
MAIN_BUS_MUX_ONLY Detect bus multiplexers only Until multiplexers stable Main bus only
MAIN_BUS Scan main bus for all devices Until sweep complete Main bus only
SCAN_FAST Rapid detection of all devices Until sweep complete Main bus + all slots
SCAN_SLOW Periodic background scanning Ongoing (configurable period) Main bus + all slots

Mode Transitions

  • IDLE → MAIN_BUS_MUX_ONLY: On initialization or when requested
  • MAIN_BUS_MUX_ONLY → MAIN_BUS: After multiplexers detected and stable
  • MAIN_BUS → SCAN_FAST: After main bus scan complete
  • SCAN_FAST → SCAN_SLOW: After fast scan sweep complete
  • Any → MAIN_BUS_MUX_ONLY: When multiplexer state changes (new mux detected or mux online/offline status changes)

Priority-Based Scanning

Unlike simple linear scanning (0x01, 0x02, 0x03...), the I2C scanner uses priority lists to scan addresses in an intelligent order based on:

  1. Common device addresses: Addresses that are frequently used by popular I2C devices
  2. Device type likelihood: Addresses associated with device types registered in the system
  3. User boost addresses: User-specified high-priority addresses via scanBoost configuration

Scan Priority Lists

Device addresses are organized into priority lists (typically 3-5 lists). The scanner cycles through these lists with different frequencies:

  • Priority 0 (Highest): Scanned most frequently
  • Priority 1: Scanned less frequently
  • Priority 2: Scanned even less frequently
  • Priority N: Scanned least frequently

The scan frequency for each priority level follows a quadratic progression: priority N is scanned every SCAN_PRIORITY_COUNTS[N] sweeps through higher priorities.

Example Priority Counts:

// Priority 0: Every 1 sweep
// Priority 1: Every 2 sweeps  
// Priority 2: Every 4 sweeps
// Priority 3: Every 9 sweeps

Benefits of Priority Scanning

  • Faster detection of common devices (e.g., IMUs, displays, sensors)
  • Reduced bus overhead by scanning less common addresses less frequently
  • Customizable through scanBoost configuration for application-specific devices

Scan Boost Configuration

High-priority addresses can be specified in configuration:

{
    "DevMan": {
        "scanBoost": ["0x6a", "0x36", "0x70"]
    }
}

These addresses are added to Priority 0 (highest priority) and will be scanned most frequently.

Bus Multiplexer Support

The scanning system supports I2C bus multiplexers (e.g., TCA9548A, PCA9548A) which allow multiple devices with the same address to coexist on the same bus by connecting them to different multiplexer slots.

Slot Numbering

  • Slot 0: Main I2C bus (no multiplexer)
  • Slots 1-N: Multiplexer slots (1-based numbering)

For a system with 2 multiplexers, each with 8 slots:

  • Main bus: Slot 0
  • Mux 0, Slot 0-7: Slots 1-8
  • Mux 1, Slot 0-7: Slots 9-16

Multiplexer Detection

Multiplexers are detected during the MAIN_BUS_MUX_ONLY phase:

  1. Scanner attempts to communicate with addresses in the configured multiplexer range
  2. Devices that respond and exhibit multiplexer behavior are registered as multiplexers
  3. Detection requires multiple consecutive successful responses (threshold-based detection to avoid false positives)
  4. Once detected, the scanner builds a list of available slots for subsequent scanning phases

Multiplexer Slot Scanning Order

To optimize detection of main-bus devices while still checking all slots:

  1. Main bus scanned twice per cycle (indices 0 and 1 in slot sequence)
  2. Multiplexer slots scanned once per cycle (indices 2 onwards)

This ensures main bus devices are detected quickly while still covering all slots.

Avoiding False Detections

The scanner implements several checks to avoid incorrectly detecting the same device multiple times:

  • Main bus devices excluded from slot scans: If a device is detected on the main bus, it won't be reported as present on multiplexer slots (even though it will respond on all slots)
  • Multiplexer address slot matching: Multiplexer addresses are only scanned on their correct slot
  • IO Expander exclusion: Defined IO expander addresses are excluded from scanning to avoid conflicts

Scan Timing

Fast vs Slow Scanning

Mode Speed Purpose
Fast Scan Maximum (time-limited per loop) Initial device detection, hot-swap detection
Slow Scan Periodic (configurable interval) Background monitoring for device changes

Fast Scanning:

  • Runs continuously during SCAN_FAST mode
  • Time-limited per service loop iteration (maxFastTimeInLoopUs)
  • Used for rapid initial detection and when changes are expected

Slow Scanning:

  • Runs periodically during SCAN_SLOW mode
  • Configurable period via busScanPeriodMs (default: typically 10-30 seconds)
  • Monitors for device hot-swapping in steady state

Configuration

{
    "DevMan": {
        "busScanPeriodMs": 20000
    }
}

Scan Sweep

A scan sweep is one complete pass through all addresses (and slots) that need to be scanned according to the current priority level.

Sweep Completion Criteria

A sweep is complete when:

  • All addresses in the current priority list have been scanned
  • All applicable slots have been checked for the current address set

After sweep completion:

  • The mode may transition to the next mode (e.g., MAIN_BUS → SCAN_FAST)
  • Priority lists are cycled according to their priority counts
  • Sweep timing is recorded for performance monitoring

Scan Process Flow

Single Address Scan

For each address to be scanned:

  1. Get Next Address: Priority-based selection from scan lists
  2. Slot Validation:
    • Skip if address is on main bus and we're scanning a slot
    • Skip if it's a multiplexer on the wrong slot
    • Skip if it's a defined IO expander
    • Skip if address is currently being polled
  3. Enable Multiplexer Slot: If scanning a slot, enable the appropriate multiplexer configuration
  4. Perform Scan: Send I2C transaction to test device presence
  5. Handle Result:
    • Device responds: Mark online, trigger device identification
    • No response: Mark offline or not present
    • Bus stuck: Attempt recovery procedures
  6. Disable Multiplexer Slots: Return multiplexers to disabled state
  7. Update State: Update bus element tracker and status manager

State Updates

When a device responds during scanning:

Device Responds
  ↓
Update Status Manager (online/offline tracking)
  ↓
Bus Element Tracker (record found on main bus or slot)
  ↓
If changing to ONLINE:
  ↓
  Trigger Device Identification
  ↓
  Store Device Type Information

Bus Stuck Handling

The scanner includes sophisticated bus stuck detection and recovery:

Detection

  • Bus stuck conditions detected during scan transactions
  • Can occur on main bus or when enabling multiplexer slots

Recovery Strategies

  1. Bus Clocking: Send clock pulses to release stuck devices
  2. Slot Disabling: Disable all multiplexer slots
  3. Power Cycling: If power control available, cycle power to problematic slot(s)
  4. Multiplexer Reset: Use hardware reset pins to reset multiplexers

Recovery Attempt Order

Before Slot Enable (main bus issue):

  1. Clock the bus
  2. Disable all slots
  3. Power cycle entire bus (if available)

After Slot Enable (single slot issue):

  1. Clock the bus
  2. Disable the problematic slot
  3. Power cycle the single slot (if available)
  4. If still stuck, escalate to full bus recovery

Multiple recovery attempts are made before declaring the bus permanently stuck.

Device Hot-Swapping

The scanner supports device hot-swapping through:

  1. Continuous Monitoring: Slow scan mode periodically checks all addresses
  2. Online/Offline Tracking: Threshold-based detection to avoid transient false positives
  3. Device Re-identification: When a device comes online, identification runs again
  4. Graceful Offline Handling: Devices that go offline are marked as such without disrupting other devices

Detection Thresholds

To avoid false positives from transient communication errors:

  • Multiple consecutive successful scans required to mark a device as online
  • Multiple consecutive failed scans required to mark a device as offline

Scan Service Function

The scanner is serviced from the I2C task at regular intervals:

bool taskService(uint64_t curTimeUs, 
                 uint64_t maxFastTimeInLoopUs, 
                 uint64_t maxSlowTimeInLoopUs)

Time Budget

  • Fast Scan: Allowed more time per service call for rapid detection
  • Slow Scan: Reduced time budget to minimize impact on polling operations

The function returns true if fast scanning is in progress, allowing the caller to adjust task timing.

Integration with Other Systems

Device Identification

When scanning detects a device coming online, it triggers device identification:

Scan Detects Device Online
  ↓
Device Identification Manager
  ↓
Identify Device Type (query WHO_AM_I, etc.)
  ↓
Store Device Type Information
  ↓
Begin Polling (if supported)

See I2C Device Identification and Polling for details on how device types are determined, devices are initialized, and data is retrieved through polling.

Polling Integration

Scanning avoids addresses that are currently being polled to prevent conflicts:

  • The scanner checks isAddrBeingPolled() before scanning an address
  • If an address is being polled, it is skipped during that sweep
  • This ensures polling operations (which retrieve real data) are not interrupted by scanning operations

Status Manager

The scanner continuously updates the BusStatusMgr with device online/offline status:

  • updateBusElemState(): Called for each scan result
  • informBusStuck(): Called when bus stuck condition detected
  • goingOffline(): Called when power cycling devices offline
  • setBusElemDeviceStatus(): Called with device identification results

Configuration Example

Complete configuration for scanning with multiplexers:

{
    "DevMan": {
        "busScanPeriodMs": 20000,
        "scanBoost": ["0x6a", "0x36"],
        "Mux": {
            "enable": true,
            "minAddr": "0x70",
            "maxAddr": "0x77",
            "rstPin": 5,
            "clearCascadeMux": false
        }
    }
}

Parameters:

  • busScanPeriodMs: Slow scan period in milliseconds
  • scanBoost: Array of high-priority addresses (hex strings)
  • Mux.enable: Enable multiplexer support
  • Mux.minAddr: Minimum multiplexer address
  • Mux.maxAddr: Maximum multiplexer address
  • Mux.rstPin: GPIO pin for hardware reset of multiplexers
  • Mux.clearCascadeMux: Clear cascaded multiplexer slots on detection

Related Documentation

Clone this wiki locally