You need the peripheral to construct the BufferedUart. It has to be moved out of the p returned by init, and into the BufferedUart. You then move the BufferedUart into the task you spawn. The trick to being able to move BufferedUart into the other task is that all task arguments must be 'static, and BufferedUart needs references to tx and rx byte buffers. So those have to be 'static. So I had to:
// the uart driver needs to be 'static to pass to the other task.
// this is safe because it is the only reference
#[allow(static_mut_refs)]
unsafe {
static mut TX_BUFFER: [u8; 128] = [0u8; 128];
static mut RX_BUFFER: [u8; 128] = [0u8; 128];
usart = BufferedUart::new(
p.USART1,
p.PA10,
p.PA9,
&mut TX_BUFFER,
&mut RX_BUFFER,
Irqs,
uconf,
)
.unwrap();
}
For the ADC peripheral, I wanted that encapsulated in its own module and struct, so getting the generics right to pass the peripheral into ::new() was tricky, but I ended up with this in main:
let mut ad = AtoD::new(
p.ADC1,
p.ADC4,
p.PC0.degrade_adc(),
p.PC1.degrade_adc(),
p.PC3.degrade_adc(),
p.GPDMA1_CH0.reborrow(),
p.GPDMA1_CH1.reborrow(),
);
And this for the struct in the AtoD module:
pub struct AtoD<'a, D1: RxDma<ADC1>, D2: RxDma<ADC4>> {
adc1: adc::Adc<'static, peripherals::ADC1>,
adc4: adc::Adc<'static, peripherals::ADC4>,
co2_pin: adc::AnyAdcChannel<'static, peripherals::ADC1>,
ref_pin: adc::AnyAdcChannel<'static, peripherals::ADC1>,
temp_pin: adc::AnyAdcChannel<'static, peripherals::ADC4>,
dma1: embassy_stm32::Peri<'a, D1>,
dma4: embassy_stm32::Peri<'a, D2>,
}
And the impl block got a little hairy with generics too:
impl<'a, D1: RxDma<ADC1>, D2: RxDma<ADC4>> AtoD<'a, D1, D2>
where
crate::Irqs: embassy_stm32::interrupt::typelevel::Binding<
<D1 as embassy_stm32::dma::ChannelInstance>::Interrupt,
embassy_stm32::dma::InterruptHandler<D1>,
>,
crate::Irqs: embassy_stm32::interrupt::typelevel::Binding<
<D2 as embassy_stm32::dma::ChannelInstance>::Interrupt,
embassy_stm32::dma::InterruptHandler<D2>,
>,
{
pub fn new(
adc1: Peri<'static, peripherals::ADC1>,
adc4: Peri<'static, peripherals::ADC4>,
co2_pin: adc::AnyAdcChannel<'static, peripherals::ADC1>,
ref_pin: adc::AnyAdcChannel<'static, peripherals::ADC1>,
temp_pin: adc::AnyAdcChannel<'static, peripherals::ADC4>,
dma1: embassy_stm32::Peri<'a, D1>,
dma4: embassy_stm32::Peri<'a, D2>,
) -> Self {
let adc1 = adc::Adc::new_with_config(
adc1,
adc::AdcConfig {
resolution: Some(adc::Resolution::BITS14),
averaging: Some(adc::Averaging::Samples64),
},
);
let adc4 = adc::Adc::new_adc4(adc4);
AtoD {
adc1,
adc4,
co2_pin,
ref_pin,
temp_pin,
dma1,
dma4,
}
}
}