refactor for streamlining
This commit is contained in:
31
HARDWARE.md
31
HARDWARE.md
@@ -1,31 +0,0 @@
|
||||
# Hardware Baseline (Bluepill + ST-Link)
|
||||
|
||||
## Board and Probe
|
||||
|
||||
- MCU board: STM32F103C8T6 Bluepill
|
||||
- Debug probe: ST-Link (SWD)
|
||||
|
||||
## SWD Wiring
|
||||
|
||||
1. ST-Link `SWDIO` -> Bluepill `PA13`
|
||||
2. ST-Link `SWCLK` -> Bluepill `PA14`
|
||||
3. ST-Link `GND` -> Bluepill `GND`
|
||||
4. ST-Link `3V3` -> Bluepill `3V3` (falls notwendig)
|
||||
5. Optional: ST-Link `NRST` -> Bluepill `NRST`
|
||||
|
||||
## Workshop I/O Wiring
|
||||
|
||||
1. LED:
|
||||
- Onboard LED an `PC13` (active-low)
|
||||
2. Button:
|
||||
- Externer Taster von `PA0` nach `GND`
|
||||
- Interner Pull-up wird im Code aktiviert
|
||||
3. Analog:
|
||||
- Poti/Sensor-Ausgang an `PA1`
|
||||
- Sensorversorgung über `3V3` + `GND`
|
||||
|
||||
## Sanity Checks
|
||||
|
||||
1. `probe-rs list` zeigt ST-Link an.
|
||||
2. `probe-rs chip list | grep STM32F103C8` findet Target.
|
||||
3. Beim Flashen keine "No probe found"-Meldung.
|
||||
96
README.md
96
README.md
@@ -6,28 +6,84 @@ Ideal für RoboCup-Interessierte aus der außerschulischen bzw. beruflichen Bild
|
||||
|
||||
## Workshop Layout
|
||||
|
||||
Dieses Repository ist als "Rust by Example"-ähnlicher Lernpfad aufgebaut:
|
||||
Jede Übung hat ihren eigenen Ordner. Der Lernpfad ist nummeriert.
|
||||
Jede Übung hat Aufgabe mit TODOs zum Lösen.
|
||||
|
||||
- `tutorial/00-setup-live` bis `tutorial/08-final-combined`
|
||||
- Jeder Schritt hat:
|
||||
- `task/` (Aufgabe mit TODOs)
|
||||
- `solution/` (Referenzlösung)
|
||||
- Teilnehmer arbeiten nur in `task/`.
|
||||
## Ablauf
|
||||
|
||||
## Quick Start
|
||||
0. Install Rust
|
||||
1. Rust Basics - Hello World
|
||||
2. Rust Basics - Typen
|
||||
3. Rust Basics - Ownership/Borrow
|
||||
4. kleines Desktop Programm
|
||||
5. Embedded - no std
|
||||
6. Embedded - LED Blinky
|
||||
7. Embedded - Button Input
|
||||
8. Embedded - Analog Readout
|
||||
9. Embedded - EmbassyRS
|
||||
|
||||
1. Host vorbereiten:
|
||||
- `bash scripts/setup-live.sh`
|
||||
2. Host prüfen:
|
||||
- `bash scripts/verify-host.sh`
|
||||
3. Probe prüfen:
|
||||
- `bash scripts/verify-probe.sh`
|
||||
4. Schritt ausführen:
|
||||
- `bash scripts/run-step.sh 01 task`
|
||||
# Hardware
|
||||
|
||||
## Core Files
|
||||
- MCU board: STM32F103C8T6 Bluepill
|
||||
- Debug probe: ST-Link (SWD)
|
||||
|
||||
- [WORKSHOP.md](/home/wieerwill/Dokumente/GitHub/didkata-rust-on-robots/WORKSHOP.md)
|
||||
- [HARDWARE.md](/home/wieerwill/Dokumente/GitHub/didkata-rust-on-robots/HARDWARE.md)
|
||||
- [TROUBLESHOOTING.md](/home/wieerwill/Dokumente/GitHub/didkata-rust-on-robots/TROUBLESHOOTING.md)
|
||||
- [references/source-map.md](/home/wieerwill/Dokumente/GitHub/didkata-rust-on-robots/references/source-map.md)
|
||||
## SWD Wiring
|
||||
|
||||
1. ST-Link `SWDIO` -> Bluepill `PA13`
|
||||
2. ST-Link `SWCLK` -> Bluepill `PA14`
|
||||
3. ST-Link `GND` -> Bluepill `GND`
|
||||
4. ST-Link `3V3` -> Bluepill `3V3`
|
||||
5. Optional: ST-Link `NRST` -> Bluepill `NRST`
|
||||
|
||||
## Workshop I/O Wiring
|
||||
|
||||
1. LED:
|
||||
- Onboard LED an `PC13` (active-low)
|
||||
2. Button:
|
||||
- Externer Taster von `PA0` nach `GND`
|
||||
- Interner Pull-up wird im Code aktiviert
|
||||
3. Analog (optional):
|
||||
- Poti/Sensor-Ausgang an `PA1`
|
||||
- Sensorversorgung über `3V3` + `GND`
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
## Host Setup
|
||||
|
||||
1. `rustup: command not found`
|
||||
- Rust via rustup installieren.
|
||||
2. `probe-rs: command not found`
|
||||
- `cargo install probe-rs-tools`
|
||||
3. Target fehlt
|
||||
- `rustup target add thumbv7m-none-eabi`
|
||||
|
||||
## Probe / Flashing
|
||||
|
||||
1. `No probe found`
|
||||
- USB-Kabel/Port prüfen
|
||||
- ST-Link Treiber/udev prüfen
|
||||
- `probe-rs list` erneut ausführen
|
||||
2. `chip not found`
|
||||
- Runner-String prüfen: `STM32F103C8`
|
||||
3. `Permission denied` (Linux)
|
||||
- udev-Regeln für ST-Link setzen und neu laden
|
||||
|
||||
## Runtime Behavior
|
||||
|
||||
1. LED blinkt nicht
|
||||
- PC13 active-low beachten
|
||||
- Versorgung prüfen
|
||||
2. Button reagiert nicht
|
||||
- Taster nach GND verdrahten
|
||||
- `PA0` korrekt belegt?
|
||||
3. Analogwerte ändern sich nicht
|
||||
- Sensor/Poti wirklich an `PA1`
|
||||
- Gemeinsame Masse sicherstellen
|
||||
|
||||
## Fallback in Session
|
||||
|
||||
Wenn eine Station nicht stabil läuft:
|
||||
|
||||
1. Mit funktionierender Nachbarn pairen.
|
||||
2. `solution/` ausführen.
|
||||
3. Später wieder auf `task/` zurückwechseln.
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
# Troubleshooting
|
||||
|
||||
## Host Setup
|
||||
|
||||
1. `rustup: command not found`
|
||||
- Rust via rustup installieren.
|
||||
2. `probe-rs: command not found`
|
||||
- `cargo install probe-rs-tools`
|
||||
3. Target fehlt
|
||||
- `rustup target add thumbv7m-none-eabi`
|
||||
|
||||
## Probe / Flashing
|
||||
|
||||
1. `No probe found`
|
||||
- USB-Kabel/Port prüfen
|
||||
- ST-Link Treiber/udev prüfen
|
||||
- `probe-rs list` erneut ausführen
|
||||
2. `chip not found`
|
||||
- Runner-String prüfen: `STM32F103C8`
|
||||
3. `Permission denied` (Linux)
|
||||
- udev-Regeln für ST-Link setzen und neu laden
|
||||
|
||||
## Runtime Behavior
|
||||
|
||||
1. LED blinkt nicht
|
||||
- PC13 active-low beachten
|
||||
- Versorgung prüfen
|
||||
2. Button reagiert nicht
|
||||
- Taster nach GND verdrahten
|
||||
- `PA0` korrekt belegt?
|
||||
3. Analogwerte ändern sich nicht
|
||||
- Sensor/Poti wirklich an `PA1`
|
||||
- Gemeinsame Masse sicherstellen
|
||||
|
||||
## Fallback in Session
|
||||
|
||||
Wenn eine Station nicht stabil läuft:
|
||||
|
||||
1. Mit funktionierender Nachbarn pairen.
|
||||
2. `solution/` ausführen.
|
||||
3. Später wieder auf `task/` zurückwechseln.
|
||||
71
WORKSHOP.md
71
WORKSHOP.md
@@ -1,71 +0,0 @@
|
||||
# Workshop Plan (60 Minutes)
|
||||
|
||||
## Goal
|
||||
|
||||
Von Rust-Basics zu echter Hardware auf STM32F103C8 Bluepill:
|
||||
|
||||
- LED blinken
|
||||
- Button einlesen
|
||||
- Analogwert einlesen
|
||||
- Ausgabe live über `probe-rs` / RTT sehen
|
||||
|
||||
## Timing
|
||||
|
||||
1. 00:00-00:10: Setup + Probe Smoke Test (`00`)
|
||||
2. 00:10-00:28: Rust Basics (`01`-`03`)
|
||||
3. 00:28-00:36: Erstes `no_std` Firmware-Projekt (`04`)
|
||||
4. 00:36-00:44: LED Blinky (`05`)
|
||||
5. 00:44-00:50: Button Input (`06`)
|
||||
6. 00:50-00:56: Analog Readout (`07`)
|
||||
7. 00:56-01:00: Integration (`08`)
|
||||
|
||||
## Rules During Workshop
|
||||
|
||||
1. Bearbeite nur `task/`.
|
||||
2. Nutze `solution/` nur als Hilfe bei Blockern.
|
||||
3. Falls >3 Minuten blockiert: Diff vergleichen, minimalen Fix übernehmen, weiter.
|
||||
4. Bei Embedded-Schritten: Board vor jedem `cargo run` korrekt verkabeln.
|
||||
|
||||
## Repo Management During Workshop
|
||||
|
||||
1. `main` enthält Aufgaben und Referenzlösungen.
|
||||
2. Instructor kann Wiederherstellungspunkte als Tags setzen:
|
||||
- `step-00-start` ... `step-08-solution`
|
||||
3. Teilnehmer arbeiten auf lokalem Branch:
|
||||
- `participant/<name>`
|
||||
4. Wenn eine Aufgabe nicht weitergeht:
|
||||
- minimalen Diff aus `solution/` übernehmen und fortfahren.
|
||||
|
||||
## Step Contract
|
||||
|
||||
Jeder Schritt enthält:
|
||||
|
||||
- `README.md` mit Ziel, Ablauf, Done-Check
|
||||
- `task/` (Aufgabe)
|
||||
- `solution/` (Referenz)
|
||||
|
||||
## Script Contract
|
||||
|
||||
- `scripts/setup-live.sh`
|
||||
- `scripts/verify-host.sh`
|
||||
- `scripts/verify-probe.sh`
|
||||
- `scripts/run-step.sh <step-id> <task|solution>`
|
||||
- `scripts/check-step.sh <step-id>`
|
||||
|
||||
## Target Contract (Embedded Steps 04-08)
|
||||
|
||||
- Target: `thumbv7m-none-eabi`
|
||||
- Runner: `probe-rs run --chip STM32F103C8`
|
||||
- Logging: `defmt-rtt` + `panic-probe`
|
||||
|
||||
## Acceptance Scenarios
|
||||
|
||||
1. Steps `01`-`03`: `cargo run` funktioniert für `task/` und `solution/`.
|
||||
2. Steps `04`-`08`: `cargo build --release` funktioniert für `task/` und `solution/`.
|
||||
3. Probe-Verbindung:
|
||||
- `probe-rs list` erkennt ST-Link.
|
||||
4. Behavior:
|
||||
- `05`: LED blinkt
|
||||
- `06`: Press/Release Logs
|
||||
- `07`: ADC-Wert reagiert auf Eingang
|
||||
- `08`: integriertes Verhalten läuft stabil
|
||||
48
shell.nix
Normal file
48
shell.nix
Normal file
@@ -0,0 +1,48 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
overrides = (builtins.fromTOML (builtins.readFile ./rust-embassy-stm32/rust-toolchain.toml));
|
||||
libPath = with pkgs; lib.makeLibraryPath [
|
||||
# load external libraries that you need in your rust project here
|
||||
];
|
||||
in
|
||||
pkgs.mkShell rec {
|
||||
nativeBuildInputs = [ pkgs.pkg-config ];
|
||||
buildInputs = with pkgs; [
|
||||
clang
|
||||
# Replace llvmPackages with llvmPackages_X, where X is the latest LLVM version (at the time of writing, 16)
|
||||
llvmPackages.bintools
|
||||
rustup
|
||||
];
|
||||
|
||||
RUSTC_VERSION = overrides.toolchain.channel;
|
||||
|
||||
# https://github.com/rust-lang/rust-bindgen#environment-variables
|
||||
LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
|
||||
|
||||
shellHook = ''
|
||||
export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
|
||||
export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/
|
||||
'';
|
||||
|
||||
# Add precompiled library to rustc search path
|
||||
RUSTFLAGS = (builtins.map (a: ''-L ${a}/lib'') [
|
||||
# add libraries here (e.g. pkgs.libvmi)
|
||||
]);
|
||||
|
||||
LD_LIBRARY_PATH = libPath;
|
||||
|
||||
# Add glibc, clang, glib, and other headers to bindgen search path
|
||||
BINDGEN_EXTRA_CLANG_ARGS =
|
||||
# Includes normal include path
|
||||
(builtins.map (a: ''-I"${a}/include"'') [
|
||||
# add dev libraries here (e.g. pkgs.libvmi.dev)
|
||||
pkgs.glibc.dev
|
||||
])
|
||||
# Includes with special directory paths
|
||||
++ [
|
||||
''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"''
|
||||
''-I"${pkgs.glib.dev}/include/glib-2.0"''
|
||||
''-I${pkgs.glib.out}/lib/glib-2.0/include/''
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
# Source Map
|
||||
|
||||
Dieses Mapping dokumentiert, welche gesammelten Quellen in welche Workshop-Bausteine eingeflossen sind.
|
||||
|
||||
## Rust Basics (`01`-`03`)
|
||||
|
||||
1. `sources/rust-by-example/*`
|
||||
- Schrittweiser Lernstil mit kleinen, lauffähigen Beispielen
|
||||
2. `sources/Introduction - A Gentle Introduction to Rust.md`
|
||||
- sanfter Einstieg in Ownership/Borrowing
|
||||
3. `sources/Learn Rust - Rust Programming Language.md`
|
||||
- Orientierung an offiziellen Lernpfaden
|
||||
|
||||
## Embedded Foundations (`04`)
|
||||
|
||||
1. `sources/Intro to Rust on Embedded Your First no_std Project with Code Examples – Hubble Network Community.md`
|
||||
- `no_std`, PAC/HAL/BSP, Einstiegspfad
|
||||
2. `sources/rust-embedded-book/src/intro/no-std.md`
|
||||
- saubere no_std-Grundlagen
|
||||
3. `sources/rust-embedded-book/src/peripherals/singletons.md`
|
||||
- Ownership auf Hardware-Peripherie übertragen
|
||||
|
||||
## Tooling and Workflow (`00`, scripts)
|
||||
|
||||
1. `sources/Embedded Rust Toolchains – Albert Skog.md`
|
||||
- Probe-rs/probe-run Workflow-Einordnung
|
||||
2. `sources/Embassy Book.md`
|
||||
- praktischer Cargo + probe-rs Runner-Ansatz
|
||||
|
||||
## STM32 Practical Steps (`05`-`08`)
|
||||
|
||||
1. `sources/rust-embassy-stm32/src/bin/{blinky.rs,button.rs,adc.rs}`
|
||||
- konkrete Zielübungen (LED/Button/ADC + Logs)
|
||||
2. `sources/STM32F4 Embedded Rust at the HAL *.md`
|
||||
- didaktische Sequenz: GPIO -> Input -> ADC -> Integration
|
||||
3. `sources/AnyLeaf articles Writing embedded firmware using Rust.md`
|
||||
- Register/HAL-Abstraktionslevel, Embedded-Rust Argumentation
|
||||
4. `sources/Brave new IO Embedded in Rust.md`
|
||||
- Ownership/Typisierung für sichere Hardwarezugriffe
|
||||
@@ -1,4 +1,4 @@
|
||||
# Task Checklist
|
||||
# 00 - install rust
|
||||
|
||||
- [ ] Rust toolchain installiert (`rustup`, `cargo`, `rustc`)
|
||||
- [ ] Target `thumbv7m-none-eabi` installiert
|
||||
@@ -28,9 +28,14 @@ if ! command -v probe-rs >/dev/null 2>&1; then
|
||||
cargo install probe-rs-tools
|
||||
sudo groupadd --system plugdev
|
||||
sudo usermod -a -G plugdev $USER
|
||||
probe-rs complete install
|
||||
else
|
||||
echo "[setup] probe-rs already installed"
|
||||
probe-rs --version
|
||||
fi
|
||||
|
||||
probe-rs list
|
||||
probe-rs info
|
||||
probe-rs chip list | grep STM32F103C8
|
||||
|
||||
echo "[setup] done"
|
||||
@@ -1,17 +0,0 @@
|
||||
# 00 - Setup Live (10 min)
|
||||
|
||||
## Goal
|
||||
|
||||
Jede Station kann Rust-Code bauen und eine Bluepill über ST-Link erkennen.
|
||||
|
||||
## Steps
|
||||
|
||||
1. install rustup
|
||||
2. add target
|
||||
3. add probe-rs
|
||||
|
||||
## Done when
|
||||
|
||||
1. `rustc`, `cargo`, `probe-rs` verfügbar.
|
||||
2. `thumbv7m-none-eabi` installiert.
|
||||
3. `probe-rs list` zeigt die Probe.
|
||||
7
tutorial/01-rust-hello/Cargo.lock
generated
Normal file
7
tutorial/01-rust-hello/Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "rust_hello_task"
|
||||
version = "0.1.0"
|
||||
@@ -1,4 +1,4 @@
|
||||
[package]
|
||||
name = "step01_rust_hello_task"
|
||||
name = "rust_hello_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
@@ -1,20 +1,15 @@
|
||||
# 01 - Rust Hello (5 min)
|
||||
|
||||
## Goal
|
||||
# 01 - Rust Hello
|
||||
|
||||
Erstes lauffähiges Rust-Programm, das Daten über `println!` ausgibt.
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 01 task`
|
||||
```bash
|
||||
cd src/
|
||||
rustc main.c
|
||||
./main.c
|
||||
```
|
||||
|
||||
## Tasks
|
||||
|
||||
1. Öffne `task/src/main.rs`.
|
||||
2. Ersetze die TODO-Werte.
|
||||
3. Starte erneut mit `cargo run`.
|
||||
|
||||
## Done when
|
||||
|
||||
1. Das Programm kompiliert.
|
||||
2. Die Ausgabe enthält euren Namen und Workshop-Titel.
|
||||
```bash
|
||||
cargo run
|
||||
```
|
||||
BIN
tutorial/01-rust-hello/solution.06p5vxa3q8owanxdnt6b423l3.rcgu.o
Normal file
BIN
tutorial/01-rust-hello/solution.06p5vxa3q8owanxdnt6b423l3.rcgu.o
Normal file
Binary file not shown.
Binary file not shown.
BIN
tutorial/01-rust-hello/src/main
Executable file
BIN
tutorial/01-rust-hello/src/main
Executable file
Binary file not shown.
@@ -3,7 +3,8 @@ fn main() {
|
||||
let participant_name = "Your Name";
|
||||
let workshop_title = "Rust on Embedded @ Didacta";
|
||||
|
||||
println!("Hello, {participant_name}!");
|
||||
println!("Welcome to: {workshop_title}");
|
||||
// TODO: Insert the strings in the output
|
||||
println!("Hello, TODO !");
|
||||
println!("Welcome to: TODO");
|
||||
println!("Next step: types, control flow, and ownership.");
|
||||
}
|
||||
BIN
tutorial/01-rust-hello/src/solution
Executable file
BIN
tutorial/01-rust-hello/src/solution
Executable file
Binary file not shown.
7
tutorial/02-rust-types-control/Cargo.lock
generated
Normal file
7
tutorial/02-rust-types-control/Cargo.lock
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "rust_types_control_task"
|
||||
version = "0.1.0"
|
||||
@@ -1,4 +1,4 @@
|
||||
[package]
|
||||
name = "step01_rust_hello_solution"
|
||||
name = "rust_types_control_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
@@ -1,20 +1,3 @@
|
||||
# 02 - Types and Control Flow (6 min)
|
||||
|
||||
## Goal
|
||||
|
||||
Mit Typen, `if`, und `match` kleine Entscheidungen ausdrücken.
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 02 task`
|
||||
|
||||
## Tasks
|
||||
|
||||
1. Passe die Schwellwerte in `classify_adc` an.
|
||||
2. Teste mit mehreren ADC-Werten.
|
||||
3. Beobachte die Ausgabe von `pressed/released` und `low/medium/high`.
|
||||
|
||||
## Done when
|
||||
|
||||
1. Das Programm kompiliert.
|
||||
2. Für unterschiedliche Werte entstehen unterschiedliche Klassifizierungen.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[package]
|
||||
name = "step02_rust_types_control_solution"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
@@ -16,14 +16,17 @@ fn classify_adc(raw: u16) -> &'static str {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// TODO: fill in some values into the arrays
|
||||
let button_samples = [false, true, true, false];
|
||||
let adc_samples: [u16; 5] = [120, 900, 1500, 2600, 3900];
|
||||
|
||||
for pressed in button_samples {
|
||||
println!("button: {}", classify_button(pressed));
|
||||
// call and print the function for the button
|
||||
println!("button: {}");
|
||||
}
|
||||
|
||||
for raw in adc_samples {
|
||||
println!("adc raw={raw:4} => {}", classify_adc(raw));
|
||||
// call and print the function for the button
|
||||
println!("adc raw={raw:4} => {}");
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
[package]
|
||||
name = "step02_rust_types_control_task"
|
||||
name = "rust_ownership_borrow_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
@@ -1,20 +1,3 @@
|
||||
# 03 - Ownership and Borrowing (7 min)
|
||||
|
||||
## Goal
|
||||
# 03 - Ownership and Borrowing
|
||||
|
||||
Ownership und Borrowing an einem kleinen Robot-State praktisch verstehen.
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 03 task`
|
||||
|
||||
## Tasks
|
||||
|
||||
1. Lies die Funktionen mit `&RobotState` und `&mut RobotState`.
|
||||
2. Ergänze die TODOs in der Task-Datei.
|
||||
3. Achte auf Compiler-Fehler, wenn mutable/immutable borrows kollidieren.
|
||||
|
||||
## Done when
|
||||
|
||||
1. Das Programm kompiliert.
|
||||
2. LED-State, Button-Count und ADC-Wert werden korrekt aktualisiert.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
[package]
|
||||
name = "step03_rust_ownership_borrow_solution"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
@@ -6,27 +6,31 @@ struct RobotState {
|
||||
}
|
||||
|
||||
fn print_state(state: &RobotState) {
|
||||
// TODO: print the different elements of RobotState
|
||||
println!(
|
||||
"state => led_on={}, button_count={}, last_adc={}",
|
||||
state.led_on, state.button_count, state.last_adc
|
||||
???
|
||||
);
|
||||
}
|
||||
|
||||
fn toggle_led(state: &mut RobotState) {
|
||||
state.led_on = !state.led_on;
|
||||
// TODO: change the LED state to the inverse of itself
|
||||
state.led_on = ??
|
||||
}
|
||||
|
||||
fn record_button_press(state: &mut RobotState) {
|
||||
state.button_count += 1;
|
||||
// TODO: increase the button counter on press
|
||||
state.button_count = ??
|
||||
}
|
||||
|
||||
fn update_adc(state: &mut RobotState, raw: u16) {
|
||||
// TODO: keep this function as the single writer for ADC state.
|
||||
state.last_adc = raw;
|
||||
// TODO: update the adc value with the given one
|
||||
state.last_adc = ??
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut state = RobotState {
|
||||
// TODO: change the RobotState so we can edit its values
|
||||
let state = RobotState {
|
||||
led_on: false,
|
||||
button_count: 0,
|
||||
last_adc: 0,
|
||||
@@ -1,4 +1,4 @@
|
||||
[package]
|
||||
name = "step03_rust_ownership_borrow_task"
|
||||
name = "rust_desktop_programm"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
3
tutorial/04-desktop-programm/README.md
Normal file
3
tutorial/04-desktop-programm/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 04 Desktop Programm
|
||||
|
||||
kleines CLI Tool um Fertigkeiten auszuprobieren
|
||||
0
tutorial/04-desktop-programm/src/main.rs
Normal file
0
tutorial/04-desktop-programm/src/main.rs
Normal file
@@ -1,20 +0,0 @@
|
||||
# 04 - Embedded no_std Hello (8 min)
|
||||
|
||||
## Goal
|
||||
|
||||
Erstes Bare-Metal-Programm mit `#![no_std]`, `#![no_main]` und RTT Logs.
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 04 task`
|
||||
|
||||
## Tasks
|
||||
|
||||
1. Lies die Top-Level-Attribute in `task/src/main.rs`.
|
||||
2. Passe die Log-Ausgaben an.
|
||||
3. Flashe mit `cargo run --release`.
|
||||
|
||||
## Done when
|
||||
|
||||
1. Firmware läuft auf Bluepill.
|
||||
2. RTT zeigt zyklisch eine "alive"-Meldung.
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "step04_embedded_no_std_hello_solution"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.7"
|
||||
cortex-m-rt = "0.7.5"
|
||||
defmt = "0.3.10"
|
||||
defmt-rtt = "0.4.2"
|
||||
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
|
||||
nb = "1.1.0"
|
||||
|
||||
[dependencies.stm32f1xx-hal]
|
||||
version = "0.11.0"
|
||||
features = ["rt", "stm32f103", "medium"]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "step04_embedded_no_std_hello_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.7"
|
||||
cortex-m-rt = "0.7.5"
|
||||
defmt = "0.3.10"
|
||||
defmt-rtt = "0.4.2"
|
||||
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
|
||||
nb = "1.1.0"
|
||||
|
||||
[dependencies.stm32f1xx-hal]
|
||||
version = "0.11.0"
|
||||
features = ["rt", "stm32f103", "medium"]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
@@ -1,20 +0,0 @@
|
||||
# 05 - LED Blink (8 min)
|
||||
|
||||
## Goal
|
||||
|
||||
Onboard-LED (PC13, active-low) per Timer toggeln.
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 05 task`
|
||||
|
||||
## Tasks
|
||||
|
||||
1. Prüfe in `task/src/main.rs`, welche Pegel "LED an/aus" bedeuten.
|
||||
2. Passe Blinkfrequenz an.
|
||||
3. Verifiziere LED und Logs.
|
||||
|
||||
## Done when
|
||||
|
||||
1. LED blinkt sichtbar.
|
||||
2. Logs zeigen den Schaltzustand.
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "step05_led_blink_task"
|
||||
name = "embedded_no_std"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
3
tutorial/05-no-std/README.md
Normal file
3
tutorial/05-no-std/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 05 - Embedded no_std
|
||||
|
||||
Erstes Bare-Metal-Programm mit `#![no_std]`, `#![no_main]` und RTT Logs.
|
||||
@@ -8,11 +8,9 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
// TODO: personalize these log lines.
|
||||
info!("step04: no_std hello on stm32f103c8");
|
||||
info!("stm: no_std hello on stm32f103c8");
|
||||
|
||||
loop {
|
||||
// TODO: we want this as a loop
|
||||
asm::delay(8_000_000);
|
||||
info!("step04: alive");
|
||||
}
|
||||
info!("stm: alive");
|
||||
}
|
||||
@@ -8,10 +8,10 @@ use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
info!("step04: boot ok");
|
||||
info!("boot ok");
|
||||
|
||||
loop {
|
||||
asm::delay(8_000_000);
|
||||
info!("step04: alive");
|
||||
info!("alive");
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
# 06 - Button Input (6 min)
|
||||
|
||||
## Goal
|
||||
|
||||
Button an PA0 (Pull-up) lesen und Press/Release als Log ausgeben.
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 06 task`
|
||||
|
||||
## Tasks
|
||||
|
||||
1. Verdrahtung prüfen: PA0 -> Button -> GND.
|
||||
2. Starte `task` und beobachte Logs.
|
||||
3. Passe Polling-Intervall an.
|
||||
|
||||
## Done when
|
||||
|
||||
1. Pressed/Released wird korrekt erkannt.
|
||||
2. Keine Flut von Wiederhol-Logs bei gehaltenem Taster.
|
||||
@@ -1,12 +0,0 @@
|
||||
[target.thumbv7m-none-eabi]
|
||||
runner = "probe-rs run --chip STM32F103C8"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "info"
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "step06_button_input_solution"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.7"
|
||||
cortex-m-rt = "0.7.5"
|
||||
defmt = "0.3.10"
|
||||
defmt-rtt = "0.4.2"
|
||||
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
|
||||
nb = "1.1.0"
|
||||
|
||||
[dependencies.stm32f1xx-hal]
|
||||
version = "0.11.0"
|
||||
features = ["rt", "stm32f103", "medium"]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
@@ -1,5 +0,0 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["rustfmt"]
|
||||
targets = ["thumbv7m-none-eabi"]
|
||||
@@ -1,12 +0,0 @@
|
||||
[target.thumbv7m-none-eabi]
|
||||
runner = "probe-rs run --chip STM32F103C8"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "info"
|
||||
@@ -1,5 +0,0 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["rustfmt"]
|
||||
targets = ["thumbv7m-none-eabi"]
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "step06_button_input_task"
|
||||
name = "led_blink_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
3
tutorial/06-led-blink/README.md
Normal file
3
tutorial/06-led-blink/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 06 - LED Blink
|
||||
|
||||
Onboard-LED (PC13, active-low) per Timer toggeln.
|
||||
@@ -16,7 +16,7 @@ fn main() -> ! {
|
||||
let mut gpioc = dp.GPIOC.split(&mut rcc);
|
||||
|
||||
// Bluepill onboard LED on PC13 is active-low.
|
||||
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
||||
// TODO: create LED Pin Input
|
||||
|
||||
let mut timer = Timer::syst(cp.SYST, &rcc.clocks).counter_hz();
|
||||
timer.start(2.Hz()).unwrap();
|
||||
@@ -1,20 +0,0 @@
|
||||
# 07 - Analog Readout (6 min)
|
||||
|
||||
## Goal
|
||||
|
||||
ADC auf PA1 lesen und Werte über RTT streamen.
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 07 task`
|
||||
|
||||
## Tasks
|
||||
|
||||
1. Verdrahtung prüfen: Analogsignal an PA1.
|
||||
2. Werte ausgeben und in drei Bereiche klassifizieren.
|
||||
3. Potentiometer/Sensor bewegen und Änderung beobachten.
|
||||
|
||||
## Done when
|
||||
|
||||
1. Rohwert ändert sich mit Eingangsspannung.
|
||||
2. Klassifizierung (`low/medium/high`) reagiert sinnvoll.
|
||||
@@ -1,12 +0,0 @@
|
||||
[target.thumbv7m-none-eabi]
|
||||
runner = "probe-rs run --chip STM32F103C8"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "info"
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "step07_analog_readout_solution"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.7"
|
||||
cortex-m-rt = "0.7.5"
|
||||
defmt = "0.3.10"
|
||||
defmt-rtt = "0.4.2"
|
||||
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
|
||||
nb = "1.1.0"
|
||||
|
||||
[dependencies.stm32f1xx-hal]
|
||||
version = "0.11.0"
|
||||
features = ["rt", "stm32f103", "medium"]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
@@ -1,5 +0,0 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["rustfmt"]
|
||||
targets = ["thumbv7m-none-eabi"]
|
||||
@@ -1,12 +0,0 @@
|
||||
[target.thumbv7m-none-eabi]
|
||||
runner = "probe-rs run --chip STM32F103C8"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "info"
|
||||
@@ -1,5 +0,0 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["rustfmt"]
|
||||
targets = ["thumbv7m-none-eabi"]
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "step05_led_blink_solution"
|
||||
name = "button_input_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
3
tutorial/07-button-input/README.md
Normal file
3
tutorial/07-button-input/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 07 - Button Input
|
||||
|
||||
Button an PA0 (Pull-up) lesen und Press/Release als Log ausgeben.
|
||||
@@ -15,8 +15,7 @@ fn main() -> ! {
|
||||
let mut rcc = dp.RCC.constrain();
|
||||
let mut gpioa = dp.GPIOA.split(&mut rcc);
|
||||
|
||||
// Button wiring: PA0 -> button -> GND
|
||||
let button = gpioa.pa0.into_pull_up_input(&mut gpioa.crl);
|
||||
// TODO: Button wiring: PA0 -> button -> GND
|
||||
|
||||
let mut timer = Timer::syst(cp.SYST, &rcc.clocks).counter_hz();
|
||||
timer.start(40.Hz()).unwrap();
|
||||
@@ -24,15 +23,9 @@ fn main() -> ! {
|
||||
let mut last_pressed = false;
|
||||
|
||||
loop {
|
||||
let pressed = button.is_low();
|
||||
if pressed != last_pressed {
|
||||
if pressed {
|
||||
info!("button: pressed");
|
||||
} else {
|
||||
info!("button: released");
|
||||
}
|
||||
last_pressed = pressed;
|
||||
}
|
||||
|
||||
// TODO: get the current button status
|
||||
// TODO: print a message when the button is pressed and released
|
||||
|
||||
// Poll at 25ms to avoid too much log spam.
|
||||
block!(timer.wait()).unwrap();
|
||||
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "step07_analog_readout_task"
|
||||
name = "analog_readout_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
3
tutorial/08-analog-readout/README.md
Normal file
3
tutorial/08-analog-readout/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 08 - Analog Readout
|
||||
|
||||
ADC auf PA1 lesen und Werte über RTT streamen.
|
||||
@@ -24,8 +24,7 @@ fn main() -> ! {
|
||||
let mut rcc = dp.RCC.constrain();
|
||||
let mut gpioa = dp.GPIOA.split(&mut rcc);
|
||||
|
||||
let mut adc = Adc::new(dp.ADC1, &mut rcc);
|
||||
let mut analog_pin = gpioa.pa1.into_analog(&mut gpioa.crl);
|
||||
// TODO: set up ADC and ADC Pin and read
|
||||
|
||||
let mut timer = Timer::syst(cp.SYST, &rcc.clocks).counter_hz();
|
||||
timer.start(10.Hz()).unwrap();
|
||||
@@ -1,22 +0,0 @@
|
||||
# 08 - Final Combined (4 min)
|
||||
|
||||
## Goal
|
||||
|
||||
Blink + Button + ADC in einem Programm kombinieren.
|
||||
|
||||
## Behavior
|
||||
|
||||
1. ADC steuert Blink-Intervall.
|
||||
2. Button toggelt Betriebsmodus:
|
||||
- `Mode::Blinking`
|
||||
- `Mode::ForcedOff`
|
||||
|
||||
## Run
|
||||
|
||||
- `bash scripts/run-step.sh 08 task`
|
||||
|
||||
## Done when
|
||||
|
||||
1. LED-Verhalten ändert sich per Button.
|
||||
2. ADC beeinflusst Blinkgeschwindigkeit im Blink-Modus.
|
||||
3. Logs zeigen Mode, ADC und Delay.
|
||||
@@ -1,12 +0,0 @@
|
||||
[target.thumbv7m-none-eabi]
|
||||
runner = "probe-rs run --chip STM32F103C8"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "info"
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "step08_final_combined_solution"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.7"
|
||||
cortex-m-rt = "0.7.5"
|
||||
defmt = "0.3.10"
|
||||
defmt-rtt = "0.4.2"
|
||||
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
|
||||
nb = "1.1.0"
|
||||
|
||||
[dependencies.stm32f1xx-hal]
|
||||
version = "0.11.0"
|
||||
features = ["rt", "stm32f103", "medium"]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
@@ -1,5 +0,0 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["rustfmt"]
|
||||
targets = ["thumbv7m-none-eabi"]
|
||||
@@ -1,83 +0,0 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::info;
|
||||
use nb::block;
|
||||
use stm32f1xx_hal::{adc::Adc, pac, prelude::*, timer::Timer};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Mode {
|
||||
Blinking,
|
||||
ForcedOff,
|
||||
}
|
||||
|
||||
fn interval_from_adc(raw: u16) -> u32 {
|
||||
100 + (u32::from(raw) * 800 / 4095)
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
let mut rcc = dp.RCC.constrain();
|
||||
let mut gpioa = dp.GPIOA.split(&mut rcc);
|
||||
let mut gpioc = dp.GPIOC.split(&mut rcc);
|
||||
|
||||
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
||||
let button = gpioa.pa0.into_pull_up_input(&mut gpioa.crl);
|
||||
|
||||
let mut adc = Adc::new(dp.ADC1, &mut rcc);
|
||||
let mut analog_pin = gpioa.pa1.into_analog(&mut gpioa.crl);
|
||||
|
||||
let mut tick = Timer::syst(cp.SYST, &rcc.clocks).counter_hz();
|
||||
tick.start(100.Hz()).unwrap();
|
||||
|
||||
let mut mode = Mode::Blinking;
|
||||
let mut last_pressed = false;
|
||||
let mut led_on = false;
|
||||
let mut elapsed_ms: u32 = 0;
|
||||
|
||||
loop {
|
||||
let pressed = button.is_low();
|
||||
if pressed && !last_pressed {
|
||||
mode = if mode == Mode::Blinking {
|
||||
info!("mode -> ForcedOff");
|
||||
Mode::ForcedOff
|
||||
} else {
|
||||
info!("mode -> Blinking");
|
||||
Mode::Blinking
|
||||
};
|
||||
}
|
||||
last_pressed = pressed;
|
||||
|
||||
let raw: u16 = adc.read(&mut analog_pin).unwrap();
|
||||
let interval_ms = interval_from_adc(raw);
|
||||
|
||||
match mode {
|
||||
Mode::Blinking => {
|
||||
elapsed_ms += 10;
|
||||
if elapsed_ms >= interval_ms {
|
||||
elapsed_ms = 0;
|
||||
led_on = !led_on;
|
||||
if led_on {
|
||||
led.set_low();
|
||||
} else {
|
||||
led.set_high();
|
||||
}
|
||||
info!("mode=Blinking adc={} interval_ms={} led_on={}", raw, interval_ms, led_on);
|
||||
}
|
||||
}
|
||||
Mode::ForcedOff => {
|
||||
led_on = false;
|
||||
led.set_high();
|
||||
elapsed_ms = 0;
|
||||
info!("mode=ForcedOff adc={} interval_ms={}", raw, interval_ms);
|
||||
}
|
||||
}
|
||||
|
||||
block!(tick.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
[target.thumbv7m-none-eabi]
|
||||
runner = "probe-rs run --chip STM32F103C8"
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x",
|
||||
"-C", "link-arg=-Tdefmt.x",
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7m-none-eabi"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "info"
|
||||
@@ -1,22 +0,0 @@
|
||||
[package]
|
||||
name = "step08_final_combined_task"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.7"
|
||||
cortex-m-rt = "0.7.5"
|
||||
defmt = "0.3.10"
|
||||
defmt-rtt = "0.4.2"
|
||||
panic-probe = { version = "0.3.2", features = ["print-defmt"] }
|
||||
nb = "1.1.0"
|
||||
|
||||
[dependencies.stm32f1xx-hal]
|
||||
version = "0.11.0"
|
||||
features = ["rt", "stm32f103", "medium"]
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
debug = 2
|
||||
lto = true
|
||||
opt-level = "z"
|
||||
@@ -1,5 +0,0 @@
|
||||
MEMORY
|
||||
{
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 64K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = ["rustfmt"]
|
||||
targets = ["thumbv7m-none-eabi"]
|
||||
@@ -1,85 +0,0 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use defmt::info;
|
||||
use nb::block;
|
||||
use stm32f1xx_hal::{adc::Adc, pac, prelude::*, timer::Timer};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
enum Mode {
|
||||
Blinking,
|
||||
ForcedOff,
|
||||
}
|
||||
|
||||
fn interval_from_adc(raw: u16) -> u32 {
|
||||
// Map 0..4095 -> 100..900 ms
|
||||
100 + (u32::from(raw) * 800 / 4095)
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
let dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
let mut rcc = dp.RCC.constrain();
|
||||
let mut gpioa = dp.GPIOA.split(&mut rcc);
|
||||
let mut gpioc = dp.GPIOC.split(&mut rcc);
|
||||
|
||||
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
||||
let button = gpioa.pa0.into_pull_up_input(&mut gpioa.crl);
|
||||
|
||||
let mut adc = Adc::new(dp.ADC1, &mut rcc);
|
||||
let mut analog_pin = gpioa.pa1.into_analog(&mut gpioa.crl);
|
||||
|
||||
// Fast base tick: all app timing derives from this.
|
||||
let mut tick = Timer::syst(cp.SYST, &rcc.clocks).counter_hz();
|
||||
tick.start(100.Hz()).unwrap(); // 10 ms
|
||||
|
||||
let mut mode = Mode::Blinking;
|
||||
let mut last_pressed = false;
|
||||
let mut led_on = false;
|
||||
let mut elapsed_ms: u32 = 0;
|
||||
|
||||
loop {
|
||||
let pressed = button.is_low();
|
||||
if pressed && !last_pressed {
|
||||
mode = if mode == Mode::Blinking {
|
||||
info!("mode -> ForcedOff");
|
||||
Mode::ForcedOff
|
||||
} else {
|
||||
info!("mode -> Blinking");
|
||||
Mode::Blinking
|
||||
};
|
||||
}
|
||||
last_pressed = pressed;
|
||||
|
||||
let raw: u16 = adc.read(&mut analog_pin).unwrap();
|
||||
let interval_ms = interval_from_adc(raw);
|
||||
|
||||
match mode {
|
||||
Mode::Blinking => {
|
||||
elapsed_ms += 10;
|
||||
if elapsed_ms >= interval_ms {
|
||||
elapsed_ms = 0;
|
||||
led_on = !led_on;
|
||||
if led_on {
|
||||
led.set_low(); // active-low
|
||||
} else {
|
||||
led.set_high();
|
||||
}
|
||||
info!("mode=Blinking adc={} interval_ms={} led_on={}", raw, interval_ms, led_on);
|
||||
}
|
||||
}
|
||||
Mode::ForcedOff => {
|
||||
led_on = false;
|
||||
led.set_high();
|
||||
elapsed_ms = 0;
|
||||
info!("mode=ForcedOff adc={} interval_ms={}", raw, interval_ms);
|
||||
}
|
||||
}
|
||||
|
||||
block!(tick.wait()).unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user