6 个版本 (3 个重大更新)
0.4.0 | 2024年3月9日 |
---|---|
0.3.1 | 2023年5月6日 |
0.3.0 | 2023年3月18日 |
0.2.0 | 2021年8月8日 |
0.0.3 |
|
#291 在 硬件支持
每月41次 下载
52KB
625 行
usbd-dfu
实现了对 usb-device
设备的 DFU 协议版本 1.1a。
关于
DFU 协议旨在提供一个标准,以便 USB 设备的固件可以进行升级。通常情况下,设备的固件由两部分组成:一个大的主固件和一个较小的引导加载程序。当设备开机时,引导加载程序启动,并运行主固件或进入“固件更新”模式。
协议实现尽量遵循由意法半导体(STMicroelectronics)的 AN3156 和 USB 设备固件升级规范(Revision 1.1)所指定的 DFU 1.1a 协议。
该库仅实现协议,实际编程、擦除或读取内存或闪存的代码不在库中,并预期由库用户提供。
支持的操作
- 读取(设备到主机)- 上传命令
- 写入(主机到设备)- 下载命令
- 擦除
- 全部擦除
不支持的操作
- 读取解除保护 - 擦除所有内容并移除读取保护。
限制
-
最大 USB 传输大小限制为
usb-device
对控制端点传输的支持大小,默认为 128 字节。 -
DFU_GETSTATUS
中的 iString 字段始终为0
。不支持特定厂商的错误描述字符串。
DFU 工具
有许多支持 DFU 协议的 USB 设备烧录工具实现,例如
许可证
贡献
除非您明确声明,否则您提交给本项目以供包含在内的任何贡献都将按照上述方式许可,不附加任何额外条款或条件。
示例
以下示例尝试专注于 DFUClass
,与目标控制器初始化和配置(USB、中断、GPIO 等)相关的部分不在示例范围内。
查看示例以获取更多信息。
请参阅 usb-device
库的文档,这些库支持目标微控制器并提供相应的硬件抽象层(HAL)。
use usb_device::prelude::*;
use usbd_dfu::*;
// DFUClass will use MyMem to actually read, erase or program the memory.
// Here, a set of constant parameters must be set. These parameters
// either change how DFUClass behaves, or define host's expectations.
struct MyMem {
buffer: [u8; 64],
flash_memory: [u8; 1024],
}
impl DFUMemIO for MyMem {
const MEM_INFO_STRING: &'static str = "@Flash/0x00000000/1*1Kg";
const INITIAL_ADDRESS_POINTER: u32 = 0x0;
const PROGRAM_TIME_MS: u32 = 8;
const ERASE_TIME_MS: u32 = 50;
const FULL_ERASE_TIME_MS: u32 = 50;
const TRANSFER_SIZE: u16 = 64;
fn read(&mut self, address: u32, length: usize) -> Result<&[u8], DFUMemError> {
// TODO: check address value
let offset = address as usize;
Ok(&self.flash_memory[offset..offset+length])
}
fn erase(&mut self, address: u32) -> Result<(), DFUMemError> {
// TODO: check address value
self.flash_memory.fill(0xff);
// TODO: verify that block is erased successfully
Ok(())
}
fn erase_all(&mut self) -> Result<(), DFUMemError> {
// There is only one block, erase it.
self.erase(0)
}
fn store_write_buffer(&mut self, src:&[u8]) -> Result<(), ()>{
self.buffer[..src.len()].copy_from_slice(src);
Ok(())
}
fn program(&mut self, address: u32, length: usize) -> Result<(), DFUMemError>{
// TODO: check address value
let offset = address as usize;
// Write buffer to a memory
self.flash_memory[offset..offset+length].copy_from_slice(&self.buffer[..length]);
// TODO: verify that memory is programmed correctly
Ok(())
}
fn manifestation(&mut self) -> Result<(), DFUManifestationError> {
// Nothing to do to activate FW
Ok(())
}
}
let mut my_mem = MyMem {
buffer: [0u8; 64],
flash_memory: [0u8; 1024],
};
// Create USB device for a target device:
// let usb_bus_alloc = UsbBus::new(peripheral);
// let usb_dev = UsbDeviceBuilder::new().build();
// Create DFUClass
let mut dfu = DFUClass::new(&usb_bus_alloc, my_mem);
// usb_dev.poll() must be called periodically, usually from USB interrupt handlers.
// When USB input/output is done, handlers in MyMem may be called.
usb_dev.poll(&mut [&mut dfu]);
示例引导加载程序实现
请参阅usbd-dfu-example 以获取一个功能示例。
依赖项
约1.5MB
约28K SLoC