Files
tinyusb/docs/reference/architecture.rst
2025-11-11 10:53:39 +07:00

283 lines
8.6 KiB
ReStructuredText

************
Architecture
************
This document explains TinyUSB's internal architecture, design principles, and how different components work together.
Design Principles
=================
Memory Safety
-------------
TinyUSB is designed for resource-constrained embedded systems with strict memory requirements:
TinyUSB uses **no dynamic allocation** - all memory is statically allocated at compile time for predictability. All buffers have bounded, compile-time defined sizes to prevent overflow issues. The TinyUSB core avoids heap allocation, resulting in **predictable memory usage** where consumption is fully deterministic.
Thread Safety
-------------
TinyUSB achieves thread safety through a deferred interrupt model:
- **ISR deferral**: USB interrupts are captured and deferred to task context
- **Single-threaded processing**: All USB protocol handling occurs in task context
- **Queue-based design**: Events are queued from ISR and processed in ``tud_task()``
- **RTOS integration**: Proper semaphore/mutex usage for shared resources
Portability
-----------
The stack is designed to work across diverse microcontroller families:
- **Hardware abstraction**: MCU-specific code isolated in portable drivers
- **OS abstraction**: RTOS dependencies isolated in OSAL layer
- **Modular design**: Features can be enabled/disabled at compile time
- **Standard compliance**: Strict adherence to USB specifications
Core Architecture
=================
Layer Structure
---------------
TinyUSB follows a layered architecture from hardware to application:
.. figure:: ../assets/stack.svg
:width: 500px
:align: left
:alt: stackup
.. raw:: html
<div class="clear-both"></div>
Component Overview
------------------
- **Application Layer**: Your main application code that uses TinyUSB APIs.
- **Class Drivers**: Implement specific USB device classes (CDC, HID, MSC, etc.) and handle class-specific requests.
- **Device/Host Core**: Implements USB protocol state machines, endpoint management, and core USB functionality.
- **OS Abstraction**: Provides threading primitives and synchronization for different RTOS environments.
- **Device/Host Controller Driver**: drivers that interface with MCU USB peripherals. Several MCUs may share a common driver.
Device Stack Architecture
=========================
This section is concerned with the **Device Stack**, i.e., the component of TinyUSB used in USB devices (that talk to a USB host).
Core Components
---------------
**Device Controller Driver (DCD)**:
- MCU-specific USB device peripheral driver
- Handles endpoint configuration and data transfers
- Abstracts hardware differences between MCU families
- Located in ``src/portable/VENDOR/USBIP/``
**USB Device Core (USBD)**:
- Implements USB device state machine
- Handles standard USB requests (Chapter 9)
- Manages device configuration and enumeration
- Located in ``src/device/``
**Class Drivers**:
- Implement USB class specifications
- Handle class-specific requests and data transfer
- Provide application APIs
- Located in ``src/class/*/``
Data Flow
---------
**Control Transfers (Setup Requests)**:
.. code-block:: none
USB Bus → DCD → USBD Core → Class Driver → Application
Standard requests handled in core
Class-specific requests → Class Driver
**Data Transfers**:
.. code-block:: none
Application → Class Driver → USBD Core → DCD → USB Bus
USB Bus → DCD → USBD Core → Class Driver → Application
Event Processing
----------------
TinyUSB uses a deferred interrupt model for thread safety:
1. **Interrupt Occurs**: USB hardware generates interrupt
2. **ISR Handler**: ``dcd_int_handler()`` captures event, minimal processing
3. **Event Queuing**: Events queued for later processing
4. **Task Processing**: ``tud_task()`` (called by application code) processes queued events
5. **Callback Execution**: Application callbacks executed in task context
.. code-block:: none
USB IRQ → ISR → Event Queue → tud_task() → Class Callbacks → Application
Host Stack Architecture
=======================
This section is concerned with the **Host Stack**, i.e., the component of TinyUSB used in USB hosts, managing connected USB devices.
Core Components
---------------
**Host Controller Driver (HCD)**:
- MCU-specific USB host peripheral driver
- Manages USB pipes and data transfers
- Handles host controller hardware
- Located in ``src/portable/VENDOR/FAMILY/``
**USB Host Core (USBH)**:
- Implements USB host functionality
- Manages device enumeration and configuration
- Handles pipe management and scheduling
- Located in ``src/host/``
**Hub Driver**:
- Manages USB hub devices
- Handles port management and device detection
- Supports multi-level hub topologies
- Located in ``src/host/``
Device Enumeration
------------------
The host stack follows USB enumeration process:
1. **Device Detection**: Hub or root hub detects device connection
2. **Reset and Address**: Reset device, assign unique address
3. **Descriptor Retrieval**: Get device, configuration, and class descriptors
4. **Driver Matching**: Find appropriate class driver for device
5. **Configuration**: Configure device and start communication
6. **Class Operation**: Normal class-specific communication
.. code-block:: none
Device Connect → Reset → Get Descriptors → Load Driver → Configure → Operate
Class Architecture
==================
Common Class Structure
----------------------
All USB classes follow a similar architecture:
**Device Classes**:
- ``*_device.c``: Device-side implementation
- ``*_device.h``: Device API definitions
- Implement class-specific descriptors
- Handle class requests and data transfer
**Host Classes**:
- ``*_host.c``: Host-side implementation
- ``*_host.h``: Host API definitions
- Manage connected devices of this class
- Provide application interface
Class Driver Interface
----------------------
See ``usbd.c``.
**Required Functions**:
- ``init()``: Initialize class driver
- ``reset()``: Reset class state
- ``open()``: Configure class endpoints
- ``control_xfer_cb()``: Handle control requests
- ``xfer_cb()``: Handle data transfer completion
**Optional Functions**:
- ``close()``: Clean up class resources
- ``deinit()``: Deinitialize class driver
- ``sof()``: Start-of-frame processing
- ``xfer_isr()``: Called from USB ISR context on transfer completion. Data will get queued for ``xfer_cb()`` only if this returns ``false``.
Descriptor Management
---------------------
Each class is responsible for:
- **Interface Descriptors**: Define class type and endpoints
- **Class-Specific Descriptors**: Additional class requirements
- **Endpoint Descriptors**: Define data transfer characteristics
Memory Management
=================
Static Allocation Model
-----------------------
TinyUSB uses only static memory allocation; it allocates fixed-size endpoint buffers for each configured endpoint, static buffers for class-specific data handling, a fixed buffer dedicated to control transfers, and static event queues for deferred interrupt processing.
Buffer Management
-----------------
**Endpoint Buffers**:
- Allocated per endpoint at compile time
- Size defined by ``CFG_TUD_*_EP_BUFSIZE`` macros
- Used for USB data transfers
**FIFO Buffers**:
- Ring buffers for streaming data
- Size defined by ``CFG_TUD_*_RX/TX_BUFSIZE`` macros
- Separate read/write pointers
Threading Model
===============
Task-Based Design
-----------------
TinyUSB uses a cooperative task model; it provides main tasks - ``tud_task()`` for device and ``tuh_task()`` for host operation. These tasks must be called regularly (typically less than 1ms intervals) to ensure all USB events are processed in task context, where application callbacks also execute.
RTOS Integration
----------------
**Bare Metal**:
- Application calls ``tud_task()`` in main loop
- No threading primitives needed
- Simplest integration method
**FreeRTOS**:
- USB task runs at high priority
- Semaphores used for synchronization
- Queue for inter-task communication
**Other RTOS**:
- Similar patterns with RTOS-specific primitives
- OSAL layer abstracts RTOS differences
Interrupt Handling
------------------
**Interrupt Service Routine**:
- Minimal processing in ISR
- Event capture and queuing only
- Quick return to avoid blocking
**Deferred Processing**:
- All complex processing in task context
- Thread-safe access to data structures
- Application callbacks in known context
Memory Usage Patterns
---------------------
**Flash Memory**:
- Core stack: 8-15KB depending on features
- Each class: 1-4KB additional
- Portable driver: 2-8KB depending on MCU
**RAM Usage**:
- Core stack: 1-2KB
- Endpoint buffers: User configurable
- Class buffers: Depends on configuration