From 79de6fab061b03718698d01c53c3ec172addaf96 Mon Sep 17 00:00:00 2001 From: J / Jacob Babich Date: Fri, 8 Apr 2022 20:51:28 -0400 Subject: [PATCH] initial commit with my changes --- .cargo/config.toml | 35 ++++++++++ .gitignore | 15 +++++ Cargo.toml | 36 +++++++++++ README.md | 135 +++++++++++++++++++++++++++++++++++++++ build.rs | 31 +++++++++ examples/allocator.rs | 56 ++++++++++++++++ examples/crash.rs | 96 ++++++++++++++++++++++++++++ examples/device.rs | 62 ++++++++++++++++++ examples/exception.rs | 37 +++++++++++ examples/hello.rs | 20 ++++++ examples/itm.rs | 33 ++++++++++ examples/panic.rs | 28 ++++++++ examples/test_on_host.rs | 57 +++++++++++++++++ memory.x | 34 ++++++++++ new-main.bin | Bin 0 -> 53268 bytes openocd.cfg | 5 ++ openocd.gdb | 40 ++++++++++++ src/lib.rs | 56 ++++++++++++++++ src/main.rs | 116 +++++++++++++++++++++++++++++++++ 19 files changed, 892 insertions(+) create mode 100644 .cargo/config.toml create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 build.rs create mode 100644 examples/allocator.rs create mode 100644 examples/crash.rs create mode 100644 examples/device.rs create mode 100644 examples/exception.rs create mode 100644 examples/hello.rs create mode 100644 examples/itm.rs create mode 100644 examples/panic.rs create mode 100644 examples/test_on_host.rs create mode 100644 memory.x create mode 100755 new-main.bin create mode 100644 openocd.cfg create mode 100644 openocd.gdb create mode 100644 src/lib.rs create mode 100644 src/main.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..9d9a5e9 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,35 @@ +[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 openocd.gdb" +# runner = "gdb-multiarch -q -x openocd.gdb" +# runner = "gdb -q -x openocd.gdb" + +rustflags = [ + # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x + # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 + "-C", "link-arg=--nmagic", + + # 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", +] + +[build] +# Pick ONE of these compilation targets +# 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/.gitignore b/.gitignore new file mode 100644 index 0000000..b25267d --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +**/*.rs.bk +.#* +.gdb_history +Cargo.lock +target/ + +# editor files +.vscode/* +!.vscode/*.md +!.vscode/*.svd +!.vscode/launch.json +!.vscode/tasks.json +!.vscode/extensions.json + +.history/ diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..dd5728e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,36 @@ +[package] +authors = ["J / Jacob Babich "] +edition = "2018" +readme = "README.md" +name = "test-cortex-m4-rust" +version = "0.1.0" + +[dependencies] +cortex-m = "0.6.0" +cortex-m-rt = "0.6.10" +cortex-m-semihosting = "0.3.3" +panic-halt = "0.2.0" + +# Uncomment for the panic example. +# panic-itm = "0.4.1" + +# Uncomment for the allocator example. +# alloc-cortex-m = "0.4.0" + +# Uncomment for the device example. +# Update `memory.x`, set target to `thumbv7em-none-eabihf` in `.cargo/config`, +# and then use `cargo build --examples device` to build it. +# [dependencies.stm32f3] +# features = ["stm32f303", "rt"] +# version = "0.7.1" + +# this lets you use `cargo fix`! +[[bin]] +name = "test-cortex-m4-rust" +test = false +bench = false + +[profile.release] +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/README.md b/README.md new file mode 100644 index 0000000..293c092 --- /dev/null +++ b/README.md @@ -0,0 +1,135 @@ +# `cortex-m-quickstart` + +> A template for building applications for ARM Cortex-M microcontrollers + +This project is developed and maintained by the [Cortex-M team][team]. + +## Dependencies + +To build embedded programs using this template you'll need: + +- Rust 1.31, 1.30-beta, nightly-2018-09-13 or a newer toolchain. e.g. `rustup + default beta` + +- The `cargo generate` subcommand. [Installation + instructions](https://github.com/ashleygwilliams/cargo-generate#installation). + +- `rust-std` components (pre-compiled `core` crate) for the ARM Cortex-M + targets. Run: + +``` console +$ rustup target add thumbv6m-none-eabi thumbv7m-none-eabi thumbv7em-none-eabi thumbv7em-none-eabihf +``` + +## Using this template + +**NOTE**: This is the very short version that only covers building programs. For +the long version, which additionally covers flashing, running and debugging +programs, check [the embedded Rust book][book]. + +[book]: https://rust-embedded.github.io/book + +0. Before we begin you need to identify some characteristics of the target + device as these will be used to configure the project: + +- The ARM core. e.g. Cortex-M3. + +- Does the ARM core include an FPU? Cortex-M4**F** and Cortex-M7**F** cores do. + +- How much Flash memory and RAM does the target device has? e.g. 256 KiB of + Flash and 32 KiB of RAM. + +- Where are Flash memory and RAM mapped in the address space? e.g. RAM is + commonly located at address `0x2000_0000`. + +You can find this information in the data sheet or the reference manual of your +device. + +In this example we'll be using the STM32F3DISCOVERY. This board contains an +STM32F303VCT6 microcontroller. This microcontroller has: + +- A Cortex-M4F core that includes a single precision FPU + +- 256 KiB of Flash located at address 0x0800_0000. + +- 40 KiB of RAM located at address 0x2000_0000. (There's another RAM region but + for simplicity we'll ignore it). + +1. Instantiate the template. + +``` console +$ cargo generate --git https://github.com/rust-embedded/cortex-m-quickstart + Project Name: app + Creating project called `app`... + Done! New project created /tmp/app + +$ cd app +``` + +2. Set a default compilation target. There are four options as mentioned at the + bottom of `.cargo/config`. For the STM32F303VCT6, which has a Cortex-M4F + core, we'll pick the `thumbv7em-none-eabihf` target. + +``` console +$ tail -n6 .cargo/config +``` + +``` toml +[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) +``` + +3. Enter the memory region information into the `memory.x` file. + +``` console +$ cat memory.x +/* Linker script for the STM32F303VCT6 */ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + FLASH : ORIGIN = 0x08000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 40K +} +``` + +4. Build the template application or one of the examples. + +``` console +$ cargo build +``` + +## VS Code + +This template includes launch configurations for debugging CortexM programs with Visual Studio Code located in the `.vscode/` directory. +See [.vscode/README.md](./.vscode/README.md) for more information. +If you're not using VS Code, you can safely delete the directory from the generated project. + +# License + +This template is licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + +- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +## Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +## Code of Conduct + +Contribution to this crate is organized under the terms of the [Rust Code of +Conduct][CoC], the maintainer of this crate, the [Cortex-M team][team], promises +to intervene to uphold that code of conduct. + +[CoC]: https://www.rust-lang.org/policies/code-of-conduct +[team]: https://github.com/rust-embedded/wg#the-cortex-m-team diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..d534cc3 --- /dev/null +++ b/build.rs @@ -0,0 +1,31 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); +} diff --git a/examples/allocator.rs b/examples/allocator.rs new file mode 100644 index 0000000..53c3023 --- /dev/null +++ b/examples/allocator.rs @@ -0,0 +1,56 @@ +//! How to use the heap and a dynamic memory allocator +//! +//! This example depends on the alloc-cortex-m crate so you'll have to add it to your Cargo.toml: +//! +//! ``` text +//! # or edit the Cargo.toml file manually +//! $ cargo add alloc-cortex-m +//! ``` +//! +//! --- + +#![feature(alloc_error_handler)] +#![no_main] +#![no_std] + +extern crate alloc; +use panic_halt as _; + +use self::alloc::vec; +use core::alloc::Layout; + +use alloc_cortex_m::CortexMHeap; +use cortex_m::asm; +use cortex_m_rt::entry; +use cortex_m_semihosting::{hprintln, debug}; + +// this is the allocator the application will use +#[global_allocator] +static ALLOCATOR: CortexMHeap = CortexMHeap::empty(); + +const HEAP_SIZE: usize = 1024; // in bytes + +#[entry] +fn main() -> ! { + // Initialize the allocator BEFORE you use it + unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) } + + // Growable array allocated on the heap + let xs = vec![0, 1, 2]; + + hprintln!("{:?}", xs).unwrap(); + + // exit QEMU + // NOTE do not run this on hardware; it can corrupt OpenOCD state + debug::exit(debug::EXIT_SUCCESS); + + loop {} +} + +// define what happens in an Out Of Memory (OOM) condition +#[alloc_error_handler] +fn alloc_error(_layout: Layout) -> ! { + asm::bkpt(); + + loop {} +} diff --git a/examples/crash.rs b/examples/crash.rs new file mode 100644 index 0000000..ab2d47b --- /dev/null +++ b/examples/crash.rs @@ -0,0 +1,96 @@ +//! Debugging a crash (exception) +//! +//! Most crash conditions trigger a hard fault exception, whose handler is defined via +//! `exception!(HardFault, ..)`. The `HardFault` handler has access to the exception frame, a +//! snapshot of the CPU registers at the moment of the exception. +//! +//! This program crashes and the `HardFault` handler prints to the console the contents of the +//! `ExceptionFrame` and then triggers a breakpoint. From that breakpoint one can see the backtrace +//! that led to the exception. +//! +//! ``` text +//! (gdb) continue +//! Program received signal SIGTRAP, Trace/breakpoint trap. +//! __bkpt () at asm/bkpt.s:3 +//! 3 bkpt +//! +//! (gdb) backtrace +//! #0 __bkpt () at asm/bkpt.s:3 +//! #1 0x080030b4 in cortex_m::asm::bkpt () at $$/cortex-m-0.5.0/src/asm.rs:19 +//! #2 rust_begin_unwind (args=..., file=..., line=99, col=5) at $$/panic-semihosting-0.2.0/src/lib.rs:87 +//! #3 0x08001d06 in core::panicking::panic_fmt () at libcore/panicking.rs:71 +//! #4 0x080004a6 in crash::hard_fault (ef=0x20004fa0) at examples/crash.rs:99 +//! #5 0x08000548 in UserHardFault (ef=0x20004fa0) at :10 +//! #6 0x0800093a in HardFault () at asm.s:5 +//! Backtrace stopped: previous frame identical to this frame (corrupt stack?) +//! ``` +//! +//! In the console output one will find the state of the Program Counter (PC) register at the time +//! of the exception. +//! +//! ``` text +//! panicked at 'HardFault at ExceptionFrame { +//! r0: 0x2fffffff, +//! r1: 0x2fffffff, +//! r2: 0x080051d4, +//! r3: 0x080051d4, +//! r12: 0x20000000, +//! lr: 0x08000435, +//! pc: 0x08000ab6, +//! xpsr: 0x61000000 +//! }', examples/crash.rs:106:5 +//! ``` +//! +//! This register contains the address of the instruction that caused the exception. In GDB one can +//! disassemble the program around this address to observe the instruction that caused the +//! exception. +//! +//! ``` text +//! (gdb) disassemble/m 0x08000ab6 +//! Dump of assembler code for function core::ptr::read_volatile: +//! 451 pub unsafe fn read_volatile(src: *const T) -> T { +//! 0x08000aae <+0>: sub sp, #16 +//! 0x08000ab0 <+2>: mov r1, r0 +//! 0x08000ab2 <+4>: str r0, [sp, #8] +//! +//! 452 intrinsics::volatile_load(src) +//! 0x08000ab4 <+6>: ldr r0, [sp, #8] +//! -> 0x08000ab6 <+8>: ldr r0, [r0, #0] +//! 0x08000ab8 <+10>: str r0, [sp, #12] +//! 0x08000aba <+12>: ldr r0, [sp, #12] +//! 0x08000abc <+14>: str r1, [sp, #4] +//! 0x08000abe <+16>: str r0, [sp, #0] +//! 0x08000ac0 <+18>: b.n 0x8000ac2 +//! +//! 453 } +//! 0x08000ac2 <+20>: ldr r0, [sp, #0] +//! 0x08000ac4 <+22>: add sp, #16 +//! 0x08000ac6 <+24>: bx lr +//! +//! End of assembler dump. +//! ``` +//! +//! `ldr r0, [r0, #0]` caused the exception. This instruction tried to load (read) a 32-bit word +//! from the address stored in the register `r0`. Looking again at the contents of `ExceptionFrame` +//! we see that the `r0` contained the address `0x2FFF_FFFF` when this instruction was executed. +//! +//! --- + +#![no_main] +#![no_std] + +use panic_halt as _; + +use core::ptr; + +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + unsafe { + // read an address outside of the RAM region; this causes a HardFault exception + ptr::read_volatile(0x2FFF_FFFF as *const u32); + } + + loop {} +} diff --git a/examples/device.rs b/examples/device.rs new file mode 100644 index 0000000..a1a219c --- /dev/null +++ b/examples/device.rs @@ -0,0 +1,62 @@ +//! Using a device crate +//! +//! Crates generated using [`svd2rust`] are referred to as device crates. These crates provide an +//! API to access the peripherals of a device. +//! +//! [`svd2rust`]: https://crates.io/crates/svd2rust +//! +//! This example depends on the [`stm32f3`] crate so you'll have to +//! uncomment it in your Cargo.toml. +//! +//! [`stm32f3`]: https://crates.io/crates/stm32f3 +//! +//! ``` +//! $ edit Cargo.toml && tail $_ +//! [dependencies.stm32f3] +//! features = ["stm32f303", "rt"] +//! version = "0.7.1" +//! ``` +//! +//! You also need to set the build target to thumbv7em-none-eabihf, +//! typically by editing `.cargo/config` and uncommenting the relevant target line. +//! +//! --- + +#![no_main] +#![no_std] + +#[allow(unused_extern_crates)] +use panic_halt as _; + +use cortex_m::peripheral::syst::SystClkSource; +use cortex_m_rt::entry; +use cortex_m_semihosting::hprint; +use stm32f3::stm32f303::{interrupt, Interrupt, NVIC}; + +#[entry] +fn main() -> ! { + let p = cortex_m::Peripherals::take().unwrap(); + + let mut syst = p.SYST; + let mut nvic = p.NVIC; + + nvic.enable(Interrupt::EXTI0); + + // configure the system timer to wrap around every second + syst.set_clock_source(SystClkSource::Core); + syst.set_reload(8_000_000); // 1s + syst.enable_counter(); + + loop { + // busy wait until the timer wraps around + while !syst.has_wrapped() {} + + // trigger the `EXTI0` interrupt + NVIC::pend(Interrupt::EXTI0); + } +} + +#[interrupt] +fn EXTI0() { + hprint!(".").unwrap(); +} diff --git a/examples/exception.rs b/examples/exception.rs new file mode 100644 index 0000000..5edb487 --- /dev/null +++ b/examples/exception.rs @@ -0,0 +1,37 @@ +//! Overriding an exception handler +//! +//! You can override an exception handler using the [`#[exception]`][1] attribute. +//! +//! [1]: https://rust-embedded.github.io/cortex-m-rt/0.6.1/cortex_m_rt_macros/fn.exception.html +//! +//! --- + +#![deny(unsafe_code)] +#![no_main] +#![no_std] + +use panic_halt as _; + +use cortex_m::peripheral::syst::SystClkSource; +use cortex_m::Peripherals; +use cortex_m_rt::{entry, exception}; +use cortex_m_semihosting::hprint; + +#[entry] +fn main() -> ! { + let p = Peripherals::take().unwrap(); + let mut syst = p.SYST; + + // configures the system timer to trigger a SysTick exception every second + syst.set_clock_source(SystClkSource::Core); + syst.set_reload(8_000_000); // period = 1s + syst.enable_counter(); + syst.enable_interrupt(); + + loop {} +} + +#[exception] +fn SysTick() { + hprint!(".").unwrap(); +} diff --git a/examples/hello.rs b/examples/hello.rs new file mode 100644 index 0000000..7069991 --- /dev/null +++ b/examples/hello.rs @@ -0,0 +1,20 @@ +//! Prints "Hello, world!" on the host console using semihosting + +#![no_main] +#![no_std] + +use panic_halt as _; + +use cortex_m_rt::entry; +use cortex_m_semihosting::{debug, hprintln}; + +#[entry] +fn main() -> ! { + hprintln!("Hello, world!").unwrap(); + + // exit QEMU + // NOTE do not run this on hardware; it can corrupt OpenOCD state + // debug::exit(debug::EXIT_SUCCESS); + + loop {} +} diff --git a/examples/itm.rs b/examples/itm.rs new file mode 100644 index 0000000..82f4150 --- /dev/null +++ b/examples/itm.rs @@ -0,0 +1,33 @@ +//! Sends "Hello, world!" through 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. +//! +//! [`itmdump`]: https://docs.rs/itm/0.2.1/itm/ +//! +//! --- + +#![no_main] +#![no_std] + +use panic_halt as _; + +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, world!"); + + loop {} +} diff --git a/examples/panic.rs b/examples/panic.rs new file mode 100644 index 0000000..94a51b7 --- /dev/null +++ b/examples/panic.rs @@ -0,0 +1,28 @@ +//! Changing the panicking behavior +//! +//! The easiest way to change the panicking behavior is to use a different [panic handler crate][0]. +//! +//! [0]: https://crates.io/keywords/panic-impl + +#![no_main] +#![no_std] + +// Pick one of these panic handlers: + +// `panic!` halts execution; the panic message is ignored +use panic_halt as _; + +// Reports panic messages to the host stderr using semihosting +// NOTE to use this you need to uncomment the `panic-semihosting` dependency in Cargo.toml +// use panic_semihosting as _; + +// Logs panic messages using the ITM (Instrumentation Trace Macrocell) +// NOTE to use this you need to uncomment the `panic-itm` dependency in Cargo.toml +// use panic_itm as _; + +use cortex_m_rt::entry; + +#[entry] +fn main() -> ! { + panic!("Oops") +} diff --git a/examples/test_on_host.rs b/examples/test_on_host.rs new file mode 100644 index 0000000..c831f11 --- /dev/null +++ b/examples/test_on_host.rs @@ -0,0 +1,57 @@ +//! Conditionally compiling tests with std and our executable with no_std. +//! +//! Rust's built in unit testing framework requires the standard library, +//! but we need to build our final executable with no_std. +//! The testing framework also generates a `main` method, so we need to only use the `#[entry]` +//! annotation when building our final image. +//! For more information on why this example works, see this excellent blog post. +//! https://os.phil-opp.com/unit-testing/ +//! +//! Running this example: +//! +//! Ensure there are no targets specified under `[build]` in `.cargo/config` +//! In order to make this work, we lose the convenience of having a default target that isn't the +//! host. +//! +//! cargo build --example test_on_host --target thumbv7m-none-eabi +//! cargo test --example test_on_host + +#![cfg_attr(test, allow(unused_imports))] + +#![cfg_attr(not(test), no_std)] +#![cfg_attr(not(test), no_main)] + +// pick a panicking behavior +#[cfg(not(test))] +use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics +// use panic_abort as _; // requires nightly +// use panic_itm as _; // logs messages over ITM; requires ITM support +// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger + +use cortex_m::asm; +use cortex_m_rt::entry; + +#[cfg(not(test))] +#[entry] +fn main() -> ! { + asm::nop(); // To not have main optimize to abort in release mode, remove when you add code + + loop { + // your code goes here + } +} + +fn add(a: i32, b: i32) -> i32 { + a + b +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn foo() { + println!("tests work!"); + assert!(2 == add(1,1)); + } +} diff --git a/memory.x b/memory.x new file mode 100644 index 0000000..b259ddb --- /dev/null +++ b/memory.x @@ -0,0 +1,34 @@ +MEMORY +{ + /* NOTE 1 K = 1 KiBi = 1024 bytes */ + /* TODO Adjust these memory regions to match your device memory layout */ + /* These values correspond to the LM3S6965, one of the few devices QEMU can emulate */ + FLASH : ORIGIN = 0x00000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 32K +} + +/* This is where the call stack will be allocated. */ +/* The stack is of the full descending type. */ +/* You may want to use this variable to locate the call stack and static + variables in different memory regions. Below is shown the default value */ +/* _stack_start = ORIGIN(RAM) + LENGTH(RAM); */ + +/* You can use this symbol to customize the location of the .text section */ +/* If omitted the .text section will be placed right after the .vector_table + section */ +/* This is required only on microcontrollers that store some configuration right + after the vector table */ +/* _stext = ORIGIN(FLASH) + 0x400; */ + +/* Example of putting non-initialized variables into custom RAM locations. */ +/* This assumes you have defined a region RAM2 above, and in the Rust + sources added the attribute `#[link_section = ".ram2bss"]` to the data + you want to place there. */ +/* Note that the section will not be zero-initialized by the runtime! */ +/* SECTIONS { + .ram2bss (NOLOAD) : ALIGN(4) { + *(.ram2bss); + . = ALIGN(4); + } > RAM2 + } INSERT AFTER .bss; +*/ diff --git a/new-main.bin b/new-main.bin new file mode 100755 index 0000000000000000000000000000000000000000..f154b7468a9a118d551211b157ea67eb5b528626 GIT binary patch literal 53268 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 literal 0 HcmV?d00001 diff --git a/openocd.cfg b/openocd.cfg new file mode 100644 index 0000000..5aec560 --- /dev/null +++ b/openocd.cfg @@ -0,0 +1,5 @@ +# Sample OpenOCD configuration for the STM32F3DISCOVERY development board + +source [find interface/stlink.cfg] + +source [find target/stm32f3x.cfg] diff --git a/openocd.gdb b/openocd.gdb new file mode 100644 index 0000000..7795319 --- /dev/null +++ b/openocd.gdb @@ -0,0 +1,40 @@ +target extended-remote :3333 + +# print demangled symbols +set print asm-demangle on + +# set backtrace limit to not have infinite backtrace loops +set backtrace limit 32 + +# detect unhandled exceptions, hard faults and panics +break DefaultHandler +break HardFault +break rust_begin_unwind +# # run the next few lines so the panic message is printed immediately +# # the number needs to be adjusted for your panic handler +# commands $bpnum +# next 4 +# end + +# *try* to stop at the user entry point (it might be gone due to inlining) +break main + +monitor arm semihosting enable + +# # send captured ITM to the file itm.fifo +# # (the microcontroller SWO pin must be connected to the programmer SWO pin) +# # 8000000 must match the core clock frequency +# monitor tpiu config internal itm.txt uart off 8000000 + +# # OR: make the microcontroller SWO pin output compatible with UART (8N1) +# # 8000000 must match the core clock frequency +# # 2000000 is the frequency of the SWO pin +# monitor tpiu config external uart off 8000000 2000000 + +# # enable ITM port 0 +# monitor itm port 0 on + +load + +# start the process but immediately halt the processor +stepi diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ef9c0b2 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,56 @@ +#![no_std] + +pub struct Board; + +impl Board { + pub fn setup_gpio_port(port: Port, options: PortSetup) -> PortIO { + PortIO + } +} + +pub enum Port { + A, + F, +} + +pub struct PortSetup; + +pub struct PortIO; + +impl PortIO { + pub fn setup_pin(pin: Pin, options: PinSetup) -> PinIO { + PinIO + } +} + +pub enum Pin { + Zero = 0, + One = 1, + Two = 2, + Three = 3, + Four = 4, + Five = 5, + Six = 6, + Seven = 7, +} + +pub struct PinSetup; + +pub struct PinIO; + +impl PinIO { + pub fn clear(&mut self) { + todo!(); + } + pub fn set(&mut self) { + todo!(); + } + pub fn toggle(&mut self) { + todo!(); + } +} + + +pub fn setup_board() -> Board { + Board +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e19fe3a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,116 @@ +#![no_std] +#![no_main] + +use core::ptr; + +use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics + +use cortex_m_rt::entry; + +// Begin .h file contents + +// GPIO registers (PORTF) +const GPIO_PORTF_DATA_R: *mut u32 = 0x400253FC as *mut u32; +const GPIO_PORTF_DIR_R: *mut u32 = 0x40025400 as *mut u32; +const GPIO_PORTF_AFSEL_R: *mut u32 = 0x40025420 as *mut u32; +const GPIO_PORTF_PUR_R: *mut u32 = 0x40025510 as *mut u32; +const GPIO_PORTF_DEN_R: *mut u32 = 0x4002551C as *mut u32; +const GPIO_PORTF_LOCK_R: *mut u32 = 0x40025520 as *mut u32; +const GPIO_PORTF_CR_R: *mut u32 = 0x40025524 as *mut u32; +const GPIO_PORTF_AMSEL_R: *mut u32 = 0x40025528 as *mut u32; +const GPIO_PORTF_PCTL_R: *mut u32 = 0x4002552C as *mut u32; + +const SYSCTL_RCGCPIO_R: *mut u32 = 0x400FE608 as *mut u32; + +// Begin starter project contents + +const GPIO_LOCK_KEY: *mut u32 = 0x4C4F434B as *mut u32; +const PF0: *mut u32 = 0x40025004 as *mut u32; +const PF4: *mut u32 = 0x40025040 as *mut u32; +const SWITCHES: *mut u32 = 0x40025044 as *mut u32; + +const SW1: u8 = 0b0001_0000; +const SW2: u8 = 0b0000_0001; + +const SYSCTL_RCGC2_GPIOF: *mut u32 = 0x00000020 as *mut u32; + +const BLACK: u8 = 0b0000_0000; +const RED: u8 = 0b0000_0010; +const GREEN: u8 = 0b0000_1000; +const BLUE: u8 = 0b0000_0100; + +fn setup_port_f() { + // 1) activate clock for Port F + unsafe { + ptr::write_volatile( + SYSCTL_RCGCPIO_R, + ptr::read_volatile(SYSCTL_RCGCPIO_R) | 0x00_00_00_20, + ); + } + + // Delay + for _ in 0u8..2u8 {} + + // 2) unlock GPIO Port F + unsafe { + ptr::write_volatile(GPIO_PORTF_LOCK_R, 0x4C4F434B); + // allow changes to PF4-0 + // only PF0 needs to be unlocked, other bits can't be locked + ptr::write_volatile(GPIO_PORTF_CR_R, 0b0001_1111); + } + + // 3) disable analog on PF + unsafe { ptr::write_volatile(GPIO_PORTF_AMSEL_R, 0x00) } + + // 4) PCTL GPIO on PF4-0 + unsafe { + ptr::write_volatile(GPIO_PORTF_PCTL_R, 0x00000000); + } + + // 5) PF4,PF0 in, PF3-1 out + unsafe { + ptr::write_volatile(GPIO_PORTF_DIR_R, 0x0E); + } + // 6) disable alt funct on PF7-0 + unsafe { + ptr::write_volatile(GPIO_PORTF_AFSEL_R, 0x00); + } + // enable pull-up on PF0 and PF4 + unsafe { + ptr::write_volatile(GPIO_PORTF_PUR_R, 0x11); + } + // 7) enable digital I/O on PF4-0 + unsafe { + ptr::write_volatile(GPIO_PORTF_DEN_R, 0x1F); + } +} + +fn input_from_port_f() -> u32 { + unsafe { + ptr::read_volatile(GPIO_PORTF_DATA_R) & u32::from(SW1 | SW2) + } +} + +fn output_to_port_f(value: u8) { + unsafe { + ptr::write_volatile(GPIO_PORTF_DATA_R, u32::from(value)); + } +} + +#[entry] +fn main() -> ! { + setup_port_f(); + + loop { + let status = input_from_port_f(); + + match status { + 0x01 => output_to_port_f(BLUE), + 0x10 => output_to_port_f(RED), + 0x00 => output_to_port_f(GREEN), + 0x11 => output_to_port_f(BLACK), + // Impossible case + _ => output_to_port_f(RED | BLUE), + } + } +}