Skip to content
Snippets Groups Projects
Commit 032a54c7 authored by Per's avatar Per
Browse files

marcus

parent fc4e64df
No related branches found
No related tags found
No related merge requests found
......@@ -641,7 +641,7 @@
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"name": "bare10 (reselase)",
"name": "bare10 (release)",
"preLaunchTask": "cargo build --example bare10 --release",
"executable": "./target/thumbv7em-none-eabihf/release/examples/bare10",
"configFiles": [
......@@ -701,5 +701,37 @@
"svdFile": "STM32F413.svd",
"cwd": "${workspaceRoot}"
},
{
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"name": "marcus (release)",
"preLaunchTask": "cargo build --example marcus --release",
"executable": "./target/thumbv7em-none-eabihf/release/examples/marcus",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"swoConfig": {
"enabled": true,
"cpuFrequency": 16000000,
"swoFrequency": 2000000,
"source": "probe",
"decoders": [
{
"type": "console",
"label": "ITM0",
"port": 0
},
{
"type": "console",
"label": "ITM1",
"port": 1
}
]
},
"svdFile": "STM32F413.svd",
"cwd": "${workspaceRoot}"
},
]
}
\ No newline at end of file
......@@ -303,5 +303,29 @@
"isDefault": true
}
},
{
"type": "shell",
"label": "cargo build --example marcus --release",
"command": "cargo build --example marcus --release --features \"hal rtfm-tq\"",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "shell",
"label": "cargo build --example equivalence --release",
"command": "cargo build --example equivalence --release --features \"hal rtfm-tq\"",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
}
},
]
}
\ No newline at end of file
......@@ -44,9 +44,10 @@ features = ["stm32f413", "rt"]
optional = true
[features]
pac = ["stm32f4"]
hal = ["stm32f4", "stm32f4xx-hal"]
rtfm = ["cortex-m-rtfm"]
pac = ["stm32f4"]
rtfm-tq = ["cortex-m-rtfm/timer-queue"]
# this lets you use `cargo fix`!
[[bin]]
......
......@@ -8,7 +8,6 @@
//! - busses and clocking
//! - gpio
#![feature(uniform_paths)] // requires nightly
#![no_std]
#![no_main]
......
......@@ -6,7 +6,6 @@
//! - abstractions in Rust
//! - structs and implementations
#![feature(uniform_paths)] // requires nightly
#![no_std]
#![no_main]
......
......@@ -5,7 +5,6 @@
//! - working with the svd2rust API
#![deny(unsafe_code)]
#![feature(uniform_paths)]
#![deny(warnings)]
#![no_main]
#![no_std]
......
//! The RTFM framework
//!
//! What it covers:
//! - Priority based scheduling
//! - Message passing
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m::{asm, iprintln};
extern crate stm32f4xx_hal as hal;
// use stm32f4::stm32f413::GPIOA;
use crate::hal::prelude::*;
use crate::hal::serial::{self, config::Config, Rx, Serial, Tx};
use hal::{gpio::Alternate, gpio::AF0, stm32::ITM};
// use heapless::consts::*;
// use heapless::spsc::{Consumer, Producer, Queue};
use nb::block;
use rtfm::{app, Instant};
// Our error type
#[derive(Debug)]
pub enum Error {
RingBufferOverflow,
UsartSendOverflow,
UsartReceiveOverflow,
}
#[derive(Debug)]
pub enum Event {
Timout,
ChannelA,
ChannelB,
}
#[derive(Debug, Copy, Clone)]
pub struct Data {
a: bool,
b: bool,
event_counter: u32,
out: bool,
}
const TIMEOUT: u32 = 16_000_000;
#[app(device = hal::stm32)]
const APP: () = {
// Late resources
static mut TX: Tx<hal::stm32::USART2> = ();
static mut RX: Rx<hal::stm32::USART2> = ();
static mut ITM: ITM = ();
static mut LED: hal::gpio::gpioa::PA5<Alternate<AF0>> = ();
// app resources
static mut DATA: Data = Data {
a: false,
b: false,
event_counter: 0,
out: false,
};
// init runs in an interrupt free section>
#[init]
fn init() {
let stim = &mut core.ITM.stim[0];
iprintln!(stim, "start");
// power on GPIOA, RM0368 6.3.11
device.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
// configure PA5 as output, RM0368 8.4.1
device.GPIOA.moder.modify(|_, w| w.moder5().bits(1));
let rcc = device.RCC.constrain();
// 16 MHz (default, all clocks)
let clocks = rcc.cfgr.freeze();
let gpioa = device.GPIOA.split();
let tx = gpioa.pa2.into_alternate_af7();
let rx = gpioa.pa3.into_alternate_af7();
let led = gpioa.pa5.into_alternate_af0();
let mut serial = Serial::usart2(
device.USART2,
(tx, rx),
Config::default().baudrate(115_200.bps()),
clocks,
)
.unwrap();
// generate interrupt on Rxne
serial.listen(serial::Event::Rxne);
// Separate out the sender and receiver of the serial port
let (tx, rx) = serial.split();
// pass on late resources
LED = led;
// Our split serial
TX = tx;
RX = rx;
// For debugging
ITM = core.ITM;
}
// idle may be interrupted by other interrupt/tasks in the system
// #[idle(resources = [RX, TX, ITM])]
#[idle]
fn idle() -> ! {
loop {
asm::wfi();
}
}
#[task(priority = 1, resources = [ITM])]
fn trace_data(byte: u8) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "data {}", byte);
}
#[task(priority = 1, resources = [ITM])]
fn trace_error(error: Error) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "{:?}", error);
}
#[interrupt(priority = 3, resources = [RX], spawn = [trace_data, trace_error, echo])]
fn USART2() {
match resources.RX.read() {
Ok(byte) => {
spawn.echo(byte).unwrap();
if spawn.trace_data(byte).is_err() {
spawn.trace_error(Error::RingBufferOverflow).unwrap();
}
}
Err(_err) => {
spawn.trace_error(Error::UsartReceiveOverflow).unwrap()
}
}
}
#[task(priority = 2, resources = [TX], spawn = [trace_error, event_a, event_b])]
fn echo(byte: u8) {
let tx = resources.TX;
if block!(tx.write(byte)).is_err() {
spawn.trace_error(Error::UsartSendOverflow).unwrap();
}
match byte {
b'a' => spawn.event_a(false).unwrap(),
b'b' => spawn.event_b(false).unwrap(),
b'A' => spawn.event_a(true).unwrap(),
b'B' => spawn.event_b(true).unwrap(),
_ => (),
}
}
#[task(priority = 1, resources = [ITM, DATA], schedule = [discrepency])]
fn event_a(val: bool) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "event a {}", val);
let data = &mut resources.DATA;
data.a = val;
// evaluate equivalenc.
data.event_counter += 1;
if data.a ^ data.b {
schedule
.discrepency(scheduled + TIMEOUT.cycles(), data.clone())
.unwrap();
data.out = false;
iprintln!(stim, "disc {:?}", data);
}
}
#[task(priority = 1, resources = [ITM, DATA], spawn = [discrepency])]
fn event_b(val: bool) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "event b {}", val);
//evaluate_equivalence(scheduled, &mut resources.DATA);
}
#[task(priority = 1, resources = [ITM, DATA])]
fn discrepency(data: Data) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "a {} b {}", data.a, data.b);
if data.event_counter == resources.DATA.event_counter {
iprintln!(stim, "timeout");
// data.force_reinit =
}
}
#[task (priority = 1, resources = [LED])]
fn periodic() {
static mut TOGGLE: bool = false;
if *TOGGLE {
resources.LED.set_low();
} else {
resources.LED.set_high();
}
*TOGGLE = !*TOGGLE;
}
extern "C" {
fn EXTI0();
fn EXTI1();
fn EXTI2();
fn EXTI3();
fn EXTI4();
}
};
// fn evaluate_equivalence(scheduled: Instant, data: &mut Data, d: event_a::Spawn) {
// data.EventCounter += 1;
// if data.A ^ data.B {
// // spawn.discrepency(scheduled + TIMEOUT.cycles(), data.EventCounter, data.A, data.B);
// }
// }
//! The RTFM framework
//!
//! What it covers:
//! - Priority based scheduling
//! - Message passing
#![no_main]
#![no_std]
extern crate panic_halt;
use cortex_m::{asm, iprintln};
extern crate stm32f4xx_hal as hal;
use crate::hal::prelude::*;
use crate::hal::serial::{self, config::Config, Rx, Serial, Tx};
use hal::stm32::ITM;
// use heapless::consts::*;
// use heapless::spsc::{Consumer, Producer, Queue};
use nb::block;
use rtfm::{app, Instant};
// Our error type
#[derive(Debug)]
pub enum Error {
RingBufferOverflow,
UsartSendOverflow,
UsartReceiveOverflow,
}
#[derive(Debug)]
pub enum Event {
Timout,
ChannelA,
ChannelB,
}
#[derive(Debug, Copy, Clone)]
pub struct Data {
state: State,
a: bool,
b: bool,
event_counter: u32,
out: bool,
}
#[derive(Debug, Copy, Clone)]
pub enum State {
S8000,
S8001,
S8004,
S8014,
S8005,
C001,
C002,
C003,
}
const TIMEOUT: u32 = 16_000_000;
#[app(device = hal::stm32)]
const APP: () = {
// Late resources
static mut TX: Tx<hal::stm32::USART2> = ();
static mut RX: Rx<hal::stm32::USART2> = ();
static mut ITM: ITM = ();
// app resources
static mut DATA: Data = Data {
state: State::S8001,
a: false,
b: false,
event_counter: 0,
out: false,
};
// init runs in an interrupt free section>
#[init(resources = [DATA])]
fn init() {
let stim = &mut core.ITM.stim[0];
iprintln!(stim, "Start {:?}", resources.DATA);
let rcc = device.RCC.constrain();
// 16 MHz (default, all clocks)
let clocks = rcc.cfgr.freeze();
let gpioa = device.GPIOA.split();
let tx = gpioa.pa2.into_alternate_af7();
let rx = gpioa.pa3.into_alternate_af7(); // try comment out
let mut serial = Serial::usart2(
device.USART2,
(tx, rx),
Config::default().baudrate(115_200.bps()),
clocks,
)
.unwrap();
// generate interrupt on Rxne
serial.listen(serial::Event::Rxne);
// Separate out the sender and receiver of the serial port
let (tx, rx) = serial.split();
// Our split serial
TX = tx;
RX = rx;
// For debugging
ITM = core.ITM;
}
// idle may be interrupted by other interrupt/tasks in the system
// #[idle(resources = [RX, TX, ITM])]
#[idle]
fn idle() -> ! {
loop {
asm::wfi();
}
}
#[task(priority = 1, resources = [ITM])]
fn trace_data(byte: u8) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "data {}", byte);
}
#[task(priority = 1, resources = [ITM])]
fn trace_error(error: Error) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "{:?}", error);
}
#[interrupt(priority = 3, resources = [RX], spawn = [trace_data, trace_error, echo])]
fn USART2() {
match resources.RX.read() {
Ok(byte) => {
spawn.echo(byte).unwrap();
if spawn.trace_data(byte).is_err() {
spawn.trace_error(Error::RingBufferOverflow).unwrap();
}
}
Err(_err) => {
spawn.trace_error(Error::UsartReceiveOverflow).unwrap()
}
}
}
#[task(priority = 2, resources = [TX], spawn = [trace_error, event_a, event_b])]
fn echo(byte: u8) {
let tx = resources.TX;
if block!(tx.write(byte)).is_err() {
spawn.trace_error(Error::UsartSendOverflow).unwrap();
}
match byte {
b'a' => spawn.event_a(false).unwrap(),
b'b' => spawn.event_b(false).unwrap(),
b'A' => spawn.event_a(true).unwrap(),
b'B' => spawn.event_b(true).unwrap(),
_ => (),
}
}
#[task(priority = 1, resources = [ITM, DATA], schedule = [discrepency])]
fn event_a(val: bool) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "event a {}", val);
let data = &mut resources.DATA;
data.a = val;
iprintln!(stim, "Start {:?}", data);
// let data = resources.DATA;
match data.state {
State::S8000 => {
if data.a ^ data.b {
schedule
.discrepency(scheduled + TIMEOUT.cycles(), data.event_counter, data.state)
.unwrap();
data.out = false;
data.state = State::S8005;
} else if !data.a & !data.b {
data.state = State::S8001
} else {
return;
}
}
State::S8001 => {
if data.a & !data.b {
schedule
.discrepency(scheduled + TIMEOUT.cycles(), data.event_counter, data.state)
.unwrap();
data.out = false;
data.state = State::S8004;
} else if !data.a & data.b {
schedule
.discrepency(scheduled + TIMEOUT.cycles(), data.event_counter, data.state)
.unwrap();
data.out = false;
data.state = State::S8014;
} else if data.a & data.b {
data.out = true;
data.state = State::S8000;
}
}
State::S8004 => {
if !data.a {
data.event_counter += 1;
data.out = false;
data.state = State::S8001;
} else if data.b {
data.event_counter += 1;
data.out = true;
data.state = State::S8000;
} else {
data.out = false;
}
}
State::S8014 => {
if !data.b {
data.event_counter += 1;
data.out = false;
data.state = State::S8001;
} else if data.a {
data.event_counter += 1;
data.out = true;
data.state = State::S8000;
} else {
data.out = false;
}
}
State::S8005 => {
if !data.a & !data.b {
data.event_counter += 1;
data.out = false;
data.state = State::S8001;
} else {
data.out = false;
}
}
_ => {
if !data.a & !data.b {
data.out = false;
data.state = State::S8001;
} else {
data.out = false;
}
}
}
iprintln!(stim, "Start {:?}", resources.DATA);
}
#[task(priority = 1, resources = [ITM, DATA], schedule = [discrepency])]
fn event_b(val: bool) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "event b {}", val);
let data = &mut resources.DATA;
data.b = val;
iprintln!(stim, "Start {:?}", data);
match data.state {
State::S8000 => {
if data.a ^ data.b {
schedule
.discrepency(scheduled + TIMEOUT.cycles(), data.event_counter, data.state)
.unwrap();
data.out = false;
data.state = State::S8005;
} else if !data.a & !data.b {
data.state = State::S8001
} else {
return;
}
}
State::S8001 => {
if data.a & !data.b {
schedule
.discrepency(scheduled + TIMEOUT.cycles(), data.event_counter, data.state)
.unwrap();
data.out = false;
data.state = State::S8004;
} else if !data.a & data.b {
schedule
.discrepency(scheduled + TIMEOUT.cycles(), data.event_counter, data.state)
.unwrap();
data.out = false;
data.state = State::S8014;
} else if data.a & data.b {
data.out = true;
data.state = State::S8000;
}
}
State::S8004 => {
if !data.a {
data.event_counter += 1;
data.out = false;
data.state = State::S8001;
} else if data.b {
data.event_counter += 1;
data.out = true;
data.state = State::S8000;
} else {
data.out = false;
}
}
State::S8014 => {
if !data.b {
data.event_counter += 1;
data.out = false;
data.state = State::S8001;
} else if data.a {
data.event_counter += 1;
data.out = true;
data.state = State::S8000;
} else {
data.out = false;
}
}
State::S8005 => {
if !data.a & !data.b {
data.event_counter += 1;
data.out = false;
data.state = State::S8001;
} else {
data.out = false;
}
}
_ => {
if !data.a & !data.b {
data.out = false;
data.state = State::S8001;
} else {
data.out = false;
}
}
}
}
#[task(priority = 1, resources = [ITM])]
fn discrepency(counter: u32, state:State) {
let stim = &mut resources.ITM.stim[0];
iprintln!(stim, "counter {} state {:?}", counter, state);
// if data.event_counter == resources.DATA.event_counter {
// iprintln!(stim, "timeout");
// // data.force_reinit =
// }
}
extern "C" {
fn EXTI0();
fn EXTI1();
fn EXTI2();
fn EXTI3();
fn EXTI4();
}
};
// fn evaluate_equivalence(scheduled: Instant, data: &mut Data, d: event_a::Spawn) {
// data.EventCounter += 1;
// if data.A ^ data.B {
// // spawn.discrepency(scheduled + TIMEOUT.cycles(), data.EventCounter, data.A, data.B);
// }
// }
//
//
//
//
// invariants
// out = true -> A & B
//
// event A false -> A = false
// event A true -> A = true
// event B false -> B = false
// event B true -> B = true
//
// A ^ B -- TIMEOUT --> !(A & B) -> out = false
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment