78/uart-uhci

0.2.1

Latest
uploaded 2 days ago
UART UHCI DMA Controller for ESP32

readme

# uart-uhci

基于 ESP32 UHCI + GDMA 的 UART DMA 接收控制器组件。使用预分配缓冲区池和 GDMA owner 机制实现持续接收,支持按需启动/停止 DMA 以配合低功耗(如释放 PM 锁)。

## 特性

- **UHCI + GDMA**:通过 UHCI 控制器将 UART 与 GDMA 连接,实现 DMA 接收
- **缓冲区池**:预分配多块 DMA 缓冲区,每块填满或 UART 空闲时触发回调
- **Idle EOF**:使用 UHCI 空闲 EOF 模式,在 UART 线空闲时结束当前 DMA 传输
- **Owner 机制**:通过 GDMA 描述符 owner 管理缓冲区归属,用户处理完后调用 `ReturnBuffer` 归还,DMA 自动继续使用
- **溢出恢复**:当所有缓冲区被 CPU 占用时 DMA 暂停并触发 `OverflowCallback`,全部归还后可自动重新挂载并恢复
- **PM 锁**:接收期间持有 PM 锁(若启用 `CONFIG_PM_ENABLE`),停止接收时释放,便于配合 light sleep
- **发送**:TX 使用标准 UART FIFO 同步写入(不占用额外 GDMA 通道)

## 依赖

- ESP-IDF >= 5.5.2
- 依赖组件:`esp_pm`、`esp_mm`、`esp_driver_uart`

## 配置结构

```c
// 缓冲区池配置
BufferPoolConfig rx_pool;
rx_pool.buffer_count = 4;   // 至少 2,建议 4 及以上
rx_pool.buffer_size  = 256; // 每块缓冲区字节数

// 总配置
UartUhci::Config config = {};
config.uart_port      = UART_NUM_1;
config.dma_burst_size = 16;  // 或 0 使用默认
config.rx_pool        = rx_pool;
```

## 基本用法

1. **创建并初始化**

```cpp
UartUhci uhci;
UartUhci::Config config = {};
config.uart_port      = UART_NUM_1;
config.dma_burst_size = 16;
config.rx_pool        = { .buffer_count = 4, .buffer_size = 256 };

esp_err_t err = uhci.Init(config);
```

2. **注册回调(必须在 StartReceive 之前)**

```cpp
// 每块缓冲区接收完成时调用(在 ISR 上下文,需尽快返回)
bool on_rx(const UartUhci::RxEventData& data, void* user_data) {
    // 使用 data.buffer->data, data.recv_size 处理数据
    // 处理完后必须归还:
    uhci.ReturnBuffer(data.buffer);
    return false; // true 表示需要 yield
}
uhci.SetRxCallback(on_rx, nullptr);

// 可选:缓冲区耗尽导致 DMA 暂停时调用
void on_overflow(void* user_data) {
    // 尽快处理并归还缓冲区,或记录溢出
}
uhci.SetOverflowCallback(on_overflow, nullptr);
```

3. **启动/停止接收**

```cpp
uhci.StartReceive();  // 开始 DMA 接收,持有 PM 锁
// ...
uhci.StopReceive();   // 停止 DMA,释放 PM 锁
```

4. **发送数据**

```cpp
uint8_t msg[] = "hello";
uhci.Transmit(msg, sizeof(msg) - 1);
```

5. **反初始化**

```cpp
uhci.Deinit();
```

## 注意事项

- **缓冲区数量**:`buffer_count` 至少为 2;过小在数据处理稍慢时容易触发溢出(所有缓冲区被 CPU 占用,DMA 暂停)。
- **回调上下文**:`RxCallback` 与 `OverflowCallback` 在 ISR 中执行,应避免阻塞和复杂逻辑,处理完后尽快 `ReturnBuffer`。
- **必须归还**:每块通过 `RxCallback` 拿到的缓冲区都必须调用 `ReturnBuffer(buffer)`,否则会导致缓冲区耗尽和 DMA 暂停。
- **溢出恢复**:发生溢出后,当所有缓冲区都被归还时,组件会清空 UART RX FIFO 并重新挂载 DMA,无需额外调用。
- **UART 初始化**:波特率、引脚等需在外部用 `uart_driver_install` / 驱动接口先配置好;本组件只负责 UHCI/GDMA 接收与发送数据到已有 UART。

## 许可证

Apache-2.0

Links

Supports all targets

License: Apache-2.0

To add this component to your project, run:

idf.py add-dependency "78/uart-uhci^0.2.1"

download archive

Stats

  • Archive size
    Archive size ~ 10.68 KB
  • Downloaded in total
    Downloaded in total 8.0k times
  • Downloaded this version
    This version: 4.1k times

Badge

78/uart-uhci version: 0.2.1
|