Archived
continue workshop
This commit is contained in:
1 parent
1f805e672b
commit
c9d5328450
32 files changed
+1354
-5
No files matched your search
@@ -0,0 +1,7 @@
|
||||
stages:
|
||||
- hello
|
||||
|
||||
hello_world:
|
||||
stage: hello
|
||||
script:
|
||||
- echo "Hello, world from GitLab CI!"
|
||||
@@ -0,0 +1,14 @@
|
||||
Embedded Rust Workshop
|
||||
==========
|
||||
|
||||
This repository contains all components of the Embedded Rust Workshop.
|
||||
|
||||
This includes:
|
||||
|
||||
- [`slides`](./slides) contains introduction slides about this workshop and embedded Rust.
|
||||
- [`exercise-book`](./exercise-book) contains the accompanying exercise book.
|
||||
- [`microbit-code`](./microbit-code/) contains all example source code and exercises which run on
|
||||
the microbit v2 target hardware
|
||||
- [`host-client`](./host-client/) contains a host client used to communicate with the microbit v2 via a serial
|
||||
interface.
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,3 @@
|
||||
# Exercise book
|
||||
|
||||
You can build this book and display it locally using `mdbook build --open`.
|
||||
File renamed without changes.
@@ -0,0 +1,5 @@
|
||||
# Summary
|
||||
|
||||
- [Introduction](./introduction.md)
|
||||
- [Preparation](./preparation.md)
|
||||
- [Blinky Exercise](./blinky-exercise.md)
|
||||
Whitespace-only changes.
@@ -0,0 +1,57 @@
|
||||
# Introduction
|
||||
|
||||
This is the exercise book accompanying the Embedded Rust Workshop.
|
||||
The Workshop provides exercises for Embedded Rust which run on the
|
||||
[BBC microbit v2](https://microbit.org/new-microbit/).
|
||||
|
||||
For this exercises, you only require the following hardware:
|
||||
|
||||
- The [microbit v2](https://microbit.org/new-microbit/).
|
||||
- A Micro-USB cable to power the microbit while also connecting it to your computer.
|
||||
|
||||
This little educational board has everything we need to teach you the practical part of embedded
|
||||
Rust, including:
|
||||
|
||||
- A 5x5 LED matrix.
|
||||
- The LSM303AGR on-board motion sensor.
|
||||
- A serial connection accessible by a USB-CDC device
|
||||
|
||||
This device has even more features and external connectivity, and you can find all
|
||||
of this information of the [microbit website](https://tech.microbit.org/hardware/).
|
||||
|
||||
## Goals
|
||||
|
||||
After working through this exercises, you should have the following skills:
|
||||
|
||||
- Extract relevant information from datasheets and/or schematics for firmware development.
|
||||
- Understand and work in embedded code using the the [`embassy`](https://embassy.dev/) asynchronous
|
||||
runtime, which includes using the `async` / `await` syntax.
|
||||
- Schedule concurrent tasks using `embassy`.
|
||||
- Work with some components of a provided HAL (or BSP).
|
||||
- Using [`embassy-time`](https://docs.rs/embassy-time/latest/embassy_time/) to perform delays and
|
||||
periodic operations or measure elapsed time.
|
||||
- Writing drivers for simple sensors
|
||||
|
||||
However, these exercises do not replace or provide a good theoretic foundation and it also does
|
||||
not teach general Rust programming. Low-level aspects like working with registers and details about
|
||||
system boot are are intentionally skipped. The next section provides some further material
|
||||
recommendations to address this.
|
||||
|
||||
## Further Materials
|
||||
|
||||
If you are a beginner in Rust, it is strongly recommended to work through the [Rust book](https://doc.rust-lang.org/book/) or work
|
||||
through some other method of your choice to learn the general language.
|
||||
|
||||
The following materials might be valuable for you as well:
|
||||
|
||||
- [The embassy book](https://embassy.dev/book/) provides additional information and documentation
|
||||
about the embassy asynchronous run-time.
|
||||
- [The Rusty bits](https://www.youtube.com/@therustybits) provides excellent visual resources
|
||||
about various embedded Rust aspects.
|
||||
- [The Ferrous Systems Rust Training slides](https://rust-training.ferrous-systems.com/latest/slides/)
|
||||
provide high-quality slides about various topics, including embedded Rust and aspects like
|
||||
system boot and peripheral access crates.
|
||||
|
||||
## Preparation
|
||||
|
||||
We are going to start with the preparation of the software tools in the [next chapter](./preparation.md).
|
||||
@@ -0,0 +1,88 @@
|
||||
# Preparation
|
||||
|
||||
## Rust and `cargo`
|
||||
|
||||
The first thing required is the Rust compiler and the `cargo` build and dependency management
|
||||
tool. The Rust installation includes the `cargo` tool, so all you need to do is install
|
||||
Rust by going to the [Rust website](https://rust-lang.org/tools/install/) and following the operating
|
||||
system specific instructions.
|
||||
|
||||
After you have done this, you can verify your installation by running:
|
||||
|
||||
```console
|
||||
cargo version
|
||||
```
|
||||
|
||||
Normally, you would have to also install the `thumbv7em-none-eabihf` toolchain and some other
|
||||
useful tools, but this is performed automatically for you through the `rust-toolchain.toml`
|
||||
file in the code directory.
|
||||
|
||||
## `flip-link` linker
|
||||
|
||||
You need to install a special linker called `flip-link` for building the software. Run
|
||||
the following command in the terminal:
|
||||
|
||||
```console
|
||||
cargo install flip-link
|
||||
```
|
||||
|
||||
## Flasher tool `probe-rs`
|
||||
|
||||
Next, you need some software which allows flashing the microbit v2 via the USB interface.
|
||||
We are going to use the `probe-rs` tool, which is well integrated into the Rust ecosystem:
|
||||
|
||||
The `probe-rs` website has [install instructions](https://probe.rs/docs/getting-started/installation/)
|
||||
for various operating systems. Follow these, and then test your installation using the following
|
||||
command
|
||||
|
||||
```console
|
||||
probe-rs --version
|
||||
```
|
||||
|
||||
## USB permission setup (Linux only)
|
||||
|
||||
Finally, if you are on Linux, you need to perform some steps related to `udev` to avoid permission
|
||||
issues. `probe-rs` has a [page with steps you can follow](https://probe.rs/docs/getting-started/probe-setup/).
|
||||
|
||||
## IDE
|
||||
|
||||
You can use any IDE of your choice which has good [Rust Analzyer Support](https://rust-analyzer.github.io/).
|
||||
|
||||
If you are looking for a solid graphical IDE, [VS Code](https://code.visualstudio.com/<35;127;26M)
|
||||
is an excellent choice. Make sure to install the [rust-analyzer plugin](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) as well.
|
||||
|
||||
## Testing everything
|
||||
|
||||
Now you should have everything you need to build and flash some application to the board.
|
||||
You can flash a test application now to test everything. We provide some test applications for you.
|
||||
|
||||
Connect the board to your computer using a Micro-USB cable. Make sure that your cable also
|
||||
supports the data interface and is not power-only.
|
||||
|
||||
Go into the `code/app` directory.
|
||||
|
||||
Now, you can run the following command to build and flash a blinky application:
|
||||
|
||||
```console
|
||||
cargo run --bin blinky
|
||||
```
|
||||
|
||||
On the console, you should see an output like this:
|
||||
|
||||
```console
|
||||
❯ cargo run --bin blinky
|
||||
Compiling rust-app v0.1.0 (/home/muellerr/Rust/rust-embedded-workshop/code/app)
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.17s
|
||||
Running `probe-rs run --chip nRF52833_xxAA --allow-erase-all target/thumbv7em-none-eabihf/debug/blinky`
|
||||
Erasing ✔ 100% [####################] 48.00 KiB @ 35.81 KiB/s (took 1s) Finished in 3.55s
|
||||
-- microbit v2 Blinky application --
|
||||
```
|
||||
|
||||
If `probe-rs` can not detect anything, make sure that (a) the board is connected through USB, and
|
||||
(b) the `udev` rules were setup properly if you are on Linux.
|
||||
|
||||
If everything goes right, you should see the LED in the top-left corner blinking with a frequency of 1 second.
|
||||
If this is the case, congratulations, you have built and flashed an embedded Rust app and you made if through
|
||||
the preparation chapter successfully!
|
||||
|
||||
In the [first exercise](./blinky-exercise.md), you are going to build most parts of a blinky.
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file not shown.
File renamed without changes.
File renamed without changes.
@@ -26,7 +26,8 @@ async fn main(_spawner: Spawner) -> ! {
|
||||
row1.set_high();
|
||||
col1.set_low();
|
||||
loop {
|
||||
defmt::debug!("blinking LED");
|
||||
row1.toggle();
|
||||
Timer::after_millis(200).await;
|
||||
Timer::after_millis(1000).await;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,15 @@
|
||||
[target.'cfg(all(target_arch = "arm", target_os = "none"))']
|
||||
# replace nRF82840_xxAA with your chip as listed in `probe-rs chip list`
|
||||
runner = "probe-rs run --chip nRF52833_xxAA --allow-erase-all"
|
||||
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Tlink.x", # use the cortex-m-rt linker script
|
||||
"-C", "linker=flip-link", # adds stack overflow protection
|
||||
"-C", "link-arg=-Tdefmt.x", # defmt support
|
||||
]
|
||||
|
||||
[build]
|
||||
target = "thumbv7em-none-eabihf"
|
||||
|
||||
[env]
|
||||
DEFMT_LOG = "info"
|
||||
Generated
+1032
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "exercises"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
embassy-executor = { version = "0.10.0", features = ["platform-cortex-m", "executor-thread", "executor-interrupt", "defmt"] }
|
||||
embassy-time = { version = "0.5.1", features = ["defmt", "defmt-timestamp-uptime"] }
|
||||
embassy-nrf = { version = "0.10.0", features = ["defmt", "nrf52833", "time-driver-rtc1", "unstable-pac", "time"] }
|
||||
|
||||
defmt = "1.0.1"
|
||||
defmt-rtt = "1.0.0"
|
||||
|
||||
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
||||
cortex-m-rt = "0.7.0"
|
||||
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
|
||||
embedded-hal = { version = "1.0" }
|
||||
embedded-hal-async = { version = "1.0" }
|
||||
embedded-hal-bus = { version = "0.3", features = ["async"] }
|
||||
embedded-io = { version = "0.7.1", features = ["defmt"] }
|
||||
embedded-io-async = { version = "0.7.0", features = ["defmt"] }
|
||||
portable-atomic = "1"
|
||||
|
||||
[profile.release]
|
||||
debug = 2
|
||||
|
||||
[package.metadata.embassy]
|
||||
build = [
|
||||
{ target = "thumbv7em-none-eabi", artifact-dir = "out/examples/nrf52840" }
|
||||
]
|
||||
@@ -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");
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
MEMORY
|
||||
{
|
||||
/* NOTE 1 K = 1 KiBi = 1024 bytes */
|
||||
FLASH : ORIGIN = 0x00000000, LENGTH = 512K
|
||||
RAM : ORIGIN = 0x20000000, LENGTH = 128K
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use exercises as _;
|
||||
use embassy_executor::Spawner;
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) -> ! {
|
||||
let _periphs = embassy_nrf::init(embassy_nrf::config::Config::default());
|
||||
|
||||
// TODOs
|
||||
//
|
||||
// Step 1: Initialize the hardware by using the `embassy_nrf::init` method.
|
||||
// Step 2: print some initial log to the console, for example the exercise name.
|
||||
// Step 3: Create an Output GPIO driver for ROW1
|
||||
// Step 4: Create an Output GPIO driver for COL1
|
||||
// Step 5: Set the GPIOs to the correct state to drive LED D2, which is the LED in
|
||||
// the upper left corner of the LED matrix
|
||||
// Step 6: Inside the empty loop, toggle the correct output to toggle the LED.
|
||||
// Step 7: Led the LED blink with a certain frequency by using embassy_time::Timer
|
||||
|
||||
loop {}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::Timer;
|
||||
use exercises as _;
|
||||
|
||||
use embassy_nrf::gpio::Output;
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) -> ! {
|
||||
let periphs = embassy_nrf::init(embassy_nrf::config::Config::default());
|
||||
|
||||
defmt::println!("-- microbit v2 Blinky application --");
|
||||
|
||||
let mut row1 = Output::new(
|
||||
periphs.P0_21,
|
||||
embassy_nrf::gpio::Level::Low,
|
||||
embassy_nrf::gpio::OutputDrive::Standard,
|
||||
);
|
||||
let _col1 = Output::new(
|
||||
periphs.P0_28,
|
||||
embassy_nrf::gpio::Level::Low,
|
||||
embassy_nrf::gpio::OutputDrive::Standard,
|
||||
);
|
||||
loop {
|
||||
row1.toggle();
|
||||
Timer::after_millis(200).await;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
#![no_std]
|
||||
|
||||
use defmt_rtt as _;
|
||||
use embassy_nrf as _;
|
||||
use panic_probe as _;
|
||||
@@ -0,0 +1,5 @@
|
||||
[toolchain]
|
||||
channel = "stable"
|
||||
components = [ "llvm-tools-preview", "clippy" ]
|
||||
targets = [ "thumbv7em-none-eabihf" ]
|
||||
profile = "default"
|
||||
@@ -1,3 +0,0 @@
|
||||
# Summary
|
||||
|
||||
- [Chapter 1](./chapter_1.md)
|
||||
@@ -1 +0,0 @@
|
||||
# Chapter 1
|
||||
@@ -0,0 +1 @@
|
||||
*lock.*
|
||||
Binary file not shown.
Reference in new issue
Block a user