Skip to content
Snippets Groups Projects
Select Git revision
  • d4e09f746c13b216da5faa0955f30198ca236cbd
  • student default protected
2 results

bare7.rs

Blame
  • Forked from Per Lindgren / e7020e_2019
    Source project has a limited visibility.
    bare7.rs 7.07 KiB
    //! bare7.rs
    //! 
    //! Serial echo
    //!
    //! What it covers:
    //! - changing the clock using Rust code
    //! - working with the svd2rust API
    //! - working with the HAL (Hardware Abstraction Layer)
    //! - USART polling (blocking wait)
    
    #![deny(unsafe_code)]
    #![no_main]
    #![no_std]
    
    extern crate panic_halt;
    
    use cortex_m::iprintln;
    use cortex_m_rt::entry;
    use nb::block;
    
    extern crate stm32f4xx_hal as hal;
    use crate::hal::prelude::*;
    use crate::hal::serial::{config::Config, Serial};
    
    #[entry]
    fn main() -> ! {
        let mut c = hal::stm32::CorePeripherals::take().unwrap();
        let stim = &mut c.ITM.stim[0];
        iprintln!(stim, "bare7");
    
        let p = hal::stm32::Peripherals::take().unwrap();
    
        let rcc = p.RCC.constrain();
    
        // 16 MHz (default, all clocks)
        let clocks = rcc.cfgr.freeze();
    
        let gpioa = p.GPIOA.split();
    
        let tx = gpioa.pa2.into_alternate_af7();
        let rx = gpioa.pa3.into_alternate_af7(); // try comment out
        // let rx = gpioa.pa3.into_alternate_af6(); // try uncomment
    
        let serial = Serial::usart2(
            p.USART2,
            (tx, rx),
            Config::default().baudrate(115_200.bps()),
            clocks,
        )
        .unwrap();
    
        // Separate out the sender and receiver of the serial port
        let (mut tx, mut rx) = serial.split();
    
        loop {
            match block!(rx.read()) {
                Ok(byte) => {
                    iprintln!(stim, "Ok {:?}", byte);
                    tx.write(byte).unwrap(); 
                }
                Err(err) => {
                    iprintln!(stim, "Error {:?}", err);
                }
            }
        }
    }
    
    // 0. Background reading:
    //    STM32F401xD STM32F401xE, section 3.11
    //    We have two AMBA High-performance Bus (AHB)
    //    APB1 low speed bus (max freq 42 MHz)
    //    APB2 high speed bus (max frex 84 MHz)
    //
    //    RM0368 Section 6.2
    //    Some important/useful clock acronymes and their use:
    //
    //    SYSCLK - the clock that drives the `core`
    //    HCLK   - the clock that drives the AMBA bus(es), memory, DMA, trace unit, etc.
    //
    //    Typically we set HCLK = SYSCLK / 1 (no prescale) for our applications
    //
    //    FCLK   - Free running clock runing at HCLK
    //
    //    CST    - CoreSystemTimer drives the SysTick counter, HCLK/(1 or 8)
    //    PCLK1  - The clock driving the APB1 (<= 42 MHz)
    //             Timers on the APB1 bus will be triggered at PCLK1 * 2
    //    PCLK2  - The clock driving the APB2 (<= 84 MHz)
    //             Timers on the APB2 bus will be triggered at PCLK2
    //
    //    Compliation:
    //    > cargo build --example bare7 --features "hal"
    //    (or use the vscode build task)
    //
    //    The "hal" feature enables the optional dependency stm32f4xx-hal".
    //
    //    Cargo.toml:
    // 
    //    [dependencies.stm32f4]
    //    version = "0.5.0"
    //    features = ["stm32f413", "rt"]
    //    optional = true
    // 
    //    [dependencies.stm32f4xx-hal]
    //    git = "https://github.com/stm32-rs/stm32f4xx-hal.git"
    //    version = "0.2.8"
    //    features = ["stm32f413", "rt"]
    //    optional = true
    //
    //    [features]
    //    pac = ["stm32f4"]
    //    hal = ["stm32f4xx-hal"]
    //
    //    Notice, stm32f4xx-hal internally enables the dependency to stm32f4, 
    //    so we don't need to explicitly enable it.
    //
    //    The HAL provides a generic abstraction over the whole stm32f4 family,
    //    as previously we use the stm32f413, since it also covers stm32f401/stm32f411.
    //
    // 1. The rcc.cfgr.x.freeze() sets the clock according to the configuration x given.
    //
    //    rcc.cfgr.freeze(); sets a default configuration.
    //    sysclk = hclk = pclk1 = pclk2 = 16MHz
    //
    //    What is wrong with the following configurations?
    //
    //    rcc.cfgr.sysclk(64.mhz()).pclk1(64.mhz()).pclk2(64.mhz()).freeze();
    //
    //    ** Max frequency of PCLK1 is 50 MHz **
    //
    //    rcc.cfgr.sysclk(84.mhz()).pclk1(42.mhz()).pclk2(64.mhz()).freeze();
    //
    //    ** Using prescales there is no way of dividing 84 to reach the wanted value of 64 for PCLK2 **
    //
    //    Commit your answers (bare7_1)
    //
    //    Tip: You may use `stm32cubemx` to get a graphical view for experimentation.
    //    This is a good tool when designing your PCB (as pinouts are given).
    //
    // 2. Now give the system with a valid clock, sysclk of 84 MHz.
    //
    //    Include the code for outputting the clock to MCO2.
    //
    //    Repeat the expermient bare6_2.
    //
    //    What is the frequency of MCO2 read by the oscilloscope.
    //
    //    ** your answer here **
    //
    //    Compute the value of SYSCLK based on the oscilloscope reading.
    //
    //    ** your answer here **
    //
    //    What is the peak to peak reading of the signal.
    //
    //    ** your answer here **
    //
    //    Make a screen dump or photo of the oscilloscope output.
    //    Save the the picture as "bare_6_84mhz_high_speed"
    //
    //    Commit your answers (bare7_2)
    //
    // 3. Now reprogram the PC9 to be "Low Speed", and re-run at 84Mz.
    //
    //    Did the frequency change in comparison to assignment 5?
    //
    //    ** your answer here **
    //
    //    What is the peak to peak reading of the signal (and why did it change)?
    //
    //    ** your answer here **
    //
    //    Make a screen dump or photo of the oscilloscope output.
    //    Save the the picture as "bare_6_84mhz_low_speed".
    //
    //    Commit your answers (bare7_3)
    //
    // 4. Revisit the `README.md` regarding serial communication.
    //    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.
    //
    //    Run the example, make sure your ITM is set to 84MHz.
    //
    //    Send a single character (byte), (set the option No end in moserial).
    //    Verify that sent bytes are echoed back, and that ITM tracing is working.
    // 
    //    If not go back check your ITM setting, clocks etc.
    //
    //    Try sending: "abcd" as a single sequence, don't send the quation marks, just abcd.
    //
    //    What did you receive, and what was the output of the ITM trace.
    //
    //    ** your answer here **
    //
    //    Explain why the buffer overflows.
    //
    //    ** your answer here **
    //
    //    commit your answers (bare7_4)
    //
    //    Discussion:
    //    Common to all MCUs is that they have multiple clocking options.
    //    Understanding the possibilities and limitations of clocking is fundamental
    //    to designing both the embedded hardware and software. Tools like
    //    `stm32cubemx` can be helpful to give you the big picture.
    //    You will likely finding it useful when designing your board (e.g., checking
    //    what functionality can be associated to each pin etc.)
    //
    //    The `stm32f4xx-hal` gives you an abstraction for programming,
    //    setting up clocks, assigning pins, etc.
    //
    //    The hal is under development, and already covers some basic functionality
    //    like serial communication. Still, in order to fully understand what is
    //    going on under the hood you need to check the documentation (data sheets,
    //    user manuals etc.)
    //
    //    Your crate can be autmatically documentedthread:
    //
    //    $ cargo doc --open --features "hal"
    //
    //    This will document both your crate and its dependencies besides the `core` library.
    //
    //    You can open the `core` library documentation by
    //
    //    $ rustup doc
    //
    //    or just show the path to the doc (to open it manually)
    //
    //    $ rustup doc --path