From 6bc62383bc28ebbce557476fbc04a653253ad5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rn-Michael?= <40151420+ldericher@users.noreply.github.com> Date: Fri, 8 Mar 2024 16:59:02 +0000 Subject: [PATCH] cortex-m-rtic blinky --- bluepill-rs/Cargo.lock | 167 ++++++++++++++++++++++++++++++++++++++- bluepill-rs/Cargo.toml | 10 ++- bluepill-rs/src/main.rs | 169 +++++++++++++++++++++++----------------- 3 files changed, 265 insertions(+), 81 deletions(-) diff --git a/bluepill-rs/Cargo.lock b/bluepill-rs/Cargo.lock index 40f1c97..f7102d9 100644 --- a/bluepill-rs/Cargo.lock +++ b/bluepill-rs/Cargo.lock @@ -2,13 +2,28 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + [[package]] name = "bare-metal" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" dependencies = [ - "rustc_version", + "rustc_version 0.2.3", ] [[package]] @@ -35,14 +50,17 @@ version = "0.1.0" dependencies = [ "cortex-m", "cortex-m-rt", + "cortex-m-rtic", "defmt", "defmt-ringbuf", "defmt-rtt", "embedded-hal 1.0.0", - "heapless", + "heapless 0.8.0", "nb 1.1.0", "panic-halt", + "stm32f1", "stm32f1xx-hal", + "systick-monotonic", ] [[package]] @@ -96,6 +114,34 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "cortex-m-rtic" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d696ae7390bdb9f7978f71ca7144256a2c4616240a6df9002da3c451f9fc8f02" +dependencies = [ + "bare-metal 1.0.0", + "cortex-m", + "cortex-m-rtic-macros", + "heapless 0.7.17", + "rtic-core", + "rtic-monotonic", + "version_check", +] + +[[package]] +name = "cortex-m-rtic-macros" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eefb40b1ca901c759d29526e5c8a0a1b246c20caaa5b4cc5d0f0b94debecd4c7" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "rtic-syntax", + "syn 1.0.109", +] + [[package]] name = "critical-section" version = "1.1.2" @@ -203,6 +249,15 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hash32" version = "0.3.1" @@ -212,16 +267,55 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version 0.4.0", + "spin", + "stable_deref_trait", +] + [[package]] name = "heapless" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "hash32", + "hash32 0.3.1", "stable_deref_trait", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "nb" version = "0.1.3" @@ -285,15 +379,54 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rtic-core" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9369355b04d06a3780ec0f51ea2d225624db777acbc60abd8ca4832da5c1a42" + +[[package]] +name = "rtic-monotonic" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb8b0b822d1a366470b9cea83a1d4e788392db763539dc4ba022bcc787fece82" + +[[package]] +name = "rtic-syntax" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f5e215601dc467752c2bddc6284a622c6f3d2bab569d992adcd5ab7e4cb9478" +dependencies = [ + "indexmap", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver", + "semver 0.9.0", ] +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.22", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "semver" version = "0.9.0" @@ -303,12 +436,27 @@ dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -380,6 +528,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "systick-monotonic" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67fb822d5c615a0ae3a4795ee5b1d06381c7faf488d861c0a4fa8e6a88d5ff84" +dependencies = [ + "cortex-m", + "fugit", + "rtic-monotonic", +] + [[package]] name = "thiserror" version = "1.0.57" diff --git a/bluepill-rs/Cargo.toml b/bluepill-rs/Cargo.toml index 095d23c..7d5892d 100644 --- a/bluepill-rs/Cargo.toml +++ b/bluepill-rs/Cargo.toml @@ -9,15 +9,17 @@ edition = "2021" defmt-ringbuf = { path = "../defmt-ringbuf", optional = true } embedded-hal = "1.0.0" +stm32f1 = { version = "0.15", features = ["stm32f103", "rt"] } +stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } nb = "1" cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = { version = "0.7.1", features = ["device"] } +cortex-m-rtic = "1.1.4" +systick-monotonic = "1.0.1" + defmt = { version = "0.3", features = ["encoding-rzcobs"] } defmt-rtt = { version = "0.4", optional = true } heapless = "0.8.0" + # Panic behaviour, see https://crates.io/keywords/panic-impl for alternatives panic-halt = "0.2.0" - -[dependencies.stm32f1xx-hal] -version = "0.10.0" -features = ["rt", "stm32f103", "medium"] diff --git a/bluepill-rs/src/main.rs b/bluepill-rs/src/main.rs index e5aeee0..8c1e870 100644 --- a/bluepill-rs/src/main.rs +++ b/bluepill-rs/src/main.rs @@ -5,97 +5,120 @@ //! Note: Without additional hardware, PC13 should not be used to drive an LED, see page 5.1.2 of //! the reference manual for an explanation. This is not an issue on the blue pill. -#![deny(unsafe_code)] +// #![deny(unsafe_code)] #![no_std] #![no_main] -use cortex_m::singleton; +// use cortex_m::singleton; use panic_halt as _; - -use nb::block; - -use cortex_m_rt::entry; -use stm32f1xx_hal::{pac, prelude::*, rcc, serial, timer::Timer}; +use stm32f1xx_hal::{dma, gpio, pac, prelude::*, rcc, serial, timer}; +use systick_monotonic::Systick; mod i2c_reg_slave; mod i2c_slave; -#[entry] -fn main() -> ! { - // Get access to the core peripherals from the cortex-m crate - let cp = cortex_m::Peripherals::take().unwrap(); - // Get access to the device specific peripherals from the peripheral access crate - let dp = pac::Peripherals::take().unwrap(); +// static mut BUFFER: Option<&mut [u8; 256]> = None; - // Take ownership over the raw flash and rcc devices and convert them into the corresponding - // HAL structs - let mut flash = dp.FLASH.constrain(); - let rcc = dp.RCC.constrain(); +#[rtic::app(device = stm32f1::stm32f103, peripherals = true)] +mod app { + use super::*; - // Freeze the configuration of all the clocks in the system and store the frozen frequencies in - // `clocks` - let clocks = rcc.cfgr.freeze_with_config( - rcc::Config { - // HSE frequency - hse: Some(8_000_000), - // PLLMUL represented by an integer -2 - pllmul: Some(9 - 2), - // PCLK1 freq must be 36 MHz or less - ppre1: stm32f1xx_hal::rcc::PPre::Div2, - // ADCCLK freq must be 14 MHz or less - adcpre: pac::rcc::cfgr::ADCPRE_A::Div6, - ..Default::default() - }, - &mut flash.acr, - ); + // A monotonic timer to enable scheduling in RTIC + #[monotonic(binds = SysTick, default = true)] + type MyMono = Systick<100>; // 100 Hz / 10 ms granularity - // Acquire the peripherals - let mut gpioa = dp.GPIOA.split(); - let mut gpioc = dp.GPIOC.split(); + #[shared] + struct Shared {} - let mut afio = dp.AFIO.constrain(); - let dma1 = dp.DMA1.split(); + #[local] + struct Local { + tx: dma::TxDma, dma::dma1::C4>, + delay: timer::Delay, + led: gpio::Pin<'C', 13, gpio::Output>, + } - // USART1 - let tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh); - let rx = gpioa.pa10; //.into_pull_up_input(&mut gpioa.crh); + #[init] + fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) { + // Take ownership over the raw flash and rcc devices and convert them into the corresponding + // HAL structs + let mut flash = cx.device.FLASH.constrain(); + let rcc = cx.device.RCC.constrain(); - let serial = serial::Serial::new( - dp.USART1, - (tx, rx), - &mut afio.mapr, - serial::Config { - baudrate: 250_000.bps(), - ..Default::default() - }, - &clocks, - ); + // Freeze the configuration of all the clocks in the system and store the frozen frequencies in + // `clocks` + let clocks = rcc.cfgr.freeze_with_config( + rcc::Config { + // HSE frequency + hse: Some(8_000_000), + // PLLMUL represented by an integer -2 + pllmul: Some(9 - 2), + // PCLK1 freq must be 36 MHz or less + ppre1: stm32f1xx_hal::rcc::PPre::Div2, + // ADCCLK freq must be 14 MHz or less + adcpre: pac::rcc::cfgr::ADCPRE_A::Div6, + ..Default::default() + }, + &mut flash.acr, + ); - let mut tx = serial.tx.with_dma(dma1.4); - let mut buf = singleton!(: [u8; 255] = [0b01010101; 255]).unwrap(); + // Initialize the monotonic + let mono = Systick::new(cx.core.SYST, clocks.sysclk().to_Hz()); - // Configure gpio C pin 13 as a push-pull output. The `crh` register is passed to the function - // in order to configure the port. For pins 0-7, crl should be passed instead. - let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); + // Acquire the peripherals + let mut gpioa = cx.device.GPIOA.split(); + let mut gpioc = cx.device.GPIOC.split(); - // Configure the syst timer to trigger an update every second - let mut timer = Timer::syst(cp.SYST, &clocks).counter_hz(); - // at 72 MHz, timer of 1 Hz overflows, use 10 Hz instead (8 Hz experimental minimum) - timer.start(10.Hz()).unwrap(); + let mut afio = cx.device.AFIO.constrain(); + let dma1 = cx.device.DMA1.split(); - // Wait for the timer to trigger an update and change the state of the LED - loop { - let xfer = tx.write(buf); - for _ in 0..10 { - block!(timer.wait()).unwrap(); + // USART1 + let tx = gpioa.pa9.into_alternate_push_pull(&mut gpioa.crh); + let rx = gpioa.pa10; //.into_pull_up_input(&mut gpioa.crh); + + let serial = serial::Serial::new( + cx.device.USART1, + (tx, rx), + &mut afio.mapr, + serial::Config { + baudrate: 250_000.bps(), + ..Default::default() + }, + &clocks, + ); + + // unsafe { + // BUFFER = Some(singleton!(: [u8; 256] = [0b01010101; 256]).unwrap()); + // } + + ( + Shared {}, + Local { + tx: serial.tx.with_dma(dma1.4), + + // Configure timer + delay: cx.device.TIM1.delay_us(&clocks), + + // Configure gpio C pin 13 as a push-pull output. The `crh` register is passed to the function + // in order to configure the port. For pins 0-7, crl should be passed instead. + led: gpioc.pc13.into_push_pull_output(&mut gpioc.crh), + }, + init::Monotonics(mono), + ) + } + + #[idle(local = [tx, delay, led])] + fn idle(cx: idle::Context) -> ! { + // Wait for the timer to trigger an update and change the state of the LED + loop { + // let xfer = cx.shared.tx.lock(|tx| tx.write(BUFFER.unwrap())); + + cx.local.delay.delay(1u32.secs()); + cx.local.led.set_high(); + + cx.local.delay.delay(1u32.secs()); + cx.local.led.set_low(); + + // xfer.wait(); } - led.set_high(); - - for _ in 0..10 { - block!(timer.wait()).unwrap(); - } - led.set_low(); - - (buf, tx) = xfer.wait(); } }