st67w611 0.1.0

Async no_std driver for ST67W611 WiFi modules using Embassy framework
Documentation
# ST67W611 Driver Architecture

## Overview

This document explains the architectural design of the ST67W611 async driver, key decisions, and usage recommendations.

## Layer Architecture

```
┌─────────────────────────────────────────────────────────────┐
│  High-Level APIs                                            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐   │
│  │  WiFi    │  │   HTTP   │  │   MQTT   │  │ Advanced │   │
│  │ Manager  │  │  Client  │  │  Client  │  │   (DNS)  │   │
│  └──────────┘  └──────────┘  └──────────┘  └──────────┘   │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  Network Device Layer                                       │
│  ┌──────────────────┐         ┌──────────────────┐         │
│  │  NetworkDevice   │         │ St67w611Driver   │         │
│  │ (Socket Mgmt)    │         │ (embassy-net)    │         │
│  └──────────────────┘         └──────────────────┘         │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  AT Command Layer                                           │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                 │
│  │ Command  │  │  Parser  │  │   RX     │                 │
│  │ Builder  │  │          │  │Processor │                 │
│  └──────────┘  └──────────┘  └──────────┘                 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│  Bus Layer (SPI Transport)                                  │
│  ┌──────────────────────────────────────────┐              │
│  │  SpiTransport (embedded-hal-async)       │              │
│  └──────────────────────────────────────────┘              │
└─────────────────────────────────────────────────────────────┘
                         Hardware SPI
```

## Key Design Decisions

### 1. No-std and No Allocator

**Decision**: Use `heapless` collections exclusively, no heap allocation.

**Rationale**:
- Embedded systems often lack heap allocators
- Predictable memory usage
- No allocation failures at runtime
- Better for safety-critical applications

**Implementation**:
- Fixed-size `heapless::Vec` and `heapless::String` throughout
- Static resource pools (response slots, sockets)
- Compile-time capacity configuration

### 2. Async/Await with Embassy

**Decision**: Built on Embassy framework, async throughout.

**Rationale**:
- Efficient cooperative multitasking without OS overhead
- Natural API for I/O operations
- Better than blocking or callback-based approaches
- Growing ecosystem in embedded Rust

**Implementation**:
- All I/O operations are async
- Uses `embassy-sync` primitives (Mutex, Signal, Channel)
- Background tasks for RX processing and data routing

### 3. Multi-Response Command Support

**Decision**: Separate handling for commands that return multiple data lines.

**Rationale**:
- WiFi scan returns multiple `+CWLAP` lines
- IP config query returns multiple `+CIPSTA` lines
- Need to collect all responses before returning to caller

**Implementation**:
- `ResponseSlot` has both a signal (for single response) and channel (for multiple)
- `send_multi_response_command()` enables collection mode
- Responses collected until final `OK` or `ERROR`

### 4. Event-Driven Architecture

**Decision**: Use channels for event distribution (WiFi events, socket events, IPD data).

**Rationale**:
- Decouples RX processing from event consumers
- Non-blocking event delivery
- Multiple consumers can wait on events

**Implementation**:
- WiFi events: Connection, disconnection, got IP
- Socket events: Connected, closed, data available
- IPD data: Actual received socket data bytes

## embassy-net Integration Challenge

### The Problem

**ST67W611 Architecture:**
```
Application → AT Commands → Module's TCP/IP Stack → WiFi → Network
              (AT+CIPSTART)   (Built-in)
```

**embassy-net Architecture:**
```
Application → smoltcp Stack → Driver (packets) → WiFi → Network
              (TCP/IP in MCU)   (Raw packets)
```

**Mismatch**:
- ST67W611 expects socket-level commands (connect, send, receive)
- embassy-net expects packet-level interface (Ethernet/IP frames)
- The module's TCP/IP stack and smoltcp would conflict

### Current Implementation

The `St67w611Driver` implements the `embassy_net::driver::Driver` trait with:

- **Link state tracking**: Works correctly, reflects WiFi connection status
-**Packet buffer infrastructure**: RX/TX queues for packet storage
-**Token-based interface**: Proper RxToken and TxToken implementations
- ⚠️ **Packet bridging**: Infrastructure present but requires custom logic

### Why Transparent Mode Isn't Feasible

**Hardware Limitation**: The ST67W611 has a maximum SPI clock of 30MHz, which provides:
- Theoretical max throughput: ~3.75 MB/s
- Practical throughput: ~1-2 MB/s (accounting for protocol overhead)

**Why this matters**:
- Raw packet forwarding would consume most/all available SPI bandwidth
- WiFi can provide 10-100+ Mbps, but SPI becomes the bottleneck
- Module's built-in TCP/IP stack is actually the **correct architecture**
- The stack handles protocol processing locally, only sending/receiving application data over SPI
- This dramatically reduces SPI traffic and improves efficiency

**Conclusion**: Transparent/packet mode is not just unimplemented—it's architecturally inappropriate for this hardware. The socket-based AT command interface is the right design.

### Socket API Approach (Correct Design)

**Architecture:**
```
Application → Socket APIs → Module TCP/IP Stack → WiFi (100+ Mbps)
              (Efficient)   (Local processing)

SPI transfers: Only application data + AT commands
Bandwidth usage: Minimal, scales with actual data
```

**Implementation Status:**
- ✅ NetworkDevice for raw socket operations
- ✅ HttpClient for HTTP/HTTPS requests
- ✅ MqttClient for pub/sub messaging
- ✅ TLS with certificate management
- ✅ DNS, SNTP, Ping utilities

### embassy-net Status

**Infrastructure provided:**
- ✅ Complete Driver trait implementation
- ✅ Packet buffers and queues
- ✅ RxToken and TxToken
- ✅ Link state tracking

**Packet bridging**: Not implemented and **not recommended** due to:
1. SPI bandwidth limitations vs WiFi throughput
2. Added complexity with minimal benefit
3. Socket APIs are more efficient and feature-complete

**Use embassy-net ONLY if:**
- You have existing code requiring embassy-net compatibility
- You understand the limitations and accept reduced performance
- You're willing to implement custom packet bridging logic

**For all other uses**: Use the socket APIs directly

The driver provides complete implementations of:
- TCP/UDP sockets via `NetworkDevice`
- HTTP/HTTPS via `HttpClient`
- MQTT via `MqttClient`
- DNS, SNTP, Ping via `advanced` module

## Memory Layout

### Static Resources

```rust
// Required static allocations:
- SpiTransport: ~16 bytes
- TmMutex<SpiTransport>: ~20 bytes
- AtProcessor: ~2KB (response slots + channels)
- WiFiManager: ~8 bytes
- NetworkDevice: ~20KB (socket pool with buffers)
- TlsManager: ~8 bytes
- Driver: ~32 bytes

Total: ~22KB
```

### Buffer Configuration

| Buffer | Default Size | Configurable | Purpose |
|--------|-------------|--------------|---------|
| SPI RX | 4096 bytes | ✅ via Config | SPI read operations |
| Socket RX | 2048 bytes × 8 | ✅ via Config | Per-socket received data |
| Multi-response | 512 bytes × 32 | Fixed | Collecting scan results |
| WiFi events | 4 slots | Fixed | WiFi state changes |
| Socket events | 16 slots | Fixed | Socket notifications |
| IPD data | 2048 bytes × 4 | Fixed | Received socket data |

**Total RAM**: ~45-50KB

## Concurrency Model

### Background Tasks

**RX Processor Task** (`processor.rx_task()`):
- Continuously reads from SPI
- Parses AT responses line-by-line
- Routes to handlers
- Switches to binary mode for +IPD

**IPD Processor Task** (`network.ipd_processor_task()`):
- Monitors IPD data channel
- Routes data to socket buffers

**User Tasks**:
- Application code using async APIs
- Cooperative multitasking via Embassy

### Synchronization

- **CriticalSectionRawMutex**: For all sync primitives
- Lock-free where possible (atomics for link state)
- No busy-waiting (all waits are async)

## API Usage Patterns

### WiFi Connection

```rust
// Initialize
driver.init_wifi(WiFiMode::Station).await?;

// Scan
let results = driver.wifi_scan().await?;

// Connect
driver.wifi_connect("SSID", "password").await?;

// Get IP
let ip_config = driver.get_ip_config().await?;
```

### TCP Socket

```rust
let device = driver.network_device();

// Allocate socket
let socket_id = device.allocate_socket(SocketProtocol::Tcp).await?;

// Connect
device.connect_socket(spi, socket_id, "example.com", 80, timeout).await?;

// Send
device.send_socket(spi, socket_id, data, timeout).await?;

// Receive
let n = device.receive_socket(spi, socket_id, buffer, timeout).await?;

// Close
device.close_socket(spi, socket_id, timeout).await?;
```

### HTTP Request

```rust
let http = driver.http_client();

// GET
let response = http.get(spi, "https://api.example.com/data").await?;

// POST
let response = http.post(spi, "https://api.example.com/endpoint", body).await?;
```

### MQTT

```rust
let mqtt = driver.mqtt_client(0);

// Connect
let mut config = MqttConfig::default();
config.client_id.push_str("my_device").unwrap();
mqtt.connect(spi, "broker.hivemq.com", 1883, &config).await?;

// Subscribe
mqtt.subscribe(spi, "topic/test", MqttQos::AtLeastOnce).await?;

// Publish
mqtt.publish(spi, "topic/test", "Hello", MqttQos::AtLeastOnce, false).await?;
```

## Porting Guide

### From FreeRTOS Driver

Embassy replacements:

| FreeRTOS | Embassy |
|----------|---------|
| `xQueueCreate` | `Channel::new()` |
| `xSemaphoreCreateBinary` | `Signal::new()` |
| `xTaskCreate` | `spawner.spawn()` |
| `vTaskDelay` | `Timer::after().await` |

### API Mapping

Similar high-level API:

```c
// C API
w6x_wifi_connect("SSID", "pwd");

// Rust API
driver.wifi_connect("SSID", "pwd").await?;
```

## Contributing

Maintain:
- No-std compatibility
- No heap allocation
- Async APIs
- Comprehensive error handling
- Tests for parsing logic
- Examples for features