The LateResources
documentation shows an example of what you're trying to do. You define a static mut
inside init
, then pass a static reference as a late resource. Have you tried that yet?
I couldn't make a static
in init and transfer it to task
, couldn't appease the borrow checker, so I ended up passing the Transfer
itself. Leaving my code here in case it'll be helpful to someone:
#[rtic::app(device = stm32f3xx_hal::pac, peripherals = true, dispatchers = [TIM20_BRK, TIM20_UP, TIM20_TRG_COM])]
mod app {
use panic_itm as _;
use stm32f3xx_hal::{
dma::{dma1::C5, Channel, Event, Transfer},
gpio,
pac,
prelude::*,
serial::{self, Serial},
};
const BUF_SIZE: usize = 1;
type RxType = serial::Rx<
pac::USART1,
gpio::Pin<gpio::Gpioa, gpio::U<10_u8>, gpio::Alternate<gpio::PushPull, 7_u8>>,
>;
type DirRedType = gpio::PE13<gpio::Output<gpio::PushPull>>;
type DirGreenType = gpio::PE15<gpio::Output<gpio::PushPull>>;
pub struct Leds {
red: DirRedType,
green: DirGreenType,
}
#[shared]
struct Shared {}
#[local]
struct Local {
recv: Option<Transfer<&'static mut [u8; BUF_SIZE], C5, RxType>>,
leds: Leds,
}
#[init(local = [tx_buf: [u8; 2] = [0; 2], rx_buf: [u8; BUF_SIZE] = [0; BUF_SIZE]])]
fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
rtic::pend(stm32f3xx_hal::interrupt::USART1_EXTI25);
ctx.device.RCC.ahbenr.modify(|_, w| w.dma1en().enabled());
let mut rcc = ctx.device.RCC.constrain();
let mut flash = ctx.device.FLASH.constrain();
let clocks = rcc.cfgr.freeze(&mut flash.acr);
let mut gpioa = ctx.device.GPIOA.split(&mut rcc.ahb);
let mut pins = (
gpioa
.pa9
.into_af7_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
gpioa
.pa10
.into_af7_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh),
);
let mut serial = Serial::new(ctx.device.USART1, pins, 9600.Bd(), clocks, &mut rcc.apb2);
let (tx, rx) = serial.split();
let mut dma1 = ctx.device.DMA1.split(&mut rcc.ahb);
dma1.ch5.enable_interrupt(Event::TransferComplete);
// DIR (the LED that lights up during serial rx)
let mut gpioe = ctx.device.GPIOE.split(&mut rcc.ahb);
let mut red_dir: DirRedType = gpioe
.pe13
.into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
let mut green_dir: DirGreenType = gpioe
.pe15
.into_push_pull_output(&mut gpioe.moder, &mut gpioe.otyper);
// Initialize speech module
// Import group 1
let tx_buf = ctx.local.tx_buf;
match hex::decode_to_slice("aa21", tx_buf) {
Ok(res) => {}
Err(err) => {
let a = 1;
}
};
let sending = tx.write_all(tx_buf, dma1.ch4);
let (tx_buf, tx_channel, tx) = sending.wait();
hex::decode_to_slice("aa37", tx_buf).unwrap();
let sending = tx.write_all(tx_buf, tx_channel);
let (tx_buf, tx_channel, tx) = sending.wait();
(
Shared {},
Local {
recv: Some(rx.read_exact(ctx.local.rx_buf, dma1.ch5)),
leds: Leds {
red: red_dir,
green: green_dir,
},
},
init::Monotonics(),
)
}
#[idle]
fn idle(_: idle::Context) -> ! {
loop {}
}
// Triggers on RX transfer completed
#[task(binds = DMA1_CH5, local = [recv], priority = 2)]
fn on_rx(ctx: on_rx::Context) {
let (rx_buf, rx_channel, rx) = ctx.local.recv.take().unwrap().wait();
led::spawn(*rx_buf).ok();
ctx.local.recv.replace(rx.read_exact(rx_buf, rx_channel));
}
#[task(local=[leds])]
fn led(ctx: led::Context, data: [u8; BUF_SIZE]) {
let leds = ctx.local.leds;
match &data {
b"\x11" => {
// Red
assert_eq!(1, 1);
leds.red.toggle().expect("cannot toggle led");
}
b"\x12" => {
// Green
assert_eq!(1, 1);
leds.green.toggle().expect("cannot toggle led");
}
_ => {}
}
}
}