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
Loading items

Target

Select target project
  • Frappe/e7020e_2021
  • rognda-6/e7020e_2021
  • Klomega/e7020e_2021
  • pln/e7020e_2021
  • CarlOsterberg/e7020e_2021
  • jonjac-6/e7020e_2021
  • deux-babiri-futari/e7020e_2021
  • samgra-7/e7020e_2021
  • JosefUtbult/e7020e_2021
  • edwkll-7/e7020e_2021
10 results
Select Git revision
Loading items
Show changes
Commits on Source (23)
......@@ -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",
......
# Changelog
<<<<<<< HEAD
=======
## 2021-03-18
- examples/usb-mouse.rs, a very small example using external hid library.
>>>>>>> 8d3a36604d8080052d125e924e11622c6bf8b01c
## 2021-03-07
- examples/rtic_bare7.rs, using embedded HAL.
......
This diff is collapsed.
This diff is collapsed.
{
// 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": [
{
"cwd": "${workspaceRoot}",
"executable": "./bin/executable.elf",
"name": "Debug Microcontroller",
"request": "launch",
"type": "cortex-debug",
"servertype": "openocd"
},
{
"cwd": "${workspaceRoot}",
"executable": "./bin/executable.elf",
"name": "Debug Microcontroller",
"request": "launch",
"type": "cortex-debug",
"servertype": "jlink"
}
]
}
\ No newline at end of file
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "cargo build --example",
"command": "cargo",
"args": [
"build",
"--example",
"${fileBasenameNoExtension}"
],
"problemMatcher": [
"$rustc"
],
"group": "build",
},
{
"label": "cargo build --example --release",
"command": "cargo",
"args": [
"build",
"--example",
"${fileBasenameNoExtension}",
"--release"
],
"problemMatcher": [
"$rustc"
],
"group": "build",
},
]
}
\ No newline at end of file
{
"version": "2.0.0",
"tasks": [
{
"type": "cargo",
"command": "build",
"problemMatcher": [
"$rustc"
],
"group": {
"kind": "build",
"isDefault": true
},
"label": "rust: cargo build"
}
]
}
\ No newline at end of file
......@@ -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 and we are using a u32 and checking if it overflows.
//
// 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)
//
......
......@@ -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,23 @@ 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 **
/*
To save space the compiler makes some optimizations in the code.
So wait is now compiled as a function and takes an argument in r0 instead of
just setting a value before it runs.
*/
//
// Commit your answers (bare2_3)
......@@ -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)
//
......
......@@ -36,7 +36,6 @@ 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 _)
}
#[inline(always)]
......@@ -83,7 +82,7 @@ const APP: () = {
//
// 1. Did you enjoy the blinking?
//
// ** your answer here **
// Yeah
//
// Now lookup the data-sheets, and read each section referred,
// 6.3.11, 8.4.1, 8.4.7
......@@ -100,12 +99,20 @@ const APP: () = {
//
// What was the error message and explain why.
//
// ** your answer here **
/*
error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
--> examples\rtic_bare4.rs:39:5
|
39 | core::ptr::read_volatile(addr as *const _)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
|
= note: consult the function's documentation for information on how to avoid undefined behavior
*/
//
// 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 **
// It is not safe. You create a copy of a register without using borrow checking so Rust consider it unsafe.
//
// Commit your answers (bare4_2)
//
......@@ -118,16 +125,18 @@ const APP: () = {
//
// Why is it important that ordering of volatile operations are ensured by the compiler?
//
// ** your answer here **
// Because we are messing around with the registers and the stack in a specific way and want it to behave exactly the way we specified.
// Thats the whole point with volatile operations.
//
// 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 **
// When we specify a specific address we really mean that address and want to know that we get exactly that address and nothing else.
// Line 44 and 38 is places where it could be really bad if the compiler assumes something else.
//
// Without the non-reordering property of `write_volatile/read_volatile` could that happen in theory
// (argue from the point of data dependencies).
//
// ** your answer here **
// We write/read from some unwanted address and get/set the wrong information. This could lead to unwanted behaviors and is not very good.
//
// Commit your answers (bare4_3)
......@@ -11,6 +11,7 @@
extern crate cortex_m;
extern crate panic_semihosting;
//use bitvec::prelude::*; <-- Might wont to look in to this.
// C like API...
mod stm32f40x {
......@@ -58,7 +59,9 @@ mod stm32f40x {
impl VolatileCell<u32> {
#[inline(always)]
pub fn modify(&self, offset: u8, width: u8, value: u32) {
// your code here
let mut value_mut = value << 32-width;
value_mut = value_mut >> 32-width;
self.write(value_mut << offset);
}
}
......@@ -179,22 +182,23 @@ const APP: () = {
// test_modify();
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)
// alternatively to set the bit high we can
// read the value, or with PA5 (bit 5) and write back
// gpioa.ODR.write(gpioa.ODR.read() | (1 << 5));
gpioa.ODR.write(gpioa.ODR.read() | (1 << 5));
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)
// alternatively to clear the bit we can
// read the value, mask out PA5 (bit 5) and write back
// gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5));
gpioa.ODR.write(gpioa.ODR.read() & !(1 << 5));
wait(10_000);
}
}
......
......@@ -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) {
......