如何在Rust嵌入式STM应用中共享HAL延迟资源?
问题解决:Rust嵌入式中sx127x_lora占用Delay所有权无法复用的问题
核心问题
sx127x_lora的LoRa::new方法会获取Delay资源的所有权,导致后续代码无法再使用该Delay实例,这是Rust所有权机制的正常表现。你使用的cortex_m::SYST Delay是正确的嵌入式阻塞延迟资源,无需更换。
解决方案
1. 检查库是否支持取回Delay所有权
部分外设库会提供初始化后归还资源的方法(比如take_delay),先查阅sx127x_lora的文档或源码:
- 如果
LoRa结构体包含类似方法,可在初始化后取回Delay:
let cp = cortex_m::Peripherals::take().unwrap(); let mut delay = cp.SYST.delay(rcc.clocks); let mut lora = sx127x_lora::LoRa::new(spi, nss, reset, 868, delay) .expect("Failed to communicate with radio module!"); // 若库提供take_delay方法,取回所有权 let mut delay = lora.take_delay(); delay.delay_ms(1000u16);
2. 使用内部可变性实现Delay共享
如果库在运行时仍需使用Delay,可通过RefCell(单线程场景)或Mutex(多线程/中断场景)实现资源共享:
use core::cell::RefCell; use cortex_m::interrupt::Mutex; use embedded_hal::blocking::delay::{DelayMs, DelayUs}; // 定义全局共享的Delay容器 static SHARED_DELAY: Mutex<RefCell<Option<SYSTDelay>>> = Mutex::new(RefCell::new(None)); let cp = cortex_m::Peripherals::take().unwrap(); let delay = cp.SYST.delay(rcc.clocks); // 将Delay存入全局容器 cortex_m::interrupt::free(|cs| { SHARED_DELAY.borrow(cs).replace(Some(delay)); }); // 实现适配的共享Delay结构体 struct SharedDelay; impl DelayMs<u16> for SharedDelay { fn delay_ms(&mut self, ms: u16) { cortex_m::interrupt::free(|cs| { SHARED_DELAY.borrow(cs) .borrow_mut() .as_mut() .unwrap() .delay_ms(ms); }); } } // 按需实现其他Delay trait(如DelayUs) impl DelayUs<u32> for SharedDelay { fn delay_us(&mut self, us: u32) { cortex_m::interrupt::free(|cs| { SHARED_DELAY.borrow(cs) .borrow_mut() .as_mut() .unwrap() .delay_us(us); }); } } // 使用SharedDelay初始化LoRa let mut lora = sx127x_lora::LoRa::new(spi, nss, reset, 868, SharedDelay) .expect("Failed to communicate with radio module!"); // 后续代码直接使用SharedDelay SharedDelay.delay_ms(1000u16);
3. 使用独立定时器实现额外Delay
如果系统有空闲的TIM外设,可以基于该定时器实现另一组Delay trait,专供自己的代码使用,与LoRa使用的SYST Delay完全隔离:
// 示例:基于TIM2实现Delay(需根据硬件调整) use stm32f4xx_hal::timer::Timer; let mut tim2 = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1); let mut custom_delay = tim2.delay(); // SYST Delay给LoRa用 let mut lora_delay = cp.SYST.delay(rcc.clocks); let mut lora = sx127x_lora::LoRa::new(spi, nss, reset, 868, lora_delay) .expect("Failed to communicate with radio module!"); // 自己的代码用custom_delay custom_delay.delay_ms(1000u16);
注意事项
- 若sx127x_lora仅在初始化阶段需要Delay,优先尝试方案1,代码最简洁;
- 多线程或中断场景必须使用
Mutex包裹RefCell,避免数据竞争; - 自定义Delay时需确保实现了库要求的所有
embedded_hal延迟trait(如DelayMs、DelayUs)。
内容的提问来源于stack exchange,提问作者CvR_XX
相关产品推荐
相关产品推荐

