From cf75bbcfb8c8010968328b51a939dd7313fc50b7 Mon Sep 17 00:00:00 2001 From: "Matthew W. Samsonoff" Date: Mon, 19 Apr 2021 13:01:18 -0400 Subject: Fix AIRCR PRIGROUP mask --- src/peripheral/scb.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index b619328..a9fb7c0 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -832,7 +832,7 @@ impl SCB { } const SCB_AIRCR_VECTKEY: u32 = 0x05FA << 16; -const SCB_AIRCR_PRIGROUP_MASK: u32 = 0x5 << 8; +const SCB_AIRCR_PRIGROUP_MASK: u32 = 0x7 << 8; const SCB_AIRCR_SYSRESETREQ: u32 = 1 << 2; impl SCB { -- cgit v1.2.3 From cf5dbcd90229a33fd6a2cedd3069cf66625d297f Mon Sep 17 00:00:00 2001 From: David O'Connor Date: Sat, 12 Jun 2021 16:03:48 -0400 Subject: Remove dependence on embedded-hal for Delay --- src/delay.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/delay.rs b/src/delay.rs index 2f5b8e0..8d3e00c 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -29,7 +29,8 @@ impl Delay { self.syst } - fn _delay_us(&mut self, us: u32) { + /// Delay using the Cortex-M systick for a certain duration, µs. + pub fn delay_us(&mut self, us: u32) { let ticks = (us as u64) * (self.ahb_frequency as u64) / 1_000_000; let full_cycles = ticks >> 24; @@ -54,6 +55,11 @@ impl Delay { self.syst.disable_counter(); } + + /// Delay using the Cortex-M systick for a certain duration, ms. + pub fn delay_ms(&mut self, ms: u32) { + self.delay_us(ms * 1_000); + } } impl DelayMs for Delay { @@ -61,10 +67,10 @@ impl DelayMs for Delay { fn delay_ms(&mut self, mut ms: u32) { // 4294967 is the highest u32 value which you can multiply by 1000 without overflow while ms > 4294967 { - self.delay_us(4294967000u32); + Delay::delay_us(self, 4294967000u32); ms -= 4294967; } - self.delay_us(ms * 1_000); + Delay::delay_us(self, ms * 1_000); } } @@ -73,28 +79,28 @@ impl DelayMs for Delay { #[inline(always)] fn delay_ms(&mut self, ms: i32) { assert!(ms >= 0); - self.delay_ms(ms as u32); + Delay::delay_ms(self, ms as u32); } } impl DelayMs for Delay { #[inline(always)] fn delay_ms(&mut self, ms: u16) { - self.delay_ms(u32::from(ms)); + Delay::delay_ms(self, u32::from(ms)); } } impl DelayMs for Delay { #[inline(always)] fn delay_ms(&mut self, ms: u8) { - self.delay_ms(u32::from(ms)); + Delay::delay_ms(self, u32::from(ms)); } } impl DelayUs for Delay { #[inline] fn delay_us(&mut self, us: u32) { - self._delay_us(us); + Delay::delay_us(self, us); } } @@ -103,20 +109,20 @@ impl DelayUs for Delay { #[inline(always)] fn delay_us(&mut self, us: i32) { assert!(us >= 0); - self.delay_us(us as u32); + Delay::delay_us(self, us as u32); } } impl DelayUs for Delay { #[inline(always)] fn delay_us(&mut self, us: u16) { - self.delay_us(u32::from(us)) + Delay::delay_us(self, u32::from(us)) } } impl DelayUs for Delay { #[inline(always)] fn delay_us(&mut self, us: u8) { - self.delay_us(u32::from(us)) + Delay::delay_us(self, u32::from(us)) } } -- cgit v1.2.3 From 1a2b6eaaf65e09688a16e00c4ccd1ad1c9c32a70 Mon Sep 17 00:00:00 2001 From: David O'Connor Date: Sat, 12 Jun 2021 16:17:48 -0400 Subject: Use overflow-workaround on delay_ms --- src/delay.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/delay.rs b/src/delay.rs index 8d3e00c..17dc654 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -30,6 +30,7 @@ impl Delay { } /// Delay using the Cortex-M systick for a certain duration, µs. + #[inline] pub fn delay_us(&mut self, us: u32) { let ticks = (us as u64) * (self.ahb_frequency as u64) / 1_000_000; @@ -57,14 +58,8 @@ impl Delay { } /// Delay using the Cortex-M systick for a certain duration, ms. - pub fn delay_ms(&mut self, ms: u32) { - self.delay_us(ms * 1_000); - } -} - -impl DelayMs for Delay { #[inline] - fn delay_ms(&mut self, mut ms: u32) { + pub fn delay_ms(&mut self, mut ms: u32) { // 4294967 is the highest u32 value which you can multiply by 1000 without overflow while ms > 4294967 { Delay::delay_us(self, 4294967000u32); @@ -74,6 +69,13 @@ impl DelayMs for Delay { } } +impl DelayMs for Delay { + #[inline] + fn delay_ms(&mut self, ms: u32) { + Delay::delay_ms(self, ms); + } +} + // This is a workaround to allow `delay_ms(42)` construction without specifying a type. impl DelayMs for Delay { #[inline(always)] -- cgit v1.2.3 From d13ebd2015b7a0326934d75fd04df5a4cba1f0a6 Mon Sep 17 00:00:00 2001 From: David O'Connor Date: Sat, 12 Jun 2021 16:20:01 -0400 Subject: Use . syntax instead of :: on delay_ms --- src/delay.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/delay.rs b/src/delay.rs index 17dc654..6f65363 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -29,7 +29,7 @@ impl Delay { self.syst } - /// Delay using the Cortex-M systick for a certain duration, µs. + /// Delay using the Cortex-M systick for a certain duration, in µs. #[inline] pub fn delay_us(&mut self, us: u32) { let ticks = (us as u64) * (self.ahb_frequency as u64) / 1_000_000; @@ -57,15 +57,15 @@ impl Delay { self.syst.disable_counter(); } - /// Delay using the Cortex-M systick for a certain duration, ms. + /// Delay using the Cortex-M systick for a certain duration, in ms. #[inline] pub fn delay_ms(&mut self, mut ms: u32) { // 4294967 is the highest u32 value which you can multiply by 1000 without overflow while ms > 4294967 { - Delay::delay_us(self, 4294967000u32); + self.delay_us(4294967000u32); ms -= 4294967; } - Delay::delay_us(self, ms * 1_000); + self.delay_us(ms * 1_000); } } -- cgit v1.2.3 From 7329f5710843ca70f1fc2f0266c11805e98db870 Mon Sep 17 00:00:00 2001 From: David O'Connor Date: Sat, 12 Jun 2021 16:23:25 -0400 Subject: remove inline on delay_us, and made u32 conversion syntax consistent --- src/delay.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/delay.rs b/src/delay.rs index 6f65363..3785907 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -30,7 +30,6 @@ impl Delay { } /// Delay using the Cortex-M systick for a certain duration, in µs. - #[inline] pub fn delay_us(&mut self, us: u32) { let ticks = (us as u64) * (self.ahb_frequency as u64) / 1_000_000; @@ -88,14 +87,14 @@ impl DelayMs for Delay { impl DelayMs for Delay { #[inline(always)] fn delay_ms(&mut self, ms: u16) { - Delay::delay_ms(self, u32::from(ms)); + Delay::delay_ms(self, ms as u32); } } impl DelayMs for Delay { #[inline(always)] fn delay_ms(&mut self, ms: u8) { - Delay::delay_ms(self, u32::from(ms)); + Delay::delay_ms(self, ms as u32); } } @@ -118,13 +117,13 @@ impl DelayUs for Delay { impl DelayUs for Delay { #[inline(always)] fn delay_us(&mut self, us: u16) { - Delay::delay_us(self, u32::from(us)) + Delay::delay_us(self, us as u32) } } impl DelayUs for Delay { #[inline(always)] fn delay_us(&mut self, us: u8) { - Delay::delay_us(self, u32::from(us)) + Delay::delay_us(self, us as u32) } } -- cgit v1.2.3 From 81336573bc47ca12e115683cf2823fa397fdcc09 Mon Sep 17 00:00:00 2001 From: David O'Connor Date: Sat, 12 Jun 2021 16:40:24 -0400 Subject: Use from instead of as --- src/delay.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/delay.rs b/src/delay.rs index 3785907..750ded1 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -31,7 +31,7 @@ impl Delay { /// Delay using the Cortex-M systick for a certain duration, in µs. pub fn delay_us(&mut self, us: u32) { - let ticks = (us as u64) * (self.ahb_frequency as u64) / 1_000_000; + let ticks = (u64::from(us)) * (u64::from(self.ahb_frequency)) / 1_000_000; let full_cycles = ticks >> 24; if full_cycles > 0 { @@ -87,14 +87,14 @@ impl DelayMs for Delay { impl DelayMs for Delay { #[inline(always)] fn delay_ms(&mut self, ms: u16) { - Delay::delay_ms(self, ms as u32); + Delay::delay_ms(self, u32::from(ms)); } } impl DelayMs for Delay { #[inline(always)] fn delay_ms(&mut self, ms: u8) { - Delay::delay_ms(self, ms as u32); + Delay::delay_ms(self, u32::from(ms)); } } @@ -117,13 +117,13 @@ impl DelayUs for Delay { impl DelayUs for Delay { #[inline(always)] fn delay_us(&mut self, us: u16) { - Delay::delay_us(self, us as u32) + Delay::delay_us(self, u32::from(us)) } } impl DelayUs for Delay { #[inline(always)] fn delay_us(&mut self, us: u8) { - Delay::delay_us(self, us as u32) + Delay::delay_us(self, u32::from(us)) } } -- cgit v1.2.3 From 4a393e091b92d95754fb7c44562767e03d172ba5 Mon Sep 17 00:00:00 2001 From: David O'Connor Date: Sat, 12 Jun 2021 17:00:28 -0400 Subject: Update src/delay.rs Co-authored-by: Vadim Kaushan --- src/delay.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/delay.rs b/src/delay.rs index 750ded1..8ed1fea 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -30,6 +30,7 @@ impl Delay { } /// Delay using the Cortex-M systick for a certain duration, in µs. + #[allow(clippy::missing_inline_in_public_items)] pub fn delay_us(&mut self, us: u32) { let ticks = (u64::from(us)) * (u64::from(self.ahb_frequency)) / 1_000_000; -- cgit v1.2.3 From 7042622bfb844611c9cdbaf1196fa76362a32a6e Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Sun, 25 Jul 2021 12:09:57 -0700 Subject: Add pre-requisites for enabling the cycle counter to docs --- src/peripheral/dwt.rs | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 043223a..8e376a8 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -64,6 +64,13 @@ pub struct Comparator { impl DWT { /// Enables the cycle counter + /// + /// The global trace enable ([`DCB::enable_trace`]) should be set before + /// enabling the cycle counter, the processor may ignore writes to the + /// cycle counter enable if the global trace is disabled + /// (implementation defined behaviour). + /// + /// [`DCB::enable_trace`]: crate::peripheral::DCB::enable_trace #[cfg(not(armv6m))] #[inline] pub fn enable_cycle_counter(&mut self) { -- cgit v1.2.3 From 9ddc44c595a611e3da51a90453c19ad83fdf2bfb Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Thu, 5 Aug 2021 21:17:00 -0700 Subject: Fix slightly misleading examples. --- src/peripheral/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 961f31d..8155a8f 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -10,7 +10,7 @@ //! ``` no_run //! # use cortex_m::peripheral::Peripherals; //! let mut peripherals = Peripherals::take().unwrap(); -//! peripherals.DWT.enable_cycle_counter(); +//! peripherals.DCB.enable_trace(); //! ``` //! //! This method can only be successfully called *once* -- this is why the method returns an @@ -29,6 +29,7 @@ //! # use cortex_m::peripheral::{DWT, Peripherals}; //! { //! let mut peripherals = Peripherals::take().unwrap(); +//! peripherals.DCB.enable_trace(); //! peripherals.DWT.enable_cycle_counter(); //! } // all the peripheral singletons are destroyed here //! @@ -44,6 +45,7 @@ //! # use cortex_m::peripheral::{DWT, Peripherals}; //! { //! let mut peripherals = Peripherals::take().unwrap(); +//! peripherals.DCB.enable_trace(); //! peripherals.DWT.enable_cycle_counter(); //! } // all the peripheral singletons are destroyed here //! -- cgit v1.2.3 From 33a6b16b84b6fbe2cd9a82934d9e2837a7237b65 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Sun, 8 Aug 2021 14:04:28 -0700 Subject: Add support for additional DWT counters This adds support for these counters: * CPI counter * Exception overhead counter * LSU counter * Folded-instruction counter --- CHANGELOG.md | 7 +++ src/peripheral/dwt.rs | 155 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index a3f8211..84375bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added +- Added support for additional DWT counters (#349) + - CPI counter + - Exception overhead counter + - LSU counter + - Folded-instruction counter + ## [v0.7.3] - 2021-07-03 ### Fixed diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 8e376a8..961f6fd 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -62,7 +62,56 @@ pub struct Comparator { reserved: u32, } +// DWT CTRL register fields +const NUMCOMP_OFFSET: u32 = 28; +const NOTRCPKT: u32 = 1 << 27; +const NOEXTTRIG: u32 = 1 << 26; +const NOCYCCNT: u32 = 1 << 25; +const NOPRFCNT: u32 = 1 << 24; +const CYCCNTENA: u32 = 1 << 0; + impl DWT { + /// Number of comparators implemented + /// + /// A value of zero indicates no comparator support. + #[inline] + pub fn num_comp() -> u8 { + // NOTE(unsafe) atomic read with no side effects + unsafe { ((*Self::ptr()).ctrl.read() >> NUMCOMP_OFFSET) as u8 } + } + + /// Returns `true` if the the implementation supports sampling and exception tracing + #[cfg(not(armv6m))] + #[inline] + pub fn has_exception_trace() -> bool { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).ctrl.read() & NOTRCPKT == 0 } + } + + /// Returns `true` if the implementation includes external match signals + #[cfg(not(armv6m))] + #[inline] + pub fn has_external_match() -> bool { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).ctrl.read() & NOEXTTRIG == 0 } + } + + /// Returns `true` if the implementation supports a cycle counter + #[cfg(not(armv6m))] + #[inline] + pub fn has_cycle_counter() -> bool { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).ctrl.read() & NOCYCCNT == 0 } + } + + /// Returns `true` if the implementation the profiling counters + #[cfg(not(armv6m))] + #[inline] + pub fn has_profiling_counter() -> bool { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).ctrl.read() & NOPRFCNT == 0 } + } + /// Enables the cycle counter /// /// The global trace enable ([`DCB::enable_trace`]) should be set before @@ -74,7 +123,22 @@ impl DWT { #[cfg(not(armv6m))] #[inline] pub fn enable_cycle_counter(&mut self) { - unsafe { self.ctrl.modify(|r| r | 1) } + unsafe { self.ctrl.modify(|r| r | CYCCNTENA) } + } + + /// Disables the cycle counter + #[cfg(not(armv6m))] + #[inline] + pub fn disable_cycle_counter(&mut self) { + unsafe { self.ctrl.modify(|r| r & !CYCCNTENA) } + } + + /// Returns `true` if the cycle counter is enabled + #[cfg(not(armv6m))] + #[inline] + pub fn cycle_counter_enabled() -> bool { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).ctrl.read() & CYCCNTENA != 0 } } /// Returns the current clock cycle count @@ -94,4 +158,93 @@ impl DWT { // NOTE(unsafe) atomic write to a stateless, write-only register unsafe { (*Self::ptr()).lar.write(0xC5AC_CE55) } } + + /// Get the CPI count + /// + /// Counts additional cycles required to execute multi-cycle instructions, + /// except those recorded by [`lsu_count`], and counts any instruction fetch + /// stalls. + /// + /// [`lsu_count`]: DWT::lsu_count + #[cfg(not(armv6m))] + #[inline] + pub fn cpi_count() -> u8 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).cpicnt.read() as u8 } + } + + /// Set the CPI count + #[cfg(not(armv6m))] + #[inline] + pub fn set_cpi_count(&mut self, count: u8) { + unsafe { self.cpicnt.write(count as u32) } + } + + /// Get the total cycles spent in exception processing + #[cfg(not(armv6m))] + #[inline] + pub fn exception_count() -> u8 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).exccnt.read() as u8 } + } + + /// Set the exception count + #[cfg(not(armv6m))] + #[inline] + pub fn set_exception_count(&mut self, count: u8) { + unsafe { self.exccnt.write(count as u32) } + } + + /// Get the total number of cycles that the processor is sleeping + /// + /// ARM recommends that this counter counts all cycles when the processor is sleeping, + /// regardless of whether a WFI or WFE instruction, or the sleep-on-exit functionality, + /// caused the entry to sleep mode. + /// However, all sleep features are implementation defined and therefore when + /// this counter counts is implementation defined. + #[cfg(not(armv6m))] + #[inline] + pub fn sleep_count() -> u8 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).sleepcnt.read() as u8 } + } + + /// Set the sleep count + #[cfg(not(armv6m))] + #[inline] + pub fn set_sleep_count(&mut self, count: u8) { + unsafe { self.sleepcnt.write(count as u32) } + } + + /// Get the additional cycles required to execute all load or store instructions + #[cfg(not(armv6m))] + #[inline] + pub fn lsu_count() -> u8 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).lsucnt.read() as u8 } + } + + /// Set the lsu count + #[cfg(not(armv6m))] + #[inline] + pub fn set_lsu_count(&mut self, count: u8) { + unsafe { self.lsucnt.write(count as u32) } + } + + /// Get the folded instruction count + /// + /// Increments on each instruction that takes 0 cycles. + #[cfg(not(armv6m))] + #[inline] + pub fn fold_count() -> u8 { + // NOTE(unsafe) atomic read with no side effects + unsafe { (*Self::ptr()).foldcnt.read() as u8 } + } + + /// Set the folded instruction count + #[cfg(not(armv6m))] + #[inline] + pub fn set_fold_count(&mut self, count: u8) { + unsafe { self.foldcnt.write(count as u32) } + } } -- cgit v1.2.3 From 52ff95e1a8ea4e63f6dc7dd7029977481eabe501 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Sat, 14 Aug 2021 08:15:45 -0700 Subject: Deprecate get_cycle_count in favor of cycle_count This follows the rust C-GETTER API guidelines. --- src/peripheral/dwt.rs | 11 +++++++++++ src/peripheral/mod.rs | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 961f6fd..21af4f1 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -144,7 +144,18 @@ impl DWT { /// Returns the current clock cycle count #[cfg(not(armv6m))] #[inline] + #[deprecated( + since = "0.7.4", + note = "Use `cycle_count` which follows the C-GETTER convention" + )] pub fn get_cycle_count() -> u32 { + Self::cycle_count() + } + + /// Returns the current clock cycle count + #[cfg(not(armv6m))] + #[inline] + pub fn cycle_count() -> u32 { // NOTE(unsafe) atomic read with no side effects unsafe { (*Self::ptr()).cyccnt.read() } } diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 961f31d..8f5678d 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -23,7 +23,7 @@ //! ``` //! A part of the peripheral API doesn't require access to a peripheral instance. This part of the //! API is provided as static methods on the peripheral types. One example is the -//! [`DWT::get_cycle_count`](struct.DWT.html#method.get_cycle_count) method. +//! [`DWT::cycle_count`](struct.DWT.html#method.cycle_count) method. //! //! ``` no_run //! # use cortex_m::peripheral::{DWT, Peripherals}; @@ -33,7 +33,7 @@ //! } // all the peripheral singletons are destroyed here //! //! // but this method can be called without a DWT instance -//! let cyccnt = DWT::get_cycle_count(); +//! let cyccnt = DWT::cycle_count(); //! ``` //! //! The singleton property can be *unsafely* bypassed using the `ptr` static method which is -- cgit v1.2.3 From 52b895f715016083096363cc0059ff2e5338a603 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Thu, 5 Aug 2021 20:55:46 -0700 Subject: Add DWT.set_cycle_count --- CHANGELOG.md | 1 + src/peripheral/dwt.rs | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index 57d7dad..67b0a57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Exception overhead counter - LSU counter - Folded-instruction counter +- Added `DWT.set_cycle_count` (#347). ### Deprecated diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 21af4f1..9e8e638 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -160,6 +160,13 @@ impl DWT { unsafe { (*Self::ptr()).cyccnt.read() } } + /// Set the cycle count + #[cfg(not(armv6m))] + #[inline] + pub fn set_cycle_count(&mut self, count: u32) { + unsafe { self.cyccnt.write(count) } + } + /// Removes the software lock on the DWT /// /// Some devices, like the STM32F7, software lock the DWT after a power cycle. -- cgit v1.2.3 From f452f5a995c6ad38c299bd3c2b9ce649d09bf1b3 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Mon, 30 Aug 2021 15:12:35 -0700 Subject: Replace URL-relative doc links with intra-doc links --- src/peripheral/nvic.rs | 2 +- src/peripheral/scb.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/nvic.rs b/src/peripheral/nvic.rs index 4332707..f0c5457 100644 --- a/src/peripheral/nvic.rs +++ b/src/peripheral/nvic.rs @@ -210,7 +210,7 @@ impl NVIC { /// # Unsafety /// /// Changing priority levels can break priority-based critical sections (see - /// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety. + /// [`register::basepri`](crate::register::basepri)) and compromise memory safety. #[inline] pub unsafe fn set_priority(&mut self, interrupt: I, prio: u8) where diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index b619328..a2f309a 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -994,7 +994,7 @@ impl SCB { /// # Unsafety /// /// Changing priority levels can break priority-based critical sections (see - /// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety. + /// [`register::basepri`](crate::register::basepri)) and compromise memory safety. #[inline] pub unsafe fn set_priority(&mut self, system_handler: SystemHandler, prio: u8) { let index = system_handler as u8; -- cgit v1.2.3 From 7887d6d5415ab401d4ada96cc9ab44f35730da0b Mon Sep 17 00:00:00 2001 From: Ralph Loader Date: Sun, 5 Sep 2021 19:29:31 +1200 Subject: Add the Cortex-M7 TCM and cache access control registers. These registers appear to specific to the Cortex-M7, so add a feature gate "cm7". --- CHANGELOG.md | 2 ++ Cargo.toml | 3 +- src/peripheral/ac.rs | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/peripheral/mod.rs | 31 +++++++++++++++++ 4 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 src/peripheral/ac.rs (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index 67b0a57..2e7d1e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - LSU counter - Folded-instruction counter - Added `DWT.set_cycle_count` (#347). +- Added support for the Cortex-M7 TCM and cache access control registers. + There is a feature `cm7` to enable access to these. ### Deprecated diff --git a/Cargo.toml b/Cargo.toml index 26aad27..19aa249 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,8 @@ bitfield = "0.13.2" embedded-hal = "0.2.4" [features] -cm7-r0p1 = [] +cm7 = [] +cm7-r0p1 = ["cm7"] inline-asm = [] linker-plugin-lto = [] diff --git a/src/peripheral/ac.rs b/src/peripheral/ac.rs new file mode 100644 index 0000000..1ac5be1 --- /dev/null +++ b/src/peripheral/ac.rs @@ -0,0 +1,93 @@ +//! Cortex-M7 TCM and Cache access control. + +use volatile_register::RW; + +/// Register block +#[repr(C)] +pub struct RegisterBlock { + /// Instruction Tightly-Coupled Memory Control Register + pub itcmcr: RW, + /// Data Tightly-Coupled Memory Control Register + pub dtcmcr: RW, + /// AHBP Control Register + pub ahbpcr: RW, + /// L1 Cache Control Register + pub cacr: RW, + /// AHB Slave Control Register + pub ahbscr: RW, + reserved0: u32, + /// Auxilary Bus Fault Status Register + pub abfsr: RW, +} + +/// ITCMCR and DTCMCR TCM enable bit. +pub const TCM_EN: u32 = 1; + +/// ITCMCR and DTCMCR TCM read-modify-write bit. +pub const TCM_RMW: u32 = 2; + +/// ITCMCR and DTCMCR TCM rety phase enable bit. +pub const TCM_RETEN: u32 = 4; + +/// ITCMCR and DTCMCR TCM size mask. +pub const TCM_SZ_MASK: u32 = 0x78; + +/// ITCMCR and DTCMCR TCM shift. +pub const TCM_SZ_SHIFT: usize = 3; + +/// AHBPCR AHBP enable bit. +pub const AHBPCR_EN: u32 = 1; + +/// AHBPCR AHBP size mask. +pub const AHBPCR_SZ_MASK: u32 = 0x0e; + +/// AHBPCR AHBP size shit. +pub const AHBPCR_SZ_SHIFT: usize = 1; + +/// CACR Shared cachedable-is-WT for data cache. +pub const CACR_SIWT: u32 = 1; + +/// CACR ECC in the instruction and data cache (disable). +pub const CACR_ECCDIS: u32 = 2; + +/// CACR Force Write-Through in the data cache. +pub const CACR_FORCEWT: u32 = 4; + +/// AHBSCR AHBS prioritization control mask. +pub const AHBSCR_CTL_MASK: u32 = 0x03; + +/// AHBSCR AHBS prioritization control shift. +pub const AHBSCR_CTL_SHIFT: usize = 0; + +/// AHBSCR Threshold execution prioity for AHBS traffic demotion, mask. +pub const AHBSCR_TPRI_MASK: u32 = 0x7fc; + +/// AHBSCR Threshold execution prioity for AHBS traffic demotion, shift. +pub const AHBSCR_TPRI_SHIFT: usize = 2; + +/// AHBSCR Failness counter initialization value, mask. +pub const AHBSCR_INITCOUNT_MASK: u32 = 0xf800; + +/// AHBSCR Failness counter initialization value, shift. +pub const AHBSCR_INITCOUNT_SHIFT: usize = 11; + +/// ABFSR Async fault on ITCM interface. +pub const ABFSR_ITCM: u32 = 1; + +/// ABFSR Async fault on DTCM interface. +pub const ABFSR_DTCM: u32 = 2; + +/// ABFSR Async fault on AHBP interface. +pub const ABFSR_AHBP: u32 = 4; + +/// ABFSR Async fault on AXIM interface. +pub const ABFSR_AXIM: u32 = 8; + +/// ABFSR Async fault on EPPB interface. +pub const ABFSR_EPPB: u32 = 16; + +/// ABFSR Indicates the type of fault on the AXIM interface, mask. +pub const ABFSR_AXIMTYPE_MASK: u32 = 0x300; + +/// ABFSR Indicates the type of fault on the AXIM interface, shift. +pub const ABFSR_AXIMTYPE_SHIFT: usize = 8; diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 8f5678d..463a6ec 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -60,6 +60,8 @@ use core::ops; use crate::interrupt; +#[cfg(cm7)] +pub mod ac; #[cfg(not(armv6m))] pub mod cbp; pub mod cpuid; @@ -91,6 +93,10 @@ mod test; #[allow(non_snake_case)] #[allow(clippy::manual_non_exhaustive)] pub struct Peripherals { + /// Cortex-M7 TCM and cache access control. + #[cfg(cm7)] + pub AC: AC, + /// Cache and branch predictor maintenance operations. /// Not available on Armv6-M. pub CBP: CBP, @@ -172,6 +178,10 @@ impl Peripherals { TAKEN = true; Peripherals { + #[cfg(cm7)] + AC: AC { + _marker: PhantomData, + }, CBP: CBP { _marker: PhantomData, }, @@ -219,6 +229,27 @@ impl Peripherals { } } +/// Access control +#[cfg(cm7)] +pub struct AC { + _marker: PhantomData<*const ()>, +} + +#[cfg(cm7)] +unsafe impl Send for AC {} + +#[cfg(cm7)] +impl AC { + /// Pointer to the register block + pub const PTR: *const self::ac::RegisterBlock = 0xE000_EF90 as *const _; + + /// Returns a pointer to the register block (to be deprecated in 0.7) + #[inline(always)] + pub const fn ptr() -> *const self::ac::RegisterBlock { + Self::PTR + } +} + /// Cache and branch predictor maintenance operations pub struct CBP { _marker: PhantomData<*const ()>, -- cgit v1.2.3