mirror of
https://github.com/hathach/tinyusb.git
synced 2025-12-01 12:24:17 +00:00
283 lines
8.6 KiB
ReStructuredText
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
|