From 1ae558524bcec663bf77761cd55437223c5a8806 Mon Sep 17 00:00:00 2001 From: Per <Per Lindgren> Date: Fri, 23 Feb 2018 01:33:45 +0100 Subject: [PATCH] loopback --- examples/loopback.rs | 190 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 examples/loopback.rs diff --git a/examples/loopback.rs b/examples/loopback.rs new file mode 100644 index 0000000..4a1e705 --- /dev/null +++ b/examples/loopback.rs @@ -0,0 +1,190 @@ +//! Serial interface loopback +#![deny(unsafe_code)] +//#![deny(warnings)] +#![feature(proc_macro)] +#![no_std] + +extern crate cortex_m_rtfm as rtfm; +extern crate f4; +extern crate heapless; + +#[macro_use] +extern crate cortex_m_debug; + +use f4::prelude::*; +use f4::Serial; +use f4::serial::Event; +use f4::time::Hertz; +//use heapless::{RingBuffer, Vec}; +use heapless::RingBuffer; +use rtfm::{app, Resource, Threshold}; + +// CONFIGURATION +const BAUD_RATE: Hertz = Hertz(115_200); + +// TASKS & RESOURCES +app! { + device: f4::stm32f40x, + + resources: { + static SEND: RingBuffer<u8, [u8; 4]> = RingBuffer::new(); + static RECEIVE: RingBuffer<u8, [u8; 6]> = RingBuffer::new(); + }, + + tasks: { + USART2: { + path: usart2_handler, + priority: 3, + resources: [USART2, RECEIVE, SEND], + }, + EXTI1: { + path: command, + priority: 2, + resources: [USART2, RECEIVE, SEND], + }, + EXTI2: { + path: error_receive_buffer_full, + priority: 1, + }, + EXTI3: { + path: error_usart_overflow, + priority: 1, + }, + } +} + +// INITIALIZATION PHASE +fn init(p: init::Peripherals, r: init::Resources) { + ipln!("init"); + let serial = Serial(p.USART2); + + serial.init(BAUD_RATE.invert(), Some(p.DMA1), p.GPIOA, p.RCC); + serial.listen(Event::Rxne); + serial.listen(Event::Txe); + + let _ = r.SEND.enqueue('a' as u8); + let _ = r.SEND.enqueue('b' as u8); + let _ = r.SEND.enqueue('c' as u8); + + rtfm::set_pending(f4::stm32f40x::Interrupt::USART2); // trigger USART2 task +} + +// IDLE LOOP +fn idle() -> ! { + // Sleep + loop { + rtfm::wfi(); + } +} + +// USART2 task +fn usart2_handler(_t: &mut Threshold, r: USART2::Resources) { + let serial = Serial(&**r.USART2); + let sr = r.USART2.sr.read(); + if sr.rxne().bit_is_set() { + // interrupt due to data received + match serial.read() { + Ok(b) => { + if b == '\n' as u8 || b == '\r' as u8 { + // we have received a `return`, trigger command to process it + rtfm::set_pending(f4::stm32f40x::Interrupt::EXTI1); + } else { + match r.RECEIVE.enqueue(b) { + Err(_) => { + // trigger error_handler on buffer overflow + rtfm::set_pending(f4::stm32f40x::Interrupt::EXTI2); + } + _ => {} + } + } + } + Err(_) => { + // trigger error on usart overflow + rtfm::set_pending(f4::stm32f40x::Interrupt::EXTI3); + r.USART2.dr.read(); // clear the error by reading the data register + } + } + } + + match r.SEND.dequeue() { + Some(b) => { + // we (still) have something in the queue to send + let _ = serial.write(b); + } + _ => { + // the que was empty so the last item was already sent + serial.unlisten(Event::Txe); + } + } +} + +#[allow(non_snake_case)] +fn command( + t: &mut Threshold, + EXTI1::Resources { + USART2, + mut SEND, + mut RECEIVE, + }: EXTI1::Resources, +) { + ipln!("command"); + + match SEND.claim_mut(t, |send, t1| { + RECEIVE.claim_mut(t1, |receive, _| { + let mut err = Ok(()); + while let Some(e) = receive.dequeue() { + err = send.enqueue(e); + } + err + }) + }) { + Err(err) => { + // error handling outside the critical section + ipln!("SEND {:?}", err); + } + _ => {} + } + + // here we assume that + USART2.claim(t, |usart, _| { + Serial(&**usart).listen(Event::Txe); + }); + // trigger the usart to send queued data + rtfm::set_pending(f4::stm32f40x::Interrupt::USART2); +} + +fn error_receive_buffer_full() { + ipln!("error_receive_buffer_full"); +} + +fn error_usart_overflow() { + ipln!("error_usart_overflow"); +} + +#[derive(Debug)] +enum Command { + Start, + Stop, + Freq(u32), +} + +fn parse(s: &str) -> Result<Command, &str> { + let mut iter = s.split(' ').filter(|c| !(c == &"")); + + match iter.next() { + Some("Stop") => Ok(Command::Stop), + Some("Start") => Ok(Command::Start), + Some("Freq") => match iter.next() { + Some(fs) => { + if let Ok(f) = fs.parse::<u32>() { + Ok(Command::Freq(f)) + } else { + Err("Invalid frequency") + } + } + None => Err("No frequency"), + }, + Some(_) => Err("Invalid command"), + None => Err("No input"), + } +} -- GitLab