diff --git a/.gitignore b/.gitignore index fa5b635adfd3649771cb7ce5759daaad02b0a996..f2416c4b387046d27de93a491929165e9c1e1b4c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,4 @@ target/ !.vscode/*.svd !.vscode/launch.json !.vscode/tasks.json -!.vscode/extensions.json \ No newline at end of file +!.vscode/extensions.json diff --git a/.vscode/launch.json b/.vscode/launch.json index d78df7ad333dbd853e08541c68836227eaaf0831..66a9784c699692e19c9d739189061df14975fa62 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,6 +9,15 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + + { + "cwd": "${workspaceRoot}", + "executable": "./bin/executable.elf", + "name": "Debug Microcontroller", + "request": "launch", + "type": "cortex-debug", + "servertype": "openocd" + }, { "type": "cortex-debug", "request": "launch", diff --git a/Cargo.toml b/Cargo.toml index 76ff65fca1fc0e15563c1daf41b133918e8e5cf7..3f6774e926000ecb64ee8ba1a248ad7be960b5c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,4 @@ -[package] + [package] authors = ["Per Lindgren <per.lindgren@ltu.se>"] edition = "2018" readme = "README.md" diff --git a/examples/rtic_bare1.rs b/examples/rtic_bare1.rs index 11248f4e1eaa427af7aff5f812ad18ea94a4037c..fa6df39179cee8d85d63d20e6009a79ebc791f42 100644 --- a/examples/rtic_bare1.rs +++ b/examples/rtic_bare1.rs @@ -20,9 +20,10 @@ const APP: () = { fn init(_cx: init::Context) { let mut x = core::u32::MAX - 1; loop { - // cortex_m::asm::bkpt(); - x += 1; - // cortex_m::asm::bkpt(); + cortex_m::asm::bkpt(); + //x += 1; + x = x.wrapping_add(1); + cortex_m::asm::bkpt(); // prevent optimization by read-volatile (unsafe) unsafe { @@ -45,11 +46,11 @@ const APP: () = { // // Paste the error message: // -// ** your answer here ** +// panicked at 'attempt to add with overflow', examples/rtic_bare1.rs:24:13 // // Explain in your own words why the code panic:ed. // -// ** your answer here ** +// It panicked because of an attempted overflow // // Commit your answer (bare1_1) // @@ -65,11 +66,18 @@ const APP: () = { // // Paste the backtrace: // -// ** your answer here +// #0 lib::__bkpt () at asm/lib.rs:49 +// #1 0x0800104e in cortex_m::asm::bkpt () at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-0.7.1/src/asm.rs:15 +// #2 panic_semihosting::panic (info=0x2000fed8) at /root/.cargo/registry/src/github.com-1ecc6299db9ec823/panic-semihosting-0.5.6/src/lib.rs:92 +// #3 0x0800039a in core::panicking::panic_fmt () at /rustc/cb75ad5db02783e8b0222fee363c5f63f7e2cf5b//library/core/src/panicking.rs:92 +// #4 0x08000374 in core::panicking::panic () at /rustc/cb75ad5db02783e8b0222fee363c5f63f7e2cf5b//library/core/src/panicking.rs:50 +// #5 0x08000ebe in rtic_bare1::init (_cx=...) at /home/tommy/Documents/Inbygda_system/e7020e_2021/examples/rtic_bare1.rs:24 +// #6 0x08000f08 in rtic_bare1::APP::main () at /home/tommy/Documents/Inbygda_system/e7020e_2021/examples/rtic_bare1.rs:15 +// {"token":181,"outOfBandRecord":[],"resultRecords":{"resultClass":"done","results":[]}} // // Explain in your own words the chain of calls. // -// ** your answer here +// The error occurs and then sends it further up and into panic and ending up in asm/lib // // Commit your answer (bare1_2) // @@ -82,20 +90,22 @@ const APP: () = { // // What is the value of `x`? // -// ** your answer here ** +// x: 4294967294 // // Explain in your own words where this value comes from. // -// ** your answer here ** +// x is initiated as usigned 32-bit integer set as max - 1 that will set it as 2^32 - 1 // // Now continue the program, since you are in a loop // the program will halt again at line 24. // // What is the value of `x`? // +// x: 4294967295 +// // Explain in your own words why `x` now has this value. // -// ** your answer here ** +// Since we increase x by 1 for every time we loop // // Now continue again. // @@ -109,7 +119,7 @@ const APP: () = { // // Explain in your own words why a panic makes sense at this point. // -// ** your answer here ** +// The panic makes sense because x overflows by increasing the max (2^32 = 4294967295) by 1. // // Commit your answer (bare1_3) // @@ -126,13 +136,13 @@ const APP: () = { // // Explain in your own words what this assembly line does. // -// ** your answer here ** +// load r0 with the value that stackpointer points to. // // In Cortex Registers (left) you can see the content of `r0` // // What value do you observe? // -// ** your answer here ** +// r0 = -2 // // You can also get the register info from GDB directly. // @@ -150,7 +160,7 @@ const APP: () = { // // Explain in your own words what is happening here. // -// ** your answer here ** +// We add 1 to r0 and update the N. Z, C and V flags. // // We move to the next assembly instruction: // @@ -159,7 +169,7 @@ const APP: () = { // // What is the reported value for `r0` // -// ** your answer here ** +// r0 = -1 // // So far so good. // @@ -190,7 +200,7 @@ const APP: () = { // // What does BCS do? // -// ** your answer here ** +// Checks if carry flag is set, if it is branches to +36 // // Now let's see what happens. // @@ -204,7 +214,7 @@ const APP: () = { // // Explain in your own words where we are heading. // -// ** your answer here ** +// we move in 20485872 into r0, 20485856 into r2 and 28 into r1 but only overwrites the 9 lowest bits. // // To validate that your answer, let's let the program continue // @@ -215,13 +225,13 @@ const APP: () = { // Explain in your own words what the code // 0x08000f28 .. 0x08000f38 achieves // +// #28 generates the panic (overflow) while r0 and r2 tells where. +// // Hint 1, look at the error message? // Hint 2, look at the call stack. // Hint 3, the code is generated by the Rust compiler to produce the error message. // there is no "magic" here, just a compiler generating code... // -// ** your answer here ** -// // Commit your answer (bare1_4) // // 5. Now we can remove the break point (click the `Remove All Breakpoints`), @@ -229,7 +239,7 @@ const APP: () = { // // Close the debug session and press F5 again to re-compile and launch the app. // -// Continue until you hit the firs breakpoint. +// Continue until you hit the first breakpoint. // // The disassembly should look like this: // @@ -273,7 +283,7 @@ const APP: () = { // // Do you see any way this code may end up in a panic? // -// ** your answer here ** +// When calling bkpt when not in debug will cause a panic. // // So clearly, the "semantics" (meaning) of the program has changed. // This is on purpose, Rust adopts "unchecked" (wrapping) additions (and subtractions) @@ -288,16 +298,45 @@ const APP: () = { // // Paste the generated assembly: // -// ** your answer here ** +// Dump of assembler code for function rtic_bare1::APP::main: +/* 0x08000eae <+0>: push {r7, lr} + 0x08000eb0 <+2>: mov r7, sp + 0x08000eb2 <+4>: sub sp, #56 ; 0x38 +=> 0x08000eb4 <+6>: bl 0x8000faa <lib::__cpsid> + 0x08000eb8 <+10>: movw r0, #0 + 0x08000ebc <+14>: movw r4, #60688 ; 0xed10 + 0x08000ec0 <+18>: movt r0, #8192 ; 0x2000 + 0x08000ec4 <+22>: movs r1, #1 + 0x08000ec6 <+24>: strb r1, [r0, #0] + 0x08000ec8 <+26>: add r0, sp, #4 + 0x08000eca <+28>: movt r4, #57344 ; 0xe000 + 0x08000ece <+32>: str r0, [sp, #20] + 0x08000ed0 <+34>: mov r0, r4 + 0x08000ed2 <+36>: strd r4, r4, [sp, #28] + 0x08000ed6 <+40>: bl 0x8000f78 <_ZN4core4cell19UnsafeCell$LT$T$GT$3get17hc981151b10f99f20E> + 0x08000eda <+44>: bl 0x8000f46 <_ZN4core3ptr13read_volatile17hb977623ea709e27cE> + 0x08000ede <+48>: orr.w r5, r0, #2 + 0x08000ee2 <+52>: str r0, [sp, #24] + 0x08000ee4 <+54>: mov r0, r4 + 0x08000ee6 <+56>: str r4, [sp, #36] ; 0x24 + 0x08000ee8 <+58>: str r5, [sp, #40] ; 0x28 + 0x08000eea <+60>: bl 0x8000f78 <_ZN4core4cell19UnsafeCell$LT$T$GT$3get17hc981151b10f99f20E> + 0x08000eee <+64>: mov r1, r5 + 0x08000ef0 <+66>: bl 0x8000f54 <_ZN4core3ptr14write_volatile17h73c310961d025d87E> + 0x08000ef4 <+70>: bl 0x8000e84 <rtic_bare1::init> + 0x08000ef8 <+74>: bl 0x8000fae <lib::__cpsie> + 0x08000efc <+78>: bl 0x8000fb2 <lib::__wfi> + 0x08000f00 <+82>: b.n 0x8000efc <rtic_bare1::APP::main+78> +End of assembler dump. */ // // Can this code generate a panic? // -// ** your answer here ** +// No. // // Is there now any reference to the panic handler? // If not, why is that the case? // -// ** your answer here ** +// When we use wrap it allows us to wrap around, hence no overflow or panic. // // commit your answers (bare1_5) // @@ -327,12 +366,30 @@ const APP: () = { // // Dump the generated assembly. // -// ** your answer here ** + /*Dump of assembler code for function rtic_bare1::init: + 0x08000e84 <+0>: push {r4, r6, r7, lr} + 0x08000e86 <+2>: add r7, sp, #8 + 0x08000e88 <+4>: sub sp, #16 + 0x08000e8a <+6>: movw r0, #5808 ; 0x16b0 + 0x08000e8e <+10>: mov r4, sp + 0x08000e90 <+12>: movt r0, #2048 ; 0x800 + 0x08000e94 <+16>: ldr r0, [r0, #0] + 0x08000e96 <+18>: str r0, [sp, #0] + 0x08000e98 <+20>: bl 0x8000fa6 <lib::__bkpt> + 0x08000e9c <+24>: ldr r0, [sp, #0] + 0x08000e9e <+26>: adds r0, #1 + 0x08000ea0 <+28>: str r0, [sp, #0] + 0x08000ea2 <+30>: bl 0x8000fa6 <lib::__bkpt> +=> 0x08000ea6 <+34>: mov r0, r4 + 0x08000ea8 <+36>: bl 0x8000f46 <_ZN4core3ptr13read_volatile17hb977623ea709e27cE> + 0x08000eac <+40>: b.n 0x8000e98 <rtic_bare1::init+20> +End of assembler dump. +*/ // // Where is the local variable stored? // What happened, and why is Rust + LLVM allowed to optimize out your code? // -// ** your answer here ** +// On the stack pointer. When volatile is commented the Rust + LLVM is allowed to make optimizations. // // Commit your answers (bare1_6) // diff --git a/examples/rtic_bare2.rs b/examples/rtic_bare2.rs index 04266d7cbbfa598a29b99e95f7310f0c80c0967c..ff4a91fe66a20e42b25ad967b5335c1c7a7040b7 100644 --- a/examples/rtic_bare2.rs +++ b/examples/rtic_bare2.rs @@ -39,7 +39,7 @@ const APP: () = { hprintln!("End {:?}", end).ok(); hprintln!("Diff {:?}", end.wrapping_sub(start)).ok(); - // wait(100); + wait(100); } }; @@ -71,16 +71,22 @@ fn wait(i: u32) { // What is the output in the Adapter Output console? // (Notice, it will take a while we loop one million times at only 16 MHz.) // -// ** your answer here ** +// Start 128543196 +// End 295543279 +// Diff 167000083 // // Rebuild and run in (Cortex Release). // -// ** your answer here ** +// Start 1088552331 +// End 1092552347 +// Diff 4000016 // // Compute the ratio between debug/release optimized code // (the speedup). // -// ** your answer here ** +// Start: 128543196/1088552331 = 0,118086372459 +// End: 295543279/1092552347 = 0,270507202526 +// Diff: 167000083/4000016 = 41,7498537506 // // commit your answers (bare2_1) // @@ -105,7 +111,17 @@ fn wait(i: u32) { // // Dump generated assembly for the "wait" function. // -// ** your answer here ** + /* Dump of assembler code for function rtic_bare2::wait: + 0x080004a0 <+0>: push {r7, lr} + 0x080004a2 <+2>: mov r7, sp + 0x080004a4 <+4>: movw r0, #16960 ; 0x4240 + 0x080004a8 <+8>: movt r0, #15 +=> 0x080004ac <+12>: nop + 0x080004ae <+14>: subs r0, #1 + 0x080004b0 <+16>: bne.n 0x80004ac <rtic_bare2::wait+12> + 0x080004b2 <+18>: pop {r7, pc} +End of assembler dump. +*/ // // Under the ARM calling convention, r0.. is used as arguments. // However in this case, we se that r0 is set by the assembly instructions, @@ -115,7 +131,8 @@ fn wait(i: u32) { // // Answer in your own words, how they assign r0 to 1000000. // -// ** your answer here ** +// By combining instruction +4 and +8 we get 0xf4240 since movt is the upper 16-bit +// and movw is lower 16-bit and converting it from hexa to decimal we get 1000000. // // Commit your answers (bare2_2) // @@ -125,10 +142,19 @@ fn wait(i: u32) { // // Dump the generated assembly for the "wait" function. // -// ** your answer here ** +// Dump of assembler code for function rtic_bare2::wait: +/* + 0x080004a0 <+0>: push {r7, lr} + 0x080004a2 <+2>: mov r7, sp +=> 0x080004a4 <+4>: nop + 0x080004a6 <+6>: subs r0, #1 + 0x080004a8 <+8>: bne.n 0x80004a4 <rtic_bare2::wait+4> + 0x080004aa <+10>: pop {r7, pc} +End of assembler dump. +*/ // // Answer in your own words, why you believe the generated code differs? // -// ** your answer here ** +// It starts the wait function where it just loops nops. // // Commit your answers (bare2_3) diff --git a/examples/rtic_bare3.rs b/examples/rtic_bare3.rs index 9173175c051d4b3e4615e0db20d2b08265d59763..033410561b1365c1255ae10c6305fe8a55a0a34e 100644 --- a/examples/rtic_bare3.rs +++ b/examples/rtic_bare3.rs @@ -13,25 +13,35 @@ use cortex_m_semihosting::hprintln; use panic_semihosting as _; use rtic::cyccnt::Instant; +use rtic::cyccnt::Duration; use stm32f4; -#[rtic::app(device = stm32f4)] +#[rtic::app(device = stm32f4, monotonic = rtic::cyccnt::CYCCNT)] const APP: () = { #[init] fn init(mut cx: init::Context) { cx.core.DWT.enable_cycle_counter(); - let start = Instant::now(); + //let start = Instant::elapsed(&Instant::now()); wait(1_000_000); let end = Instant::now(); - + let timeElapsed = start.elapsed(); + + //let diff_f = Duration::as_cycles(&(end-start)); + //let diff = Duration::as_cycles(&end.duration_since(start)); + let diff_elapsed = Duration::as_cycles(&timeElapsed); // notice all printing outside of the section to measure! hprintln!("Start {:?}", start).ok(); hprintln!("End {:?}", end).ok(); - // hprintln!("Diff {:?}", (end - start) ).ok(); + //hprintln!("Diff {:?}", diff).ok(); + //hprintln!("Diff {:?}", diff_f).ok(); + hprintln!("Diff {:?}", diff_elapsed).ok(); + } }; + + // burns CPU cycles by just looping `i` times #[inline(never)] #[no_mangle] @@ -42,6 +52,7 @@ fn wait(i: u32) { } } + // 0. Setup // // > cargo doc --open @@ -62,7 +73,8 @@ fn wait(i: u32) { // // What is the output in the Adapter Output console? // -// ** your answer here ** +// Start Instant(47356) +// End Instant(4047373) // // As you see line 31 is commented out (we never print the difference). // @@ -76,7 +88,9 @@ fn wait(i: u32) { // // What is now the output in the Adapter Output console? // -// ** your answer here ** +// Start Instant(4025484479) +// End Instant(4029484495) +// Diff 4000016 // // Commit your answers (bare3_1) // @@ -86,7 +100,9 @@ fn wait(i: u32) { // // What is now the output in the Adapter Output console? // -// ** your answer here ** +// Start Instant(1525994886) +// End Instant(1529994902) +// Diff 4000016 // // Commit your answers (bare3_2) // @@ -95,7 +111,9 @@ fn wait(i: u32) { // // What is now the output in the Adapter Output console? // -// ** your answer here ** +// Start Instant(4000822764) +// End Instant(4004822780) +// Diff 4000020 // // Commit your answers (bare3_3) // diff --git a/examples/rtt_rtic_blinky.rs b/examples/rtt_rtic_blinky.rs index 67e5eaa3e7dc86d26abb4cd3afd906360c580598..1e4dfdfdddf65c90f335928a00b92ab48454f85d 100644 --- a/examples/rtt_rtic_blinky.rs +++ b/examples/rtt_rtic_blinky.rs @@ -14,6 +14,7 @@ const APP: () = { struct Resources { // late resources GPIOA: stm32::GPIOA, + GPIOC: stm32::GPIOC, } #[init(schedule = [toggle])] fn init(cx: init::Context) -> init::LateResources { @@ -41,9 +42,11 @@ const APP: () = { // configure PA5 as output, RM0368 8.4.1 device.GPIOA.moder.modify(|_, w| w.moder5().bits(1)); + device.GPIOC.moder.modify(|_, w| w.moder13().bits(0)); // pass on late resources init::LateResources { GPIOA: device.GPIOA, + GPIOC: device.GPIOC, } } @@ -54,6 +57,7 @@ const APP: () = { continue; } } + read_bit(); #[task(resources = [GPIOA], schedule = [toggle])] fn toggle(cx: toggle::Context) {