commit 2b90c2d401a8c278072864817343aa3b547bc10b Author: Sebastian Date: Sun Apr 28 16:29:57 2024 +0200 Initial commit diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..4a1ca49 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,18 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-rs run --chip STM32F103C8" +rustflags = [ + "-C", "linker=flip-link", + "-C", "link-arg=-Tlink.x", + "-C", "link-arg=-Tdefmt.x", + # 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", +] + +[build] +target = "thumbv7m-none-eabi" # Cortex-M3 + +[alias] +rb = "run --bin" +rrb = "run --release --bin" +bbr = "build --release --bin" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..869df07 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..f217ee1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,62 @@ +[package] +name = "AS5048_test" +edition = "2021" +version = "0.1.0" + +[dependencies] +cortex-m = { version = "0.7", features = ["critical-section-single-core"] } +defmt = { version = "0.3", features = ["encoding-rzcobs"] } +defmt-brtt = { version = "0.1", default-features = false, features = ["rtt"] } +panic-probe = { version = "0.3", features = ["print-defmt"] } +rtic = { version = "2.0.0", features = [ "thumbv7-backend" ] } +stm32f1xx-hal = { version = "0.10.0", features = ["stm32f103", "rt", "medium"] } +rtic-monotonics = { version = "1.0.0", features = [ "cortex-m-systick" ]} +as5048a = "0.2.1" +num-traits = { version = "0.2", default-features = false, features = ["libm"] } + + +# cargo build/run +[profile.dev] +codegen-units = 1 +debug = 2 +debug-assertions = true # <- +incremental = false +opt-level = 'z' # <- +overflow-checks = true # <- + +# cargo test +[profile.test] +codegen-units = 1 +debug = 2 +debug-assertions = true # <- +incremental = false +opt-level = 3 # <- +overflow-checks = true # <- + +# cargo build/run --release +[profile.release] +codegen-units = 1 +debug = 2 +debug-assertions = false # <- +incremental = false +lto = 'fat' +opt-level = 3 # <- +overflow-checks = false # <- + +# cargo test --release +[profile.bench] +codegen-units = 1 +debug = 2 +debug-assertions = false # <- +incremental = false +lto = 'fat' +opt-level = 3 # <- +overflow-checks = false # <- + +# uncomment this to switch from the crates.io version of defmt to its git version +# check app-template's README for instructions +# [patch.crates-io] +# defmt = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version supported by probe-rs (see changelog)" } +# defmt-rtt = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version supported by probe-rs (see changelog)" } +# defmt-test = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version supported by probe-rs (see changelog)" } +# panic-probe = { git = "https://github.com/knurling-rs/defmt", rev = "use defmt version supported by probe-rs (see changelog)" } diff --git a/memory.x b/memory.x new file mode 100644 index 0000000..89459b6 --- /dev/null +++ b/memory.x @@ -0,0 +1,6 @@ +/* Fake bluepill using STM32F103C8T6 */ +MEMORY +{ + FLASH : ORIGIN = 0x08000000, LENGTH = 64K + RAM : ORIGIN = 0x20000000, LENGTH = 20K +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..770e703 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,137 @@ +#![no_main] +#![no_std] +#![feature(type_alias_impl_trait)] +use defmt_brtt as _; // global logger + +use panic_probe as _; +use stm32f1xx_hal as _; + +// same panicking *behavior* as `panic-probe` but doesn't print a panic message +// this prevents the panic message being printed *twice* when `defmt::panic` is invoked +#[defmt::panic_handler] +fn panic() -> ! { + cortex_m::asm::udf() +} + +// TODO(7) Configure the `rtic::app` macro +#[rtic::app( + device = stm32f1xx_hal::pac, + // TODO: Replace the `FreeInterrupt1, ...` with free interrupt vectors if software tasks are used + // You can usually find the names of the interrupt vectors in the some_hal::pac::interrupt enum. + dispatchers = [SPI3] +)] +mod app { + + use stm32f1xx_hal::{ + gpio::{gpioc, Alternate, Output, Pin, PushPull}, + pac, + prelude::*, + spi::{self, Mode, Phase, Polarity, Spi}, + }; + + use as5048a::AS5048A; + + use rtic_monotonics::systick::Systick; + + type EncoderSPI = Spi< + pac::SPI1, + spi::Spi1NoRemap, + (Pin<'A', 5, Alternate>, Pin<'A', 6>, Pin<'A', 7, Alternate>), + u8, + >; + + // Shared resources go here + #[shared] + struct Shared { + // TODO: Add resources + } + + // Local resources go here + #[local] + struct Local { + encoder: AS5048A>, + board_led: gpioc::PC13>, + } + + #[init] + fn init(cx: init::Context) -> (Shared, Local) { + defmt::info!("init"); + + let mut flash = cx.device.FLASH.constrain(); + let rcc = cx.device.RCC.constrain(); + + // Freeze the configuration of all the clocks in the system and store the frozen frequencies in + // `clocks` + let clocks = rcc + .cfgr + .use_hse(8.MHz()) + .sysclk(16.MHz()) + .pclk1(4.MHz()) + .freeze(&mut flash.acr); + + defmt::info!("Clock Setup done"); + + let systick_mono_token = rtic_monotonics::create_systick_token!(); + Systick::start(cx.core.SYST, clocks.pclk1().raw(), systick_mono_token); + + let mut afio = cx.device.AFIO.constrain(); + + // Acquire the GPIOC peripheral + let mut gpioa = cx.device.GPIOA.split(); + let mut gpioc = cx.device.GPIOC.split(); + + let board_led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); + + let sck = gpioa.pa5.into_alternate_push_pull(&mut gpioa.crl); + let miso = gpioa.pa6; + let mosi = gpioa.pa7.into_alternate_push_pull(&mut gpioa.crl); + let cs = gpioa.pa4.into_push_pull_output(&mut gpioa.crl); + + let spi = Spi::spi1( + cx.device.SPI1, + (sck, miso, mosi), + &mut afio.mapr, + Mode { + phase: Phase::CaptureOnSecondTransition, + polarity: Polarity::IdleLow, + }, + 500.kHz(), + clocks, + ); + + defmt::info!("SPI Setup done"); + + let encoder = AS5048A::new(spi, cs); + + defmt::info!("Encoder Setup done"); + + read_sensor::spawn().ok(); + + ( + Shared { + // Initialization of shared resources go here + }, + Local { encoder, board_led }, + ) + } + + #[task(local = [encoder, board_led])] + async fn read_sensor(cx: read_sensor::Context) { + let encoder = cx.local.encoder; + let board_led = cx.local.board_led; + + loop { + board_led.toggle(); + + let (diag, gain) = encoder.diag_gain().unwrap(); + defmt::info!("diag: {:08b} gain: {}", diag, gain); + defmt::info!("magnitude: {:?}", encoder.magnitude().unwrap()); + + let raw_angle = encoder.angle().unwrap(); + let angle_deg = raw_angle as u32 * 3600 / 16384; + defmt::info!("angle: {:?}", angle_deg); + + Systick::delay(200.millis()).await; + } + } +}