From 72a101c2ebaa67b0e7cdb6cb7c088171dc8866e5 Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Mon, 27 Dec 2021 19:59:12 +0100 Subject: [PATCH 1/3] Upgrade examples to rtic v1.0.0 --- Cargo.toml | 2 +- examples/ethernet-nucleo-h743zi2.rs | 2 +- examples/ethernet-rtic-stm32h735g-dk.rs | 60 ++-- examples/ethernet-rtic-stm32h747i-disco.rs | 60 ++-- examples/fmc.rs | 336 ++++++++++----------- examples/rtic.rs | 59 ++-- examples/rtic_low_power.rs | 82 ++--- examples/rtic_timers.rs | 91 +++--- examples/sai-i2s-passthru.rs | 69 +++-- examples/spi-dma-rtic.rs | 60 ++-- 10 files changed, 436 insertions(+), 385 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a550be08..ba29717c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ optional = true [dev-dependencies] cortex-m-rt = ">=0.6.15,<0.8" -cortex-m-rtic = { version = "0.5.8", default-features = false, features = ["cortex-m-7"] } +cortex-m-rtic = { version = "1.0.0" } log = "0.4.11" panic-halt = "0.2.0" panic-rtt-target = { version = "0.1.0", features = ["cortex-m"] } diff --git a/examples/ethernet-nucleo-h743zi2.rs b/examples/ethernet-nucleo-h743zi2.rs index b0c432d3..4312fabb 100644 --- a/examples/ethernet-nucleo-h743zi2.rs +++ b/examples/ethernet-nucleo-h743zi2.rs @@ -1,3 +1,4 @@ +#![deny(warnings)] #![no_main] #![no_std] @@ -11,7 +12,6 @@ extern crate cortex_m; mod utilities; use log::info; -use stm32h7xx_hal::gpio::Speed; use stm32h7xx_hal::hal::digital::v2::OutputPin; use stm32h7xx_hal::rcc::CoreClocks; use stm32h7xx_hal::{ethernet, ethernet::PHY}; diff --git a/examples/ethernet-rtic-stm32h735g-dk.rs b/examples/ethernet-rtic-stm32h735g-dk.rs index 66597142..46031523 100644 --- a/examples/ethernet-rtic-stm32h735g-dk.rs +++ b/examples/ethernet-rtic-stm32h735g-dk.rs @@ -11,14 +11,13 @@ #![no_main] #![no_std] -use cortex_m; -use rtic::app; - #[macro_use] #[allow(unused)] mod utilities; use log::info; +use core::sync::atomic::AtomicU32; + use smoltcp::iface::{ Interface, InterfaceBuilder, Neighbor, NeighborCache, Route, Routes, SocketStorage, @@ -26,13 +25,7 @@ use smoltcp::iface::{ use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr, Ipv6Cidr}; -use stm32h7xx_hal::gpio; -use stm32h7xx_hal::hal::digital::v2::OutputPin; -use stm32h7xx_hal::rcc::CoreClocks; -use stm32h7xx_hal::{ethernet, ethernet::PHY}; -use stm32h7xx_hal::{prelude::*, stm32}; - -use core::sync::atomic::{AtomicU32, Ordering}; +use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32}; /// Configure SYSTICK for 1ms timebase fn systick_init(mut syst: stm32::SYST, clocks: CoreClocks) { @@ -111,16 +104,27 @@ impl<'a> Net<'a> { } } -#[app(device = stm32h7xx_hal::stm32, peripherals = true)] -const APP: () = { - struct Resources { +#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)] +mod app { + use stm32h7xx_hal::hal::digital::v2::OutputPin; + use stm32h7xx_hal::{ethernet, ethernet::PHY, gpio, prelude::*}; + + use super::*; + use core::sync::atomic::Ordering; + + #[shared] + struct SharedResources {} + #[local] + struct LocalResources { net: Net<'static>, lan8742a: ethernet::phy::LAN8742A, link_led: gpio::gpioc::PC3>, } #[init] - fn init(mut ctx: init::Context) -> init::LateResources { + fn init( + mut ctx: init::Context, + ) -> (SharedResources, LocalResources, init::Monotonics) { utilities::logger::init(); // Initialise power... let pwr = ctx.device.PWR.constrain(); @@ -202,35 +206,39 @@ const APP: () = { // 1ms tick systick_init(ctx.core.SYST, ccdr.clocks); - init::LateResources { - net, - lan8742a, - link_led, - } + ( + SharedResources {}, + LocalResources { + net, + lan8742a, + link_led, + }, + init::Monotonics(), + ) } - #[idle(resources = [lan8742a, link_led])] + #[idle(local = [lan8742a, link_led])] fn idle(ctx: idle::Context) -> ! { loop { // Ethernet - match ctx.resources.lan8742a.poll_link() { - true => ctx.resources.link_led.set_low(), - _ => ctx.resources.link_led.set_high(), + match ctx.local.lan8742a.poll_link() { + true => ctx.local.link_led.set_low(), + _ => ctx.local.link_led.set_high(), } .ok(); } } - #[task(binds = ETH, resources = [net])] + #[task(binds = ETH, local = [net])] fn ethernet_event(ctx: ethernet_event::Context) { unsafe { ethernet::interrupt_handler() } let time = TIME.load(Ordering::Relaxed); - ctx.resources.net.poll(time as i64); + ctx.local.net.poll(time as i64); } #[task(binds = SysTick, priority=15)] fn systick_tick(_: systick_tick::Context) { TIME.fetch_add(1, Ordering::Relaxed); } -}; +} diff --git a/examples/ethernet-rtic-stm32h747i-disco.rs b/examples/ethernet-rtic-stm32h747i-disco.rs index 3ef87116..22699652 100644 --- a/examples/ethernet-rtic-stm32h747i-disco.rs +++ b/examples/ethernet-rtic-stm32h747i-disco.rs @@ -11,14 +11,13 @@ #![no_main] #![no_std] -use cortex_m; -use rtic::app; - #[macro_use] #[allow(unused)] mod utilities; use log::info; +use core::sync::atomic::AtomicU32; + use smoltcp::iface::{ Interface, InterfaceBuilder, Neighbor, NeighborCache, Route, Routes, SocketStorage, @@ -26,13 +25,7 @@ use smoltcp::iface::{ use smoltcp::time::Instant; use smoltcp::wire::{HardwareAddress, IpAddress, IpCidr, Ipv6Cidr}; -use stm32h7xx_hal::gpio; -use stm32h7xx_hal::hal::digital::v2::OutputPin; -use stm32h7xx_hal::rcc::CoreClocks; -use stm32h7xx_hal::{ethernet, ethernet::PHY}; -use stm32h7xx_hal::{prelude::*, stm32}; - -use core::sync::atomic::{AtomicU32, Ordering}; +use stm32h7xx_hal::{ethernet, rcc::CoreClocks, stm32}; /// Configure SYSTICK for 1ms timebase fn systick_init(mut syst: stm32::SYST, clocks: CoreClocks) { @@ -111,16 +104,27 @@ impl<'a> Net<'a> { } } -#[app(device = stm32h7xx_hal::stm32, peripherals = true)] -const APP: () = { - struct Resources { +#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)] +mod app { + use stm32h7xx_hal::hal::digital::v2::OutputPin; + use stm32h7xx_hal::{ethernet, ethernet::PHY, gpio, prelude::*}; + + use super::*; + use core::sync::atomic::Ordering; + + #[shared] + struct SharedResources {} + #[local] + struct LocalResources { net: Net<'static>, lan8742a: ethernet::phy::LAN8742A, link_led: gpio::gpioi::PI14>, } #[init] - fn init(mut ctx: init::Context) -> init::LateResources { + fn init( + mut ctx: init::Context, + ) -> (SharedResources, LocalResources, init::Monotonics) { utilities::logger::init(); // Initialise power... let pwr = ctx.device.PWR.constrain(); @@ -205,35 +209,39 @@ const APP: () = { // 1ms tick systick_init(ctx.core.SYST, ccdr.clocks); - init::LateResources { - net, - lan8742a, - link_led, - } + ( + SharedResources {}, + LocalResources { + net, + lan8742a, + link_led, + }, + init::Monotonics(), + ) } - #[idle(resources = [lan8742a, link_led])] + #[idle(local = [lan8742a, link_led])] fn idle(ctx: idle::Context) -> ! { loop { // Ethernet - match ctx.resources.lan8742a.poll_link() { - true => ctx.resources.link_led.set_low(), - _ => ctx.resources.link_led.set_high(), + match ctx.local.lan8742a.poll_link() { + true => ctx.local.link_led.set_low(), + _ => ctx.local.link_led.set_high(), } .ok(); } } - #[task(binds = ETH, resources = [net])] + #[task(binds = ETH, local = [net])] fn ethernet_event(ctx: ethernet_event::Context) { unsafe { ethernet::interrupt_handler() } let time = TIME.load(Ordering::Relaxed); - ctx.resources.net.poll(time as i64); + ctx.local.net.poll(time as i64); } #[task(binds = SysTick, priority=15)] fn systick_tick(_: systick_tick::Context) { TIME.fetch_add(1, Ordering::Relaxed); } -}; +} diff --git a/examples/fmc.rs b/examples/fmc.rs index 027454a7..9bfc5985 100644 --- a/examples/fmc.rs +++ b/examples/fmc.rs @@ -1,7 +1,7 @@ //! FMC Example //! //! Tested on a STM32H747I-DISCO - +#![deny(warnings)] #![no_main] #![no_std] @@ -12,13 +12,11 @@ use core::slice; #[allow(dead_code)] mod utilities; -use rtic::app; - extern crate cortex_m; -extern crate rtic; +use cortex_m_rt::entry; use stm32h7xx_hal::gpio::Speed; -use stm32h7xx_hal::prelude::*; +use stm32h7xx_hal::{pac, prelude::*}; use stm32_fmc::devices::is42s32800g_6; @@ -36,190 +34,186 @@ macro_rules! fmc_pins { }; } -#[app(device = stm32h7xx_hal::stm32, peripherals = true)] -const APP: () = { - // the program entry point - #[init] - fn init(mut ctx: init::Context) { - let dp = ctx.device; - - // Initialise power... - let pwr = dp.PWR.constrain(); - let pwrcfg = example_power!(pwr).freeze(); - - // Initialise clocks... - let rcc = dp.RCC.constrain(); - let ccdr = rcc - .sys_ck(200.mhz()) - .hclk(200.mhz()) // FMC clock from HCLK by default - .freeze(pwrcfg, &dp.SYSCFG); - - // Get the delay provider. - let mut delay = ctx.core.SYST.delay(ccdr.clocks); - - // Initialise system... - ctx.core.SCB.enable_icache(); - // See Errata Sheet 2.2.1 - //ctx.core.SCB.enable_dcache(&mut ctx.core.CPUID); - ctx.core.DWT.enable_cycle_counter(); - - // Initialise IO... - let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD); - let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE); - let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF); - let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); - let gpioh = dp.GPIOH.split(ccdr.peripheral.GPIOH); - let gpioi = dp.GPIOI.split(ccdr.peripheral.GPIOI); - - // ---------------------------------------------------------- - // Configure MPU for external SDRAM - // MPU config for SDRAM write-through - let sdram_size = 32 * 1024 * 1024; - - { - let mpu = ctx.core.MPU; - let scb = &mut ctx.core.SCB; - let size = sdram_size; - // Refer to ARM®v7-M Architecture Reference Manual ARM DDI 0403 - // Version E.b Section B3.5 - const MEMFAULTENA: u32 = 1 << 16; - - unsafe { - /* Make sure outstanding transfers are done */ - cortex_m::asm::dmb(); - - scb.shcsr.modify(|r| r & !MEMFAULTENA); - - /* Disable the MPU and clear the control register*/ - mpu.ctrl.write(0); - } +#[entry] +fn main() -> ! { + let mut cp = cortex_m::Peripherals::take().unwrap(); + let dp = pac::Peripherals::take().unwrap(); + + // Initialise power... + let pwr = dp.PWR.constrain(); + let pwrcfg = example_power!(pwr).freeze(); + + // Initialise clocks... + let rcc = dp.RCC.constrain(); + let ccdr = rcc + .sys_ck(200.mhz()) + .hclk(200.mhz()) // FMC clock from HCLK by default + .freeze(pwrcfg, &dp.SYSCFG); + + // Get the delay provider. + let mut delay = cp.SYST.delay(ccdr.clocks); + + // Initialise system... + cp.SCB.enable_icache(); + // See Errata Sheet 2.2.1 + //cp.SCB.enable_dcache(&mut cp.CPUID); + cp.DWT.enable_cycle_counter(); + + // Initialise IO... + let gpiod = dp.GPIOD.split(ccdr.peripheral.GPIOD); + let gpioe = dp.GPIOE.split(ccdr.peripheral.GPIOE); + let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF); + let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG); + let gpioh = dp.GPIOH.split(ccdr.peripheral.GPIOH); + let gpioi = dp.GPIOI.split(ccdr.peripheral.GPIOI); + + // ---------------------------------------------------------- + // Configure MPU for external SDRAM + // MPU config for SDRAM write-through + let sdram_size = 32 * 1024 * 1024; + + { + let mpu = cp.MPU; + let scb = &mut cp.SCB; + let size = sdram_size; + // Refer to ARM®v7-M Architecture Reference Manual ARM DDI 0403 + // Version E.b Section B3.5 + const MEMFAULTENA: u32 = 1 << 16; + + unsafe { + /* Make sure outstanding transfers are done */ + cortex_m::asm::dmb(); + + scb.shcsr.modify(|r| r & !MEMFAULTENA); + + /* Disable the MPU and clear the control register*/ + mpu.ctrl.write(0); + } - const REGION_NUMBER0: u32 = 0x00; - const REGION_BASE_ADDRESS: u32 = 0xD000_0000; + const REGION_NUMBER0: u32 = 0x00; + const REGION_BASE_ADDRESS: u32 = 0xD000_0000; - const REGION_FULL_ACCESS: u32 = 0x03; - const REGION_CACHEABLE: u32 = 0x01; - const REGION_WRITE_BACK: u32 = 0x01; - const REGION_ENABLE: u32 = 0x01; + const REGION_FULL_ACCESS: u32 = 0x03; + const REGION_CACHEABLE: u32 = 0x01; + const REGION_WRITE_BACK: u32 = 0x01; + const REGION_ENABLE: u32 = 0x01; - assert_eq!( - size & (size - 1), - 0, - "SDRAM memory region size must be a power of 2" - ); - assert_eq!( - size & 0x1F, - 0, - "SDRAM memory region size must be 32 bytes or more" - ); - fn log2minus1(sz: u32) -> u32 { - for i in 5..=31 { - if sz == (1 << i) { - return i - 1; - } + assert_eq!( + size & (size - 1), + 0, + "SDRAM memory region size must be a power of 2" + ); + assert_eq!( + size & 0x1F, + 0, + "SDRAM memory region size must be 32 bytes or more" + ); + fn log2minus1(sz: u32) -> u32 { + for i in 5..=31 { + if sz == (1 << i) { + return i - 1; } - panic!("Unknown SDRAM memory region size!"); } + panic!("Unknown SDRAM memory region size!"); + } - //info!("SDRAM Memory Size 0x{:x}", log2minus1(size as u32)); - - // Configure region 0 - // - // Cacheable, outer and inner write-back, no write allocate. So - // reads are cached, but writes always write all the way to SDRAM - unsafe { - mpu.rnr.write(REGION_NUMBER0); - mpu.rbar.write(REGION_BASE_ADDRESS); - mpu.rasr.write( - (REGION_FULL_ACCESS << 24) - | (REGION_CACHEABLE << 17) - | (REGION_WRITE_BACK << 16) - | (log2minus1(size as u32) << 1) - | REGION_ENABLE, - ); - } + //info!("SDRAM Memory Size 0x{:x}", log2minus1(size as u32)); + + // Configure region 0 + // + // Cacheable, outer and inner write-back, no write allocate. So + // reads are cached, but writes always write all the way to SDRAM + unsafe { + mpu.rnr.write(REGION_NUMBER0); + mpu.rbar.write(REGION_BASE_ADDRESS); + mpu.rasr.write( + (REGION_FULL_ACCESS << 24) + | (REGION_CACHEABLE << 17) + | (REGION_WRITE_BACK << 16) + | (log2minus1(size as u32) << 1) + | REGION_ENABLE, + ); + } - const MPU_ENABLE: u32 = 0x01; - const MPU_DEFAULT_MMAP_FOR_PRIVILEGED: u32 = 0x04; + const MPU_ENABLE: u32 = 0x01; + const MPU_DEFAULT_MMAP_FOR_PRIVILEGED: u32 = 0x04; - // Enable - unsafe { - mpu.ctrl.modify(|r| { - r | MPU_DEFAULT_MMAP_FOR_PRIVILEGED | MPU_ENABLE - }); + // Enable + unsafe { + mpu.ctrl + .modify(|r| r | MPU_DEFAULT_MMAP_FOR_PRIVILEGED | MPU_ENABLE); - scb.shcsr.modify(|r| r | MEMFAULTENA); + scb.shcsr.modify(|r| r | MEMFAULTENA); - // Ensure MPU settings take effect - cortex_m::asm::dsb(); - cortex_m::asm::isb(); - } + // Ensure MPU settings take effect + cortex_m::asm::dsb(); + cortex_m::asm::isb(); } + } - // ---------------------------------------------------------- - // SDRAM - // Initialise SDRAM... - let sdram_pins = fmc_pins! { - // A0-A11 - gpiof.pf0, gpiof.pf1, gpiof.pf2, gpiof.pf3, - gpiof.pf4, gpiof.pf5, gpiof.pf12, gpiof.pf13, - gpiof.pf14, gpiof.pf15, gpiog.pg0, gpiog.pg1, - // BA0-BA1 - gpiog.pg4, gpiog.pg5, - // D0-D31 - gpiod.pd14, gpiod.pd15, gpiod.pd0, gpiod.pd1, - gpioe.pe7, gpioe.pe8, gpioe.pe9, gpioe.pe10, - gpioe.pe11, gpioe.pe12, gpioe.pe13, gpioe.pe14, - gpioe.pe15, gpiod.pd8, gpiod.pd9, gpiod.pd10, - gpioh.ph8, gpioh.ph9, gpioh.ph10, gpioh.ph11, - gpioh.ph12, gpioh.ph13, gpioh.ph14, gpioh.ph15, - gpioi.pi0, gpioi.pi1, gpioi.pi2, gpioi.pi3, - gpioi.pi6, gpioi.pi7, gpioi.pi9, gpioi.pi10, - // NBL0 - NBL3 - gpioe.pe0, gpioe.pe1, gpioi.pi4, gpioi.pi5, - gpioh.ph7, // SDCKE1 - gpiog.pg8, // SDCLK - gpiog.pg15, // SDNCAS - gpioh.ph6, // SDNE1 (!CS) - gpiof.pf11, // SDRAS - gpioh.ph5 // SDNWE - }; - - let mut sdram = dp.FMC.sdram( - sdram_pins, - is42s32800g_6::Is42s32800g {}, - ccdr.peripheral.FMC, - &ccdr.clocks, - ); + // ---------------------------------------------------------- + // SDRAM + // Initialise SDRAM... + let sdram_pins = fmc_pins! { + // A0-A11 + gpiof.pf0, gpiof.pf1, gpiof.pf2, gpiof.pf3, + gpiof.pf4, gpiof.pf5, gpiof.pf12, gpiof.pf13, + gpiof.pf14, gpiof.pf15, gpiog.pg0, gpiog.pg1, + // BA0-BA1 + gpiog.pg4, gpiog.pg5, + // D0-D31 + gpiod.pd14, gpiod.pd15, gpiod.pd0, gpiod.pd1, + gpioe.pe7, gpioe.pe8, gpioe.pe9, gpioe.pe10, + gpioe.pe11, gpioe.pe12, gpioe.pe13, gpioe.pe14, + gpioe.pe15, gpiod.pd8, gpiod.pd9, gpiod.pd10, + gpioh.ph8, gpioh.ph9, gpioh.ph10, gpioh.ph11, + gpioh.ph12, gpioh.ph13, gpioh.ph14, gpioh.ph15, + gpioi.pi0, gpioi.pi1, gpioi.pi2, gpioi.pi3, + gpioi.pi6, gpioi.pi7, gpioi.pi9, gpioi.pi10, + // NBL0 - NBL3 + gpioe.pe0, gpioe.pe1, gpioi.pi4, gpioi.pi5, + gpioh.ph7, // SDCKE1 + gpiog.pg8, // SDCLK + gpiog.pg15, // SDNCAS + gpioh.ph6, // SDNE1 (!CS) + gpiof.pf11, // SDRAS + gpioh.ph5 // SDNWE + }; - let ram_slice = unsafe { - // Initialise controller and SDRAM - let ram_ptr: *mut u32 = sdram.init(&mut delay); + let mut sdram = dp.FMC.sdram( + sdram_pins, + is42s32800g_6::Is42s32800g {}, + ccdr.peripheral.FMC, + &ccdr.clocks, + ); - // Get 16-bit words - let ram_ptr = ram_ptr as *mut u16; + let ram_slice = unsafe { + // Initialise controller and SDRAM + let ram_ptr: *mut u32 = sdram.init(&mut delay); - // Convert raw pointer to slice - let ram_slice = slice::from_raw_parts_mut(ram_ptr, sdram_size); + // Get 16-bit words + let ram_ptr = ram_ptr as *mut u16; - // Return a 4-word slice - let size = mem::size_of::() * 4usize; - let mut chunks = ram_slice.chunks_exact_mut(size); - chunks.next().unwrap() - }; + // Convert raw pointer to slice + let ram_slice = slice::from_raw_parts_mut(ram_ptr, sdram_size); - // ---------------------------------------------------------- - // Use memory in SDRAM + // Return a 4-word slice + let size = mem::size_of::() * 4usize; + let mut chunks = ram_slice.chunks_exact_mut(size); + chunks.next().unwrap() + }; - ram_slice[0] = 1u16; - ram_slice[1] = 2; - ram_slice[2] = 3; - ram_slice[3] = 4; + // ---------------------------------------------------------- + // Use memory in SDRAM - assert_eq!(ram_slice[0], 1); + ram_slice[0] = 1u16; + ram_slice[1] = 2; + ram_slice[2] = 3; + ram_slice[3] = 4; - loop { - cortex_m::asm::nop() - } + assert_eq!(ram_slice[0], 1); + + loop { + cortex_m::asm::nop() } -}; +} diff --git a/examples/rtic.rs b/examples/rtic.rs index 4d2316a0..7b0d073d 100644 --- a/examples/rtic.rs +++ b/examples/rtic.rs @@ -3,31 +3,32 @@ #![no_std] #![no_main] -extern crate rtic; - -use stm32h7xx_hal::hal::digital::v2::ToggleableOutputPin; - -use rtic::app; -use stm32h7xx_hal::gpio::gpioc::{PC13, PC3}; -use stm32h7xx_hal::gpio::{Edge, ExtiPin, Floating, Input}; -use stm32h7xx_hal::gpio::{Output, PushPull}; -use stm32h7xx_hal::prelude::*; - #[macro_use] -#[path = "utilities/power.rs"] -mod power; - -use panic_halt as _; - -#[app(device = stm32h7xx_hal::stm32, peripherals = true)] -const APP: () = { - struct Resources { +mod utilities; + +#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)] +mod app { + use stm32h7xx_hal::gpio::gpioc::{PC13, PC3}; + use stm32h7xx_hal::gpio::{Edge, ExtiPin, Floating, Input}; + use stm32h7xx_hal::gpio::{Output, PushPull}; + use stm32h7xx_hal::hal::digital::v2::ToggleableOutputPin; + use stm32h7xx_hal::prelude::*; + + use super::*; + + #[shared] + struct SharedResources {} + #[local] + struct LocalResources { button: PC13>, led: PC3>, } #[init] - fn init(mut ctx: init::Context) -> init::LateResources { + fn init( + mut ctx: init::Context, + ) -> (SharedResources, LocalResources, init::Monotonics) { + utilities::logger::init(); let pwr = ctx.device.PWR.constrain(); let pwrcfg = example_power!(pwr).freeze(); @@ -44,15 +45,19 @@ const APP: () = { button.trigger_on_edge(&mut ctx.device.EXTI, Edge::Rising); button.enable_interrupt(&mut ctx.device.EXTI); - init::LateResources { - button, - led: gpioc.pc3.into_push_pull_output(), - } + ( + SharedResources {}, + LocalResources { + button, + led: gpioc.pc3.into_push_pull_output(), + }, + init::Monotonics(), + ) } - #[task(binds = EXTI15_10, resources = [button, led])] + #[task(binds = EXTI15_10, local = [button, led])] fn button_click(ctx: button_click::Context) { - ctx.resources.button.clear_interrupt_pending_bit(); - ctx.resources.led.toggle().unwrap(); + ctx.local.button.clear_interrupt_pending_bit(); + ctx.local.led.toggle().unwrap(); } -}; +} diff --git a/examples/rtic_low_power.rs b/examples/rtic_low_power.rs index 8a618920..540ed3dd 100644 --- a/examples/rtic_low_power.rs +++ b/examples/rtic_low_power.rs @@ -19,22 +19,27 @@ #![no_std] #![no_main] -extern crate panic_itm; extern crate rtic; -use stm32h7xx_hal::hal::digital::v2::{OutputPin, ToggleableOutputPin}; - -use rtic::app; -use stm32h7xx_hal::gpio::gpioc::{PC2, PC3, PC4}; -use stm32h7xx_hal::gpio::{Edge, ExtiPin, Output, PushPull}; -use stm32h7xx_hal::prelude::*; -use stm32h7xx_hal::rcc::LowPowerMode; -use stm32h7xx_hal::stm32::{LPTIM3, TIM1, TIM2}; -use stm32h7xx_hal::timer::{Enabled, Event, LpTimer, Timer}; - -#[app(device = stm32h7xx_hal::stm32, peripherals = true)] -const APP: () = { - struct Resources { +#[macro_use] +mod utilities; + +#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)] +mod app { + use stm32h7xx_hal::gpio::gpioc::{PC2, PC3, PC4}; + use stm32h7xx_hal::gpio::{Edge, ExtiPin, Output, PushPull}; + use stm32h7xx_hal::hal::digital::v2::{OutputPin, ToggleableOutputPin}; + use stm32h7xx_hal::prelude::*; + use stm32h7xx_hal::rcc::LowPowerMode; + use stm32h7xx_hal::stm32::{LPTIM3, TIM1, TIM2}; + use stm32h7xx_hal::timer::{Enabled, Event, LpTimer, Timer}; + + use super::*; + + #[shared] + struct SharedResources {} + #[local] + struct LocalResources { led1: PC2>, led2: PC3>, led3: PC4>, @@ -44,7 +49,10 @@ const APP: () = { } #[init] - fn init(ctx: init::Context) -> init::LateResources { + fn init( + ctx: init::Context, + ) -> (SharedResources, LocalResources, init::Monotonics) { + utilities::logger::init(); let mut syscfg = ctx.device.SYSCFG; // Run D3 / SRD domain @@ -54,7 +62,7 @@ const APP: () = { ctx.device.PWR.cpucr.modify(|_, w| w.run_srd().set_bit()); let pwr = ctx.device.PWR.constrain(); - let vos = pwr.freeze(); + let vos = example_power!(pwr).freeze(); // RCC let rcc = ctx.device.RCC.constrain(); @@ -117,38 +125,42 @@ const APP: () = { led2.set_high().ok(); led3.set_high().ok(); - init::LateResources { - led1, - led2, - led3, - timer1, - timer2, - timer3, - } + ( + SharedResources {}, + LocalResources { + led1, + led2, + led3, + timer1, + timer2, + timer3, + }, + init::Monotonics(), + ) } // RTIC inserts a default idle loop that calls asm::wfi() - #[task(binds = EXTI15_10, resources = [], priority = 1)] + #[task(binds = EXTI15_10, local = [], priority = 1)] fn exti15_10_interrupt(_: exti15_10_interrupt::Context) { // Once the wakeup is triggered, we loop here forever } - #[task(binds = TIM1_UP, resources = [led1, timer1], priority = 2)] + #[task(binds = TIM1_UP, local = [led1, timer1], priority = 2)] fn timer1_tick(ctx: timer1_tick::Context) { - ctx.resources.timer1.clear_irq(); - ctx.resources.led1.toggle().unwrap(); + ctx.local.timer1.clear_irq(); + ctx.local.led1.toggle().unwrap(); } - #[task(binds = TIM2, resources = [led2, timer2], priority = 2)] + #[task(binds = TIM2, local = [led2, timer2], priority = 2)] fn timer2_tick(ctx: timer2_tick::Context) { - ctx.resources.timer2.clear_irq(); - ctx.resources.led2.toggle().unwrap(); + ctx.local.timer2.clear_irq(); + ctx.local.led2.toggle().unwrap(); } - #[task(binds = LPTIM3, resources = [led3, timer3], priority = 2)] + #[task(binds = LPTIM3, local = [led3, timer3], priority = 2)] fn timer3_tick(ctx: timer3_tick::Context) { - ctx.resources.timer3.clear_irq(); - ctx.resources.led3.toggle().unwrap(); + ctx.local.timer3.clear_irq(); + ctx.local.led3.toggle().unwrap(); } -}; +} diff --git a/examples/rtic_timers.rs b/examples/rtic_timers.rs index 5b843c40..65ab0b4f 100644 --- a/examples/rtic_timers.rs +++ b/examples/rtic_timers.rs @@ -4,26 +4,24 @@ #![no_std] #![no_main] -extern crate rtic; - -use stm32h7xx_hal::hal::digital::v2::ToggleableOutputPin; - -use rtic::app; -use stm32h7xx_hal::gpio::gpioi::{PI12, PI13, PI14, PI15}; -use stm32h7xx_hal::gpio::{Output, PushPull}; -use stm32h7xx_hal::prelude::*; -use stm32h7xx_hal::stm32::{TIM1, TIM12, TIM17, TIM2}; -use stm32h7xx_hal::timer::{Event, Timer}; - #[macro_use] -#[path = "utilities/power.rs"] -mod power; - -use panic_halt as _; - -#[app(device = stm32h7xx_hal::stm32, peripherals = true)] -const APP: () = { - struct Resources { +mod utilities; + +#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)] +mod app { + use stm32h7xx_hal::gpio::gpioi::{PI12, PI13, PI14, PI15}; + use stm32h7xx_hal::gpio::{Output, PushPull}; + use stm32h7xx_hal::hal::digital::v2::ToggleableOutputPin; + use stm32h7xx_hal::prelude::*; + use stm32h7xx_hal::stm32::{TIM1, TIM12, TIM17, TIM2}; + use stm32h7xx_hal::timer::{Event, Timer}; + + use super::*; + + #[shared] + struct SharedResources {} + #[local] + struct LocalResources { timer1: Timer, timer2: Timer, timer3: Timer, @@ -35,7 +33,10 @@ const APP: () = { } #[init] - fn init(ctx: init::Context) -> init::LateResources { + fn init( + ctx: init::Context, + ) -> (SharedResources, LocalResources, init::Monotonics) { + utilities::logger::init(); let pwr = ctx.device.PWR.constrain(); let pwrcfg = example_power!(pwr).freeze(); @@ -73,39 +74,43 @@ const APP: () = { // GPIO let gpioi = ctx.device.GPIOI.split(ccdr.peripheral.GPIOI); - init::LateResources { - timer1, - timer2, - timer3, - timer4, - led1: gpioi.pi12.into_push_pull_output(), - led2: gpioi.pi13.into_push_pull_output(), - led3: gpioi.pi14.into_push_pull_output(), - led4: gpioi.pi15.into_push_pull_output(), - } + ( + SharedResources {}, + LocalResources { + timer1, + timer2, + timer3, + timer4, + led1: gpioi.pi12.into_push_pull_output(), + led2: gpioi.pi13.into_push_pull_output(), + led3: gpioi.pi14.into_push_pull_output(), + led4: gpioi.pi15.into_push_pull_output(), + }, + init::Monotonics(), + ) } - #[task(binds = TIM1_UP, resources = [led1, timer1])] + #[task(binds = TIM1_UP, local = [led1, timer1])] fn timer1_tick(ctx: timer1_tick::Context) { - ctx.resources.timer1.clear_irq(); - ctx.resources.led1.toggle().unwrap(); + ctx.local.timer1.clear_irq(); + ctx.local.led1.toggle().unwrap(); } - #[task(binds = TIM2, resources = [led2, timer2])] + #[task(binds = TIM2, local = [led2, timer2])] fn timer2_tick(ctx: timer2_tick::Context) { - ctx.resources.timer2.clear_irq(); - ctx.resources.led2.toggle().unwrap(); + ctx.local.timer2.clear_irq(); + ctx.local.led2.toggle().unwrap(); } - #[task(binds = TIM8_BRK_TIM12, resources = [led3, timer3])] + #[task(binds = TIM8_BRK_TIM12, local = [led3, timer3])] fn timer3_tick(ctx: timer3_tick::Context) { - ctx.resources.timer3.clear_irq(); - ctx.resources.led3.toggle().unwrap(); + ctx.local.timer3.clear_irq(); + ctx.local.led3.toggle().unwrap(); } - #[task(binds = TIM17, resources = [led4, timer4])] + #[task(binds = TIM17, local = [led4, timer4])] fn timer4_tick(ctx: timer4_tick::Context) { - ctx.resources.timer4.clear_irq(); - ctx.resources.led4.toggle().unwrap(); + ctx.local.timer4.clear_irq(); + ctx.local.led4.toggle().unwrap(); } -}; +} diff --git a/examples/sai-i2s-passthru.rs b/examples/sai-i2s-passthru.rs index 6bf14954..9c5d91e3 100644 --- a/examples/sai-i2s-passthru.rs +++ b/examples/sai-i2s-passthru.rs @@ -1,50 +1,53 @@ // This demo code runs on the Electro Smith Daisy Seed board // https://www.electro-smith.com/daisy -#![allow(unused_macros)] #![deny(warnings)] -// #![deny(unsafe_code)] +#![deny(unsafe_code)] #![no_main] #![no_std] -use rtic::app; - -use cortex_m::asm::nop; - -use cortex_m::asm::delay as delay_cycles; - -pub use stm32h7xx_hal::hal::digital::v2::OutputPin; -use stm32h7xx_hal::prelude::*; -use stm32h7xx_hal::rcc::rec::Sai1ClkSel; -use stm32h7xx_hal::sai::{ - self, I2SChanConfig, I2SDataSize, I2SDir, I2SSync, I2sUsers, Sai, - SaiChannel, SaiI2sExt, I2S, -}; -use stm32h7xx_hal::stm32; -use stm32h7xx_hal::time::{Hertz, U32Ext}; - -use stm32h7xx_hal::traits::i2s::FullDuplex; - #[macro_use] mod utilities; -use log::info; +use stm32h7xx_hal::time::Hertz; pub const AUDIO_SAMPLE_HZ: Hertz = Hertz(48_000); // Using PLL3_P for SAI1 clock // The rate should be equal to sample rate * 256 // But not less than so targetting 257 const PLL3_P_HZ: Hertz = Hertz(AUDIO_SAMPLE_HZ.0 * 257); -#[app( device = stm32h7xx_hal::stm32, peripherals = true )] -const APP: () = { - struct Resources { +#[rtic::app( device = stm32h7xx_hal::stm32, peripherals = true )] +mod app { + use cortex_m::asm::delay as delay_cycles; + use cortex_m::asm::nop; + + use stm32h7xx_hal::hal::digital::v2::OutputPin; + use stm32h7xx_hal::prelude::*; + use stm32h7xx_hal::rcc::rec::Sai1ClkSel; + use stm32h7xx_hal::sai::{ + self, I2SChanConfig, I2SDataSize, I2SDir, I2SSync, I2sUsers, Sai, + SaiChannel, SaiI2sExt, I2S, + }; + use stm32h7xx_hal::traits::i2s::FullDuplex; + use stm32h7xx_hal::{stm32, time::U32Ext}; + + use super::*; + use log::info; + + #[shared] + struct SharedResources { + #[lock_free] audio: Sai, } + #[local] + struct LocalResources {} #[init] - fn init(mut ctx: init::Context) -> init::LateResources { + fn init( + mut ctx: init::Context, + ) -> (SharedResources, LocalResources, init::Monotonics) { utilities::logger::init(); let pwr = ctx.device.PWR.constrain(); - let vos = pwr.freeze(); + let vos = example_power!(pwr).freeze(); // Clocks let ccdr = ctx @@ -110,13 +113,17 @@ const APP: () = { audio.try_send(0, 0).unwrap(); info!("Startup complete!"); - init::LateResources { audio } + ( + SharedResources { audio }, + LocalResources {}, + init::Monotonics(), + ) } - #[task( binds = SAI1, resources = [audio] )] + #[task(binds = SAI1, shared = [audio] )] fn passthru(ctx: passthru::Context) { - if let Ok((left, right)) = ctx.resources.audio.try_read() { - ctx.resources.audio.try_send(left, right).unwrap(); + if let Ok((left, right)) = ctx.shared.audio.try_read() { + ctx.shared.audio.try_send(left, right).unwrap(); } } @@ -127,4 +134,4 @@ const APP: () = { nop(); } } -}; +} diff --git a/examples/spi-dma-rtic.rs b/examples/spi-dma-rtic.rs index 17550a47..c208bf5f 100644 --- a/examples/spi-dma-rtic.rs +++ b/examples/spi-dma-rtic.rs @@ -9,16 +9,9 @@ use core::mem::MaybeUninit; -use embedded_hal::digital::v2::OutputPin; -use rtic::app; - #[macro_use] -#[allow(unused)] mod utilities; -use hal::prelude::*; -use stm32h7xx_hal as hal; - // The number of bytes to transfer. const BUFFER_SIZE: usize = 100; @@ -30,9 +23,16 @@ const BUFFER_SIZE: usize = 100; #[link_section = ".axisram.buffers"] static mut BUFFER: MaybeUninit<[u8; BUFFER_SIZE]> = MaybeUninit::uninit(); -#[app(device = stm32h7xx_hal::stm32, peripherals = true)] -const APP: () = { - struct Resources { +#[rtic::app(device = stm32h7xx_hal::stm32, peripherals = true)] +mod app { + use embedded_hal::digital::v2::OutputPin; + use hal::prelude::*; + use stm32h7xx_hal as hal; + + use super::*; + + #[shared] + struct SharedResources { cs: hal::gpio::gpiob::PB12>, transfer: hal::dma::Transfer< hal::dma::dma::Stream1, @@ -43,8 +43,12 @@ const APP: () = { >, } + #[local] + struct LocalResources {} #[init] - fn init(ctx: init::Context) -> init::LateResources { + fn init( + ctx: init::Context, + ) -> (SharedResources, LocalResources, init::Monotonics) { utilities::logger::init(); // Initialise power... @@ -129,27 +133,35 @@ const APP: () = { _, > = hal::dma::Transfer::init(streams.1, spi, buffer, None, config); - init::LateResources { cs, transfer } + ( + SharedResources { cs, transfer }, + LocalResources {}, + init::Monotonics(), + ) } - #[task(binds=DMA1_STR1, resources=[transfer, cs], priority=2)] + #[task(binds=DMA1_STR1, shared = [transfer, cs], priority=2)] fn dma_complete(mut ctx: dma_complete::Context) { // If desired, the transfer can scheduled again here to continue transmitting. - let cs = &mut ctx.resources.cs; - ctx.resources.transfer.clear_transfer_complete_interrupt(); - ctx.resources.transfer.pause(|spi| { - // At this point, the DMA transfer is done, but the data is still in the SPI output - // FIFO. Wait for it to complete before disabling CS. - while spi.inner().sr.read().txc().bit_is_clear() {} - cs.set_high().unwrap(); + let mut cs = ctx.shared.cs; + ctx.shared.transfer.lock(|transfer| { + cs.lock(|cs| { + transfer.clear_transfer_complete_interrupt(); + transfer.pause(|spi| { + // At this point, the DMA transfer is done, but the data is still in the SPI output + // FIFO. Wait for it to complete before disabling CS. + while spi.inner().sr.read().txc().bit_is_clear() {} + cs.set_high().unwrap(); + }); + }); }); } - #[idle(resources=[transfer, cs])] + #[idle(shared = [transfer, cs])] fn idle(mut ctx: idle::Context) -> ! { // Start the DMA transfer over SPI. - let mut cs = ctx.resources.cs; - ctx.resources.transfer.lock(|transfer| { + let mut cs = ctx.shared.cs; + ctx.shared.transfer.lock(|transfer| { cs.lock(|cs| { transfer.start(|spi| { // Set CS low for the transfer. @@ -169,4 +181,4 @@ const APP: () = { cortex_m::asm::nop(); } } -}; +} From 303a0b9fe571d54c5ac8a949ee2b8a7335e69ab7 Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Mon, 27 Dec 2021 20:33:33 +0100 Subject: [PATCH 2/3] Allow unsafe with log-itm feature flag for examples Whilst still allowing #![deny(unsafe_code)] in the examples themselves --- examples/utilities/logger.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/utilities/logger.rs b/examples/utilities/logger.rs index 164e03cf..746d24d2 100644 --- a/examples/utilities/logger.rs +++ b/examples/utilities/logger.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "log-itm", allow(unsafe_code))] + cfg_if::cfg_if! { if #[cfg(any(feature = "log-itm"))] { use panic_itm as _; From 660ea7af80ca59530f2d323fc414a5bacf2d3ef5 Mon Sep 17 00:00:00 2001 From: Richard Meadows <962920+richardeoin@users.noreply.github.com> Date: Mon, 3 Jan 2022 22:24:43 +0100 Subject: [PATCH 3/3] Tidy nested lock calls --- examples/spi-dma-rtic.rs | 46 +++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/examples/spi-dma-rtic.rs b/examples/spi-dma-rtic.rs index c208bf5f..8eb02e7d 100644 --- a/examples/spi-dma-rtic.rs +++ b/examples/spi-dma-rtic.rs @@ -141,39 +141,33 @@ mod app { } #[task(binds=DMA1_STR1, shared = [transfer, cs], priority=2)] - fn dma_complete(mut ctx: dma_complete::Context) { + fn dma_complete(ctx: dma_complete::Context) { // If desired, the transfer can scheduled again here to continue transmitting. - let mut cs = ctx.shared.cs; - ctx.shared.transfer.lock(|transfer| { - cs.lock(|cs| { - transfer.clear_transfer_complete_interrupt(); - transfer.pause(|spi| { - // At this point, the DMA transfer is done, but the data is still in the SPI output - // FIFO. Wait for it to complete before disabling CS. - while spi.inner().sr.read().txc().bit_is_clear() {} - cs.set_high().unwrap(); - }); + (ctx.shared.transfer, ctx.shared.cs).lock(|transfer, cs| { + transfer.clear_transfer_complete_interrupt(); + transfer.pause(|spi| { + // At this point, the DMA transfer is done, but the data is still in the SPI output + // FIFO. Wait for it to complete before disabling CS. + while spi.inner().sr.read().txc().bit_is_clear() {} + cs.set_high().unwrap(); }); }); } #[idle(shared = [transfer, cs])] - fn idle(mut ctx: idle::Context) -> ! { + fn idle(ctx: idle::Context) -> ! { // Start the DMA transfer over SPI. - let mut cs = ctx.shared.cs; - ctx.shared.transfer.lock(|transfer| { - cs.lock(|cs| { - transfer.start(|spi| { - // Set CS low for the transfer. - cs.set_low().unwrap(); - - // Enable TX DMA support, enable the SPI peripheral, and start the transaction. - spi.enable_dma_tx(); - spi.inner_mut().cr1.modify(|_, w| w.spe().enabled()); - spi.inner_mut().cr1.modify(|_, w| w.cstart().started()); - - // The transaction immediately begins as the TX FIFO is now being filled by DMA. - }); + (ctx.shared.transfer, ctx.shared.cs).lock(|transfer, cs| { + transfer.start(|spi| { + // Set CS low for the transfer. + cs.set_low().unwrap(); + + // Enable TX DMA support, enable the SPI peripheral, and start the transaction. + spi.enable_dma_tx(); + spi.inner_mut().cr1.modify(|_, w| w.spe().enabled()); + spi.inner_mut().cr1.modify(|_, w| w.cstart().started()); + + // The transaction immediately begins as the TX FIFO is now being filled by DMA. }); });