rust - Rust嵌入式商店外围设备

标签 rust embedded bare-metal

我正在尝试在nrf52-dk板上工作,并试图使指示灯闪烁并同时使SPI工作。
我一次可以让一个或另一个工作,但不能一次都工作。
我很确定nrf52810_hal::pac::Peripherals::take()不应被多次调用,因为它的数据会更改所有引用,但是当我指定管脚时它会被移动。
我不确定如何在不使用变量的情况下不传递它就能使它工作。
在下面的示例中,始终写出“PERIPHERALS为null”,并且由于紧随其后的语句而使代码感到 panic 。
我确实需要使PERIPHERALS是“静态mut”,因为我需要在另一个“线程”中使用它们,因为这是一个称为中断的函数,我无法向其传递数据。

#![no_main]
#![no_std]

#[allow(unused_extern_crates)]
use panic_halt as _;

use asm_delay::AsmDelay;
use cortex_m_rt::entry;
use cortex_m_semihosting::hprint;
use hal::gpio::Level;
use hal::pac::interrupt;
use nrf52810_hal as hal;
use nrf52810_hal::prelude::*;
use nrf52810_pac as nrf;
use nrf52810_pac::{Interrupt, NVIC};

static mut PERIPHERALS: Option<nrf::Peripherals> = None;

#[entry]
unsafe fn main() -> ! {
    let p = hal::pac::Peripherals::take().unwrap();
    let port0 = hal::gpio::p0::Parts::new(p.P0);
    let spiclk = port0.p0_25.into_push_pull_output(Level::Low).degrade();
    let spimosi = port0.p0_24.into_push_pull_output(Level::Low).degrade();
    let spimiso = port0.p0_23.into_floating_input().degrade();
    let pins = hal::spim::Pins {
        sck: spiclk,
        miso: Some(spimiso),
        mosi: Some(spimosi),
    };
    let spi = hal::Spim::new(
        p.SPIM0,
        pins,
        hal::spim::Frequency::K500,
        hal::spim::MODE_0,
        0,
    );

    let reference_data = "Hello World!".as_bytes();
    let mut eh_spi = embedded_hal_spy::new(spi, |_| {});
    use embedded_hal::blocking::spi::Write;
    match eh_spi.write(reference_data) {
        Ok(_) => {}
        Err(_) => {}
    }
    PERIPHERALS = nrf::Peripherals::take();
    if PERIPHERALS.is_none() {
        hprint!("PERIPHERALS are null!").unwrap();
    }
    NVIC::unmask(Interrupt::SWI0_EGU0);
    let mut d = AsmDelay::new(asm_delay::bitrate::U32BitrateExt::mhz(74));

    PERIPHERALS
        .as_ref()
        .unwrap()
        .P0
        .dir
        .write(|w| w.pin20().output());
    PERIPHERALS
        .as_ref()
        .unwrap()
        .P0
        .out
        .write(|w| w.pin20().low());

    loop {
        NVIC::pend(Interrupt::SWI0_EGU0);
        d.delay_ms(100u32);
    }
}

#[interrupt]
fn SWI0_EGU0() {
    static mut LED_STATE: bool = false;
    flip_led(LED_STATE);
    *LED_STATE = !*LED_STATE;
}

fn flip_led(led_state: &mut bool) {
    match led_state {
        true => unsafe {
            PERIPHERALS
                .as_ref()
                .unwrap()
                .P0
                .out
                .write(|w| w.pin20().low());
        },
        false => unsafe {
            PERIPHERALS
                .as_ref()
                .unwrap()
                .P0
                .out
                .write(|w| w.pin20().high());
        },
    }
}

最佳答案

您实际上是否需要从中断上下文访问所有Peripherals?可能不是,您可能只需要访问那里的特定外围设备。您可以将其从Peripherals结构中移到static中。然后,在main中将所需的外围设备作为本地变量存储在其中,在static中将其他所有内容存储为本地变量。
但在我看来,还有一个更好的解决方案:使用RTIC。它旨在处理该确切的用例。它使您可以准确地指定在哪种情况下需要哪些资源,并使这些资源在那里可用。您甚至可以安全地在不同上下文之间共享资源。它将根据需要自动使用互斥锁保护它们。
我不能高度推荐RTIC。对我来说,不使用它的唯一原因是,如果我的程序没有任何中断处理程序。

关于rust - Rust嵌入式商店外围设备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63067919/

相关文章:

rust - 调用lambda时“Cannot infer an appropriate lifetime”

oop - 为什么 Rust 不支持 trait 对象向上转换?

c - Wiznet W5100 拔出电缆检测

embedded - 使用 openOCD 在 Cortex-M (STM32F4) 上提取 ETB 轨迹

interrupt - Lego Mindstorm EV3 上的裸机中断处理(TexasInstruments Sitara AM1808 SoC)

c - Intel Galileo 裸机 UART

static - 我可以避免在没有 `static mut` 的情况下重新编译我的平台层吗?

rust - 如何证明 Rust 类型系统支持代数数据类型 (ADT)?

embedded - ppc32和ppc64函数栈计算

qt - 什么是 Qt 裸机?