From 48bb15cc0edabd3469154c689d16dc791bed0db8 Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Sun, 6 Jan 2019 23:45:39 +0100
Subject: [PATCH] bare6 wip

---
 .vscode/launch.json |  84 ++++++++++++++++-
 .vscode/tasks.json  |  12 +++
 examples/bare5.rs   |  45 +++++----
 examples/bare6.rs   | 224 ++++++++++++++++++++++++++++++++++++++++++++
 examples/device.rs  |   7 --
 examples/itm.rs     |   7 +-
 6 files changed, 342 insertions(+), 37 deletions(-)
 create mode 100644 examples/bare6.rs

diff --git a/.vscode/launch.json b/.vscode/launch.json
index e793d8c..56464e7 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -352,7 +352,64 @@
             "type": "cortex-debug",
             "request": "launch",
             "servertype": "openocd",
-            "name": "c bare6 84Mhz",
+            "name": "bare6 (debug) 16Mhz",
+            "preLaunchTask": "cargo build --example bare6 --features stm32f4",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare6",
+            "configFiles": [
+                "interface/stlink.cfg",
+                "target/stm32f4x.cfg"
+            ],
+            "postLaunchCommands": [
+                "monitor reset halt"
+            ],
+            "swoConfig": {
+                "enabled": true,
+                "cpuFrequency": 16000000,
+                "swoFrequency": 2000000, // you may try 1000000 if not working
+                "source": "probe",
+                "decoders": [
+                    {
+                        "type": "console",
+                        "label": "ITM",
+                        "port": 0
+                    }
+                ]
+            },
+            "cwd": "${workspaceRoot}"
+        },
+        {
+            "type": "cortex-debug",
+            "request": "launch",
+            "servertype": "openocd",
+            "name": "bare6 (debug) 64Mhz",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare6",
+            "configFiles": [
+                "interface/stlink.cfg",
+                "target/stm32f4x.cfg"
+            ],
+            "postLaunchCommands": [
+                "monitor reset init"
+            ],
+            "swoConfig": {
+                "enabled": true,
+                "cpuFrequency": 64000000,
+                "swoFrequency": 2000000, // you may try 1000000 if not working
+                "source": "probe",
+                "decoders": [
+                    {
+                        "type": "console",
+                        "label": "ITM",
+                        "port": 0
+                    }
+                ]
+            },
+            "cwd": "${workspaceRoot}"
+        },
+        {
+            "type": "cortex-debug",
+            "request": "launch",
+            "servertype": "openocd",
+            "name": "bare6 (debug) 84Mhz",
             "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare6",
             "configFiles": [
                 "interface/stlink.cfg",
@@ -366,6 +423,31 @@
                 "cpuFrequency": 84000000,
                 "swoFrequency": 2000000, // you may try 1000000 if not working
                 "source": "probe",
+                "decoders": [
+                    {
+                        "type": "console",
+                        "label": "ITM",
+                        "port": 0
+                    }
+                ]
+            },
+            "cwd": "${workspaceRoot}"
+        },
+        {
+            "type": "cortex-debug",
+            "request": "launch",
+            "servertype": "openocd",
+            "name": "bare7 (debug) 16Mhz",
+            "executable": "./target/thumbv7em-none-eabihf/debug/examples/bare7",
+            "configFiles": [
+                "interface/stlink.cfg",
+                "target/stm32f4x.cfg"
+            ],
+            "swoConfig": {
+                "enabled": true,
+                "cpuFrequency": 16000000,
+                "swoFrequency": 2000000, // you may try 1000000 if not working
+                "source": "probe",
                 "decoders": [
                     {
                         "type": "console",
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index acffa43..841b615 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -183,5 +183,17 @@
                 "isDefault": true
             }
         },
+        {
+            "type": "shell",
+            "label": "cargo build --example bare6 --features stm32f4",
+            "command": "cargo build --example bare6 --features stm32f4",
+            "problemMatcher": [
+                "$rustc"
+            ],
+            "group": {
+                "kind": "build",
+                "isDefault": true
+            }
+        },
     ]
 }
\ No newline at end of file
diff --git a/examples/bare5.rs b/examples/bare5.rs
index d1a67f0..b55ee6b 100644
--- a/examples/bare5.rs
+++ b/examples/bare5.rs
@@ -136,25 +136,25 @@ fn wait(i: u32) {
 
 // simple test of Your `modify`
 //fn test() {
-    // let t:VolatileCell<u32> = unsafe {  core::mem::uninitialized() };
-    // t.write(0);
-    // assert!(t.read() == 0);
-    // t.modify(3, 3, 0b10101);
-    // //
-    // //     10101   
-    // //    ..0111000
-    // //    ---------
-    // //    000101000
-    // assert!(t.read() == 0b101 << 3);
-    // t.modify(4, 3, 0b10001);
-    // //    000101000
-    // //      111
-    // //      001
-    // //    000011000
-    // assert!(t.read() == 0b011 << 3);
-    
-    // if << is used, your code will panic in dev, but not in release mode
-    // t.modify(32, 3, 1);
+// let t:VolatileCell<u32> = unsafe {  core::mem::uninitialized() };
+// t.write(0);
+// assert!(t.read() == 0);
+// t.modify(3, 3, 0b10101);
+// //
+// //     10101
+// //    ..0111000
+// //    ---------
+// //    000101000
+// assert!(t.read() == 0b101 << 3);
+// t.modify(4, 3, 0b10001);
+// //    000101000
+// //      111
+// //      001
+// //    000011000
+// assert!(t.read() == 0b011 << 3);
+
+// if << is used, your code will panic in dev, but not in release mode
+// t.modify(32, 3, 1);
 //}
 
 // system startup, can be hidden from the user
@@ -163,7 +163,6 @@ fn main() -> ! {
     let rcc = unsafe { &mut *RCC::get() }; // get the reference to RCC in memory
     let gpioa = unsafe { &mut *GPIOA::get() }; // get the reference to GPIOA in memory
 
-
     // test(); // uncomment to run test
     idle(rcc, gpioa);
     loop {}
@@ -227,9 +226,9 @@ fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) {
 //
 //    Discussion:
 //    As with algebraic operations, defalut semantics differ in between
-//    debug/dev and release builds. E.g., debug << rhs is checked, rhs must be less 
+//    debug/dev and release builds. E.g., debug << rhs is checked, rhs must be less
 //    than 32 (for 32 bit datatypes).
-// 
+//
 //    Notice, over-shifting (where bits are spilled) is always considered legal,
 //    its just the shift amuount that is checked.
-//    There are explicit unchecked versions available if so wanted.
\ No newline at end of file
+//    There are explicit unchecked versions available if so wanted.
diff --git a/examples/bare6.rs b/examples/bare6.rs
new file mode 100644
index 0000000..f2d6f75
--- /dev/null
+++ b/examples/bare6.rs
@@ -0,0 +1,224 @@
+//! 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;
+
+// use cortex_m_semihosting::hprintln;
+use stm32f4::stm32f411;
+use stm32f411::{DWT, GPIOA, NVIC, /* interrupt, Peripherals,  Interrupt, ITM, */ RCC};
+
+#[entry]
+fn main() -> ! {
+    let p = stm32f411::Peripherals::take().unwrap();
+    let mut c = stm32f411::CorePeripherals::take().unwrap();
+
+    //p.GPIOA.odr.write(|w| w.bits(1));
+
+    //let stim = &mut p.
+
+    let stim = &mut c.ITM.stim[0];
+    iprintln!(stim, "Hello, bare6!");
+
+    // // let dwt = unsafe { &mut *DWT.get() }; // get the reference to DWD in memory
+    // // let rcc = unsafe { &mut *RCC.get() }; // get the reference to RCC in memory
+    // // let gpioa = unsafe { &mut *GPIOA.get() }; // get the reference to GPIOA in memory
+    // // let gpioc = unsafe { &mut *GPIOC.get() }; // get the reference to GPIOC in memory
+    // // let flash = unsafe { &mut *FLASH.get() }; // get the reference to FLASH in memory
+
+    // p.DWT.enable_cycle_counter();
+    // // clock_out(rcc, gpioc);
+    // // //clock::set_84_mhz(rcc, flash);
+    idle(stim, c.DWT, p.RCC, p.GPIOA);
+
+    loop {}
+}
+
+// // user application
+fn idle(stim: &mut Stim, dwt: DWT, 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, 8000_0000 cycles = period 0.5s
+    // at 64 Mhz, 8000_0000 cycles = period 0.125s
+    let cycles = 8000_0000;
+    loop {
+        //  ipln!("led on");
+        // set PA5 high, RM0368 8.4.7
+        gpioa.bsrr.write(|w| w.bs5().set_bit());
+        wait_cycles(&dwt, cycles);
+
+        // ipln!("led off");
+        // set PA5 low, RM0368 8.4.7
+        gpioa.bsrr.write(|w| w.br5().set_bit());
+        wait_cycles(&dwt, 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(dwt: &DWT, nr_cycles: u32) {
+    let t = dwt.cyccnt.read().wrapping_add(nr_cycles);
+    while (dwt.cyccnt.read().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: &mut RCC, gpioc: &mut 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| unsafe { 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| unsafe { 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
+//
+// you may use either ITM tracing using ITM dump or internally in
+// vscode using the new "cortex debug" plugin
+//
+// 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
+// (make sure you have the latest openocd v 0.10)
+//
+// 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)
+//
+// what is the frequency of blinking
+// ** your answer here **
+//
+// commit your answers (bare6_3)
+//
+// 4. 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_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
+// ** your answer here **
+//
+// why does it differ?
+// ** 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)
diff --git a/examples/device.rs b/examples/device.rs
index baf5ca2..f78e482 100644
--- a/examples/device.rs
+++ b/examples/device.rs
@@ -12,13 +12,6 @@
 //!
 //! [`stm32f103xx`]: https://crates.io/crates/stm32f103xx
 //!
-//! ```
-//! $ edit Cargo.toml && tail $_
-//! [dependencies.stm32f103xx]
-//! features = ["rt"]
-//! version = "0.10.0"
-//! ```
-//!
 //! ---
 
 #![no_main]
diff --git a/examples/itm.rs b/examples/itm.rs
index ab3e188..b4c9401 100644
--- a/examples/itm.rs
+++ b/examples/itm.rs
@@ -1,12 +1,7 @@
-//! Sends "Hello, world!" through the ITM port 0
+//! Sends "Hello, agian!" over the ITM port 0
 //!
 //! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
 //!
-//! **NOTE** Cortex-M0 chips don't support ITM.
-//!
-//! You'll have to connect the microcontroller's SWO pin to the SWD interface. Note that some
-//! development boards don't provide this option.
-//!
 //! You'll need [`itmdump`] to receive the message on the host plus you'll need to uncomment two
 //! `monitor` commands in the `.gdbinit` file.
 //!
-- 
GitLab