Skip to content
Snippets Groups Projects
Commit 1ae55852 authored by Per's avatar Per
Browse files

loopback

parent 53157279
No related branches found
No related tags found
No related merge requests found
//! 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"),
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment