stm32f4xx-hal
stm32f4xx-hal copied to clipboard
Add usart-interrupt example
Hello. I tried several ways to use usart with interrupt, but they all failed with the error external reset detected. The error didn't appear when interrupt was not used. This is a confusing problem.
And I have another question. serial will be moved by the method serial.split(), and we have to use this if we want to use usart with dma. But we can only get the mutable reference in rtic, this can not be moved. So is it possible to use usart with interrupt, dma and rtic?
Thanks.
Here is some of my attempts.
stm32f3xx-hal rtic succeed
#![no_main]
#![no_std]
use cortex_m_semihosting::hprintln;
use hal::{
gpio::{self, PushPull, AF7},
pac::USART1,
prelude::*,
rcc::RccExt,
serial::{Event, Serial},
};
use panic_semihosting as _;
use stm32f3xx_hal as hal;
type SerialType = Serial<
USART1,
(
gpio::gpioa::PA9<AF7<PushPull>>,
gpio::gpioa::PA10<AF7<PushPull>>,
),
>;
#[rtic::app(device = stm32f3xx_hal::pac, peripherals = true)]
const APP: () = {
struct Resources {
serial: SerialType,
}
#[init]
fn init(cx: init::Context) -> init::LateResources {
let dp: hal::pac::Peripherals = cx.device;
let mut rcc = dp.RCC.constrain();
let clocks = rcc
.cfgr
.sysclk(48_u32.MHz())
.freeze(&mut dp.FLASH.constrain().acr);
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
let 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(dp.USART1, pins, 9600_u32.Bd(), clocks, &mut rcc.apb2);
serial.listen(Event::Rxne);
init::LateResources { serial }
}
#[task(binds = USART1_EXTI25, resources = [serial])]
fn serial(cx: serial::Context) {
let serial: &mut SerialType = cx.resources.serial;
if serial.is_rxne() {
serial.unlisten(Event::Rxne);
match serial.read() {
Ok(byte) => {
serial.write(byte).unwrap();
serial.listen(Event::Tc);
// This will cause a few millisecond to execute the function.
// And this will result in partial data not being received.
// hprintln!("{}", byte as char).unwrap();
}
Err(_error) => {
hprintln!("read error").unwrap();
}
}
}
if serial.is_tc() {
serial.unlisten(Event::Tc);
serial.listen(Event::Rxne);
}
}
};
stm32f4xx-hal ritc I tried USART1, USART2, USART3, they all failed.
#![no_main]
#![no_std]
use cortex_m::peripheral::NVIC;
use cortex_m_semihosting::hprintln;
use hal::{
gpio::{
gpioc::{PC10, PC11},
Alternate, AF7,
},
pac::USART3,
prelude::*,
rcc::RccExt,
serial::{config::Config, Event, Serial},
};
use panic_semihosting as _;
use stm32f4xx_hal as hal;
type SerialType = Serial<USART3, (PC10<Alternate<AF7>>, PC11<Alternate<AF7>>)>;
#[rtic::app(device = stm32f4xx_hal::pac, peripherals = true)]
const APP: () = {
struct Resources {
serial: SerialType,
}
#[init]
fn init(cx: init::Context) -> init::LateResources {
let dp: hal::pac::Peripherals = cx.device;
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.use_hse(8_u32.mhz()).freeze();
let gpioc = dp.GPIOC.split();
let pins = (
gpioc.pc10.into_alternate_af7(),
gpioc.pc11.into_alternate_af7(),
);
let mut serial = Serial::usart3(
dp.USART3,
pins,
Config::default().baudrate(9600_u32.bps()),
clocks,
)
.unwrap();
unsafe {
NVIC::unmask(hal::interrupt::USART3);
}
serial.listen(Event::Rxne);
init::LateResources { serial }
}
#[idle(resources = [serial])]
fn idle(_cx: idle::Context) -> ! {
loop {
cortex_m::asm::nop();
}
}
#[task(binds = USART3, resources = [serial])]
fn serial(cx: serial::Context) {
let serial: &mut SerialType = cx.resources.serial;
if serial.is_rxne() {
serial.unlisten(Event::Rxne);
if let Ok(context) = serial.read() {
serial.listen(Event::Txe);
serial.write(context).unwrap();
} else {
hprintln!("read error").unwrap();
}
}
if serial.is_txe() {
serial.unlisten(Event::Txe);
serial.listen(Event::Rxne);
}
}
};
stm32f4xx-hal failed
#![no_main]
#![no_std]
use cortex_m::peripheral::NVIC;
use cortex_m_semihosting::hprintln;
use panic_semihosting as _;
use cortex_m_rt::entry;
use stm32f4xx_hal as hal;
use hal::{
gpio::{
gpioa::{PA2, PA3},
Alternate, AF7,
},
interrupt,
pac::USART2,
prelude::*,
serial::config::Config,
serial::Serial,
stm32,
};
type SerialType = Serial<USART2, (PA2<Alternate<AF7>>, PA3<Alternate<AF7>>)>;
static mut SERIAL: Option<SerialType> = None;
unsafe fn get_serial() -> &'static mut SerialType {
if let Some(ref mut gpioe) = SERIAL {
&mut *gpioe
} else {
panic!()
}
}
#[entry]
fn main() -> ! {
let dp = stm32::Peripherals::take().unwrap();
let gpioa = dp.GPIOA.split();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.use_hse(8.mhz()).freeze();
let tx_pin = gpioa.pa2.into_alternate_af7();
let rx_pin = gpioa.pa3.into_alternate_af7();
let mut serial = Serial::usart2(
dp.USART2,
(tx_pin, rx_pin),
Config::default().baudrate(9600.bps()),
clocks,
)
.unwrap();
unsafe {
NVIC::unmask(hal::interrupt::USART2);
}
serial.listen(hal::serial::Event::Rxne);
unsafe {
SERIAL = Some(serial);
}
loop {
cortex_m::asm::nop();
}
}
#[interrupt]
fn USART2() {
let serial = unsafe { get_serial() };
if serial.is_rxne() {
if let Ok(word) = serial.read() {
serial.unlisten(hal::serial::Event::Rxne);
serial.write(word).unwrap();
} else {
hprintln!("read error").unwrap();
}
}
if serial.is_txe() {
serial.unlisten(hal::serial::Event::Txe);
serial.listen(hal::serial::Event::Rxne);
}
}