From 4c83d66bc3721acf835b22f3645cf2b4e8fdae23 Mon Sep 17 00:00:00 2001
From: Jonas Jacobsson <01joja@gamil.com>
Date: Fri, 12 Mar 2021 23:28:57 +0100
Subject: [PATCH] Got one led to work

---
 examples/all_combinations_of_colurs.rs | 293 +++++++++++++++++++++++++
 examples/green_to_blink2.rs            | 195 ++++++++++++++++
 examples/rtic_bare6.rs                 |   2 +-
 examples/rtic_bare7.rs                 |  36 ++-
 examples/rtic_bare8.rs                 |  30 ++-
 examples/rtic_bare9.rs                 |  46 +++-
 src/main.rs                            | 119 +++++++++-
 7 files changed, 682 insertions(+), 39 deletions(-)
 create mode 100644 examples/all_combinations_of_colurs.rs
 create mode 100644 examples/green_to_blink2.rs

diff --git a/examples/all_combinations_of_colurs.rs b/examples/all_combinations_of_colurs.rs
new file mode 100644
index 0000000..c969b8b
--- /dev/null
+++ b/examples/all_combinations_of_colurs.rs
@@ -0,0 +1,293 @@
+//! rtic_bare7.rs
+//!
+//! HAL OutputPin abstractions
+//!
+//! What it covers:
+//! - using embedded hal, and the OutputPin abstraction
+
+#![no_main]
+#![no_std]
+
+
+use panic_rtt_target as _;
+use rtic::cyccnt::{Instant, U32Ext as _};
+use rtt_target::{rprintln, rtt_init_print};
+use stm32f4xx_hal::stm32;
+
+use stm32f4xx_hal::{
+    gpio::{gpioa::PA1, gpioa::PA2, gpioa::PA3, Output, PushPull},
+    prelude::*,
+};
+
+use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin};
+
+const OFFSET: u32 = 50_000_000;
+
+#[rtic::app(device = stm32f4xx_hal::stm32, monotonic = rtic::cyccnt::CYCCNT, peripherals = true)]
+const APP: () = {
+    struct Resources {
+        // late resources
+        //GPIOA: stm32::GPIOA,
+        led_red: PA3<Output<PushPull>>,
+        led_green: PA2<Output<PushPull>>,
+        led_blue: PA1<Output<PushPull>>,
+    }
+    #[init(schedule = [toggle])]
+    fn init(cx: init::Context) -> init::LateResources {
+        rtt_init_print!();
+        rprintln!("init");
+
+
+        let mut core = cx.core;
+        let device = cx.device;
+
+
+        // Initialize (enable) the monotonic timer (CYCCNT)
+        core.DCB.enable_trace();
+        core.DWT.enable_cycle_counter();
+
+        // semantically, the monotonic timer is frozen at time "zero" during `init`
+        // NOTE do *not* call `Instant::now` in this context; it will return a nonsense value
+        let now = cx.start; // the start time of the system
+
+        // Schedule `toggle` to run 8e6 cycles (clock cycles) in the future
+        let number_of_toggles = 0;
+        cx.schedule.toggle(now + OFFSET.cycles(),number_of_toggles).unwrap();
+
+        // power on GPIOA, RM0368 6.3.11
+        device.RCC.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
+        // configure PA3 as output, RM0368 8.4.1
+        device.GPIOA.moder.modify(|_, w| w.moder3().bits(1));
+        device.GPIOA.moder.modify(|_, w| w.moder2().bits(1));
+        device.GPIOA.moder.modify(|_, w| w.moder1().bits(1));
+
+        
+        let gpioa = device.GPIOA.split();
+        
+        // pass on late resources
+        init::LateResources {
+            //GPIOA: device.GPIOA,
+            led_red: gpioa.pa3.into_push_pull_output(),
+            led_green: gpioa.pa2.into_push_pull_output(),
+            led_blue: gpioa.pa1.into_push_pull_output(),
+        }
+    }
+
+    #[idle]
+    fn idle(_cx: idle::Context) -> ! {
+        rprintln!("idle");
+        loop {
+            continue;
+        }
+    }
+
+    #[task(resources = [led_green,led_blue,led_red], schedule = [toggle])]
+    fn toggle(cx: toggle::Context, mut no_toggled: i32) {
+        static mut TOGGLE: bool = false;
+        //rprintln!("toggle  @ {:?}", Instant::now());
+        //rprintln!("times I have toggled {:?}", no_toggled);
+        no_toggled +=1;
+
+        if no_toggled % 8 == 0{
+            rprintln!("White");
+            cx.resources.led_red.set_high().ok();
+            cx.resources.led_green.set_high().ok();
+            cx.resources.led_blue.set_high().ok();
+        } else if no_toggled % 8 == 1{
+            rprintln!("Green-yellow"); //Needs more oomph to be real yellow.
+            cx.resources.led_red.set_high().ok();
+            cx.resources.led_green.set_high().ok();
+            cx.resources.led_blue.set_low().ok();
+        } else if no_toggled % 8 == 2{
+            rprintln!("Purple");
+            cx.resources.led_red.set_high().ok();
+            cx.resources.led_green.set_low().ok();
+            cx.resources.led_blue.set_high().ok();
+        } else if no_toggled % 8 == 3{
+            rprintln!("Light blue");
+            cx.resources.led_red.set_low().ok();
+            cx.resources.led_green.set_high().ok();
+            cx.resources.led_blue.set_high().ok();
+        } else if no_toggled % 8 == 4{
+            rprintln!("Red");
+            cx.resources.led_red.set_high().ok();
+            cx.resources.led_green.set_low().ok();
+            cx.resources.led_blue.set_low().ok();
+        } else if no_toggled % 8 == 5{
+            rprintln!("Green");
+            cx.resources.led_red.set_low().ok();
+            cx.resources.led_green.set_high().ok();
+            cx.resources.led_blue.set_low().ok();
+        } else if no_toggled % 8 == 6{
+            rprintln!("Blue");
+            cx.resources.led_red.set_low().ok();
+            cx.resources.led_green.set_low().ok();
+            cx.resources.led_blue.set_high().ok();
+        } else {
+            rprintln!("Off");
+            cx.resources.led_red.set_low().ok();
+            cx.resources.led_green.set_low().ok();
+            cx.resources.led_blue.set_low().ok();
+        }
+
+        //*TOGGLE = !*TOGGLE;
+        cx.schedule.toggle(cx.scheduled + OFFSET.cycles(),no_toggled).unwrap();
+    }
+
+    extern "C" {
+        fn EXTI0();
+    }
+};
+
+fn _toggle_generic<E>(led: &mut dyn OutputPin<Error = E>, toggle: &mut bool) {
+    if *toggle {
+        led.set_high().ok();
+    } else {
+        led.set_low().ok();
+    }
+
+    *toggle = !*toggle;
+}
+
+fn _toggleable_generic<E>(led: &mut dyn ToggleableOutputPin<Error = E>) {
+    led.toggle().ok();
+}
+
+// 1. In this example you will use RTT.
+//
+//    > cargo run --example rtic_bare7
+//
+//    Look in the generated documentation for `set_high`/`set_low`.
+//    (You created documentation for your dependencies in previous exercise
+//    so you can just search (press `S`) for `OutputPin`).
+//    You will find that these methods are implemented for `Output` pins.
+//
+//    Now change your code to use these functions instead of the low-level GPIO API.
+//
+//    HINTS:
+//    - A GPIOx peripheral can be `split` into individual PINs Px0..Px15).
+//    - A Pxy, can be turned into an `Output` by `into_push_pull_output`.
+//    - You may optionally set other pin properties as well (such as `speed`).
+//    - An `Output` pin provides `set_low`/`set_high`
+//    - Instead of passing `GPIO` resource to the `toggle` task pass the
+//      `led: PA5<Output<PushPull>>` resource instead.
+//
+//    Comment your code to explain the steps taken.
+//
+//    Confirm that your implementation correctly toggles the LED as in
+//    previous exercise.
+//
+//    Commit your code (bare7_1)
+//
+// 2. Further generalizations:
+//
+//    Now look at the documentation for `embedded_hal::digital::v2::OutputPin`.
+//
+//    You see that the OutputPin trait defines `set_low`/`set_high` functions.
+//    Your task is to alter the code to use the `set_low`/`set_high` API.
+//
+//    The function `_toggle_generic` is generic to any object that
+//    implements the `OutputPin<Error = E>` trait.
+//
+//    Digging deeper we find the type parameter `E`, which in this case
+//    is left generic (unbound).
+//
+//    It will be instantiated with a concrete type argument when called.
+//
+//    Our `PA5<Output<PushPull>>` implements `OutputPin` trait, thus
+//    we can pass the `led` resource to `_toggle_generic`.
+//    
+//    The error type is given by the stm32f4xx-hal implementation:
+//    where `core::convert::Infallible` is used to indicate
+//    there are no errors to be expected (hence infallible).
+//
+//    Additionally, `_toggle_generic` takes a mutable reference
+//    `toggle: &mut bool`, so you need to pass your `TOGGLE` variable.
+//
+//    As you see, `TOGGLE` holds the "state", switching between
+//    `true` and `false` (to make your led blink).
+//
+//    Change your code into using the `_toggle_generic` function.
+//    (You may rename it to `toggle_generic` if wished.)
+//
+//    Confirm that your implementation correctly toggles the LED as in
+//    previous exercise.
+//
+//    Commit your code (bare7_2)
+//
+// 3. What about the state?
+//
+//    In your code `TOGGLE` holds the "state". However, the underlying
+//    hardware ALSO holds the state (if the corresponding bit is set/cleared).
+//
+//    What if we can leverage that, and guess what we can!!!!
+//
+//    Look at the documentation for `embedded_hal::digital::v2::ToggleableOutputPin`,
+//    and the implementation of:
+//
+//    fn _toggleable_generic(led: &mut dyn ToggleableOutputPin<Error = Infallible>) {
+//      led.toggle().ok();
+//    }
+//
+//    The latter does not take any state variable, instead it directly `toggle()`
+//    the `ToggleableOutputPin`.
+//
+//    Now alter your code to leverage on the `_toggleable_generic` function.
+//    (You should be able to remove the `TOGGLE` state variable altogether.)
+//
+//    Confirm that your implementation correctly toggles the LED as in
+//    previous exercise.
+//
+//    Commit your code (bare7_3)
+//
+// 4. Discussion:
+//
+//    In this exercise you have gone from a very hardware specific implementation,
+//    to leveraging abstractions (batteries included).
+//
+//    Your final code amounts to "configuration" rather than "coding".
+//
+//    This reduces the risk of errors (as you let the libraries do the heavy lifting).
+//
+//    This also improves code-re use. E.g., if you were to do something less
+//    trivial then merely toggling you can do that in a generic manner,
+//    breaking out functionality into "components" re-usable in other applications.
+//
+//    Of course the example is trivial, you don't gain much here, but the principle
+//    is the same behind drivers for USART communication, USB, PMW3389 etc.
+//
+// 5. More details:
+//    
+//    Looking closer at the implementation:
+//    `led: &mut dyn OutputPin<Error = E>`
+//
+//    You may ask what kind of mumbo jumbo is at play here.
+//
+//    This is the way to express that we expect a mutable reference to a trait object 
+//    that implements the `OutputPin`. Since we will change the underlying object
+//    (in this case an GPIOA pin 5) the reference needs to be mutable.
+// 
+//    Trait objects are further explained in the Rust book.
+//    The `dyn` keyword indicates dynamic dispatch (through a VTABLE).
+//    https://doc.rust-lang.org/std/keyword.dyn.html
+//
+//    Notice: the Rust compiler (rustc + LLVM) is really smart. In many cases
+//    it can analyse the call chain, and conclude the exact trait object type at hand.
+//    In such cases the dynamic dispatch is turned into a static dispatch
+//    and the VTABLE is gone, and we have a zero-cost abstraction.
+//
+//    If the trait object is stored for e.g., in an array along with other
+//    trait objects (of different concrete type), there is usually no telling
+//    the concrete type of each element, and we will have dynamic dispatch.
+//    Arguably, this is also a zero-cost abstraction, as there is no (obvious)
+//    way to implement it more efficiently. Remember, zero-cost is not without cost
+//    just that it is as good as it possibly gets (you can't make it better by hand).
+//
+//    You can also force the compiler to deduce the type at compile time, by using
+//    `impl` instead of `dyn`, if you are sure you don't want the compiler to
+//    "fallback" to dynamic dispatch.
+//
+//    You might find Rust to have long compile times. Yes you are right,
+//    and this type of deep analysis done in release mode is part of the story.
+//    On the other hand, the aggressive optimization allows us to code 
+//    in a generic high level fashion and still have excellent performing binaries.
\ No newline at end of file
diff --git a/examples/green_to_blink2.rs b/examples/green_to_blink2.rs
new file mode 100644
index 0000000..040bfb1
--- /dev/null
+++ b/examples/green_to_blink2.rs
@@ -0,0 +1,195 @@
+//! bare8.rs
+//!
+//! Serial
+//!
+//! What it covers:
+//! - serial communication
+//! - bad design
+
+#![no_main]
+#![no_std]
+
+use panic_rtt_target as _;
+
+
+use stm32f4xx_hal::{
+    gpio::{gpioa::PA, Output, PushPull},
+    prelude::*,
+    serial::{config::Config, Rx, Serial, Tx},
+    stm32::USART2,
+    nb::block,
+};
+
+use rtic::app;
+use rtt_target::{rprintln, rtt_init_print};
+
+#[app(device = stm32f4xx_hal::stm32, peripherals = true)]
+const APP: () = {
+    struct Resources {
+        // Late resources
+        TX: Tx<USART2>,
+        RX: Rx<USART2>,
+    }
+
+    // init runs in an interrupt free section
+    #[init]
+    fn init(cx: init::Context) -> init::LateResources {
+        rtt_init_print!();
+        rprintln!("init");
+
+        let device = cx.device;
+
+        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 serial = Serial::usart2(
+            device.USART2,
+            (tx, rx),
+            Config::default().baudrate(115_200.bps()),
+            clocks,
+        )
+        .unwrap();
+
+        // Separate out the sender and receiver of the serial port
+        let (tx, rx) = serial.split();
+
+        // Late resources
+        init::LateResources { TX: tx, RX: rx }
+    }
+
+    // idle may be interrupted by other interrupts/tasks in the system
+    #[idle(resources = [RX, TX])]
+    fn idle(cx: idle::Context) -> ! {
+        let rx = cx.resources.RX;
+        let tx = cx.resources.TX;
+        let mut received = 0;
+        let mut errors = 0;
+
+        loop {
+            match block!(rx.read()) {
+                Ok(byte) => {
+                    rprintln!("Ok {:?}", byte);
+                    tx.write(byte).unwrap();
+                    received +=1;
+                }
+                Err(err) => {
+                    rprintln!("Error {:?}", err);
+                    let test:u8 = 13;
+                    tx.write(test).unwrap();
+                    errors +=1;
+                }
+            }
+            rprintln!("Numbers of received: {:?}", received);
+            rprintln!("Numbers of errors: {:?}", errors);
+        }
+    }
+};
+
+// 0. Background
+//
+//    The Nucleo st-link programmer provides a Virtual Com Port (VCP).
+//    It is connected to the PA2(TX)/PA3(RX) pins of the stm32f401/411.
+//    On the host, the VCP is presented under `/dev/ttyACMx`, where
+//    `x` is an enumerated number (ff 0 is busy it will pick 1, etc.)
+//
+// 1. In this example we use RTT.
+//
+//    > cargo run --example rtic_bare8
+//
+//    Start a terminal program, e.g., `moserial`.
+//    Connect to the port
+//
+//    Device       /dev/ttyACM0
+//    Baude Rate   115200
+//    Data Bits    8
+//    Stop Bits    1
+//    Parity       None
+//
+//    This setting is typically abbreviated as 115200 8N1.
+//
+//    Send a single character (byte), (set the option `No end` in `moserial`).
+//    Verify that sent bytes are echoed back, and that RTT tracing is working.
+//
+//    Try sending "a", don't send the quotation marks, just a.
+//
+//    What do you receive in `moserial`?
+//
+//      I can't run moserial (Windows). But PuTTY seems to get a.
+//
+//    What do you receive in the RTT terminal?
+//
+//      OK 97
+//
+//    Try sending: "abcd" as a single sequence, don't send the quotation marks, just abcd.
+//
+//    What did you receive in `moserial`?
+//
+//      	ad (Running PuTTY. Not moserial)
+//
+//    What do you receive in the RTT terminal?
+//
+//      Ok 97
+//      Error Overrun
+//      Ok 100
+//
+//    What do you believe to be the problem?
+//
+//    Hint: Look at the code in `idle` what does it do?
+//
+//      The buffer have not been read from and has not been cleared.
+//
+//    Experiment a bit, what is the max length sequence you can receive without errors?
+//
+//      8 bits or 1 byte.
+//
+//    Commit your answers (bare8_1)
+//
+// 2. Add a local variable `received` that counts the number of bytes received.
+//    Add a local variable `errors` that counts the number of errors.
+//
+//    Adjust the RTT trace to print the added information inside the loop.
+//
+//    Compile/run reconnect, and verify that it works as intended.
+//
+//    Commit your development (bare8_2)
+//
+// 3. Experiment a bit, what is the max length sequence you can receive without errors?
+//
+//      1
+//
+//    How did the added tracing/instrumentation affect the behavior?
+//
+//      I now only receive a back.
+//
+//    Commit your answer (bare8_3)
+//
+// 4. Now try compile and run the same experiment 3 but in --release mode.
+//
+//    > cargo run --example rtic_bare8 --release
+//
+//    Reconnect your `moserial` terminal.
+//
+//    Experiment a bit, what is the max length sequence you can receive without errors?
+//
+//      Now I receive "ad" again
+//
+//    Commit your answer (bare8_4)
+//
+// 5. Discussion
+//
+//    (If you ever used Arduino, you might feel at home with the `loop` and poll design.)
+//
+//    Typically, this is what you can expect from a polling approach, if you
+//    are not very careful what you are doing. This exemplifies a bad design.
+//
+//    Loss of data might be Ok for some applications but this typically NOT what we want.
+//
+//    (With that said, Arduino gets away with some simple examples as their drivers do
+//    internal magic - buffering data etc.)
diff --git a/examples/rtic_bare6.rs b/examples/rtic_bare6.rs
index 255ff36..4faa076 100644
--- a/examples/rtic_bare6.rs
+++ b/examples/rtic_bare6.rs
@@ -98,7 +98,7 @@ const APP: () = {
         rprintln!("toggle  @ {:?}", Instant::now());
 
         if *TOGGLE {
-            cx.resources.GPIOA.bsrr.write(|w| w.bs5().set_bit());
+            cx.resources.GPIOA.bsrr.write(|w| w.bs5z().set_bit());
         } else {
             cx.resources.GPIOA.bsrr.write(|w| w.br5().set_bit());
         }
diff --git a/examples/rtic_bare7.rs b/examples/rtic_bare7.rs
index 0f2dea1..50b167a 100644
--- a/examples/rtic_bare7.rs
+++ b/examples/rtic_bare7.rs
@@ -8,6 +8,7 @@
 #![no_main]
 #![no_std]
 
+
 use panic_rtt_target as _;
 use rtic::cyccnt::{Instant, U32Ext as _};
 use rtt_target::{rprintln, rtt_init_print};
@@ -17,7 +18,7 @@ use stm32f4xx_hal::{
     gpio::{gpioa::PA5, Output, PushPull},
     prelude::*,
 };
-;
+
 use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin};
 
 const OFFSET: u32 = 8_000_000;
@@ -26,17 +27,19 @@ const OFFSET: u32 = 8_000_000;
 const APP: () = {
     struct Resources {
         // late resources
-        GPIOA: stm32::GPIOA,
-        // led: PA5<Output<PushPull>>,
+        //GPIOA: stm32::GPIOA,
+        led: PA5<Output<PushPull>>,
     }
     #[init(schedule = [toggle])]
     fn init(cx: init::Context) -> init::LateResources {
         rtt_init_print!();
         rprintln!("init");
 
+
         let mut core = cx.core;
         let device = cx.device;
 
+
         // Initialize (enable) the monotonic timer (CYCCNT)
         core.DCB.enable_trace();
         core.DWT.enable_cycle_counter();
@@ -46,16 +49,21 @@ const APP: () = {
         let now = cx.start; // the start time of the system
 
         // Schedule `toggle` to run 8e6 cycles (clock cycles) in the future
-        cx.schedule.toggle(now + OFFSET.cycles()).unwrap();
+        let number_of_toggles = 0;
+        cx.schedule.toggle(now + OFFSET.cycles(),number_of_toggles).unwrap();
 
         // 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 gpioa = device.GPIOA.split();
+        
         // pass on late resources
         init::LateResources {
-            GPIOA: device.GPIOA,
+            //GPIOA: device.GPIOA,
+            led: gpioa.pa5.into_push_pull_output(),
         }
     }
 
@@ -67,19 +75,25 @@ const APP: () = {
         }
     }
 
-    #[task(resources = [GPIOA], schedule = [toggle])]
-    fn toggle(cx: toggle::Context) {
+    #[task(resources = [led], schedule = [toggle])]
+    fn toggle(cx: toggle::Context, mut no_toggled: i32) {
         static mut TOGGLE: bool = false;
         rprintln!("toggle  @ {:?}", Instant::now());
+        rprintln!("times I have toggled {:?}", no_toggled);
+        no_toggled +=1;
 
+        /*
         if *TOGGLE {
-            cx.resources.GPIOA.bsrr.write(|w| w.bs5().set_bit());
+            cx.resources.led.set_high();
         } else {
-            cx.resources.GPIOA.bsrr.write(|w| w.br5().set_bit());
+            cx.resources.led.set_low();
         }
+        */
+
+        _toggleable_generic(cx.resources.led);
 
-        *TOGGLE = !*TOGGLE;
-        cx.schedule.toggle(cx.scheduled + OFFSET.cycles()).unwrap();
+        //*TOGGLE = !*TOGGLE;
+        cx.schedule.toggle(cx.scheduled + OFFSET.cycles(),no_toggled).unwrap();
     }
 
     extern "C" {
diff --git a/examples/rtic_bare8.rs b/examples/rtic_bare8.rs
index b4b18ee..040bfb1 100644
--- a/examples/rtic_bare8.rs
+++ b/examples/rtic_bare8.rs
@@ -11,13 +11,13 @@
 
 use panic_rtt_target as _;
 
-use nb::block;
 
 use stm32f4xx_hal::{
     gpio::{gpioa::PA, Output, PushPull},
     prelude::*,
     serial::{config::Config, Rx, Serial, Tx},
     stm32::USART2,
+    nb::block,
 };
 
 use rtic::app;
@@ -69,17 +69,25 @@ const APP: () = {
     fn idle(cx: idle::Context) -> ! {
         let rx = cx.resources.RX;
         let tx = cx.resources.TX;
+        let mut received = 0;
+        let mut errors = 0;
 
         loop {
             match block!(rx.read()) {
                 Ok(byte) => {
                     rprintln!("Ok {:?}", byte);
                     tx.write(byte).unwrap();
+                    received +=1;
                 }
                 Err(err) => {
                     rprintln!("Error {:?}", err);
+                    let test:u8 = 13;
+                    tx.write(test).unwrap();
+                    errors +=1;
                 }
             }
+            rprintln!("Numbers of received: {:?}", received);
+            rprintln!("Numbers of errors: {:?}", errors);
         }
     }
 };
@@ -113,31 +121,33 @@ const APP: () = {
 //
 //    What do you receive in `moserial`?
 //
-//    ** your answer here **
+//      I can't run moserial (Windows). But PuTTY seems to get a.
 //
 //    What do you receive in the RTT terminal?
 //
-//    ** your answer here **
+//      OK 97
 //
 //    Try sending: "abcd" as a single sequence, don't send the quotation marks, just abcd.
 //
 //    What did you receive in `moserial`?
 //
-//    ** your answer here **
+//      	ad (Running PuTTY. Not moserial)
 //
 //    What do you receive in the RTT terminal?
 //
-//    ** your answer here **
+//      Ok 97
+//      Error Overrun
+//      Ok 100
 //
 //    What do you believe to be the problem?
 //
 //    Hint: Look at the code in `idle` what does it do?
 //
-//    ** your answer here **
+//      The buffer have not been read from and has not been cleared.
 //
 //    Experiment a bit, what is the max length sequence you can receive without errors?
 //
-//    ** your answer here **
+//      8 bits or 1 byte.
 //
 //    Commit your answers (bare8_1)
 //
@@ -152,11 +162,11 @@ const APP: () = {
 //
 // 3. Experiment a bit, what is the max length sequence you can receive without errors?
 //
-//    ** your answer here **
+//      1
 //
 //    How did the added tracing/instrumentation affect the behavior?
 //
-//    ** your answer here **
+//      I now only receive a back.
 //
 //    Commit your answer (bare8_3)
 //
@@ -168,7 +178,7 @@ const APP: () = {
 //
 //    Experiment a bit, what is the max length sequence you can receive without errors?
 //
-//    ** your answer here **
+//      Now I receive "ad" again
 //
 //    Commit your answer (bare8_4)
 //
diff --git a/examples/rtic_bare9.rs b/examples/rtic_bare9.rs
index a1fc61c..6c3d4bb 100644
--- a/examples/rtic_bare9.rs
+++ b/examples/rtic_bare9.rs
@@ -13,17 +13,23 @@ use stm32f4xx_hal::{
     prelude::*,
     serial::{config::Config, Event, Rx, Serial, Tx},
     stm32::USART2,
+    nb::block,
 };
 
 use rtic::app;
 use rtt_target::{rprintln, rtt_init_print};
 
+
 #[app(device = stm32f4xx_hal::stm32, peripherals = true)]
 const APP: () = {
     struct Resources {
         // Late resources
         TX: Tx<USART2>,
         RX: Rx<USART2>,
+        #[init(0)]
+        fel: u32,
+        #[init(0)]
+        corr: u32,
     }
 
     // init runs in an interrupt free section
@@ -59,7 +65,7 @@ const APP: () = {
         let (tx, rx) = serial.split();
 
         // Late resources
-        init::LateResources { TX: tx, RX: rx }
+        init::LateResources { TX: tx, RX: rx}
     }
 
     // idle may be interrupted by other interrupts/tasks in the system
@@ -71,23 +77,51 @@ const APP: () = {
     }
 
     // capacity sets the size of the input buffer (# outstanding messages)
-    #[task(resources = [TX], priority = 1, capacity = 128)]
-    fn rx(cx: rx::Context, data: u8) {
+    #[task(resources = [TX], priority = 2, capacity = 128)]
+    fn rx(cx: rx::Context,data:u8) {
         let tx = cx.resources.TX;
         tx.write(data).unwrap();
+    }
+
+    #[task(priority = 1,resources = [fel,corr])]
+    fn trace(cx: trace::Context, worked: bool,data:u8,){
+        match worked{
+            true => {
+                *cx.resources.corr +=1;
+                rprintln!("Ok {:?}", data);
+            }
+            false =>{
+                *cx.resources.fel +=1;
+                rprintln!("some error");
+            }
+        }
+        rprintln!("correct {}", cx.resources.corr);
+        rprintln!("errors {}", cx.resources.fel);
         rprintln!("data {}", data);
     }
 
     // Task bound to the USART2 interrupt.
-    #[task(binds = USART2,  priority = 2, resources = [RX], spawn = [rx])]
+    #[task(binds = USART2,  priority = 3, resources = [RX], spawn = [rx,trace])]
     fn usart2(cx: usart2::Context) {
         let rx = cx.resources.RX;
-        let data = rx.read().unwrap();
+        let data;
+        match (rx.read()) {
+            Ok(byte) => {
+                data = byte;
+                let result = cx.spawn.trace(true,byte);
+            }
+            Err(err) => {
+                data = 0;
+                rprintln!("Error {:?}", err);
+                cx.spawn.trace(false,data).unwrap();
+            }
+        }
         cx.spawn.rx(data).unwrap();
     }
 
     extern "C" {
         fn EXTI0();
+        fn USART1();
     }
 };
 
@@ -148,7 +182,7 @@ const APP: () = {
 //
 //    Were you able to crash it?
 //
-//    ** your answer here **
+//        Yes
 //
 //    Notice, the input tracing in `moserial` seems broken, and may loose data.
 //    So don't be alarmed if data is missing, its a GUI tool after all.
diff --git a/src/main.rs b/src/main.rs
index 7922596..04dfbf9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,20 +1,117 @@
+#![deny(unsafe_code)]
+#![deny(warnings)]
 #![no_std]
 #![no_main]
 
-// pick a panicking behavior
-use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
-// use panic_abort as _; // requires nightly
+// pick a panicking behavior// use panic_abort as _; // requires nightly
 // use panic_itm as _; // logs messages over ITM; requires ITM support
 // use panic_semihosting as _; // logs messages to the host stderr; requires a debugger
 
-use cortex_m::asm;
-use cortex_m_rt::entry;
 
-#[entry]
-fn main() -> ! {
-    asm::nop(); // To not have main optimize to abort in release mode, remove when you add code
+use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
+use rtt_target::{rprintln, rtt_init_print};
+
+
+use cortex_m::peripheral::DWT;
+use stm32f4xx_hal::stm32;
+
+//use cortex_m::asm;
+//use cortex_m_rt::entry;
+
+use rtic::cyccnt::{Instant, U32Ext as _};
+
+
+#[rtic::app(device = stm32f4xx_hal::stm32, monotonic = rtic::cyccnt::CYCCNT, peripherals = true)]
+const APP: () = {
+    struct Resources {
+        // late resources
+        GPIOA: stm32::GPIOA,
+        GPIOC: stm32::GPIOC,
+        //button: <stm32::GPIOC as int>::PC13,
+    }
+
+    #[init(schedule = [toggle])]
+    fn init(cx: init::Context) -> init::LateResources {
+        rtt_init_print!();
+        rprintln!("init");
+
+        for i in 0..11 {
+            rprintln!("RTIC Says Hello, world {}!!", i);
+        }
+
+        let mut core = cx.core;
+        let device = cx.device;
+
+        
+        // Initialize (enable) the monotonic timer (CYCCNT)
+        core.DCB.enable_trace();
+        // required on Cortex-M7 devices that software lock the DWT (e.g. STM32F7)
+        DWT::unlock();
+        core.DWT.enable_cycle_counter();
 
-    loop {
-        // your code goes here
+        // semantically, the monotonic timer is frozen at time "zero" during `init`
+        // NOTE do *not* call `Instant::now` in this context; it will return a nonsense value
+        let now = cx.start; // the start time of the system
+
+        // Schedule `toggle` to run 8e6 cycles (clock cycles) in the future
+        cx.schedule.toggle(now + 8_000_000.cycles()).unwrap();
+
+        // 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));
+
+        // Test button thingy. Think I put PC13 to input
+        device.GPIOC.moder.modify(|_, w| w.moder13().bits(0));
+        // device.GPIOC.pupdr.modify(|_, w| w.pupdr13().bits(0));
+        
+        // pass on late resources
+        init::LateResources {
+            GPIOA: device.GPIOA,
+            GPIOC: device.GPIOC,
+            //button: device.button,
+        }
     }
-}
+
+    
+    #[idle]
+    fn idle(_cx: idle::Context) -> ! {
+        rprintln!("lets get lazy");
+        loop {
+            continue;
+        }
+    }
+    
+    
+
+    #[task(resources = [GPIOA,GPIOC], schedule = [toggle])]
+    fn toggle(cx: toggle::Context) {
+        static mut TOGGLE: bool = false;
+        rprintln!("toggle  @ {:?}", Instant::now());
+
+        if *TOGGLE {
+            cx.resources.GPIOA.bsrr.write(|w| w.bs5().set_bit());
+        } else {
+            cx.resources.GPIOA.bsrr.write(|w| w.br5().set_bit());
+        }
+
+<<<<<<< HEAD
+=======
+        //cx.resources.GPIOC.PullDown;
+
+>>>>>>> 3104a68743e72194c1e8649cdee76a82240fc05e
+        *TOGGLE = !*TOGGLE;
+        cx.schedule
+            .toggle(cx.scheduled + 16_000_000.cycles())
+            .unwrap();
+<<<<<<< HEAD
+=======
+        
+>>>>>>> 3104a68743e72194c1e8649cdee76a82240fc05e
+    }
+
+    extern "C" {
+        fn EXTI0();
+    }
+};
+
-- 
GitLab