start with rust report
This commit is contained in:
40
report-3/rts10_rust/.cargo/config.toml
Normal file
40
report-3/rts10_rust/.cargo/config.toml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
[target.thumbv7em-none-eabihf]
|
||||||
|
# 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 = "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)
|
||||||
|
# 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)
|
||||||
13
report-3/rts10_rust/.gitignore
vendored
Normal file
13
report-3/rts10_rust/.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
**/*.rs.bk
|
||||||
|
.#*
|
||||||
|
.gdb_history
|
||||||
|
Cargo.lock
|
||||||
|
target/
|
||||||
|
|
||||||
|
# editor files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/*.md
|
||||||
|
!.vscode/*.svd
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/extensions.json
|
||||||
109
report-3/rts10_rust/.vscode/README.md
vendored
Normal file
109
report-3/rts10_rust/.vscode/README.md
vendored
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# VS Code Configuration
|
||||||
|
|
||||||
|
Example configurations for debugging programs in-editor with VS Code.
|
||||||
|
This directory contains configurations for two platforms:
|
||||||
|
|
||||||
|
- `LM3S6965EVB` on QEMU
|
||||||
|
- `STM32F303x` via OpenOCD
|
||||||
|
|
||||||
|
## Required Extensions
|
||||||
|
|
||||||
|
If you have the `code` command in your path, you can run the following commands to install the necessary extensions.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
code --install-extension rust-lang.rust
|
||||||
|
code --install-extension marus25.cortex-debug
|
||||||
|
```
|
||||||
|
|
||||||
|
Otherwise, you can use the Extensions view to search for and install them, or go directly to their marketplace pages and click the "Install" button.
|
||||||
|
|
||||||
|
- [Rust Language Server (RLS)](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust)
|
||||||
|
- [Cortex-Debug](https://marketplace.visualstudio.com/items?itemName=marus25.cortex-debug)
|
||||||
|
|
||||||
|
## Use
|
||||||
|
|
||||||
|
The quickstart comes with two debug configurations.
|
||||||
|
Both are configured to build the project, using the default settings from `.cargo/config`, prior to starting a debug session.
|
||||||
|
|
||||||
|
1. QEMU: Starts a debug session using an emulation of the `LM3S6965EVB` mcu.
|
||||||
|
- This works on a fresh `cargo generate` without modification of any of the settings described above.
|
||||||
|
- Semihosting output will be written to the Output view `Adapter Output`.
|
||||||
|
- `ITM` logging does not work with QEMU emulation.
|
||||||
|
|
||||||
|
2. OpenOCD: Starts a debug session for a `STM32F3DISCOVERY` board (or any `STM32F303x` running at 8MHz).
|
||||||
|
- Follow the instructions above for configuring the build with `.cargo/config` and the `memory.x` linker script.
|
||||||
|
- `ITM` output will be written to the Output view `SWO: ITM [port: 0, type: console]` output.
|
||||||
|
|
||||||
|
### Git
|
||||||
|
|
||||||
|
Files in the `.vscode/` directory are `.gitignore`d by default because many files that may end up in the `.vscode/` directory should not be committed and shared.
|
||||||
|
If you would like to save this debug configuration to your repository and share it with your team, you'll need to explicitly `git add` the files to your repository.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git add -f .vscode/launch.json
|
||||||
|
git add -f .vscode/tasks.json
|
||||||
|
git add -f .vscode/*.svd
|
||||||
|
```
|
||||||
|
|
||||||
|
## Customizing for other targets
|
||||||
|
|
||||||
|
For full documentation, see the [Cortex-Debug][cortex-debug] repository.
|
||||||
|
|
||||||
|
### Device
|
||||||
|
|
||||||
|
Some configurations use this to automatically find the SVD file.
|
||||||
|
Replace this with the part number for your device.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"device": "STM32F303VCT6",
|
||||||
|
```
|
||||||
|
|
||||||
|
### OpenOCD Config Files
|
||||||
|
|
||||||
|
The `configFiles` property specifies a list of files to pass to OpenOCD.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"configFiles": [
|
||||||
|
"interface/stlink-v2-1.cfg",
|
||||||
|
"target/stm32f3x.cfg"
|
||||||
|
],
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [OpenOCD config docs][openocd-config] for more information and the [OpenOCD repository for available configuration files][openocd-repo].
|
||||||
|
|
||||||
|
### SVD
|
||||||
|
|
||||||
|
The SVD file is a standard way of describing all registers and peripherals of an ARM Cortex-M mCU.
|
||||||
|
Cortex-Debug needs this file to display the current register values for the peripherals on the device.
|
||||||
|
|
||||||
|
You can probably find the SVD for your device on the vendor's website.
|
||||||
|
|
||||||
|
|
||||||
|
For example, the STM32F3DISCOVERY board uses an mcu from the `STM32F303x` line of processors.
|
||||||
|
All the SVD files for the STM32F3 series are available on [ST's Website][stm32f3].
|
||||||
|
Download the [stm32f3 SVD pack][stm32f3-svd], and copy the `STM32F303.svd` file into `.vscode/`.
|
||||||
|
This line of the config tells the Cortex-Debug plug in where to find the file.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"svdFile": "${workspaceRoot}/.vscode/STM32F303.svd",
|
||||||
|
```
|
||||||
|
|
||||||
|
For other processors, simply copy the correct `*.svd` file into the project and update the config accordingly.
|
||||||
|
|
||||||
|
### CPU Frequency
|
||||||
|
|
||||||
|
If your device is running at a frequency other than 8MHz, you'll need to modify this line of `launch.json` for the `ITM` output to work correctly.
|
||||||
|
|
||||||
|
```json
|
||||||
|
"cpuFrequency": 8000000,
|
||||||
|
```
|
||||||
|
|
||||||
|
### Other GDB Servers
|
||||||
|
|
||||||
|
For information on setting up GDB servers other than OpenOCD, see the [Cortex-Debug repository][cortex-debug].
|
||||||
|
|
||||||
|
[cortex-debug]: https://github.com/Marus/cortex-debug
|
||||||
|
[stm32f3]: https://www.st.com/content/st_com/en/products/microcontrollers-microprocessors/stm32-32-bit-arm-cortex-mcus/stm32-mainstream-mcus/stm32f3-series.html#resource
|
||||||
|
[stm32f3-svd]: https://www.st.com/resource/en/svd/stm32f3_svd.zip
|
||||||
|
[openocd-config]: http://openocd.org/doc/html/Config-File-Guidelines.html
|
||||||
|
[openocd-repo]: https://sourceforge.net/p/openocd/code/ci/master/tree/tcl/
|
||||||
14
report-3/rts10_rust/.vscode/extensions.json
vendored
Normal file
14
report-3/rts10_rust/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||||
|
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||||
|
|
||||||
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
|
"recommendations": [
|
||||||
|
"rust-lang.rust-analyzer",
|
||||||
|
"marus25.cortex-debug",
|
||||||
|
],
|
||||||
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
"rust-lang.rust",
|
||||||
|
]
|
||||||
|
}
|
||||||
34
report-3/rts10_rust/.vscode/launch.json
vendored
Normal file
34
report-3/rts10_rust/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
/* Configuration for the STM32F303 Discovery board */
|
||||||
|
"type": "cortex-debug",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug (OpenOCD)",
|
||||||
|
"servertype": "openocd",
|
||||||
|
"cwd": "${workspaceRoot}",
|
||||||
|
"preLaunchTask": "Cargo Build (debug)",
|
||||||
|
"runToEntryPoint": "main",
|
||||||
|
"executable": "./target/thumbv7em-none-eabihf/debug/rts10_rust",
|
||||||
|
"device": "STM32F411VET6",
|
||||||
|
"configFiles": [
|
||||||
|
"interface/stlink.cfg",
|
||||||
|
"target/stm32f4x.cfg"
|
||||||
|
],
|
||||||
|
"svdFile": "${workspaceRoot}/.vscode/stm32f411.svd",
|
||||||
|
"postLaunchCommands": [
|
||||||
|
"monitor arm semihosting enable"
|
||||||
|
],
|
||||||
|
"swoConfig": {
|
||||||
|
"enabled": true,
|
||||||
|
"cpuFrequency": 8000000,
|
||||||
|
"swoFrequency": 2000000,
|
||||||
|
"source": "probe",
|
||||||
|
"decoders": [
|
||||||
|
{ "type": "console", "label": "Hello", "port": 0 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
27110
report-3/rts10_rust/.vscode/stm32f411.svd
vendored
Normal file
27110
report-3/rts10_rust/.vscode/stm32f411.svd
vendored
Normal file
File diff suppressed because it is too large
Load Diff
66
report-3/rts10_rust/.vscode/tasks.json
vendored
Normal file
66
report-3/rts10_rust/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||||
|
// for the documentation about the tasks.json format
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This is the default cargo build task,
|
||||||
|
* but we need to provide a label for it,
|
||||||
|
* so we can invoke it from the debug launcher.
|
||||||
|
*/
|
||||||
|
"label": "Cargo Build (debug)",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "cargo build ",
|
||||||
|
"args": [],
|
||||||
|
"problemMatcher": [
|
||||||
|
"$rustc"
|
||||||
|
],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Cargo Build (release)",
|
||||||
|
"type": "process",
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["build", "--release"],
|
||||||
|
"problemMatcher": [
|
||||||
|
"$rustc"
|
||||||
|
],
|
||||||
|
"group": "build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Cargo Build Examples (debug)",
|
||||||
|
"type": "process",
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["build","--examples"],
|
||||||
|
"problemMatcher": [
|
||||||
|
"$rustc"
|
||||||
|
],
|
||||||
|
"group": "build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Cargo Build Examples (release)",
|
||||||
|
"type": "process",
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["build","--examples", "--release"],
|
||||||
|
"problemMatcher": [
|
||||||
|
"$rustc"
|
||||||
|
],
|
||||||
|
"group": "build"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Cargo Clean",
|
||||||
|
"type": "process",
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["clean"],
|
||||||
|
"problemMatcher": [],
|
||||||
|
"group": "build"
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
33
report-3/rts10_rust/Cargo.toml
Normal file
33
report-3/rts10_rust/Cargo.toml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
[package]
|
||||||
|
authors = ["LailaTheElf <mail@lailatheelf.nl>"]
|
||||||
|
edition = "2021"
|
||||||
|
readme = "README.md"
|
||||||
|
name = "rts10_rust"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cortex-m = "0.7.7"
|
||||||
|
cortex-m-rt = "0.7.3"
|
||||||
|
panic-halt = "0.2"
|
||||||
|
alloc-cortex-m = "0.4.4"
|
||||||
|
cortex-m-semihosting = ">=0.5"
|
||||||
|
embedded-hal = "1.0.0"
|
||||||
|
|
||||||
|
[dependencies.stm32f4]
|
||||||
|
version = "0.15.1"
|
||||||
|
features = ["stm32f411", "rt"]
|
||||||
|
|
||||||
|
[dependencies.stm32f4xx-hal]
|
||||||
|
version = "0.22.0"
|
||||||
|
features = ["stm32f411"]
|
||||||
|
|
||||||
|
# this lets you use `cargo fix`!
|
||||||
|
# [[bin]]
|
||||||
|
# name = "rts10_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
|
||||||
11
report-3/rts10_rust/README.md
Normal file
11
report-3/rts10_rust/README.md
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Het quickstart project
|
||||||
|
Dit project is gebaseerd op de repo van [Cortex-M-Quickstart](https://github.com/rust-embedded/cortex-m-quickstart).
|
||||||
|
|
||||||
|
De volgende dingen zijn aangepast en toegevoegd:
|
||||||
|
- [x] Target is ingesteld voor de STM32F411 naar thumbv7em-none-eabihf in [config.toml](.cargo/config.toml)
|
||||||
|
- [x] Memory map is aangepast naar de STM32F411 in [memory.x](memory.x)
|
||||||
|
- [x] SVD bestand is toegevoegd voor de STM32F411, dit beschrijf alle registers. [stm32f411.svd](.vscode/stm32f411.svd)
|
||||||
|
- [x] VS code task is aangepast om main te kunnen compileren en debuggen in [tasks.json](.vscode/tasks.json)
|
||||||
|
- [x] ARM semihosting is aangezet voor openocd in [launch.json](.vscode/launch.json)
|
||||||
|
- [x] Juiste dependencies aangezet voor heap allocation
|
||||||
|
- [x] Allocator.rs voorbeeld aangepast voor gebruik Box()
|
||||||
31
report-3/rts10_rust/build.rs
Normal file
31
report-3/rts10_rust/build.rs
Normal file
@@ -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");
|
||||||
|
}
|
||||||
32
report-3/rts10_rust/memory.x
Normal file
32
report-3/rts10_rust/memory.x
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/* Memories definition, aangepast voor de STM32F411 */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
FLASH : ORIGIN = 0x8000000, LENGTH = 512K
|
||||||
|
RAM : ORIGIN = 0x20000000, LENGTH = 128K
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
*/
|
||||||
96
report-3/rts10_rust/src/leds.rs
Normal file
96
report-3/rts10_rust/src/leds.rs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
use embedded_hal::digital::{ErrorType as DigitalErrorType, OutputPin, PinState};
|
||||||
|
|
||||||
|
pub trait UpdateLeds<Red: OutputPin, Green: OutputPin, Blue: OutputPin> {
|
||||||
|
fn red_toggle(&mut self) -> Result<(), <Red as DigitalErrorType>::Error>;
|
||||||
|
fn red_on(&mut self) -> Result<(), <Red as DigitalErrorType>::Error>;
|
||||||
|
fn red_off(&mut self) -> Result<(), <Red as DigitalErrorType>::Error>;
|
||||||
|
fn green_toggle(&mut self) -> Result<(), <Green as DigitalErrorType>::Error> ;
|
||||||
|
fn green_on(&mut self) -> Result<(), <Green as DigitalErrorType>::Error>;
|
||||||
|
fn green_off(&mut self) -> Result<(), <Green as DigitalErrorType>::Error>;
|
||||||
|
fn blue_toggle(&mut self) -> Result<(), <Blue as DigitalErrorType>::Error>;
|
||||||
|
fn blue_on(&mut self) -> Result<(), <Blue as DigitalErrorType>::Error>;
|
||||||
|
fn blue_off(&mut self) -> Result<(), <Blue as DigitalErrorType>::Error>;
|
||||||
|
}
|
||||||
|
pub struct Leds<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> {
|
||||||
|
red: &'a mut Red,
|
||||||
|
red_state: PinState,
|
||||||
|
green: &'a mut Green,
|
||||||
|
green_state: PinState,
|
||||||
|
blue: &'a mut Blue,
|
||||||
|
blue_state: PinState,
|
||||||
|
}
|
||||||
|
impl<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> Leds<'a, Red, Green, Blue> {
|
||||||
|
pub fn new(red: &'a mut Red, green: &'a mut Green, blue: &'a mut Blue) -> Self {
|
||||||
|
let _ = red.set_low();
|
||||||
|
let _ = green.set_low();
|
||||||
|
let _ = blue.set_low();
|
||||||
|
Self {
|
||||||
|
red,
|
||||||
|
red_state: PinState::Low,
|
||||||
|
green,
|
||||||
|
green_state: PinState::Low,
|
||||||
|
blue,
|
||||||
|
blue_state: PinState::Low,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin>
|
||||||
|
UpdateLeds<Red, Green, Blue>
|
||||||
|
for Leds<'a, Red, Green, Blue> {
|
||||||
|
fn red_toggle(&mut self) -> Result<(), <Red as DigitalErrorType>::Error> {
|
||||||
|
if self.red_state == PinState::Low {
|
||||||
|
self.red_state = PinState::High;
|
||||||
|
} else {
|
||||||
|
self.red_state = PinState::Low;
|
||||||
|
}
|
||||||
|
self.red.set_state(self.red_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn red_on(&mut self) -> Result<(), <Red as DigitalErrorType>::Error> {
|
||||||
|
self.red_state = PinState::High;
|
||||||
|
self.red.set_state(self.red_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn red_off(&mut self) -> Result<(), <Red as DigitalErrorType>::Error> {
|
||||||
|
self.red_state = PinState::Low;
|
||||||
|
self.red.set_state(self.red_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn green_toggle(&mut self) -> Result<(), <Green as DigitalErrorType>::Error> {
|
||||||
|
if self.green_state == PinState::Low {
|
||||||
|
self.green_state = PinState::High;
|
||||||
|
} else {
|
||||||
|
self.green_state = PinState::Low;
|
||||||
|
}
|
||||||
|
self.green.set_state(self.green_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn green_on(&mut self) -> Result<(), <Green as DigitalErrorType>::Error> {
|
||||||
|
self.green_state = PinState::High;
|
||||||
|
self.green.set_state(self.green_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn green_off(&mut self) -> Result<(), <Green as DigitalErrorType>::Error> {
|
||||||
|
self.green_state = PinState::Low;
|
||||||
|
self.green.set_state(self.green_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blue_toggle(&mut self) -> Result<(), <Blue as DigitalErrorType>::Error> {
|
||||||
|
if self.blue_state == PinState::Low {
|
||||||
|
self.blue_state = PinState::High;
|
||||||
|
} else {
|
||||||
|
self.blue_state = PinState::Low;
|
||||||
|
}
|
||||||
|
self.blue.set_state(self.blue_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blue_on(&mut self) -> Result<(), <Blue as DigitalErrorType>::Error> {
|
||||||
|
self.blue_state = PinState::High;
|
||||||
|
self.blue.set_state(self.blue_state)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn blue_off(&mut self) -> Result<(), <Blue as DigitalErrorType>::Error> {
|
||||||
|
self.blue_state = PinState::Low;
|
||||||
|
self.blue.set_state(self.blue_state)
|
||||||
|
}
|
||||||
|
}
|
||||||
57
report-3/rts10_rust/src/main.rs
Normal file
57
report-3/rts10_rust/src/main.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#![deny(unsafe_code)]
|
||||||
|
#![allow(clippy::empty_loop)]
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
// Halt on panic
|
||||||
|
use panic_halt as _; // panic handler
|
||||||
|
|
||||||
|
use cortex_m_rt::entry;
|
||||||
|
use stm32f4xx_hal::{self as hal};
|
||||||
|
|
||||||
|
use crate::hal::{pac, prelude::*};
|
||||||
|
use cortex_m_semihosting::hprintln;
|
||||||
|
|
||||||
|
mod leds;
|
||||||
|
use crate::leds::{UpdateLeds, Leds};
|
||||||
|
mod state_machine;
|
||||||
|
use crate::state_machine::StateMachine;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
if let (Some(dp), Some(cp)) = (
|
||||||
|
pac::Peripherals::take(),
|
||||||
|
cortex_m::peripheral::Peripherals::take(),
|
||||||
|
) {
|
||||||
|
//GPIOD ophalen
|
||||||
|
let gpiod = dp.GPIOD.split();
|
||||||
|
//pd12 is pin type
|
||||||
|
let mut green = gpiod.pd12.into_push_pull_output();
|
||||||
|
let mut red = gpiod.pd14.into_push_pull_output();
|
||||||
|
let mut blue = gpiod.pd15.into_push_pull_output();
|
||||||
|
let mut leds = Leds::new(&mut red, &mut green, &mut blue);
|
||||||
|
let mut state_machine = StateMachine::new(&mut leds);
|
||||||
|
|
||||||
|
//Klok instellen
|
||||||
|
let rcc = dp.RCC.constrain();
|
||||||
|
let clocks = rcc.cfgr.sysclk(48.MHz()).freeze();
|
||||||
|
|
||||||
|
|
||||||
|
// Create a delay abstraction based on SysTick
|
||||||
|
let mut delay = cp.SYST.delay(&clocks);
|
||||||
|
let mut status:bool = false;
|
||||||
|
loop {
|
||||||
|
// On for 1s, off for 1s.
|
||||||
|
let _ = leds.red_toggle();
|
||||||
|
let _ = leds.green_toggle();
|
||||||
|
let _ = leds.blue_toggle();
|
||||||
|
status ^= true;
|
||||||
|
delay.delay_ms(1000_u32);
|
||||||
|
|
||||||
|
//dit verschijnt in een van de open terminals in vscode
|
||||||
|
hprintln!("Led {:?}", status.then(|| "aan!").unwrap_or("uit!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
89
report-3/rts10_rust/src/state_machine.rs
Normal file
89
report-3/rts10_rust/src/state_machine.rs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
use embedded_hal::digital::OutputPin;
|
||||||
|
|
||||||
|
use crate::leds::UpdateLeds;
|
||||||
|
|
||||||
|
enum States {
|
||||||
|
Red(StateRed),
|
||||||
|
Blue(StateBlue),
|
||||||
|
Green(StateGreen),
|
||||||
|
}
|
||||||
|
|
||||||
|
trait State {
|
||||||
|
fn new() -> Self;
|
||||||
|
fn second_passed(&self) -> States;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StateRed {
|
||||||
|
time_passed: u32
|
||||||
|
}
|
||||||
|
impl State for StateRed {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
time_passed: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn second_passed(&self) -> States {
|
||||||
|
if self.time_passed + 1 >= 4 {
|
||||||
|
States::Green(StateGreen::new())
|
||||||
|
} else {
|
||||||
|
States::Red(Self {
|
||||||
|
time_passed: self.time_passed + 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StateGreen {
|
||||||
|
time_passed: u32
|
||||||
|
}
|
||||||
|
impl State for StateGreen {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
time_passed: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn second_passed(&self) -> States {
|
||||||
|
if self.time_passed + 1 >= 3 {
|
||||||
|
States::Blue(StateBlue::new())
|
||||||
|
} else {
|
||||||
|
States::Green(Self {
|
||||||
|
time_passed: self.time_passed + 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StateBlue {}
|
||||||
|
impl State for StateBlue {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
fn second_passed(&self) -> States {
|
||||||
|
States::Red(StateRed::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trait Leds<Red: OutputPin, Green: OutputPin, Blue: OutputPin>: UpdateLeds<Red, Green, Blue>;
|
||||||
|
|
||||||
|
pub struct StateMachine<'a, T: UpdateLeds<_, _, _>>
|
||||||
|
{
|
||||||
|
state: States,
|
||||||
|
leds: &'a mut T,
|
||||||
|
}
|
||||||
|
impl<'a, T: UpdateLeds<_, _, _>>
|
||||||
|
StateMachine<'a, T>
|
||||||
|
{
|
||||||
|
pub fn new(leds: &'a mut T) -> Self {
|
||||||
|
Self {
|
||||||
|
state: States::Red(StateRed::new()),
|
||||||
|
leds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn second_passed(&mut self) {
|
||||||
|
self.state = match &self.state {
|
||||||
|
States::Red(state) => state.second_passed(),
|
||||||
|
States::Blue(state) => state.second_passed(),
|
||||||
|
States::Green(state) => state.second_passed(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,9 +8,118 @@ auther:
|
|||||||
name_short: "E.L.F. van Reenen"
|
name_short: "E.L.F. van Reenen"
|
||||||
---
|
---
|
||||||
|
|
||||||
# RTS10 - Rust opdracht
|
# Rust Verslag
|
||||||
|
|
||||||
Ik heb niet genoeg tijd gehad om dat dit vak te werken, dus mijn code werkt niet zoals dat het moet, het werkt wel. Ik heb veel geëxperimenteerd met Rustlings, ik hierdoor nog enthousiaster geworden om Rust beter te leren. Het is echt een andere denkwijze als C/C++. Rust laat je echt goed denken hoe de code moet werkten en maakt het erg moeilijk om onzichtbare bugs te maken.
|
## Opdracht 8.2
|
||||||
|
|
||||||
|
> Maak een toestandsmachine volgens de State Pattern methode zoals beschreven in
|
||||||
|
> het boek. Er zijn drie toestanden: rood, groen en oranje. Tussen de toestanden
|
||||||
|
> wordt geschakeld op basis van tijd: respectievelijk $4s&, &3s& en &1s&.
|
||||||
|
|
||||||
|
De State Pattern methode in rust maakt gebuik van structs en traits. Om dit
|
||||||
|
mognelijk te maken moet er een struct zijn die de leds kan aansturen. Hiervoor
|
||||||
|
is het de Pin struct van de stm32f4xx-hal nodig in in struct. Om mijn
|
||||||
|
implementatie makkelijker onderhoudbaar te maken worden de Pin structs
|
||||||
|
doorgegeven aan de state machine struct. Hiervoor is een triad nodig die
|
||||||
|
functions voor het aanpassen van de led status beschijft. De `toggle` functie
|
||||||
|
die gebruikt wordt in het voorbeeld is niet geimplementeerd via een trait.
|
||||||
|
Deze kan dus niet gebruikt worden zonder de hal aan te passen. In de
|
||||||
|
documentatie van de pin struct implementeerd die de OutputPin trait van de
|
||||||
|
embedded_hal crate^[https://docs.rs/stm32f4xx-hal/0.22.0/stm32f4xx_hal/gpio/struct.Pin.html#impl-OutputPin-for-Pin%3CP,+N,+Output%3CMODE%3E%3E-1]. Dus deze crate is toegevoed aan het project zodat hier
|
||||||
|
gebruik van gemaakt kan worden.
|
||||||
|
|
||||||
|
Om te testen of dit werkt is er een stuct aangemaakt met een simple toggle
|
||||||
|
functie en de embeded_hal geimporteerd. Dit is gedaan met de volgende code:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use embedded_hal::digital::{ErrorType as DigitalErrorType, OutputPin, PinState};
|
||||||
|
|
||||||
|
struct Leds<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> {
|
||||||
|
red: &'a mut Red,
|
||||||
|
red_state: PinState,
|
||||||
|
green: &'a mut Green,
|
||||||
|
green_state: PinState,
|
||||||
|
blue: &'a mut Blue,
|
||||||
|
blue_state: PinState,
|
||||||
|
}
|
||||||
|
impl<'a, Red: OutputPin, Green: OutputPin, Blue: OutputPin> Leds<'a, Red, Green, Blue> {
|
||||||
|
pub fn new(red: &'a mut Red, green: &'a mut Green, blue: &'a mut Blue) -> Self {
|
||||||
|
let _ = red.set_low();
|
||||||
|
let _ = green.set_low();
|
||||||
|
let _ = blue.set_low();
|
||||||
|
Self {
|
||||||
|
red,
|
||||||
|
red_state: PinState::Low,
|
||||||
|
green,
|
||||||
|
green_state: PinState::Low,
|
||||||
|
blue,
|
||||||
|
blue_state: PinState::Low,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn red_toggle(&mut self) -> Result<(), <Red as DigitalErrorType>::Error> {
|
||||||
|
if self.red_state == PinState::Low {
|
||||||
|
self.red_state = PinState::High;
|
||||||
|
} else {
|
||||||
|
self.red_state = PinState::Low;
|
||||||
|
}
|
||||||
|
self.red.set_state(self.red_state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Daarnaast is ook de main functie aangepast naar het volgende:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
if let (Some(dp), Some(cp)) = (
|
||||||
|
pac::Peripherals::take(),
|
||||||
|
cortex_m::peripheral::Peripherals::take(),
|
||||||
|
) {
|
||||||
|
//GPIOD ophalen
|
||||||
|
let gpiod = dp.GPIOD.split();
|
||||||
|
// create structs for pins
|
||||||
|
let mut green = gpiod.pd12.into_push_pull_output();
|
||||||
|
let mut red = gpiod.pd14.into_push_pull_output();
|
||||||
|
let mut blue = gpiod.pd15.into_push_pull_output();
|
||||||
|
// create leds struct
|
||||||
|
let mut leds = Leds::new(&mut red, &mut green, &mut blue);
|
||||||
|
|
||||||
|
//Klok instellen
|
||||||
|
let rcc = dp.RCC.constrain();
|
||||||
|
let clocks = rcc.cfgr.sysclk(48.MHz()).freeze();
|
||||||
|
|
||||||
|
// Create a delay abstraction based on SysTick
|
||||||
|
let mut delay = cp.SYST.delay(&clocks);
|
||||||
|
let mut status:bool = false;
|
||||||
|
loop {
|
||||||
|
// On for 1s, off for 1s.
|
||||||
|
let _ = leds.red_toggle();
|
||||||
|
status ^= true;
|
||||||
|
delay.delay_ms(1000_u32);
|
||||||
|
|
||||||
|
//dit verschijnt in een van de open terminals in vscode
|
||||||
|
hprintln!("Led {:?}", status.then(|| "aan!").unwrap_or("uit!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### state machine
|
||||||
|
|
||||||
|
De statemachine is geimplementeerd in zijn eigen struct
|
||||||
|
|
||||||
|
- Box is not available without malloc. switch to an enum
|
||||||
|
|
||||||
|
|
||||||
|
Ik heb niet genoeg tijd gehad om dat dit vak te werken, dus mijn code werkt niet
|
||||||
|
zoals dat het moet, het werkt wel. Ik heb veel geëxperimenteerd met Rustlings,
|
||||||
|
ik hierdoor nog enthousiaster geworden om Rust beter te leren. Het is echt een
|
||||||
|
andere denkwijze als C/C++. Rust laat je echt goed denken hoe de code moet
|
||||||
|
werkten en maakt het erg moeilijk om onzichtbare bugs te maken.
|
||||||
|
|
||||||
## code
|
## code
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user