first commit
This commit is contained in:
commit
57a257d47b
21
.cargo/config.toml
Normal file
21
.cargo/config.toml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
[target.thumbv6m-none-eabi]
|
||||||
|
runner = 'probe-rs run --chip STM32L010RBTx'
|
||||||
|
|
||||||
|
rustflags = [
|
||||||
|
"-C", "link-arg=--nmagic",
|
||||||
|
"-C", "link-arg=-Tlink.x",
|
||||||
|
"-C", "link-arg=-Tdefmt.x",
|
||||||
|
"-C", "link-arg=--no-rosegment"
|
||||||
|
]
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "thumbv6m-none-eabi"
|
||||||
|
|
||||||
|
[env]
|
||||||
|
DEFMT_LOG = "trace"
|
||||||
|
|
||||||
|
[alias]
|
||||||
|
main = "embed --release --bin main"
|
||||||
|
rb = "embed --release --bin"
|
||||||
|
s = "size --bin main -- -B -x"
|
||||||
|
sr = "size --release --bin main -- -B -x"
|
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Generated by Cargo
|
||||||
|
# will have compiled files and executables
|
||||||
|
debug/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
|
Cargo.lock
|
||||||
|
|
||||||
|
# These are backup files generated by rustfmt
|
||||||
|
**/*.rs.bk
|
||||||
|
|
||||||
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
|
*.pdb
|
72
Cargo.toml
Normal file
72
Cargo.toml
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
[package]
|
||||||
|
name = "stm32_app"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
authors = ["wieerwill <jeutter@wieerwill.de>"]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
embassy-stm32 = { version = "0.1.0", features = [
|
||||||
|
"defmt",
|
||||||
|
"memory-x",
|
||||||
|
"stm32l010rb",
|
||||||
|
"time-driver-any",
|
||||||
|
"exti",
|
||||||
|
"unstable-pac",
|
||||||
|
"exti",
|
||||||
|
"time",
|
||||||
|
] }
|
||||||
|
cortex-m = { version = "0.7.6", features = [
|
||||||
|
"inline-asm",
|
||||||
|
"critical-section-single-core",
|
||||||
|
] }
|
||||||
|
cortex-m-rt = "0.7.0"
|
||||||
|
defmt = "0.3"
|
||||||
|
defmt-rtt = "0.4"
|
||||||
|
panic-probe = { version = "0.3", features = ["print-defmt"] }
|
||||||
|
embassy-sync = { version = "0.6.0", features = [
|
||||||
|
"defmt",
|
||||||
|
] }
|
||||||
|
embassy-executor = { version = "0.6.0", features = [
|
||||||
|
"arch-cortex-m",
|
||||||
|
"executor-thread",
|
||||||
|
"executor-interrupt",
|
||||||
|
"defmt",
|
||||||
|
"integrated-timers",
|
||||||
|
] }
|
||||||
|
embassy-time = { version = "0.3.1", features = [
|
||||||
|
"defmt",
|
||||||
|
"defmt-timestamp-uptime",
|
||||||
|
"tick-hz-32_768",
|
||||||
|
] }
|
||||||
|
embassy-futures = { version = "0.1.1", features = [
|
||||||
|
"defmt",
|
||||||
|
] }
|
||||||
|
static_cell = "2"
|
||||||
|
portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
|
||||||
|
heapless = "0.8.0"
|
||||||
|
|
||||||
|
# cargo build/run
|
||||||
|
[profile.dev]
|
||||||
|
codegen-units = 1
|
||||||
|
debug = 2
|
||||||
|
debug-assertions = true
|
||||||
|
incremental = false
|
||||||
|
opt-level = 0
|
||||||
|
overflow-checks = true
|
||||||
|
|
||||||
|
# cargo build/run --release
|
||||||
|
[profile.release]
|
||||||
|
codegen-units = 1 # reduce Code Generation Units
|
||||||
|
debug = true # symbols are nice and they don't increase the size on Flash
|
||||||
|
debug-assertions = false
|
||||||
|
incremental = false
|
||||||
|
lto = true # Link Time Optimization
|
||||||
|
opt-level = "z" # Optimize for size "s" or "z"
|
||||||
|
overflow-checks = true
|
||||||
|
# strip = "symbols" # or true, removes all output from rtt
|
||||||
|
# panic = "abort" # abort immediately rather than unwind
|
||||||
|
# location-detail="none" # Remove Location Details
|
||||||
|
|
||||||
|
[target.stm32l010rb]
|
||||||
|
runner = 'probe-rs run --chip stm32l010rbtx'
|
103
Embed.toml
Normal file
103
Embed.toml
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
[default.probe]
|
||||||
|
# USB vendor ID
|
||||||
|
# usb_vid = "1337"
|
||||||
|
# USB product ID
|
||||||
|
# usb_pid = "1337"
|
||||||
|
# Serial number
|
||||||
|
# serial = "12345678"
|
||||||
|
# The protocol to be used for communicating with the target.
|
||||||
|
protocol = "Swd"
|
||||||
|
# The speed in kHz of the data link to the target.
|
||||||
|
# speed = 1337
|
||||||
|
|
||||||
|
[default.flashing]
|
||||||
|
# Whether or not the target should be flashed.
|
||||||
|
enabled = true
|
||||||
|
# Whether or not bytes erased but not rewritten with data from the ELF
|
||||||
|
# should be restored with their contents before erasing.
|
||||||
|
restore_unwritten_bytes = false
|
||||||
|
# The path where an SVG of the assembled flash layout should be written to.
|
||||||
|
# flash_layout_output_path = "out.svg"
|
||||||
|
# Triggers a full chip erase instead of a page by page erase.
|
||||||
|
do_chip_erase = false
|
||||||
|
# Whether to disable double buffering
|
||||||
|
disable_double_buffering = false
|
||||||
|
# Whether to verify flash contents after downloading
|
||||||
|
verify = true
|
||||||
|
|
||||||
|
[default.reset]
|
||||||
|
# Whether or not the target should be reset.
|
||||||
|
# When flashing is enabled as well, the target will be reset after flashing regardless of this setting.
|
||||||
|
enabled = true
|
||||||
|
# Whether or not the target should be halted after reset.
|
||||||
|
halt_afterwards = false
|
||||||
|
|
||||||
|
[default.general]
|
||||||
|
# The chip name of the chip to be debugged.
|
||||||
|
chip = "STM32L010RBTx"
|
||||||
|
# A list of chip descriptions to be loaded during runtime.
|
||||||
|
chip_descriptions = []
|
||||||
|
# The default log level to be used. Possible values are one of:
|
||||||
|
# "OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"
|
||||||
|
# If not set, the `RUST_LOG` environment variable will be used.
|
||||||
|
log_level = "WARN"
|
||||||
|
# Use this flag to assert the nreset & ntrst pins during attaching the probe to the chip.
|
||||||
|
connect_under_reset = false
|
||||||
|
|
||||||
|
[default.rtt]
|
||||||
|
# Whether or not an RTTUI should be opened after flashing.
|
||||||
|
enabled = true
|
||||||
|
# The duration in ms for which the logger should retry to attach to RTT.
|
||||||
|
timeout = 10000
|
||||||
|
# Whether to save rtt history buffer on exit.
|
||||||
|
log_enabled = true
|
||||||
|
# Where to save rtt history buffer relative to manifest path.
|
||||||
|
log_path = "./target/logs"
|
||||||
|
# A list of up (target -> host) channel settings associations to be displayed. If left empty, all channels are displayed.
|
||||||
|
# object key - RTT channel identifier number
|
||||||
|
# mode (Optional) - RTT operation mode. Describes how the target handles RTT outputs that won't
|
||||||
|
# fit in the buffer. If left unset, the firmware will determine the default
|
||||||
|
# for each RTT up channel.
|
||||||
|
# * NoBlockSkip - Skip writing the data completely if it doesn't fit in its
|
||||||
|
# entirety.
|
||||||
|
# * NoBlockTrim - Write as much as possible of the data and ignore the rest.
|
||||||
|
# * BlockIfFull - Spin until the host reads data. Can result in app freezing.
|
||||||
|
# format (Optional) - How to interpret data from target firmware. One of:
|
||||||
|
# * String - Directly show output from the target (default)
|
||||||
|
# * Defmt - Format output on the host, see https://defmt.ferrous-systems.com/
|
||||||
|
# * BinaryLE - Display as raw hex
|
||||||
|
# show_location (Optional) - Whether to show the location of defmt messages in the UI.
|
||||||
|
# show_timestamps (Optional) - Whether to show the timestamps of String and Defmt messages in the UI, if available.
|
||||||
|
# socket (Optional) - Server socket address (for optional external frontend or endpoint).
|
||||||
|
# log_format (Optional) - Control the output format for `format = Defmt`.
|
||||||
|
up_channels = [
|
||||||
|
# { channel = 0, mode = "BlockIfFull", format = "Defmt", show_location = true },
|
||||||
|
# { channel = 1, mode = "BlockIfFull", format = "String", show_timestamps = false, socket = "127.0.0.1:12345" },
|
||||||
|
]
|
||||||
|
|
||||||
|
# A list of down (host -> target) channel settings. You can select a down channel for each UI tab,
|
||||||
|
# which will be used to send data to the target.
|
||||||
|
# object key - RTT channel identifier number
|
||||||
|
# mode (Optional) - RTT operation mode. Describes how the target handles RTT outputs that won't
|
||||||
|
# fit in the buffer. If left unset, the firmware will determine the default
|
||||||
|
# for each RTT down channel.
|
||||||
|
down_channels = [
|
||||||
|
# { channel = 0, mode = "BlockIfFull" }
|
||||||
|
]
|
||||||
|
|
||||||
|
# UI tab settings. All up channels are displayed, except when hidden here. You can specify how each
|
||||||
|
# tab is displayed and whether they allow sending data to the target.
|
||||||
|
# up_channel - The channel_number of the RTT up channel to display
|
||||||
|
# hide (Optional) - Whether to hide the tab. Defaults to false.
|
||||||
|
# down_channel (Optional) - The channel_number of the RTT down channel to use for this tab.
|
||||||
|
# name (Optional) - String to be displayed in the RTTUI tab. Defaults to the channel name.
|
||||||
|
tabs = [
|
||||||
|
# { up_channel = 0, down_channel = 0, name = "My channel" },
|
||||||
|
# { up_channel = 1, hide = true },
|
||||||
|
]
|
||||||
|
|
||||||
|
[default.gdb]
|
||||||
|
# Whether or not a GDB server should be opened after flashing.
|
||||||
|
enabled = false
|
||||||
|
# The connection string in host:port format wher the GDB server will open a socket.
|
||||||
|
gdb_connection_string = "127.0.0.1:1337"
|
19
README.md
Normal file
19
README.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# STM32 Firmware with Rust and Embassy
|
||||||
|
Used Chip in this Project was a STM32L0, the low power edition. Other targets are easily exchangeable.
|
||||||
|
|
||||||
|
# Dev Tools
|
||||||
|
- rustup 1.27.1
|
||||||
|
- rustc 1.81.0
|
||||||
|
- Cargo 1.81.0
|
||||||
|
- Probe-RS
|
||||||
|
|
||||||
|
# Binaries
|
||||||
|
All binaries are compiled and then transfered to the connected board (if exist). Then the RTT Console will be opened to read and debug.
|
||||||
|
|
||||||
|
The ready binary is a .elf file in the `target` folder.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo rb blinky # blinky example
|
||||||
|
cargo main # main program
|
||||||
|
./elf-to-hex.sh # convert main program to Hex and versionize
|
||||||
|
```
|
15
elf-to-hex.sh
Executable file
15
elf-to-hex.sh
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
objcopy -O ihex target/thumbv6m-none-eabi/release/main target/main.hex -S
|
||||||
|
|
||||||
|
# read version number
|
||||||
|
version=$(awk -F ' = ' '$1 ~ /version/ { gsub(/[\"]/, "", $2); printf("%s",$2) }' Cargo.toml)
|
||||||
|
# check if version was found
|
||||||
|
if [[ -z "$version" ]]; then
|
||||||
|
echo "Error: Version not found in Cargo.toml"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Firmware Version $version"
|
||||||
|
|
||||||
|
# write version into filename
|
||||||
|
mv target/main.hex target/FW-$version-main.hex
|
||||||
|
echo "target/FW-$version-main.hex"
|
6
rust-toolchain.toml
Normal file
6
rust-toolchain.toml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Before upgrading check that everything is available on all tier1 targets here:
|
||||||
|
# https://rust-lang.github.io/rustup-components-history
|
||||||
|
[toolchain]
|
||||||
|
channel = "stable"
|
||||||
|
components = [ "rustfmt" ]
|
||||||
|
targets = [ "thumbv6m-none-eabi" ]
|
37
src/bin/adc.rs
Normal file
37
src/bin/adc.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::adc::{Adc, SampleTime};
|
||||||
|
use embassy_stm32::peripherals::ADC1;
|
||||||
|
use embassy_stm32::{adc, bind_interrupts};
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct AdcIrqs {
|
||||||
|
ADC1 => adc::InterruptHandler<ADC1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
let mut adc = Adc::new(p.ADC1, AdcIrqs);
|
||||||
|
adc.set_sample_time(SampleTime::CYCLES79_5);
|
||||||
|
let mut pin = p.PA1;
|
||||||
|
|
||||||
|
let mut vrefint = adc.enable_vref();
|
||||||
|
let vrefint_sample = adc.read(&mut vrefint).await;
|
||||||
|
let convert_to_millivolts = |sample| {
|
||||||
|
// Embedded reference voltage
|
||||||
|
const VREFINT_MV: u32 = 1224; // mV
|
||||||
|
(u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
|
||||||
|
};
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let v = adc.read(&mut pin).await;
|
||||||
|
info!("--> {} - {} mV", v, convert_to_millivolts(v));
|
||||||
|
Timer::after_millis(100).await;
|
||||||
|
}
|
||||||
|
}
|
25
src/bin/blinky.rs
Normal file
25
src/bin/blinky.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
let mut led = Output::new(p.PA9, Level::High, Speed::Low);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
info!("high");
|
||||||
|
led.set_high();
|
||||||
|
Timer::after_millis(300).await;
|
||||||
|
|
||||||
|
info!("low");
|
||||||
|
led.set_low();
|
||||||
|
Timer::after_millis(300).await;
|
||||||
|
}
|
||||||
|
}
|
25
src/bin/button.rs
Normal file
25
src/bin/button.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::exti::ExtiInput;
|
||||||
|
use embassy_stm32::gpio::Pull;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
// Initialize and create handle for devicer peripherals
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
// Configure the button pin and obtain handler.
|
||||||
|
let mut button = ExtiInput::new(p.PC2, p.EXTI2, Pull::Up);
|
||||||
|
|
||||||
|
info!("Press the button...");
|
||||||
|
loop {
|
||||||
|
button.wait_for_falling_edge().await;
|
||||||
|
info!("Pressed!");
|
||||||
|
button.wait_for_rising_edge().await;
|
||||||
|
info!("Released!");
|
||||||
|
}
|
||||||
|
}
|
16
src/bin/hello.rs
Normal file
16
src/bin/hello.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
|
let _p = embassy_stm32::init(Default::default());
|
||||||
|
loop {
|
||||||
|
Timer::after_secs(1).await;
|
||||||
|
info!("Hello World");
|
||||||
|
}
|
||||||
|
}
|
20
src/bin/main.rs
Normal file
20
src/bin/main.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::{info, debug};
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
|
let _p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
info!("Hello World");
|
||||||
|
debug!("Start your application here");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
Timer::after_secs(1).await;
|
||||||
|
info!(".");
|
||||||
|
}
|
||||||
|
}
|
46
src/bin/pwm.rs
Normal file
46
src/bin/pwm.rs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::gpio::OutputType::PushPull;
|
||||||
|
use embassy_stm32::time::hz;
|
||||||
|
use embassy_stm32::timer::low_level::CountingMode::EdgeAlignedUp;
|
||||||
|
use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm};
|
||||||
|
use embassy_stm32::timer::Channel;
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) -> ! {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
let buzz_pin = PwmPin::new_ch1(p.PB13, PushPull);
|
||||||
|
let mut pwm = SimplePwm::new(
|
||||||
|
p.TIM21,
|
||||||
|
Some(buzz_pin),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
hz(2000),
|
||||||
|
EdgeAlignedUp,
|
||||||
|
);
|
||||||
|
|
||||||
|
let max_duty = pwm.get_max_duty();
|
||||||
|
// Configure the Duty Cycle to 50%
|
||||||
|
pwm.set_duty(Channel::Ch2, max_duty / 2);
|
||||||
|
|
||||||
|
pwm.enable(Channel::Ch2);
|
||||||
|
|
||||||
|
let mut frequence = 300;
|
||||||
|
loop {
|
||||||
|
info!("on, freq {}hz", frequence);
|
||||||
|
pwm.set_frequency(hz(frequence));
|
||||||
|
pwm.enable(Channel::Ch2);
|
||||||
|
Timer::after_millis(1000).await;
|
||||||
|
info!("off");
|
||||||
|
pwm.disable(Channel::Ch2);
|
||||||
|
Timer::after_millis(500).await;
|
||||||
|
frequence += 20;
|
||||||
|
}
|
||||||
|
}
|
28
src/bin/spawner.rs
Normal file
28
src/bin/spawner.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn run() {
|
||||||
|
loop {
|
||||||
|
info!("Tick");
|
||||||
|
Timer::after_secs(1).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(spawner: Spawner) -> ! {
|
||||||
|
let _p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
spawner.spawn(run()).unwrap();
|
||||||
|
Timer::after_secs(1).await;
|
||||||
|
spawner.spawn(run()).unwrap();
|
||||||
|
loop {
|
||||||
|
Timer::after_secs(2).await;
|
||||||
|
info!("Tack");
|
||||||
|
}
|
||||||
|
}
|
31
src/bin/spi.rs
Normal file
31
src/bin/spi.rs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::gpio::{Level, Output, Speed};
|
||||||
|
use embassy_stm32::spi::{Config, Spi};
|
||||||
|
use embassy_stm32::time::Hertz;
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
let mut spi_config = Config::default();
|
||||||
|
spi_config.frequency = Hertz(1_000_000);
|
||||||
|
|
||||||
|
let mut spi = Spi::new_blocking(p.SPI1, p.PB3, p.PA7, p.PA6, spi_config);
|
||||||
|
|
||||||
|
let mut cs = Output::new(p.PA15, Level::High, Speed::VeryHigh);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut buf = [0x0Au8; 4];
|
||||||
|
cs.set_low();
|
||||||
|
unwrap!(spi.blocking_transfer_in_place(&mut buf));
|
||||||
|
cs.set_high();
|
||||||
|
info!("xfer {=[u8]:x}", buf);
|
||||||
|
Timer::after_millis(300).await;
|
||||||
|
}
|
||||||
|
}
|
42
src/bin/uart.rs
Normal file
42
src/bin/uart.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::usart::{Config, InterruptHandler, Uart};
|
||||||
|
use embassy_stm32::{bind_interrupts, peripherals};
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs{
|
||||||
|
LPUART1 => InterruptHandler<peripherals::LPUART1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
info!("Starting system");
|
||||||
|
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.baudrate = 9600;
|
||||||
|
|
||||||
|
let mut usart = Uart::new(
|
||||||
|
p.LPUART1, p.PC0, p.PC1, Irqs, p.DMA1_CH2, p.DMA1_CH3, config,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
unwrap!(usart.write(b"Hello Embassy World!\r\n").await);
|
||||||
|
|
||||||
|
let mut buf = [0u8; 300];
|
||||||
|
loop {
|
||||||
|
let result = usart.read_until_idle(&mut buf).await;
|
||||||
|
match result {
|
||||||
|
Ok(size) => {
|
||||||
|
info!("result {}, size {}", result, size);
|
||||||
|
}
|
||||||
|
Err(_err) => {
|
||||||
|
info!("error...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
src/bin/watchdog.rs
Normal file
25
src/bin/watchdog.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use defmt::*;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_stm32::wdg::IndependentWatchdog;
|
||||||
|
use embassy_time::Timer;
|
||||||
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
#[embassy_executor::main]
|
||||||
|
async fn main(_spawner: Spawner) {
|
||||||
|
// Initialize and create handle for devicer peripherals
|
||||||
|
let p = embassy_stm32::init(Default::default());
|
||||||
|
|
||||||
|
// Configure the independent watchdog timer
|
||||||
|
let mut wdg = IndependentWatchdog::new(p.IWDG, 2_000_000);
|
||||||
|
|
||||||
|
info!("Watchdog start");
|
||||||
|
wdg.unleash();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
Timer::after_secs(1).await;
|
||||||
|
wdg.pet();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user