You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 07:54:52