diff --git a/.cargo/config b/.cargo/config
new file mode 100644
index 0000000000000000000000000000000000000000..52ebeba2fb2c4473e622ed5be35ebc4a856643c5
--- /dev/null
+++ b/.cargo/config
@@ -0,0 +1,37 @@
+[target.thumbv7m-none-eabi]
+# uncomment this to make `cargo run` execute programs on QEMU
+# runner = "qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel"
+
+[target.'cfg(all(target_arch = "arm", target_os = "none"))']
+# uncomment ONE of these three option to make `cargo run` start a GDB session
+# which option to pick depends on your system
+# runner = "arm-none-eabi-gdb -q -x jlink.gdb"
+runner = "arm-none-eabi-gdb -q -x openocd.gdb"
+# runner = "gdb-multiarch -q -x openocd.gdb"
+# runner = "gdb -q -x openocd.gdb"
+
+rustflags = [
+  # LLD (shipped with the Rust toolchain) is used as the default linker
+  "-C", "link-arg=-Tlink.x",
+
+  # if you run into problems with LLD switch to the GNU linker by commenting out
+  # this line
+  # "-C", "linker=arm-none-eabi-ld",
+
+  # if you need to link to pre-compiled C libraries provided by a C toolchain
+  # use GCC as the linker by commenting out both lines above and then
+  # uncommenting the three lines below
+  # "-C", "linker=arm-none-eabi-gcc",
+  # "-C", "link-arg=-Wl,-Tlink.x",
+  # "-C", "link-arg=-nostartfiles",
+
+  # uncomment for unchecked wrapping arithmetics also in dev mode
+  # "-Z", "force-overflow-checks=off",
+]
+
+[build]
+# Pick ONE of these compilation targets
+# target = "thumbv6m-none-eabi"    # Cortex-M0 and Cortex-M0+
+# target = "thumbv7m-none-eabi"    # Cortex-M3
+# target = "thumbv7em-none-eabi"   # Cortex-M4 and Cortex-M7 (no FPU)
+target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..ab13ba67d6f00e40938c9baa70e283455618b087
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,50 @@
+[package]
+name = "app"
+categories = ["embedded", "no-std"]
+authors = ["Per Lindgren <per.lindgren@ltu.se>", "Emil Fresk <emil.fresk@gmail.com>"]
+description = "Example project"
+keywords = ["arm", "cortex-m", "mav"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/korken89/trustflight_firmware"
+version = "0.1.0"
+edition = "2018"
+
+[dependencies]
+panic-halt              = "0.2"
+panic-semihosting       = "0.5"
+cortex-m-rtfm           = "0.5.1"
+cortex-m-semihosting    = "0.3.5"
+cortex-m                = "0.6.2"
+aligned                 = "0.3.2"
+ufmt                    = "0.1.0"
+
+[dependencies.cortex-m-rt]
+version          = "0.6.12"
+
+
+[dependencies.stm32f4xx-hal]
+version         = "0.6.0"
+features        = ["stm32f401", "rt"]
+optional        = true
+
+# this lets you use `cargo fix`!
+[[bin]]
+name            = "app"
+test            = false
+bench           = false
+
+# Built options for different examples
+# [[example]]
+
+
+[profile.dev]
+opt-level       = 1
+codegen-units   = 16
+debug           = true
+lto             = false
+
+[profile.release]
+opt-level       = "s"   # optimize for size
+codegen-units   = 1     # better optimizations
+debug           = true  # symbols are nice and they don't increase the size on Flash
+lto             = true  # better optimizations
diff --git a/examples/hello.rs b/examples/hello.rs
new file mode 100644
index 0000000000000000000000000000000000000000..f36bdb3edeb66447ed3290aef1408356f3e64eea
--- /dev/null
+++ b/examples/hello.rs
@@ -0,0 +1,15 @@
+//! Prints "Hello, world!" on the host console using semihosting
+
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m_rt::entry;
+use cortex_m_semihosting::hprintln;
+
+#[entry]
+fn main() -> ! {
+    hprintln!("Hello, world!").unwrap();
+    loop {}
+}
diff --git a/examples/itm.rs b/examples/itm.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b4c9401c792eb1cb985e3fbde67b6c6c157f1222
--- /dev/null
+++ b/examples/itm.rs
@@ -0,0 +1,27 @@
+//! Sends "Hello, agian!" over the ITM port 0
+//!
+//! ITM is much faster than semihosting. Like 4 orders of magnitude or so.
+//!
+//! You'll need [`itmdump`] to receive the message on the host plus you'll need to uncomment two
+//! `monitor` commands in the `.gdbinit` file.
+//!
+//! [`itmdump`]: https://docs.rs/itm/0.2.1/itm/
+//!
+//! ---
+
+#![no_main]
+#![no_std]
+
+extern crate panic_halt;
+
+use cortex_m::{iprintln, Peripherals};
+use cortex_m_rt::entry;
+
+#[entry]
+fn main() -> ! {
+    let mut p = Peripherals::take().unwrap();
+    let stim = &mut p.ITM.stim[0];
+
+    iprintln!(stim, "Hello, again!");
+    loop {}
+}
diff --git a/memory.x b/memory.x
new file mode 100644
index 0000000000000000000000000000000000000000..71fdf8bbe01ae7754018c150bd7dd1b1147b87d5
--- /dev/null
+++ b/memory.x
@@ -0,0 +1,11 @@
+MEMORY
+{
+  /* NOTE K = KiBi = 1024 bytes */
+  FLASH : ORIGIN = 0x08000000, LENGTH = 64K 
+  RAM : ORIGIN = 0x20000000, LENGTH = 32K
+}
+
+/* This is where the call stack will be allocated. */
+/* The stack is of the full descending type. */
+/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */
+_stack_start = ORIGIN(RAM) + LENGTH(RAM);
\ No newline at end of file
diff --git a/openocd.cfg b/openocd.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..05967f2f0a1154d7b8a41e27d7ecfb71c9c5481d
--- /dev/null
+++ b/openocd.cfg
@@ -0,0 +1,12 @@
+source [find interface/stlink.cfg]
+
+transport select hla_swd
+
+# increase working area to 64KB
+# set WORKAREASIZE 0x10000
+
+source [find target/stm32f4x.cfg]
+
+# reset_config srst_only
+
+# tpiu config internal /tmp/itm.fifo uart off 16000000 1000000
diff --git a/openocd.gdb b/openocd.gdb
new file mode 100644
index 0000000000000000000000000000000000000000..92d2058e4bc28237b019a303554516029769d43a
--- /dev/null
+++ b/openocd.gdb
@@ -0,0 +1,25 @@
+target extended-remote :3333
+
+set print asm-demangle on
+monitor arm semihosting enable
+
+monitor tpiu config internal /tmp/itm.fifo uart off 16000000 2000000
+
+# enable itm ports
+monitor itm port 0 on 
+monitor itm port 1 on
+monitor itm port 2 on
+
+# *try* to stop at the user entry point (it might be gone due to inlining)
+break main
+
+# detect unhandled exceptions, hard faults and panics
+break HardFault
+break core::panicking::panic_fmt
+
+# un-comment to check that flashing was successful
+# compare-sections
+
+monitor reset init
+load
+stepi
\ No newline at end of file