# FreeRTOS Task Architecture

## Kernel Configuration

| Parameter | Value |
|-----------|-------|
| FreeRTOS Version | 10.0.0 |
| Scheduling | Cooperative (non-preemptive) |
| Tick Rate | 1000 Hz (1 ms tick) |
| Heap Size | 11.5 KB |
| Memory Allocator | libc malloc/free |
| Max Task Count | 12 application tasks + idle |

**Config file:** `src/config/FreeRTOSConfig.h`

## Task List

| Task ID | Name | Stack Size | Priority | Purpose |
|---------|------|------------|----------|---------|
| `taskid_USBLoad` | USB Load | — | — | USB audio data upload to host |
| `taskid_HID_Command` | HID Command | — | — | Process incoming HID feature reports |
| `taskid_HID_Report` | HID Report | — | — | Send periodic telemetry reports |
| `taskid_I2C` | I2C | — | — | I2C transaction management |
| `taskid_TIMED_START` | Timed Start | — | — | Sequenced power-on operations |
| `taskid_ADC` | ADC | — | — | CC pin and temperature ADC sampling |
| `taskid_LED` | LED | — | — | RGB LED animation (breathing) |
| `taskid_FAN` | FAN | — | — | Fan PWM control with soft start |
| `taskid_video_proc` | Video Proc | 1024 bytes | Idle | Display state machine, VXR management |
| `taskid_USART` | USART | — | — | Serial debug output |
| `taskid_IDLE` | Idle | — | — | FreeRTOS idle task |
| `taskid_Tmr_Svc` | Timer Service | — | — | FreeRTOS software timer callbacks |

## Cooperative Scheduling

The firmware uses **cooperative scheduling** (`configUSE_PREEMPTION = 0`). Tasks voluntarily yield the CPU by:
- Calling `taskYIELD()`
- Blocking on a semaphore, queue, or notification
- Calling `vTaskDelay()` or `vTaskDelayUntil()`

This simplifies concurrency but requires careful design to avoid any task monopolizing the CPU.

## I2C Synchronization

I2C is the most contention-prone resource, with multiple tasks needing bus access:

### Evolution of I2C Handling

| Version | Approach | Issues |
|---------|----------|--------|
| Pre-v0.3.7 | Busy-wait polling | Proximity sensor glitches (missed RXRDY interrupt, STOP bit not set in time) |
| v0.3.7D | FreeRTOS scheduling disabled during I2C | Fixed proximity but corrupted microphone audio (USB upload task starved) |
| v0.3.7E | Interrupt-driven I2C + FreeRTOS semaphores | Fixed both proximity and microphone issues |
| v0.3.9 | Reduced I2C interrupt priority | Fixed occasional display blackouts when changing brightness (higher-priority threads were clobbering lower-priority I2C transactions) |

### Current Design (v0.3.9+)

- **Two I2C instances:**
  - DDIC I2C (FLEXCOM 1): Display driver IC bus @ 100 kHz
  - MCU I2C (FLEXCOM 4): Peripheral bus @ 100 kHz (OLED, FPGA, USB hub, proximity)
- **Interrupt-driven:** I2C peripheral generates interrupts for TXRDY, RXRDY, TXCOMP
- **Semaphore-based:** Tasks block on a binary semaphore while waiting for I2C completion
- **Mutex protection:** Each I2C instance has a FreeRTOS mutex to serialize access across tasks
- **Reduced interrupt priority:** I2C interrupts set below FreeRTOS ceiling to prevent kernel API corruption

## Task Notifications

The video processing task uses FreeRTOS task notifications extensively as a lightweight event mechanism:

| Notification Bit | Purpose |
|------------------|---------|
| Bit 0 | 1.0V rail ready |
| Bit 1 | 1.8V + OLED power ready |
| Bit 2 | VXR reset requested |
| Bit 3 | Debug proximity disabled |
| Bit 4 | Colorbar test requested |
| Bit 5 | Display power disable |
| Bit 6 | Display power enable |
| Bit 7 | New fan speed (deferred) |
| Bit 8 | Eye-tracking overcurrent error |
| Bit 9 | Eye-tracking error cleared |
| Bit 10 | Tundra UART activity |
| Bit 11 | VXR power down |
| Bit 12 | VXR power up |
| Bit 20 | Stack overflow detected |

## Flash Access Serialization

Flash operations (user signature reads/writes and EEPROM emulation) are protected by a dedicated FreeRTOS mutex, separate from the I2C mutexes:

- `flash_mutex_take()` — acquire before any Flash operation
- `flash_mutex_give()` — release after operation completes

This prevents corruption if multiple tasks attempt Flash access simultaneously.

## USB Start-of-Frame

The USB controller generates a Start-of-Frame interrupt every 1 ms. The `main_sof_action()` callback is used for LED management and other periodic housekeeping.

## Stack Monitoring

All task stack watermarks can be queried via HID command `s` to detect tasks approaching overflow. The `scripts/stack_monitor.py` tool provides real-time visualization.
