Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions doc-dev/other/flashing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Firmware Flashing Implementation

This directory contains documentation for implementing autonomous module firmware flashing on the UHK right half.

## Goal

Move K-boot protocol implementation from the Agent (desktop tool) to the right half firmware, enabling autonomous module firmware updates without Agent involvement in the flashing process.

## Documentation Files

| File | Description |
|------|-------------|
| [configuration-buffer.md](configuration-buffer.md) | Config buffer APIs and memory layout |
| [usb-communication.md](usb-communication.md) | USB command infrastructure |
| [module-communication.md](module-communication.md) | I2C/UART slave scheduler and module discovery |
| [kboot-protocol.md](kboot-protocol.md) | K-boot protocol details for porting |

## Current Architecture

```
┌─────────────┐ USB ┌─────────────┐ I2C ┌─────────────┐
│ Agent │ ────────────────▶│ Right Half │ ───────────────▶│ Module │
│ (Desktop) │ │ (Buspal) │ │ (Bootloader)│
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
│ K-boot protocol │ Forward packets │
│ implementation │ transparently │
│ │ │
```

**Problem**: K-boot protocol logic is in the Agent. Right half only forwards packets.

## Target Architecture

```
┌─────────────┐ USB ┌─────────────┐ I2C ┌─────────────┐
│ Agent │ ────────────────▶│ Right Half │ ───────────────▶│ Module │
│ (Desktop) │ │ (K-boot) │ │ (Bootloader)│
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
│ Upload firmware │ K-boot protocol │
│ binary only │ implementation │
│ │ │
```

**Goal**: Agent uploads firmware binary. Right half handles K-boot protocol.

## Two-Phase Implementation

### Phase 1: USB Transfer to Right Half

1. Analyze existing configuration buffer APIs (see [configuration-buffer.md](configuration-buffer.md))
2. Design firmware upload protocol
3. Implement chunked USB transfer (similar to config write)
4. Store firmware in staging buffer or stream directly

### Phase 2: Right Half to Module

1. Port K-boot protocol from Agent (see [kboot-protocol.md](kboot-protocol.md))
2. Implement I2C transport layer
3. Implement flashing state machine:
- Reboot module to bootloader
- Erase flash
- Write firmware chunks
- Verify and reset

## Proposed USB Commands

| Command | ID | Description |
|---------|-----|-------------|
| StartModuleFirmwareUpload | 0x20 | Begin firmware upload (module ID, size) |
| WriteModuleFirmwareChunk | 0x21 | Write firmware data chunk |
| FlashModule | 0x22 | Start flashing (uses uploaded firmware) |
| GetFlashingStatus | 0x23 | Query flashing progress |
| AbortFlashing | 0x24 | Cancel flashing operation |

## Key Challenges

1. **Memory**: Module firmware (~40-60 KB) exceeds config buffer (~32 KB)
- Solution: Stream directly to module, or use UHK80 external flash

2. **Timing**: I2C transfers while maintaining keyboard responsiveness
- Solution: Use slave scheduler, low priority for flashing

3. **Error Recovery**: Handle I2C failures, power loss during flash
- Solution: Verify writes, implement retry logic

4. **State Management**: Track flashing progress across multiple USB commands
- Solution: Implement state machine with persistent state

## Technical Constraints

- Firmware must fit in available RAM or be streamed
- K-boot protocol requires both I2C and UART support
- Must handle communication failures gracefully
- Module must remain functional if flashing fails

## Success Criteria

- [ ] Firmware can be uploaded to right half via USB
- [ ] Right half can autonomously flash connected module
- [ ] No dependency on Agent for K-boot protocol execution
- [ ] Agent only uploads firmware binary, doesn't manage flashing
141 changes: 141 additions & 0 deletions doc-dev/other/flashing/configuration-buffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Configuration Buffer APIs

This document describes the user configuration buffer system that could potentially be used for firmware image storage during module flashing.

## Buffer Architecture

The firmware uses a **three-buffer system** for configuration management:

```c
typedef enum {
ConfigBufferId_HardwareConfig,
ConfigBufferId_StagingUserConfig,
ConfigBufferId_ValidatedUserConfig,
} config_buffer_id_t;
```

### Memory Sizes

| Platform | Hardware Config | User Config |
|----------|----------------|-------------|
| UHK60 | 64 bytes | 32,704 bytes |
| UHK80 | 64 bytes | 32,768 bytes |

**Note**: Module firmware images are typically 40-60 KB for UHK60 modules, which exceeds the current user config buffer capacity. Alternative storage strategies may be needed.

## Core Data Structures

### Buffer Structure

From `right/src/config_parser/basic_types.h`:

```c
typedef struct {
bool isValid; // Flag indicating if buffer contains valid configuration
uint8_t *buffer; // Pointer to raw byte buffer
uint16_t offset; // Current read/write position for parsing
} config_buffer_t;
```

### Buffer Instances

From `right/src/config_parser/config_globals.c`:

```c
config_buffer_t HardwareConfigBuffer;
config_buffer_t StagingUserConfigBuffer;
config_buffer_t ValidatedUserConfigBuffer;
```

## Key Functions

### Buffer Access

```c
// Get buffer descriptor from ID
config_buffer_t* ConfigBufferIdToConfigBuffer(config_buffer_id_t configBufferId);

// Get buffer size
uint16_t ConfigBufferIdToBufferSize(config_buffer_id_t configBufferId);

// Validate buffer ID
bool IsConfigBufferIdValid(config_buffer_id_t configBufferId);
```

### Parsing Primitives

From `right/src/config_parser/basic_types.h`:

```c
uint8_t ReadUInt8(config_buffer_t *buffer);
uint16_t ReadUInt16(config_buffer_t *buffer);
uint32_t ReadUInt32(config_buffer_t *buffer);
```

## USB Read/Write APIs

### Read Config Command

**File**: `right/src/usb_commands/usb_command_read_config.c`

**Protocol**:
- Byte 0: Command (0x04)
- Byte 1: Config buffer ID
- Byte 2: Length to read (max 62 bytes)
- Bytes 3-4: Offset (little-endian uint16)
- Response: [Status(1)] [Data(length)]

### Write Config Command

**File**: `right/src/usb_commands/usb_command_write_config.c`

**Protocol**:
- Byte 0: Command (0x05 or 0x06)
- Byte 1: Length to write
- Bytes 2-3: Offset (little-endian uint16)
- Bytes 4+: Data to write (max 59 bytes per packet)

## Storage Operations

### UHK60 - EEPROM

**File**: `right/src/eeprom.c`

```c
status_t EEPROM_LaunchTransfer(storage_operation_t operation,
config_buffer_id_t configBufferId,
void (*successCallback));
```

- I2C-based EEPROM at 100 kHz (I2C1 at 1 MHz)
- 64-byte page writes
- Sequential page writes with callbacks

### UHK80 - Flash

**File**: `device/src/flash.c`

```c
uint8_t Flash_LaunchTransfer(storage_operation_t operation,
config_buffer_id_t configBufferId,
void (*successCallback));
```

- Flash area API with 4K alignment
- Erase before write required

## Implications for Firmware Storage

Current configuration buffer capacity (~32 KB) is insufficient for typical module firmware images (~40-60 KB). Options include:

1. **Streaming approach**: Transfer firmware in chunks directly to module without storing in RAM
2. **External storage**: Use separate flash region on UHK80
3. **Multiple transfers**: Split firmware and transfer in multiple sessions

## Key Source Files

- `right/src/config_manager.h` - Runtime config struct
- `right/src/config_parser/config_globals.h` - Buffer types & IDs
- `right/src/config_parser/basic_types.h` - Parsing primitives
- `right/src/eeprom.c` - UHK60 storage
- `device/src/flash.c` - UHK80 storage
Loading