Rust 嵌入式商店外设
Rust embedded store Peripherals
我正在尝试在 nrf52-dk
开发板上工作,并尝试让灯闪烁并同时让 SPI 工作。
我可以让一个或另一个同时工作,但不能同时工作。
我很确定 nrf52810_hal::pac::Peripherals::take()
不应被多次调用,因为它的数据会更改所有引用,但当我指定引脚时它会被移动。
我不确定如何在不传入变量的情况下使它工作而不用完变量。
在下面的例子中,“PERIPHERALS are null”总是被写出来,并且代码因为它后面的语句而崩溃。
我确实需要将 PERIPHERALS 设置为“static 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 都不为过。对我来说,不使用它的唯一原因是,如果我的程序没有任何中断处理程序。
我正在尝试在 nrf52-dk
开发板上工作,并尝试让灯闪烁并同时让 SPI 工作。
我可以让一个或另一个同时工作,但不能同时工作。
我很确定 nrf52810_hal::pac::Peripherals::take()
不应被多次调用,因为它的数据会更改所有引用,但当我指定引脚时它会被移动。
我不确定如何在不传入变量的情况下使它工作而不用完变量。
在下面的例子中,“PERIPHERALS are null”总是被写出来,并且代码因为它后面的语句而崩溃。
我确实需要将 PERIPHERALS 设置为“static 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 都不为过。对我来说,不使用它的唯一原因是,如果我的程序没有任何中断处理程序。