Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • student
1 result

Target

Select target project
  • pln/e7020e_2019
  • Henrik/e7020e_2019
  • wijk/e7020e_2019
  • sheepwall/e7020e_2019
  • Tiberg/e7020e_2019
  • Tyllstrom/e7020e_2019
  • Ridgep/e7020e_2019
7 results
Select Git revision
  • nrf52
  • student
2 results
Show changes
Commits on Source (37)
......@@ -28,7 +28,7 @@ optional = true
[dependencies.cortex-m]
version = "0.5.8"
# features = ["inline-asm"] # <- currently requires nightly compiler
features = ["inline-asm"] # <- currently requires nightly compiler
# Uncomment for the allocator example.
# alloc-cortex-m = "0.3.5"
......@@ -40,7 +40,7 @@ optional = true
[dependencies.stm32f4xx-hal]
git = "https://github.com/stm32-rs/stm32f4xx-hal.git"
version = "0.2.8"
version = "0.3.0"
features = ["stm32f413", "rt"]
optional = true
......
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}
\ No newline at end of file
......@@ -17,9 +17,10 @@ extern crate panic_halt;
// Minimal runtime / startup for Cortex-M microcontrollers
use cortex_m_rt::entry;
use cortex_m_semihosting::hprintln;
// a constant (cannot be changed at run-time)
const X_INIT: u32 = 10;
const X_INIT: u32 = u32::max_value();
// global mutabale variables (changed using unsafe code)
static mut X: u32 = X_INIT;
......@@ -31,15 +32,31 @@ fn main() -> ! {
let mut x = unsafe { X };
loop {
x += 1; // <- place breakpoint here (3)
x = x.wrapping_add(1); // <- place breakpoint here (3)
write_x(1);
write_y(read_x());
}
}
fn write_x(i: u32){
unsafe{
X += 1;
Y = X;
assert!(x == X && X == Y);
X = X.wrapping_add(1);
}
}
fn write_y(i: u32){
unsafe{
Y = i;
}
}
fn read_x() -> u32{
unsafe{
X
}
}
// 0. Compile/build the example in debug (dev) mode.
//
// > cargo build --example bare0
......@@ -48,25 +65,27 @@ fn main() -> ! {
// 1. Run the program in the debugger, let the program run for a while and
// then press pause. Look in the (Local -vscode) Variables view what do you find.
//
// ** your answer here **
// x = 7893536
//
// In the Expressions (WATCH -vscode) view add X and Y
// what do you find
//
// ** your answer here **
// X = 7893536
// Y = 7893536
//
// Step through one complete iteration of the loop
// and see how the (Local) Variables are updated
// can you foresee what will eventually happen?
//
// ** place your answer here **
// x will increment then X will increment, then Y will be set as the same as X and then
// it will assert the changes.
//
// Commit your answers (bare0_1)
//
// 2. Alter the constant X_INIT so that `x += 1` directly causes `x` to wrap
// what happens when `x` wraps
//
// ** your answer here **
// Core panic, since the u32 int will overflow
//
// Commit your answers (bare0_2)
//
......@@ -74,10 +93,12 @@ fn main() -> ! {
//
// Change (both) += opertions to use wrapping_add
// load and run the progam, what happens
// ** your answer here **
//
// The variables wrapped around back to 0.
//
// Now continue exectution, what happens
// ** your answer here **
//
// The variables was incremeted as normal.
//
// Commit your answers (bare0_3)
//
......@@ -86,7 +107,7 @@ fn main() -> ! {
//
// 4. Change the asserion to `assert!(x == X && X == Y + 1)`, what happens?
//
// ** place your answer here **
// The assert fails and we get core panic.
//
// Commit your answers (bare0_4)
//
......
......@@ -55,10 +55,11 @@ fn main() -> ! {
// loop, (press pause/suspend to verify this).
// what is the output in the ITM console
//
// ** your answer here **
// There is no output in the ITM console
//
// What is the output in the semihosting (openocd) console
// ** your answer here **
//
// There is no special output here either
//
// Commit your answers (bare1_1)
//
......@@ -67,8 +68,38 @@ fn main() -> ! {
//
// What is the output of:
// (gdb) disassemble
//
// ** your answer here **
//Dump of assembler code for function main:
// 0x08000400 <+0>: sub sp, #16
// 0x08000402 <+2>: movs r0, #0
// 0x08000404 <+4>: str r0, [sp, #12]
// 0x08000406 <+6>: b.n 0x8000408 <main+8>
// 0x08000408 <+8>: ldr r0, [sp, #12]
// 0x0800040a <+10>: adds r1, r0, #1
// 0x0800040c <+12>: mov r2, r1
// 0x0800040e <+14>: cmp r1, r0
// 0x08000410 <+16>: str r2, [sp, #8]
// 0x08000412 <+18>: bvs.n 0x800042c <main+44>
// 0x08000414 <+20>: b.n 0x8000416 <main+22>
// 0x08000416 <+22>: ldr r0, [sp, #8]
// 0x08000418 <+24>: str r0, [sp, #12]
// 0x0800041a <+26>: ldr r1, [sp, #12]
// 0x0800041c <+28>: subs r2, r1, #1
// 0x0800041e <+30>: cmp r1, #1
// 0x08000420 <+32>: str r2, [sp, #4]
// 0x08000422 <+34>: bvs.n 0x800043a <main+58>
// 0x08000424 <+36>: b.n 0x8000426 <main+38>
// 0x08000426 <+38>: ldr r0, [sp, #4]
// 0x08000428 <+40>: str r0, [sp, #12]
// => 0x0800042a <+42>: b.n 0x8000408 <main+8>
// 0x0800042c <+44>: movw r0, #2268 ; 0x8dc
// 0x08000430 <+48>: movt r0, #2048 ; 0x800
// 0x08000434 <+52>: bl 0x800045c <panic>
// 0x08000438 <+56>: udf #254 ; 0xfe
// 0x0800043a <+58>: movw r0, #2340 ; 0x924
// 0x0800043e <+62>: movt r0, #2048 ; 0x800
// 0x08000442 <+66>: bl 0x800045c <panic>
// 0x08000446 <+70>: udf #254 ; 0xfe
// End of assembler dump.
//
// Commit your answers (bare1_2)
//
......@@ -78,7 +109,40 @@ fn main() -> ! {
// What is the output of:
// (gdb) disassemble
//
// ** your answer here **
//Dump of assembler code for function main:
// 0x08000404 <+0>: sub sp, #16
// 0x08000406 <+2>: movs r0, #0
// 0x08000408 <+4>: str r0, [sp, #12]
// 0x0800040a <+6>: b.n 0x800040c <main+8>
// 0x0800040c <+8>: ldr r0, [sp, #12]
// 0x0800040e <+10>: adds r1, r0, #1
// 0x08000410 <+12>: mov r2, r1
// 0x08000412 <+14>: cmp r1, r0
// 0x08000414 <+16>: str r2, [sp, #8]
// 0x08000416 <+18>: bvs.n 0x8000436 <main+50>
// 0x08000418 <+20>: b.n 0x800041a <main+22>
// 0x0800041a <+22>: ldr r0, [sp, #8]
// 0x0800041c <+24>: str r0, [sp, #12]
// 0x0800041e <+26>: bl 0x8000400 <cortex_m::asm::nop>
// 0x08000422 <+30>: b.n 0x8000424 <main+32>
// 0x08000424 <+32>: ldr r0, [sp, #12]
// 0x08000426 <+34>: subs r1, r0, #1
// 0x08000428 <+36>: cmp r0, #1
// 0x0800042a <+38>: str r1, [sp, #4]
// 0x0800042c <+40>: bvs.n 0x8000444 <main+64>
// 0x0800042e <+42>: b.n 0x8000430 <main+44>
// 0x08000430 <+44>: ldr r0, [sp, #4]
// 0x08000432 <+46>: str r0, [sp, #12]
// => 0x08000434 <+48>: b.n 0x800040c <main+8>
// 0x08000436 <+50>: movw r0, #2268 ; 0x8dc
// 0x0800043a <+54>: movt r0, #2048 ; 0x800
// 0x0800043e <+58>: bl 0x8000466 <panic>
// 0x08000442 <+62>: udf #254 ; 0xfe
// 0x08000444 <+64>: movw r0, #2340 ; 0x924
// 0x08000448 <+68>: movt r0, #2048 ; 0x800
// 0x0800044c <+72>: bl 0x8000466 <panic>
// 0x08000450 <+76>: udf #254 ; 0xfe
// End of assembler dump.
//
// Commit your answers (bare1_3)
//
......@@ -88,7 +152,42 @@ fn main() -> ! {
// What is the output of:
// (gdb) disassemble
//
// ** your answer here **
//Dump of assembler code for function main:
// 0x08000404 <+0>: sub sp, #16
// 0x08000406 <+2>: movs r0, #0
// 0x08000408 <+4>: str r0, [sp, #12]
// 0x0800040a <+6>: b.n 0x800040c <main+8>
// 0x0800040c <+8>: ldr r0, [sp, #12]
// 0x0800040e <+10>: adds r1, r0, #1
// 0x08000410 <+12>: mov r2, r1
// 0x08000412 <+14>: cmp r1, r0
// 0x08000414 <+16>: str r2, [sp, #8]
// 0x08000416 <+18>: bvs.n 0x800043a <main+54>
// 0x08000418 <+20>: b.n 0x800041a <main+22>
// 0x0800041a <+22>: ldr r0, [sp, #8]
// 0x0800041c <+24>: str r0, [sp, #12]
// 0x0800041e <+26>: bl 0x8000400 <cortex_m::asm::nop>
// 0x08000422 <+30>: b.n 0x8000424 <main+32>
// => 0x08000424 <+32>: bkpt 0x0000
// 0x08000426 <+34>: b.n 0x8000428 <main+36>
// 0x08000428 <+36>: ldr r0, [sp, #12]
// 0x0800042a <+38>: subs r1, r0, #1
// 0x0800042c <+40>: cmp r0, #1
// 0x0800042e <+42>: str r1, [sp, #4]
// 0x08000430 <+44>: bvs.n 0x8000448 <main+68>
// 0x08000432 <+46>: b.n 0x8000434 <main+48>
// 0x08000434 <+48>: ldr r0, [sp, #4]
// 0x08000436 <+50>: str r0, [sp, #12]
// 0x08000438 <+52>: b.n 0x800040c <main+8>
// 0x0800043a <+54>: movw r0, #2268 ; 0x8dc
// 0x0800043e <+58>: movt r0, #2048 ; 0x800
// 0x08000442 <+62>: bl 0x800046a <panic>
// 0x08000446 <+66>: udf #254 ; 0xfe
// 0x08000448 <+68>: movw r0, #2340 ; 0x924
// 0x0800044c <+72>: movt r0, #2048 ; 0x800
// 0x08000450 <+76>: bl 0x800046a <panic>
// 0x08000454 <+80>: udf #254 ; 0xfe
// End of assembler dump.
//
// Commit your answers (bare1_4)
//
......@@ -98,10 +197,12 @@ fn main() -> ! {
// > cargo build --example bare1 --release
// (or using the vscode build task)
//
// Compare the generated assembly for the loop
// between the dev (unoptimized) and release (optimized) build.
//
// ** your answer here **
// Dump of assembler code for function main:
// 0x08000400 <+0>: nop
// 0x08000402 <+2>: bkpt 0x0000
// => 0x08000404 <+4>: b.n 0x8000400 <main>
// End of assembler dump.
// Of course this is much shorter, since it is optimized
//
// commit your answers (bare1_5)
//
......
......@@ -71,18 +71,22 @@ fn main() -> ! {
//
// What is the output in the ITM console?
//
// ** your answer here **
// We get
// Start 524429147
// End 1149429355
//
// Rebuild and run in release mode
//
// > cargo build --example bare2 --release
//
// ** your answer here **
// We get
// Start 3475270380
// End 3479270838
//
// Compute the ratio between debug/release optimized code
// (the speedup).
//
// ** your answer here **
// 156.3
//
// commit your answers (bare2_1)
//
......
......@@ -18,8 +18,10 @@ use cortex_m_semihosting::{hprint, hprintln};
#[entry]
fn main() -> ! {
hprintln!("bare3").unwrap();
let s = "ABCD";
let bs = s.as_bytes();
let s: &str = "ABCD";
let bs: &[u8] = s.as_bytes();
let c: &u8;
let i: &i32;
hprintln!("s = {}", s).unwrap();
hprintln!("bs = {:?}", bs).unwrap();
......@@ -29,16 +31,16 @@ fn main() -> ! {
hprint!("{},", c).unwrap();
}
let a: [u8; 4] = [65u8; 4];
let mut a = [0u8; 4];
hprintln!("iterate iterate using (raw) indexing").unwrap();
for i in 0..s.len() {
hprintln!("{},", bs[i]).unwrap();
}
hprintln!("").unwrap();
let a = [65u8; 4];
//let mut a = [0u8; 4];
a.clone_from_slice(&bs[..]); //Copies from bs into a
hprintln!("").unwrap();
hprintln!("a = {}", core::str::from_utf8(&a).unwrap()).unwrap();
......@@ -52,27 +54,36 @@ fn main() -> ! {
//
// 1. What is the output in the `openocd` (Adapter Output) console?
//
// ** your answer here **
// bare3
// s = ABCD
// bs = [65, 66, 67, 68]
// iterate over slice
// 65,66,67,68,iterate iterate using (raw) indexing
// 65,
// 66,
// 67,
// 68,
// a = AAAA
//
// What is the type of `s`?
//
// ** your answer here **
// string
//
// What is the type of `bs`?
//
// ** your answer here **
// u8 array
//
// What is the type of `c`?
//
// ** your answer here **
// it is a pointer to a u8 element in an array
//
// What is the type of `a`?
//
// ** your answer here **
// u8 array
//
// What is the type of `i`?
//
// ** your answer here **
// i32
//
// Commit your answers (bare3_1)
//
......@@ -84,7 +95,7 @@ fn main() -> ! {
//`
// Run the program, what happens and why?
//
// ** your answer here **
// Does not print anything for a, since 0 in ascii is null
//
// Commit your answers (bare3_3)
//
......
......@@ -36,8 +36,8 @@ use address::*;
#[inline(always)]
fn read_u32(addr: u32) -> u32 {
unsafe { core::ptr::read_volatile(addr as *const _) }
//core::ptr::read_volatile(addr as *const _)
//unsafe { core::ptr::read_volatile(addr as *const _) }
core::ptr::read_volatile(addr as *const _)
}
#[inline(always)]
......@@ -84,7 +84,7 @@ fn main() -> ! {
//
// 1. Did you enjoy the blinking?
//
// ** your answer here **
// Yes, the blinking was nice!
//
// Now lookup the data-sheets, and read each section referred,
// 6.3.11, 8.4.1, 8.4.7
......@@ -92,6 +92,12 @@ fn main() -> ! {
// Document each low level access *code* by the appropriate section in the
// data sheet.
//
// 6.3.11: RCC_APB1ENR
//
// 8.4.1: GPIOx_MODER where x can be A-E and H
//
// 8.4.7: GPIOx_BSRR where x can be A-E and H
//
// Commit your answers (bare4_1)
//
// 2. Comment out line 40 and uncomment line 41 (essentially omitting the `unsafe`)
......@@ -101,12 +107,14 @@ fn main() -> ! {
//
// What was the error message and explain why.
//
// ** your answer here **
// call to unsafe function is unsafe and requires unsafe function or block.
// This happens because the variable is volatile.
//
// Digging a bit deeper, why do you think `read_volatile` is declared `unsafe`.
// (https://doc.rust-lang.org/core/ptr/fn.read_volatile.html, for some food for thought )
//
// ** your answer here **
// The volatile value might not be guaranteed to be the same between reads. So it is declared unsafe since it might not
// be the same as intended.
//
// Commit your answers (bare4_2)
//
......@@ -119,16 +127,16 @@ fn main() -> ! {
//
// Why is it important that ordering of volatile operations are ensured by the compiler?
//
// ** your answer here **
// Since some operations has to be executed before others.
//
// Give an example in the above code, where reordering might make things go horribly wrong
// (hint, accessing a peripheral not being powered...)
//
// ** your answer here **
// If we swap row 59-60 with 63-64, then we wont get the nice blinking anymore.
//
// Without the non-reording proprety of `write_volatile/read_volatile` could that happen in theory
// (argue from the point of data dependencies).
//
// ** your answer here **
// Writing/Reading in wrong order may end up in unexpected results
//
// Commit your answers (bare4_3)
......@@ -57,12 +57,17 @@ mod stm32f40x {
// width (field width)
// value (new value that the field should take)
//
// impl VolatileCell<u32> {
// #[inline(always)]
// pub fn modify(&self, offset: u8, width: u8, value: u32) {
// // your code here
// }
// }
impl VolatileCell<u32> {
#[inline(always)]
pub fn modify(&self, offset: u8, width: u8, value: u32) {
let currentVal = self.read();
let b = 0b11111111;
let mask = !( (b << offset + width) | !(b << offset) );
let maskedVal = mask & (value << offset);
let modVal = (currentVal & !mask) | maskedVal;
self.write(modVal);
}
}
#[repr(C)]
#[allow(non_snake_case)]
......@@ -141,27 +146,27 @@ 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);
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 (debug), but not in release mode
// t.modify(32, 3, 1);
//}
t.modify(32, 3, 1);
}
// system startup, can be hidden from the user
#[entry]
......@@ -169,7 +174,7 @@ 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
test(); // uncomment to run test
idle(rcc, gpioa);
loop {}
}
......@@ -177,27 +182,33 @@ fn main() -> ! {
// user application
fn idle(rcc: &mut RCC, gpioa: &mut GPIOA) {
// power on GPIOA
let r = rcc.AHB1ENR.read(); // read
rcc.AHB1ENR.write(r | 1 << (0)); // set enable
// let r = rcc.AHB1ENR.read(); // read
// rcc.AHB1ENR.write(r | 1 << (0)); // set enable
rcc.AHB1ENR.modify(0, 1, 0b1);
// configure PA5 as output
let r = gpioa.MODER.read() & !(0b11 << (5 * 2)); // read and mask
gpioa.MODER.write(r | 0b01 << (5 * 2)); // set output mode
gpioa.MODER.modify(5*2, 2, 0b01);
// let r = gpioa.MODER.read() & !(0b11 << (5 * 2)); // read and mask
// gpioa.MODER.write(r | 0b01 << (5 * 2)); // set output mode
loop {
// set PA5 high
gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led)
// gpioa.BSRRH.write(1 << 5); // set bit, output hight (turn on led)
// gpioa.ODR.write(gpioa.ODR.read() | (1 << 5));
wait(10_000);
gpioa.ODR.modify(5, 1, 0b1);
wait(1_119_982);
// wait(10_000);
// set PA5 low
gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led)
// gpioa.BSRRL.write(1 << 5); // clear bit, output low (turn off led)
// gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5));
wait(10_000);
gpioa.ODR.modify(5, 1, 0b0);
// wait(10_000);
wait(1_119_982);
}
}
// 0. Build and run the application.
//
// > cargo build --example bare5
......
......@@ -83,7 +83,7 @@ fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
// mco2 : SYSCLK = 0b00
// mcopre : divide by 4 = 0b110
rcc.cfgr
.modify(|_, w| unsafe { w.mco2().bits(0b00).mco2pre().bits(0b110) });
.modify(|_, w| unsafe { w.mco2().sysclk().mco2pre().bits(0b110) });
// power on GPIOC, RM0368 6.3.11
rcc.ahb1enr.modify(|_, w| w.gpiocen().set_bit());
......@@ -128,7 +128,7 @@ fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
//
// What is the frequency of blinking?
//
// ** your answer here **
// 1s, 1Hz
//
// commit your answers (bare6_1)
//
......@@ -137,15 +137,15 @@ fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
//
// What is the frequency of MCO2 read by the oscilloscope?
//
// ** your answer here **
// 4Mhz
//
// Compute the value of SYSCLK based on the oscilloscope reading
//
// ** your answer here **
// 16Mhz
//
// What is the peak to peak reading of the signal?
//
// ** your answer here **
// 5.9V
//
// Make a folder called "pictures" in your git project.
// Make a screen dump or photo of the oscilloscope output.
......@@ -165,7 +165,7 @@ fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
//`
// What is the frequency of blinking?
//
// ** your answer here **
// 1s, 1Hz
//
// Commit your answers (bare6_3)
//
......@@ -173,15 +173,15 @@ fn clock_out(rcc: &RCC, gpioc: &GPIOC) {
//
// What is the frequency of MCO2 read by the oscilloscope?
//
// ** your answer here **
// 16Mhz
//
// Compute the value of SYSCLK based on the oscilloscope reading.
//
// ** your answer here **
// 64Mhz
//
// What is the peak to peak reading of the signal?
//
// ** your answer here **
// 5.7V
//
// Make a screen dump or photo of the oscilloscope output.
// Save the the picture as "bare_6_64mhz_high_speed".
......
......@@ -33,7 +33,8 @@ fn main() -> ! {
let rcc = p.RCC.constrain();
// 16 MHz (default, all clocks)
let clocks = rcc.cfgr.freeze();
//let clocks = rcc.cfgr.freeze();
let clocks = rcc.cfgr.sysclk(84.mhz()).pclk1(42.mhz()).pclk2(64.mhz()).freeze();
let gpioa = p.GPIOA.split();
......@@ -49,6 +50,9 @@ fn main() -> ! {
)
.unwrap();
let gpioc = p.GPIOC.split();
gpioc.pc9.into_alternate_af0().set_speed(hal::gpio::Speed::Low);
// Separate out the sender and receiver of the serial port
let (mut tx, mut rx) = serial.split();
......@@ -125,11 +129,12 @@ fn main() -> ! {
//
// rcc.cfgr.sysclk(64.mhz()).pclk1(64.mhz()).pclk2(64.mhz()).freeze();
//
// ** your answer here **
// The maximum frequency of pclk1 is 42MHz, and it needs to be the same frequency as the system clock.
// Which it is not since it is set to 16MHz
//
// rcc.cfgr.sysclk(84.mhz()).pclk1(42.mhz()).pclk2(64.mhz()).freeze();
//
// ** your answer here **
// Here is the same reason, the sysclk is only different.
//
// Commit your answers (bare7_1)
//
......@@ -144,15 +149,15 @@ fn main() -> ! {
//
// What is the frequency of MCO2 read by the oscilloscope.
//
// ** your answer here **
// 84Mhz
//
// Compute the value of SYSCLK based on the oscilloscope reading.
//
// ** your answer here **
// 84Mhz
//
// What is the peak to peak reading of the signal.
//
// ** your answer here **
// 7.8V
//
// Make a screen dump or photo of the oscilloscope output.
// Save the the picture as "bare_6_84mhz_high_speed"
......@@ -163,11 +168,11 @@ fn main() -> ! {
//
// Did the frequency change in comparison to assignment 5?
//
// ** your answer here **
// It is unreadable
//
// What is the peak to peak reading of the signal (and why did it change)?
//
// ** your answer here **
// Around 70mV, it changes too much to really see whats going on
//
// Make a screen dump or photo of the oscilloscope output.
// Save the the picture as "bare_6_84mhz_low_speed".
......
pictures/bare_6_16mhz_high_speed.png

26.4 KiB

pictures/bare_6_64mhz_high_speed.png

33.4 KiB

pictures/bare_6_84mhz_low_speed.png

20.1 KiB

pictures/bare_7_84mhz_high_speed.png

26.2 KiB