esp no_std rust 在深度睡眠期间保留数据

问题描述 投票:0回答:1

我目前尝试将基于 esp-idf (c)esp 应用程序移植到 rust esp

no_std

我有一个问题,我尝试解决了很长一段时间,但找不到合适的解决方案。

//! Stores measurements and sends once `x` measurements are collected

#![no_std]
#![no_main]

use core::time::Duration;

use esp_backtrace as _;
use esp_hal::prelude::ram;
use esp_hal::{entry, peripherals::Peripherals};
use esp_println::println;

mod sleep;
use self::sleep::enter_deep as enter_deep_sleep;

#[derive(Clone, Copy, Debug)]
pub struct FloatMeasurement {
    /// The measured temperature in degree Celsius (°C).
    pub temperature: f32,
    /// The measured relative humidity in percent (%).
    pub humidity: f32,
}

use heapless::Vec;

#[ram(rtc_fast)]
static MEASUREMENTS: &'static Vec<FloatMeasurement, 10> = &Vec::new();

#[entry]
fn main() -> ! {
    let peripherals = Peripherals::take();

    loop {
        println!("{}", MEASUREMENTS.len());

        // not working below
        let _ = MEASUREMENTS.push(FloatMeasurement {
            temperature: 1.0,
            humidity: 2.0,
        });
        println!("{}", MEASUREMENTS.len());

        // if e.g. 10 then send and reset vec

        enter_deep_sleep(peripherals.LPWR, Duration::from_secs(4).into());
    }
}

以上是我的应用程序中提取的不起作用的部分。

我发现 heapless Vector 是一个很好的东西,可以满足我的需求。

然后我找到了 Once_cell 作为解决方案,但经过几次尝试后我无法使其工作。 如果它被全局声明为静态,我将无法获得可变引用。 如果我将其声明为:

static MEASUREMENTS: &'static mut Vec<FloatMeasurement, 10> = &mut Vec::new();

我失败了

mutable references are not allowed in the final value of statics

我会非常高兴获得帮助,如何正确地拥有像全局可访问的数据列表之类的东西,我可以在其中写入和读取,只有1线程访问它进行读/写,所以实际上不需要互斥体存在。

lazy_static 似乎也能做到我想要的,但它似乎已被弃用,并且我发现的替代品仅适用于 std 环境。

---- 编辑 ----

摘录如下答案。

rust embedded
1个回答
0
投票

我没有使用once_cell或其他任何东西,因为我将其保持在最低限度。 请注意,如果需要线程或其他并发访问该数据结构,则需要某种锁定。

#![no_std]
#![no_main]

use core::time::Duration;

use esp_backtrace as _;
use esp_hal::prelude::ram;
use esp_hal::{
    clock::ClockControl,
    delay::Delay,
    entry,
    peripherals::Peripherals,
    prelude::*,
    rtc_cntl::sleep::{RtcSleepConfig, TimerWakeupSource},
    system::SystemControl,
};
use esp_println::println;
use esp_hal::rtc_cntl::Rtc;

#[derive(Clone, Copy, Debug)]
pub struct FloatMeasurement {
    /// The measurred temperature in degree Celsius (°C).
    pub temperature: f32,
    /// The measured relative humidity in percent (%).
    pub humidity: f32,
}

use heapless::Vec;

#[ram(rtc_fast)]
static mut MEASUREMENTS: Vec<FloatMeasurement, 10> = Vec::<FloatMeasurement, 10>::new();

#[entry]
fn main() -> ! {
    let peripherals = Peripherals::take();
    let mut cfg = RtcSleepConfig::deep();
    cfg.set_rtc_fastmem_pd_en(false);
    let wakeup_source = TimerWakeupSource::new(Duration::from_secs(2));
    let mut rtc = Rtc::new(peripherals.LPWR);
    rtc.rwdt.enable();
    unsafe {
        // safe here because only 1 thread exists and we can be sure only we access it.
        println!("length {}", MEASUREMENTS.len());
        let _ = MEASUREMENTS.push(FloatMeasurement {
            temperature: 1.0,
            humidity: 2.0,
        });
        for x in MEASUREMENTS.iter() {
            println!("{}", x.humidity);
        }
        println!("--------------");
    }
    let system = SystemControl::new(peripherals.SYSTEM);
    let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
    let delay = Delay::new(&clocks);
    delay.delay(500.millis());
    rtc.sleep(&cfg, &[&wakeup_source]);
    loop {}
}

这段代码工作完美..在尝试让它工作的过程中,我使问题变得过于复杂:)实际上,当进入深度睡眠时,RTC内存被关闭..所以解决方案是..保持它打开(参见下面的代码片段) )

`cfg.set_rtc_fastmem_pd_en(false);`

我得到了 esp-rs 团队的提示。 https://github.com/esp-rs/esp-hal/issues/2516

(从编辑的问题中提取,问题编辑回来。)

© www.soinside.com 2019 - 2024. All rights reserved.