Compare commits

...

10 Commits

Author SHA1 Message Date
34b11fb262 Nix flake for rustup dev shell 2025-10-16 22:57:44 +02:00
7ad309d78d Fix device example 2025-10-16 22:57:30 +02:00
711ec0f93f Blinky STM32F3-DISCOVERY 2025-10-16 22:57:16 +02:00
Daniel Egger
ac02415275 Merge pull request #132 from rust-embedded/no-nop
Remove unnecessary nop from main loops
2025-06-17 22:45:38 +02:00
Adam Greig
6aa25500e6 Remove unnecessary nop from main loops 2025-06-17 19:11:13 +01:00
andber1
0f9748a5e1 Update crates and adapt example code 2024-12-15 08:59:23 -08:00
Alex Martens
a34dd4f1c5 Merge pull request #125 from 30Wedge/fix-crash-example
Add a user-defined HardFault handler to print ExceptionFrame in crash…
2024-07-13 07:26:24 -07:00
30Wedge
6929b56b4a Add a user-defined HardFault handler to print ExceptionFrame in crash example 2024-05-08 17:23:49 -04:00
Adam Greig
cf52e9e29e Merge pull request #124 from angusholder/patch-2
Fix typo in Cargo.toml
2024-03-28 16:01:30 +00:00
Angus Holder
54e1059ae5 Fix typo in Cargo.toml 2024-03-28 15:59:04 +00:00
13 changed files with 203 additions and 56 deletions

View File

@@ -1,13 +1,13 @@
[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"
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"
runner = "gdb -q -x openocd.gdb"
rustflags = [
# Previously, the linker arguments --nmagic and -Tlink.x were set here.
@@ -29,9 +29,9 @@ rustflags = [
[build]
# Pick ONE of these default compilation targets
# target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
target = "thumbv7m-none-eabi" # Cortex-M3
# 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)
target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
# target = "thumbv8m.base-none-eabi" # Cortex-M23
# target = "thumbv8m.main-none-eabi" # Cortex-M33 (no FPU)
# target = "thumbv8m.main-none-eabihf" # Cortex-M33 (with FPU)

View File

@@ -1,32 +1,33 @@
[package]
authors = ["{{authors}}"]
authors = ["jasper"]
edition = "2018"
readme = "README.md"
name = "{{project-name}}"
name = "embedded-rs"
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"
cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
cortex-m-rt = "0.7"
cortex-m-semihosting = "0.5"
panic-halt = "1.0.0"
# stm32f3 = "0.7.1"
# Uncomment for the panic example.
# panic-itm = "0.4.1"
# Uncomment for the allocator example.
# alloc-cortex-m = "0.4.0"
# embedded-alloc = "0.6.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"
# and then use `cargo build --example device` to build it.
[dependencies.stm32f3]
features = ["stm32f303", "rt"]
version = "^0.16.0"
# this lets you use `cargo fix`!
[[bin]]
name = "{{project-name}}"
name = "embedded-rs"
test = false
bench = false

View File

@@ -1,15 +1,14 @@
//! 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:
//! This example depends on the embedded-alloc 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
//! $ cargo add embedded-alloc
//! ```
//!
//! ---
#![feature(alloc_error_handler)]
#![no_main]
#![no_std]
@@ -17,28 +16,33 @@ extern crate alloc;
use panic_halt as _;
use self::alloc::vec;
use core::alloc::Layout;
use core::ptr::addr_of_mut;
use alloc_cortex_m::CortexMHeap;
use cortex_m::asm;
// Linked-List First Fit Heap allocator (feature = "llff")
use embedded_alloc::LlffHeap as Heap;
// Two-Level Segregated Fit Heap allocator (feature = "tlsf")
// use embedded_alloc::TlsfHeap as Heap;
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
static HEAP: Heap = Heap::empty();
#[entry]
fn main() -> ! {
// Initialize the allocator BEFORE you use it
unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) }
{
use core::mem::MaybeUninit;
const HEAP_SIZE: usize = 1024;
static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
unsafe { HEAP.init(addr_of_mut!(HEAP_MEM) as usize, HEAP_SIZE) }
}
// Growable array allocated on the heap
let xs = vec![0, 1, 2];
hprintln!("{:?}", xs).unwrap();
hprintln!("{:?}", xs);
// exit QEMU
// NOTE do not run this on hardware; it can corrupt OpenOCD state
@@ -46,11 +50,3 @@ fn main() -> ! {
loop {}
}
// define what happens in an Out Of Memory (OOM) condition
#[alloc_error_handler]
fn alloc_error(_layout: Layout) -> ! {
asm::bkpt();
loop {}
}

View File

@@ -82,8 +82,10 @@
use panic_halt as _;
use core::ptr;
use core::fmt::Write;
use cortex_m_rt::entry;
use cortex_m_rt::{entry, exception, ExceptionFrame};
use cortex_m_semihosting::hio;
#[entry]
fn main() -> ! {
@@ -94,3 +96,12 @@ fn main() -> ! {
loop {}
}
#[exception(trampoline = true)]
unsafe fn HardFault(ef: &ExceptionFrame) -> ! {
if let Ok(mut hstdout) = hio::hstdout() {
writeln!(hstdout, "{:#?}", ef).ok();
}
loop {}
}

View File

@@ -40,7 +40,9 @@ fn main() -> ! {
let mut syst = p.SYST;
let mut nvic = p.NVIC;
nvic.enable(Interrupt::EXTI0);
unsafe {
nvic.iser[Interrupt::EXTI0 as usize / 32].write(1 << (Interrupt::EXTI0 as usize % 32));
}
// configure the system timer to wrap around every second
syst.set_clock_source(SystClkSource::Core);
@@ -58,5 +60,5 @@ fn main() -> ! {
#[interrupt]
fn EXTI0() {
hprint!(".").unwrap();
hprint!(".");
}

View File

@@ -33,5 +33,5 @@ fn main() -> ! {
#[exception]
fn SysTick() {
hprint!(".").unwrap();
hprint!(".");
}

View File

@@ -10,11 +10,11 @@ use cortex_m_semihosting::{debug, hprintln};
#[entry]
fn main() -> ! {
hprintln!("Hello, world!").unwrap();
hprintln!("Hello, world!");
// exit QEMU
// NOTE do not run this on hardware; it can corrupt OpenOCD state
debug::exit(debug::EXIT_SUCCESS);
// debug::exit(debug::EXIT_SUCCESS);
loop {}
}

View File

@@ -28,14 +28,11 @@ use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch
// 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
}

61
flake.lock generated Normal file
View File

@@ -0,0 +1,61 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1760423683,
"narHash": "sha256-Tb+NYuJhWZieDZUxN6PgglB16yuqBYQeMJyYBGCXlt8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a493e93b4a259cd9fea8073f89a7ed9b1c5a1da2",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

48
flake.nix Normal file
View File

@@ -0,0 +1,48 @@
# Adapted from https://wiki.nixos.org/wiki/Rust#Installation_via_rustup
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
flake-utils.url = "github:numtide/flake-utils";
};
outputs =
{
nixpkgs,
flake-utils,
...
}:
flake-utils.lib.eachDefaultSystem (
system:
let
pkgs = import nixpkgs {
inherit system;
};
in
with pkgs;
{
devShells.default = mkShell {
strictDeps = true;
nativeBuildInputs = [
rustup
rustPlatform.bindgenHook
rustfmt
clippy
rust-analyzer
pkg-config
openocd
gdb
qemu
inetutils # telnet for OpenOCD console
];
buildInputs = [
# Libraries here
openssl
];
RUSTC_VERSION = "stable";
shellHook = ''
export PATH="''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-${stdenv.hostPlatform.rust.rustcTarget}/bin:''${CARGO_HOME:-~/.cargo}/bin:$PATH"
'';
};
}
);
}

View File

@@ -3,8 +3,8 @@ 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 = 64K
FLASH : ORIGIN = 0x08000000, LENGTH = 256K
RAM : ORIGIN = 0x20000000, LENGTH = 40K
}
/* This is where the call stack will be allocated. */

View File

@@ -36,5 +36,5 @@ monitor arm semihosting enable
load
# start the process but immediately halt the processor
stepi
# Run to main
continue

View File

@@ -7,14 +7,45 @@ use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch
// 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::peripheral::{syst, Peripherals};
use cortex_m_rt::entry;
use stm32f3::stm32f303;
#[entry]
fn main() -> ! {
asm::nop(); // To not have main optimize to abort in release mode, remove when you add code
let cortex_peripherals = Peripherals::take().unwrap();
let mut systick = cortex_peripherals.SYST;
systick.set_clock_source(syst::SystClkSource::Core);
systick.set_reload(8_000_000); // 1s
systick.clear_current();
let device_peripherals = stm32f303::Peripherals::take().unwrap();
let rcc = device_peripherals.RCC;
rcc.ahbenr().write(|w| w.iopeen().set_bit());
// PE9: LD3 (red)
// PE8: LD4 (blue)
// PE10: LD5 (orange)
let gpioe = device_peripherals.GPIOE;
gpioe
.moder()
.write(|w| w.moder9().output().moder8().output().moder10().output());
gpioe.bsrr().write(|w| w.bs9().set_bit());
gpioe.bsrr().write(|w| w.bs8().set_bit());
gpioe.bsrr().write(|w| w.bs10().set_bit());
systick.enable_counter();
let mut enabled = true;
loop {
// your code goes here
while !systick.has_wrapped() {}
enabled = !enabled;
gpioe.odr().write(|w| {
w.odr8()
.bit(enabled)
.odr9()
.bit(enabled)
.odr10()
.bit(enabled)
});
}
}