Skip to content
Snippets Groups Projects
Select Git revision
  • 4c83d66bc3721acf835b22f3645cf2b4e8fdae23
  • master default protected
2 results

rtic_bare8.rs

Blame
  • Forked from Per Lindgren / e7020e_2021
    Source project has a limited visibility.
    rtic_bare8.rs 5.25 KiB
    //! 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.)