Rust嵌入式USB设备驱动库embassy-usb-synopsys-otg的使用,支持Synopsys OTG控制器的高性能USB协议栈开发
Rust嵌入式USB设备驱动库embassy-usb-synopsys-otg的使用
简介
embassy-usb-synopsys-otg是一个专为Synopsys USB OTG核心设备设计的Embassy USB驱动库。它实现了embassy-usb-driver
的通用功能,适用于所有使用Synopsys OTG IP的芯片。
该库包含驱动程序的"核心"部分,这些是所有使用Synopsys OTG IP的芯片共通的代码,但不包含芯片特定的初始化代码(如时钟设置和GPIO复用)。通常情况下,开发者不会直接使用这个库,而是通过硬件抽象层(HAL)来使用它。
支持的HAL列表
embassy-stm32
:支持STMicroelectronics STM32系列芯片esp-hal
:支持Espressif ESP32系列芯片
如需将此库集成到您设备的HAL中,需要添加设备特定的初始化代码。可以参考上述HAL库的实现方式。
安装方法
在项目目录中运行以下命令:
cargo add embassy-usb-synopsys-otg
或在Cargo.toml中添加:
embassy-usb-synopsys-otg = "0.3.0"
完整示例
以下是基于STM32 HAL的完整示例代码:
use embassy_stm32::{
peripherals::USB_OTG_FS,
usb_otg::{Driver, Config},
time::Hertz,
Config as StmConfig,
};
use embassy_usb::{
driver::EndpointError,
Builder, UsbDevice,
};
use embassy_usb_class::cdc_acm::{CdcAcmClass, State};
// USB配置参数
const USB_CONFIG: Config = Config {
usb_speed: embassy_stm32::usb_otg::UsbSpeed::FullSpeed,
pin_dm: None,
pin_dp: None,
};
#[embassy_executor::task]
async fn usb_task(driver: Driver<'static, USB_OTG_FS>) {
// 缓冲区分配
let mut device_descriptor = [0; 256];
let mut config_descriptor = [0; 256];
let mut bos_descriptor = [0; 256];
let mut control_buf = [0; 64];
// CDC ACM类初始化
let state = State::new();
// USB设备构建
let mut builder = Builder::new(
driver,
&mut device_descriptor,
&mut config_descriptor,
&mut bos_descriptor,
&mut control_buf,
);
// 添加CDC ACM类
let mut class = CdcAcmClass::new(&mut builder, state, 64);
// 构建USB设备
let mut usb = builder.build();
// 运行USB设备
let mut usb_fut = usb.run();
// 事件处理循环
loop {
embassy_futures::select::select(
usb_fut,
class.wait_connection(),
).await;
}
}
#[embassy_executor::main]
async fn main(spawner: embassy_executor::Spawner) {
// 硬件初始化
let p = embassy_stm32::init(StmConfig::default());
// USB驱动初始化
let driver = Driver::new(p.USB_OTG_FS, USB_CONFIG);
// 启动USB任务
spawner.spawn(usb_task(driver)).unwrap();
// 主循环
loop {
embassy_time::Timer::after(embassy_time::Duration::from_secs(1)).await;
}
}
代码说明
-
硬件配置部分:
- 使用
embassy_stm32::init
初始化STM32硬件 - 配置USB OTG驱动的工作模式和参数
- 使用
-
USB任务部分:
- 分配必要的缓冲区
- 初始化CDC ACM类(模拟串口)
- 构建USB设备描述符
- 运行USB设备并处理事件
-
主程序部分:
- 初始化硬件和USB驱动
- 启动独立的USB任务
- 运行主程序循环
注意事项
- 示例基于STM32平台,移植到其他平台需调整初始化代码
- 实际项目需根据需求配置USB描述符
- 需要完善错误处理机制
- 缓冲区大小应根据实际需求调整
许可证信息
本库采用MIT或Apache-2.0双许可证。
1 回复
embassy-usb-synopsys-otg - Rust嵌入式USB设备驱动库
简介
embassy-usb-synopsys-otg
是一个用于嵌入式系统的Rust USB协议栈库,专门支持Synopsys OTG控制器。它是Embassy嵌入式异步运行时生态系统的一部分,提供了高性能的USB设备功能实现。
这个库特别适合需要在嵌入式设备上实现USB功能的开发者,支持多种USB设备类(Device Classes)和自定义功能。
主要特性
- 支持Synopsys OTG控制器
- 异步API设计
- 支持多种USB设备类(HID, CDC, MSC等)
- 可自定义设备描述符
- 低内存占用
- 与Embassy运行时无缝集成
使用方法
添加依赖
首先在Cargo.toml中添加依赖:
[dependencies]
embassy-usb-synopsys-otg = "0.1"
embassy-executor = "0.1"
embassy-time = { version = "0.1", features = ["time-driver"] }
基本示例
以下是一个简单的USB设备初始化示例:
use embassy_executor::Spawner;
use embassy_usb_synopsys_otg::Driver;
use embassy_usb_synopsys-otg::Builder;
use embassy_usb_synopsys-otg::Config;
#[embassy_executor::main]
async fn main(spawner: Spawner) {
// 初始化硬件
let p = embassy_stm32::init(Default::default());
// 创建USB驱动
let driver = Driver::new(
p.USB_OTG_HS,
p.PA12,
p.PA11,
&mut embassy_stm32::usb_otg_hs::CONFIG,
);
// 配置USB设备
let mut config = Config::new();
config.manufacturer = Some("Embassy");
config.product = Some("USB example");
config.serial_number = Some("12345678");
config.max_power = 100;
config.max_packet_size_0 = 64;
// 创建设备构建器
let mut builder = Builder::new(
driver,
config,
&mut [0; 256], // 描述符缓冲区
);
// 这里可以添加各种USB功能类
// builder.hid(...);
// builder.cdc(...);
// 构建USB设备
let usb = builder.build();
// 运行USB任务
spawner.spawn(usb_task(usb)).unwrap();
// 主应用逻辑...
}
#[embassy_executor::task]
async fn usb_task(usb: embassy_usb_synopsys-otg::UsbDevice<'static, Driver<'static>>) {
usb.run().await;
}
完整HID设备示例
下面是一个完整的HID键盘设备实现示例:
use embassy_executor::Spawner;
use embassy_usb_synopsys_otg::{Driver, Builder, Config};
use embassy_usb_synopsys_otg::class::hid::{HID, HidReaderWriter, HIDConfig, KeyboardReport};
use embassy_time::Timer;
#[embassy_executor::main]
async fn main(spawner: Spawner) {
// 初始化硬件
let p = embassy_stm32::init(Default::default());
// 创建USB驱动
let driver = Driver::new(
p.USB_OTG_HS,
p.PA12,
p.PA11,
&mut embassy_stm32::usb_otg_hs::CONFIG,
);
// 配置USB设备
let mut config = Config::new();
config.manufacturer = Some("Embassy");
config.product = Some("HID Keyboard");
config.serial_number = Some("12345678");
config.max_power = 100;
config.max_packet_size_0 = 64;
// 创建设备构建器
let mut builder = Builder::new(
driver,
config,
&mut [0; 256],
);
// 添加HID功能类
let hid = HID::new(&mut builder, HIDConfig {
report_descriptor: KeyboardReport::desc(),
request_handler: None,
poll_ms: 60,
max_packet_size: 64,
});
let hid = hid.into_reader_writer().unwrap();
// 构建USB设备
let usb = builder.build();
// 启动任务
spawner.spawn(usb_task(usb)).unwrap();
spawner.spawn(hid_task(hid)).unwrap();
}
#[embassy_executor::task]
async fn usb_task(usb: embassy_usb_synopsys_otg::UsbDevice<'static, Driver<'static>>) {
usb.run().await;
}
#[embassy_executor::task]
async fn hid_task(mut hid: HidReaderWriter<'static, Driver<'static>>) {
let mut report = KeyboardReport {
modifier: 0,
reserved: 0,
leds: 0,
keycodes: [0; 6],
};
// 模拟按键按下/释放
loop {
// 按下A键
report.keycodes[0] = 0x04; // HID usage code for 'a'
// 发送按键按下报告
hid.write(&report).await.ok();
Timer::after_millis(100).await;
// 释放所有按键
report.keycodes[0] = 0x00;
hid.write(&report).await.ok();
Timer::after_secs(1).await;
}
}
完整CDC串口设备示例
下面是一个完整的USB CDC ACM(串口)设备实现示例:
use embassy_executor::Spawner;
use embassy_usb_synopsys_otg::{Driver, Builder, Config};
use embassy_usb_synopsys_otg::class::cdc_acm::CdcAcmClass;
use embassy_time::Timer;
#[embassy_executor::main]
async fn main(spawner: Spawner) {
// 初始化硬件
let p = embassy_stm32::init(Default::default());
// 创建USB驱动
let driver = Driver::new(
p.USB_OTG_HS,
p.PA12,
p.PA11,
&mut embassy_stm32::usb_otg_hs::CONFIG,
);
// 配置USB设备
let mut config = Config::new();
config.manufacturer = Some("Embassy");
config.product = Some("CDC Serial");
config.serial_number = Some("12345678");
config.max_power = 100;
config.max_packet_size_0 = 64;
// 创建设备构建器
let mut builder = Builder::new(
driver,
config,
&mut [0; 256],
);
// 添加CDC功能类
let cdc = CdcAcmClass::new(&mut builder, 64);
// 构建USB设备
let usb = builder.build();
// 启动任务
spawner.spawn(usb_task(usb)).unwrap();
spawner.spawn(cdc_task(cdc)).unwrap();
}
#[embassy_executor::task]
async fn usb_task(usb: embassy_usb_synopsys_otg::UsbDevice<'static, Driver<'static>>) {
usb.run().await;
}
#[embassy_executor::task]
async fn cdc_task(mut cdc: CdcAcmClass<'static, Driver<'static>>) {
let mut buf = [0; 64];
// 发送欢迎消息
cdc.write(b"USB CDC Serial Device Ready!\r\n").await.ok();
loop {
// 读取数据
let n = match cdc.read(&mut buf).await {
Ok(n) => n,
Err(_) => continue,
};
if n > 0 {
// 回显接收到的数据
cdc.write(&buf[..n]).await.ok();
// 添加换行符
if buf[n-1] != b'\n' {
cdc.write(b"\r\n").await.ok();
}
}
Timer::after_millis(10).await;
}
}
高级配置
自定义描述符
use embassy_usb_synopsys_otg::descriptor::*;
let mut builder = /* ... */;
builder.device(
&[
DeviceDescriptor::new(0x0200, 0xff, 0xff, 0, 64, 0x1234, 0x5678, 0x0100, 1, 2, 3, 1),
// 接口、端点等描述符...
],
&[
&langid::ENGLISH_US,
// 其他字符串描述符...
],
);
电源管理
// 在Config中配置电源相关参数
let mut config = Config::new();
config.max_power = 500; // 500mA
config.self_powered = true;
注意事项
- 需要根据具体硬件调整引脚和USB控制器配置
- 描述符缓冲区大小需要足够容纳所有描述符
- 不同的STM32系列可能有不同的USB外设实现
- 在低功耗应用中需要考虑USB挂起/恢复功能