Skip to content
Snippets Groups Projects
Select Git revision
  • 24de0017cead1740f6e17feff5dfdb96f6fddd9d
  • master default protected
  • usb
  • fresk
4 results

bare6.rs

Blame
  • bare6.rs 6.42 KiB
    //! bare6.rs
    //!
    //! Clocking
    //!
    //! What it covers:
    //! - setting the clock via script (again)
    //! - routing the clock to a PIN for monitoring by an oscilloscope
    //! - changing the clock using Rust code
    //!
    
    // #![feature(used)]
    // #![no_std]
    
    // extern crate f4;
    // extern crate stm32f40x;
    
    // #[macro_use]
    // extern crate cortex_m_debug;
    // use f4::clock;
    // use f4::prelude::*;
    // use stm32f40x::{DWT, FLASH, GPIOA, GPIOC, RCC};
    
    #![no_main]
    #![no_std]
    #![feature(uniform_paths)]
    
    extern crate panic_halt;
    
    use cortex_m::{iprint, iprintln, peripheral::itm::Stim, peripheral::syst::SystClkSource};
    use cortex_m_rt::{entry, exception};
    
    use stm32f4::stm32f411;
    use stm32f411::{interrupt,  Interrupt, DWT, GPIOA, GPIOC, ITM, NVIC, RCC, SYST};
    
    
    #[entry]
    fn main() -> ! {
        let p = stm32f411::Peripherals::take().unwrap();
        let mut c = stm32f411::CorePeripherals::take().unwrap();
    
        let stim = &mut c.ITM.stim[0];
        iprintln!(stim, "Hello, bare6!");
    
        c.DWT.enable_cycle_counter();
        unsafe {
            c.DWT.cyccnt.write(0);
        }
        let t = DWT::get_cycle_count();
        iprintln!(stim, "{}", t);
    
        clock_out(&p.RCC, &p.GPIOC);
        // clock::set_84_mhz(rcc, flash);
        idle(stim, p.RCC, p.GPIOA);
    
        loop {}
    }
    
    // // user application
    fn idle(stim: &mut Stim, rcc: RCC, gpioa: GPIOA) {
        iprintln!(stim, "idle");
    
        // power on GPIOA, RM0368 6.3.11
        rcc.ahb1enr.modify(|_, w| w.gpioaen().set_bit());
    
        // configure PA5 as output, RM0368 8.4.1
        gpioa.moder.modify(|_, w| w.moder5().bits(1));
    
        // at 16 Mhz, 8_000_000 cycles = period 0.5s
        // at 64 Mhz, 4*8_000_000 cycles = period 0.55s
        // let cycles = 8_000_000;
        let cycles = 4*8_000_000;
        
        loop {
            iprintln!(stim, "on {}",  DWT::get_cycle_count());
            // set PA5 high, RM0368 8.4.7
            gpioa.bsrr.write(|w| w.bs5().set_bit());
            wait_cycles(cycles);
    
            
            iprintln!(stim, "off {}",  DWT::get_cycle_count());
            // set PA5 low, RM0368 8.4.7
            gpioa.bsrr.write(|w| w.br5().set_bit());
            wait_cycles(cycles);
        }
    }
    
    // uses the DWT.CYCNT
    // doc: ARM trm_100166_0001_00_en.pdf, chapter 9.2
    // we use the `cortex-m` abstraction, as re-exported by the stm32f40x
    fn wait_cycles(nr_cycles: u32) {
        let t = DWT::get_cycle_count().wrapping_add(nr_cycles);
        while (DWT::get_cycle_count().wrapping_sub(t) as i32) < 0 {}
    }
    
    // see the Reference Manual RM0368 (www.st.com/resource/en/reference_manual/dm00096844.pdf)
    // rcc,     chapter 6
    // gpio,    chapter 8
    fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
        // output MCO2 to pin PC9
    
        // mco2 	: SYSCLK = 0b00
        // mcopre 	: divide by 4 = 0b110
        rcc.cfgr
            .modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) });
    
        // power on GPIOC, RM0368 6.3.11
        rcc.ahb1enr.modify(|_, w| w.gpiocen().set_bit());
    
        // MCO_2 alternate function AF0, STM32F401xD STM32F401xE data sheet
        // table 9
        // AF0, gpioc reset value = AF0
    
        // configure PC9 as alternate function 0b10, RM0368 6.2.10
        gpioc.moder.modify(|_, w|  w.moder9().bits(0b10) );
    
        // otyper reset state push/pull, in reset state (don't need to change)
    
        // ospeedr 0b11 = high speed
        gpioc
            .ospeedr
            .modify(|_, w| w.ospeedr9().bits(0b11) );
    }
    
    // 1. Compile and run the example, in 16Mhz
    //    The processor SYSCLK defaults to HCI 16Mhz
    //    (this is what you get after a `monitor reset halt`).
    //
    //    Confirm that your ITM dump traces the init, idle and led on/off.
    //    Make sure your TPIU is set to a system clock at 16Mhz
    //
    //    What is the frequency of blinking?
    //
    //    ** your answer here **
    //
    //    commit your answers (bare6_1)
    //
    // 2. Now connect an oscilloscope to PC9, which is set to
    //    output the MCO2.
    //
    //    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 folder called "pictures" in your git project.
    //    Make a screen dump or photo of the oscilloscope output.
    //    Save the the picture as "bare_6_16mhz_high_speed".
    //
    //    commit your answaaasers (bare6_2)
    //
    // 3. Now run the example in 64Mz
    //    You can do that by issuing a `monitor reset init`
    //    which reprograms SYSCLK to 4*HCI.
    //
    //
    //    Confirm that your ITM dump traces the init, idle and led on/off
    //    (make sure your TPIU is set to a system clock at 64Mhz)
    //
    //    Uncommnet: `let cycles = 4 * 8_000_000;
    //`
    //    What is the frequency of blinking?
    //
    //    ** your answer here **
    //
    //    commit your answers (bare6_3)
    //
    // 4. Repeat experiment 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_64mhz_high_speed".
    //
    //    commit your answers (bare6_4)
    //
    // 5. Now we will put the MCU in 84MHz using the function
    //    clock::set_84_mhz(rcc, flash);
    //
    //    This function is part of the `f4` support crate (by Johonnes Sjölund)
    //    besides `rcc` (for clocking) it takes `flash` as a parameter to set
    //    up correct latency (wait states) for the flash memory (where our
    //    program typically resides). This is required since the flash cannot
    //    operate at the full 84MHz, so the MCU has to wait for the memory.
    //
    //    Repeat the experiment 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 (bare6_5)
    //
    // 6. 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 (bare6_6)