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 720282fb8ee406a14c56f67ed1595c24133f7e5d Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 28 Apr 2021 18:23:03 +0200 Subject: tpiu: impl functions related to trace data output --- src/peripheral/tpiu.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'src') diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 11cb79e..ab8f710 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -4,6 +4,8 @@ use volatile_register::{RO, RW, WO}; +use crate::peripheral::TPIU; + /// Register block #[repr(C)] pub struct RegisterBlock { @@ -29,3 +31,71 @@ pub struct RegisterBlock { /// TPIU Type pub _type: RO, } + +/// The available protocols for the trace output. +pub enum TraceProtocol { + /// Parallel trace port mode + Parallel = 0b00, + /// Asynchronous SWO, using Manchester encoding + AsyncSWOManchester = 0b01, + /// Asynchronous SWO, using NRZ encoding + AsyncSWONRZ = 0b10, +} + +/// The SWO options supported by the TPIU. +#[allow(dead_code)] +pub struct SWOSupports { + /// Whether UART/NRZ encoding is supported for SWO. + nrz_encoding: bool, + /// Whether Manchester encoding is supported for SWO. + manchester_encoding: bool, + /// Whether parallel trace port operation is supported. + parallel_operation: bool, + /// The minimum implemented FIFO queue size of the TPIU for trace data. + min_queue_size: u8, +} + +impl TPIU { + /// Sets the prescaler value for a wanted baud rate of the Serial + /// Wire Output (SWO) in relation to a given asynchronous refernce + /// clock rate. + #[inline] + pub fn set_swo_baud_rate(&mut self, ref_clk_rate: u32, baud_rate: u32) { + unsafe { + self.acpr.write((ref_clk_rate / baud_rate) - 1); + } + } + + /// Sets the used protocol for the trace output. + #[inline] + pub fn set_trace_output_protocol(&mut self, proto: TraceProtocol) { + unsafe { self.sppr.write(proto as u32) } + } + + /// Whether to enable the formatter. If disabled, only ITM and DWT + /// trace sources are passed through. Data from the ETM is + /// discarded. + #[inline] + pub fn enable_continuous_formatting(&mut self, bit: bool) { + unsafe { + if bit { + self.ffcr.modify(|r| r | (1 << 1)); + } else { + self.ffcr.modify(|r| r & !(1 << 1)); + } + } + } + + /// Reads the supported trace output modes and the minimum size of + /// the TPIU FIFO queue for trace data. + #[inline] + pub fn get_swo_supports() -> SWOSupports { + let _type = unsafe { (*Self::ptr())._type.read() }; + SWOSupports { + nrz_encoding: (_type & (1 << 11)) == 1, // NRZVALID + manchester_encoding: (_type & (1 << 10)) == 1, // MANCVALID + parallel_operation: (_type & (1 << 9)) == 1, // PTINVALID + min_queue_size: (_type & (0b111 << 6)) as u8, // FIFOSZ + } + } +} -- cgit v1.2.3 From f75f17f764bded9a75475683ac12a55ed1925d67 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 28 Apr 2021 18:46:39 +0200 Subject: dwt: impl functions related to trace generation --- src/peripheral/dwt.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 043223a..4684f75 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -70,6 +70,34 @@ impl DWT { unsafe { self.ctrl.modify(|r| r | 1) } } + /// Whether to enable exception tracing + // TODO find out if this is supported om armv6m + #[inline] + pub fn enable_exception_tracing(&mut self, bit: bool) { + unsafe { + // EXCTRCENA + if bit { + self.ctrl.modify(|r| r | (1 << 16)); + } else { + self.ctrl.modify(|r| r & !(1 << 16)); + } + } + } + + /// Whether to periodically generate PC samples + // TODO find out if this is supported on armv6m + #[inline] + pub fn enable_pc_samples(&mut self, bit: bool) { + unsafe { + // PCSAMPLENA + if bit { + self.ctrl.modify(|r| r | (1 << 12)); + } else { + self.ctrl.modify(|r| r & !(1 << 12)); + } + } + } + /// Returns the current clock cycle count #[cfg(not(armv6m))] #[inline] -- cgit v1.2.3 From 8c53e6069b319d8d7e2c9b4a5bb58eba6dd31226 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 00:35:15 +0200 Subject: tpiu: fix always-zero field-comparison --- src/peripheral/tpiu.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index ab8f710..694204d 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -92,9 +92,9 @@ impl TPIU { pub fn get_swo_supports() -> SWOSupports { let _type = unsafe { (*Self::ptr())._type.read() }; SWOSupports { - nrz_encoding: (_type & (1 << 11)) == 1, // NRZVALID - manchester_encoding: (_type & (1 << 10)) == 1, // MANCVALID - parallel_operation: (_type & (1 << 9)) == 1, // PTINVALID + nrz_encoding: (_type & (1 << 11)) != 0, // NRZVALID + manchester_encoding: (_type & (1 << 10)) != 0, // MANCVALID + parallel_operation: (_type & (1 << 9)) != 0, // PTINVALID min_queue_size: (_type & (0b111 << 6)) as u8, // FIFOSZ } } -- cgit v1.2.3 From be983a3cb4c46646172e92a1b8abaf872faed58b Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 02:23:16 +0200 Subject: dwt: configure address comparison using struct --- src/peripheral/dwt.rs | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 4684f75..fd2c6d6 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -116,3 +116,146 @@ impl DWT { unsafe { (*Self::ptr()).lar.write(0xC5AC_CE55) } } } + +/// Whether the comparator should match on read, write or read/write operations. +#[derive(Debug, PartialEq)] +pub enum AccessType { + /// Generate packet only when matched adress is read from. + ReadOnly, + /// Generate packet only when matched adress is written to. + WriteOnly, + /// Generate packet when matched adress is both read from and written to. + ReadWrite, +} + +/// The sequence of packet(s) that should be emitted on comparator match. +#[derive(Debug, PartialEq)] +pub enum EmitOption { + /// Emit only trace data value packet. + Data, + /// Emit only trace address packet. + Address, + /// Emit only trace PC value packet + /// NOTE: only compatible with [AccessType::ReadWrite]. + PC, + /// Emit trace address and data value packets. + AddressData, + /// Emit trace PC value and data value packets. + PCData, +} + +/// Settings for address matching +#[derive(Debug)] +pub struct ComparatorAddressSettings { + /// The address to match against. + pub address: u32, + /// The address mask to match against. + pub mask: u32, + /// What sequence of packet(s) to emit on comparator match. + pub emit: EmitOption, + /// Whether to match on read, write or read/write operations. + pub access_type: AccessType, +} + +/// The available functions of a DWT comparator. +#[derive(Debug)] +pub enum ComparatorFunction { + /// Compare accessed memory addresses. + Address(ComparatorAddressSettings), +} + +/// Possible error values returned on [Comparator::configure]. +#[derive(Debug)] +pub enum DWTError { + /// Invalid combination of [AccessType] and [EmitOption]. + InvalidFunction, +} + +impl Comparator { + /// Configure the function of the comparator + pub fn configure(&mut self, settings: ComparatorFunction) -> Result<(), DWTError> { + match settings { + ComparatorFunction::Address(settings) => unsafe { + if settings.emit == EmitOption::PC && settings.access_type != AccessType::ReadWrite + { + return Err(DWTError::InvalidFunction); + } + + self.function.modify(|mut r| { + // clear DATAVMATCH; dont compare data value + r &= !(1 << 8); + + // clear CYCMATCH: dont compare cycle counter value + // NOTE: only needed for comparator 0, but is SBZP + r &= !(1 << 7); + + let mut set_function = |fun, emit_range| { + r &= u32::MAX << 4; // zero the FUNCTION field first + r |= fun; + + if emit_range { + r |= 1 << 5; + } else { + r &= !(1 << 5); + } + }; + + // FUNCTION, EMITRANGE + // See Table C1-14 + match (&settings.access_type, &settings.emit) { + (AccessType::ReadOnly, EmitOption::Data) => { + set_function(0b1100, false); + } + (AccessType::ReadOnly, EmitOption::Address) => { + set_function(0b1100, true); + } + (AccessType::ReadOnly, EmitOption::AddressData) => { + set_function(0b1110, true); + } + (AccessType::ReadOnly, EmitOption::PCData) => { + set_function(0b1110, false); + } + + (AccessType::WriteOnly, EmitOption::Data) => { + set_function(0b1101, false); + } + (AccessType::WriteOnly, EmitOption::Address) => { + set_function(0b1101, true); + } + (AccessType::WriteOnly, EmitOption::AddressData) => { + set_function(0b1111, true); + } + (AccessType::WriteOnly, EmitOption::PCData) => { + set_function(0b1111, false); + } + + (AccessType::ReadWrite, EmitOption::Data) => { + set_function(0b0010, false); + } + (AccessType::ReadWrite, EmitOption::Address) => { + set_function(0b0001, true); + } + (AccessType::ReadWrite, EmitOption::AddressData) => { + set_function(0b0010, true); + } + (AccessType::ReadWrite, EmitOption::PCData) => { + set_function(0b0011, false); + } + + (AccessType::ReadWrite, EmitOption::PC) => { + set_function(0b0001, false); + } + (_, EmitOption::PC) => unreachable!(), // cannot return Err here; handled above + } + + r + }); + + self.comp.write(settings.address); + self.mask.write(settings.mask); + }, + } + + Ok(()) + } +} -- cgit v1.2.3 From 930558078e32bff74c101e2f1725f4d94f8c6902 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 02:26:51 +0200 Subject: dwt: add missing #[inline] --- src/peripheral/dwt.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index fd2c6d6..77be0cc 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -173,6 +173,7 @@ pub enum DWTError { impl Comparator { /// Configure the function of the comparator + #[inline] pub fn configure(&mut self, settings: ComparatorFunction) -> Result<(), DWTError> { match settings { ComparatorFunction::Address(settings) => unsafe { -- cgit v1.2.3 From 9285dccd332e2f14f2dfa7c2eacda652717fc1e0 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 03:00:42 +0200 Subject: dcb: add note about vendor-specific trace options --- src/peripheral/dcb.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/peripheral/dcb.rs b/src/peripheral/dcb.rs index 5689cb4..056150b 100644 --- a/src/peripheral/dcb.rs +++ b/src/peripheral/dcb.rs @@ -25,6 +25,10 @@ impl DCB { /// `peripheral::DWT` cycle counter to work properly. /// As by STM documentation, this flag is not reset on /// soft-reset, only on power reset. + /// + /// Note: vendor-specific registers may have to be set to completely + /// enable tracing. For example, on the STM32F401RE, `TRACE_MODE` + /// and `TRACE_IOEN` must be configured in `DBGMCU_CR` register. #[inline] pub fn enable_trace(&mut self) { // set bit 24 / TRCENA -- cgit v1.2.3 From 859f9d848d4a0cb9ffcd36b8fec9f14e846921b2 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 12:38:57 +0200 Subject: dwt: reimplement with bitfield --- src/peripheral/dwt.rs | 141 +++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 76 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 77be0cc..84ea6a7 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -5,12 +5,13 @@ use volatile_register::WO; use volatile_register::{RO, RW}; use crate::peripheral::DWT; +use bitfield::bitfield; /// Register block #[repr(C)] pub struct RegisterBlock { /// Control - pub ctrl: RW, + pub ctrl: RW, /// Cycle Count #[cfg(not(armv6m))] pub cyccnt: RW, @@ -50,6 +51,16 @@ pub struct RegisterBlock { pub lsr: RO, } +bitfield! { + /// Control register. + #[repr(C)] + #[derive(Copy, Clone)] + pub struct Ctrl(u32); + get_cyccntena, set_cyccntena: 0; + get_pcsamplena, set_pcsamplena: 12; + get_exctrcena, set_exctrcena: 16; +} + /// Comparator #[repr(C)] pub struct Comparator { @@ -58,16 +69,33 @@ pub struct Comparator { /// Comparator Mask pub mask: RW, /// Comparator Function - pub function: RW, + pub function: RW, reserved: u32, } +bitfield! { + #[repr(C)] + #[derive(Copy, Clone)] + /// Comparator FUNCTIONn register. + pub struct Function(u32); + get_function, set_function: 3, 0; + get_emitrange, set_emitrange: 5; + get_cycmatch, set_cycmatch: 7; + get_datavmatch, set_datavmatch: 8; + get_matched, _: 24; +} + impl DWT { /// Enables the cycle counter #[cfg(not(armv6m))] #[inline] pub fn enable_cycle_counter(&mut self) { - unsafe { self.ctrl.modify(|r| r | 1) } + unsafe { + self.ctrl.modify(|mut r| { + r.set_cyccntena(true); + r + }); + } } /// Whether to enable exception tracing @@ -75,12 +103,10 @@ impl DWT { #[inline] pub fn enable_exception_tracing(&mut self, bit: bool) { unsafe { - // EXCTRCENA - if bit { - self.ctrl.modify(|r| r | (1 << 16)); - } else { - self.ctrl.modify(|r| r & !(1 << 16)); - } + self.ctrl.modify(|mut r| { + r.set_exctrcena(bit); + r + }); } } @@ -89,12 +115,10 @@ impl DWT { #[inline] pub fn enable_pc_samples(&mut self, bit: bool) { unsafe { - // PCSAMPLENA - if bit { - self.ctrl.modify(|r| r | (1 << 12)); - } else { - self.ctrl.modify(|r| r & !(1 << 12)); - } + self.ctrl.modify(|mut r| { + r.set_pcsamplena(bit); + r + }); } } @@ -174,7 +198,7 @@ pub enum DWTError { impl Comparator { /// Configure the function of the comparator #[inline] - pub fn configure(&mut self, settings: ComparatorFunction) -> Result<(), DWTError> { + pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DWTError> { match settings { ComparatorFunction::Address(settings) => unsafe { if settings.emit == EmitOption::PC && settings.access_type != AccessType::ReadWrite @@ -183,71 +207,36 @@ impl Comparator { } self.function.modify(|mut r| { - // clear DATAVMATCH; dont compare data value - r &= !(1 << 8); - - // clear CYCMATCH: dont compare cycle counter value - // NOTE: only needed for comparator 0, but is SBZP - r &= !(1 << 7); + // don't compare data value + r.set_datavmatch(false); - let mut set_function = |fun, emit_range| { - r &= u32::MAX << 4; // zero the FUNCTION field first - r |= fun; - - if emit_range { - r |= 1 << 5; - } else { - r &= !(1 << 5); - } - }; + // dont compare cycle counter value + // NOTE: only needed forp comparator 0, but is SBZP. + r.set_cycmatch(false); // FUNCTION, EMITRANGE // See Table C1-14 - match (&settings.access_type, &settings.emit) { - (AccessType::ReadOnly, EmitOption::Data) => { - set_function(0b1100, false); - } - (AccessType::ReadOnly, EmitOption::Address) => { - set_function(0b1100, true); - } - (AccessType::ReadOnly, EmitOption::AddressData) => { - set_function(0b1110, true); - } - (AccessType::ReadOnly, EmitOption::PCData) => { - set_function(0b1110, false); - } - - (AccessType::WriteOnly, EmitOption::Data) => { - set_function(0b1101, false); - } - (AccessType::WriteOnly, EmitOption::Address) => { - set_function(0b1101, true); - } - (AccessType::WriteOnly, EmitOption::AddressData) => { - set_function(0b1111, true); - } - (AccessType::WriteOnly, EmitOption::PCData) => { - set_function(0b1111, false); - } - - (AccessType::ReadWrite, EmitOption::Data) => { - set_function(0b0010, false); - } - (AccessType::ReadWrite, EmitOption::Address) => { - set_function(0b0001, true); - } - (AccessType::ReadWrite, EmitOption::AddressData) => { - set_function(0b0010, true); - } - (AccessType::ReadWrite, EmitOption::PCData) => { - set_function(0b0011, false); - } - - (AccessType::ReadWrite, EmitOption::PC) => { - set_function(0b0001, false); - } + let (function, emit_range) = match (&settings.access_type, &settings.emit) { + (AccessType::ReadOnly, EmitOption::Data) => (0b1100, false), + (AccessType::ReadOnly, EmitOption::Address) => (0b1100, true), + (AccessType::ReadOnly, EmitOption::AddressData) => (0b1110, true), + (AccessType::ReadOnly, EmitOption::PCData) => (0b1110, false), + + (AccessType::WriteOnly, EmitOption::Data) => (0b1101, false), + (AccessType::WriteOnly, EmitOption::Address) => (0b1101, true), + (AccessType::WriteOnly, EmitOption::AddressData) => (0b1111, true), + (AccessType::WriteOnly, EmitOption::PCData) => (0b1111, false), + + (AccessType::ReadWrite, EmitOption::Data) => (0b0010, false), + (AccessType::ReadWrite, EmitOption::Address) => (0b0001, true), + (AccessType::ReadWrite, EmitOption::AddressData) => (0b0010, true), + (AccessType::ReadWrite, EmitOption::PCData) => (0b0011, false), + + (AccessType::ReadWrite, EmitOption::PC) => (0b0001, false), (_, EmitOption::PC) => unreachable!(), // cannot return Err here; handled above - } + }; + r.set_function(function); + r.set_emitrange(emit_range); r }); -- cgit v1.2.3 From b533eb60c3a90d0eac38f142f942aaa1d3bd5256 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 13:15:35 +0200 Subject: itm: impl functions related to trace generation --- src/peripheral/itm.rs | 124 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index c0d560f..b23ce8e 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -7,6 +7,9 @@ use core::ptr; use volatile_register::{RO, RW, WO}; +use crate::peripheral::ITM; +use bitfield::bitfield; + /// Register block #[repr(C)] pub struct RegisterBlock { @@ -20,7 +23,7 @@ pub struct RegisterBlock { pub tpr: RW, reserved2: [u32; 15], /// Trace Control - pub tcr: RW, + pub tcr: RW, reserved3: [u32; 75], /// Lock Access pub lar: WO, @@ -28,6 +31,22 @@ pub struct RegisterBlock { pub lsr: RO, } +bitfield! { + /// Trace Control Register. + #[repr(C)] + #[derive(Copy, Clone)] + pub struct Tcr(u32); + get_itmena, set_itmena: 0; + get_tsena, set_tsena: 1; + get_syncena, set_synena: 2; + get_txena, set_txena: 3; + get_swoena, set_swoena: 4; + get_tsprescale, set_tsprecale: 9, 8; + get_gtsfreq, set_gtsfreq: 11, 10; + get_tracebusid, set_tracebusid: 22, 16; + busy, _: 23; +} + /// Stimulus Port pub struct Stim { register: UnsafeCell, @@ -69,3 +88,106 @@ impl Stim { unsafe { ptr::read_volatile(self.register.get()) & 0b11 != 0 } } } + +/// The possible local timestamp options. +#[derive(Debug, PartialEq)] +pub enum LocalTimestampOptions { + /// Disable local timestamps. + Disabled, + /// Enable local timestamps and use no prescaling. + Enabled, + /// Enable local timestamps and set the prescaler to divide the + /// reference clock by 4. + EnabledDiv4, + /// Enable local timestamps and set the prescaler to divide the + /// reference clock by 16. + EnabledDiv16, + /// Enable local timestamps and set the prescaler to divide the + /// reference clock by 64. + EnabledDiv64, +} + +/// The possible global timestamp options. +#[derive(Debug)] +pub enum GlobalTimestampOptions { + /// Disable global timestamps. + Disabled, + /// Generate a global timestamp approximately every 128 cycles. + Every128Cycles, + /// Generate a global timestamp approximately every 8921 cycles. + Every8192Cycles, + /// Generate a global timestamp after every packet, if the output FIFO is empty. + EveryPacket, +} + +/// The possible clock sources for timestamp counters. +#[derive(Debug)] +pub enum TimestampClkSrc { + /// Clock timestamp counters using the system processor clock. + SystemClock, + /// Clock timestamp counters using the asynchronous clock from the + /// TPIU interface. + /// + /// NOTE: The timestamp counter is held in reset while the output + /// line is idle. + AsyncTPIU, +} + +/// blah +#[derive(Debug)] +pub struct ITMSettings { + /// Whether to enable ITM. + pub enable: bool, + /// Whether DWT packets should be forwarded to ITM. + pub forward_dwt: bool, + /// The local timestamp options that should be applied. + pub local_timestamps: LocalTimestampOptions, + /// The global timestamp options that should be applied. + pub global_timestamps: GlobalTimestampOptions, + /// The trace bus ID to use when multi-trace sources are in use. + /// `None` specifies that only a single trace source is in use and + /// has the same effect as `Some(0)`. + pub bus_id: Option, + /// The clock that should increase timestamp counters. + pub timestamp_clk_src: TimestampClkSrc, +} + +impl ITM { + /// Removes the software lock on the ITM. + #[inline] + pub fn unlock(&mut self) { + // NOTE(unsafe) atomic write to a stateless, write-only register + unsafe { self.lar.write(0xC5AC_CE55) } + } + + /// Configures the ITM with the passed [ITMSettings]. + #[inline] + pub fn configure(&mut self, settings: ITMSettings) { + unsafe { + self.tcr.modify(|mut r| { + r.set_itmena(settings.enable); + r.set_tsena(settings.local_timestamps != LocalTimestampOptions::Disabled); + r.set_txena(settings.forward_dwt); + r.set_tsprecale(match settings.local_timestamps { + LocalTimestampOptions::Disabled | LocalTimestampOptions::Enabled => 0b00, + LocalTimestampOptions::EnabledDiv4 => 0b10, + LocalTimestampOptions::EnabledDiv16 => 0b10, + LocalTimestampOptions::EnabledDiv64 => 0b11, + }); + r.set_gtsfreq(match settings.global_timestamps { + GlobalTimestampOptions::Disabled => 0b00, + GlobalTimestampOptions::Every128Cycles => 0b01, + GlobalTimestampOptions::Every8192Cycles => 0b10, + GlobalTimestampOptions::EveryPacket => 0b11, + }); + r.set_swoena(match settings.timestamp_clk_src { + TimestampClkSrc::SystemClock => false, + TimestampClkSrc::AsyncTPIU => true, + }); + r.set_tracebusid(settings.bus_id.unwrap_or(0).into()); + + r + }); + } + } +} -- cgit v1.2.3 From fb604a76148f8756c3fe4d12458984024d80324d Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 13:27:44 +0200 Subject: tpiu: fix flipped SWOSupports field, reimplement with bitfield --- src/peripheral/tpiu.rs | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 694204d..5443fc0 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -5,6 +5,7 @@ use volatile_register::{RO, RW, WO}; use crate::peripheral::TPIU; +use bitfield::bitfield; /// Register block #[repr(C)] @@ -21,7 +22,7 @@ pub struct RegisterBlock { pub sppr: RW, reserved2: [u32; 132], /// Formatter and Flush Control - pub ffcr: RW, + pub ffcr: RW, reserved3: [u32; 810], /// Lock Access pub lar: WO, @@ -29,7 +30,26 @@ pub struct RegisterBlock { pub lsr: RO, reserved4: [u32; 4], /// TPIU Type - pub _type: RO, + pub _type: RO, +} + +bitfield! { + /// Formatter and flush control register. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Ffcr(u32); + get_enfcont, set_enfcont: 1; +} + +bitfield! { + /// Type Register. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Type(u32); + u8, fifosz, _: 8, 6; + ptinvalid, _: 9; + mancvalid, _: 10; + nrzvalid, _: 11; } /// The available protocols for the trace output. @@ -78,11 +98,10 @@ impl TPIU { #[inline] pub fn enable_continuous_formatting(&mut self, bit: bool) { unsafe { - if bit { - self.ffcr.modify(|r| r | (1 << 1)); - } else { - self.ffcr.modify(|r| r & !(1 << 1)); - } + self.ffcr.modify(|mut r| { + r.set_enfcont(bit); + r + }); } } @@ -92,10 +111,10 @@ impl TPIU { pub fn get_swo_supports() -> SWOSupports { let _type = unsafe { (*Self::ptr())._type.read() }; SWOSupports { - nrz_encoding: (_type & (1 << 11)) != 0, // NRZVALID - manchester_encoding: (_type & (1 << 10)) != 0, // MANCVALID - parallel_operation: (_type & (1 << 9)) != 0, // PTINVALID - min_queue_size: (_type & (0b111 << 6)) as u8, // FIFOSZ + nrz_encoding: _type.nrzvalid(), + manchester_encoding: _type.mancvalid(), + parallel_operation: !_type.ptinvalid(), + min_queue_size: _type.fifosz(), } } } -- cgit v1.2.3 From 085e738359d03c7a72ecb6e8c1b05c2ad27e982f Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 13:29:25 +0200 Subject: itm, dwt: limit some bitfields to u8 --- src/peripheral/dwt.rs | 2 +- src/peripheral/itm.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 84ea6a7..4097c8d 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -78,7 +78,7 @@ bitfield! { #[derive(Copy, Clone)] /// Comparator FUNCTIONn register. pub struct Function(u32); - get_function, set_function: 3, 0; + u8, get_function, set_function: 3, 0; get_emitrange, set_emitrange: 5; get_cycmatch, set_cycmatch: 7; get_datavmatch, set_datavmatch: 8; diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index b23ce8e..83d891f 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -41,9 +41,9 @@ bitfield! { get_syncena, set_synena: 2; get_txena, set_txena: 3; get_swoena, set_swoena: 4; - get_tsprescale, set_tsprecale: 9, 8; - get_gtsfreq, set_gtsfreq: 11, 10; - get_tracebusid, set_tracebusid: 22, 16; + u8, get_tsprescale, set_tsprecale: 9, 8; + u8, get_gtsfreq, set_gtsfreq: 11, 10; + u8, get_tracebusid, set_tracebusid: 22, 16; busy, _: 23; } -- 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 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 From 669c872a29921260e1e9f03f7592397c60fdbc07 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:41:35 +0200 Subject: dwt: feature gate trace and PC samples out of armv6m --- src/peripheral/dwt.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 4097c8d..57c9063 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -99,7 +99,7 @@ impl DWT { } /// Whether to enable exception tracing - // TODO find out if this is supported om armv6m + #[cfg(not(armv6m))] #[inline] pub fn enable_exception_tracing(&mut self, bit: bool) { unsafe { @@ -111,7 +111,7 @@ impl DWT { } /// Whether to periodically generate PC samples - // TODO find out if this is supported on armv6m + #[cfg(not(armv6m))] #[inline] pub fn enable_pc_samples(&mut self, bit: bool) { unsafe { @@ -210,8 +210,8 @@ impl Comparator { // don't compare data value r.set_datavmatch(false); - // dont compare cycle counter value - // NOTE: only needed forp comparator 0, but is SBZP. + // don't compare cycle counter value + // NOTE: only needed for comparator 0, but is SBZP. r.set_cycmatch(false); // FUNCTION, EMITRANGE -- cgit v1.2.3 From 362ad2df6034aea26f7f5d7fe6615e9b1436f997 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:42:29 +0200 Subject: itm: fix field spelling --- src/peripheral/itm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 83d891f..946f71c 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -41,7 +41,7 @@ bitfield! { get_syncena, set_synena: 2; get_txena, set_txena: 3; get_swoena, set_swoena: 4; - u8, get_tsprescale, set_tsprecale: 9, 8; + u8, get_tsprescale, set_tsprescale: 9, 8; u8, get_gtsfreq, set_gtsfreq: 11, 10; u8, get_tracebusid, set_tracebusid: 22, 16; busy, _: 23; @@ -168,7 +168,7 @@ impl ITM { r.set_itmena(settings.enable); r.set_tsena(settings.local_timestamps != LocalTimestampOptions::Disabled); r.set_txena(settings.forward_dwt); - r.set_tsprecale(match settings.local_timestamps { + r.set_tsprescale(match settings.local_timestamps { LocalTimestampOptions::Disabled | LocalTimestampOptions::Enabled => 0b00, LocalTimestampOptions::EnabledDiv4 => 0b10, LocalTimestampOptions::EnabledDiv16 => 0b10, -- cgit v1.2.3 From 02853a4f03f6028b8998fc8909d9b13306dd5d11 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:51:53 +0200 Subject: itm: remove useless conversion --- src/peripheral/itm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 946f71c..24b926d 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -184,7 +184,7 @@ impl ITM { TimestampClkSrc::SystemClock => false, TimestampClkSrc::AsyncTPIU => true, }); - r.set_tracebusid(settings.bus_id.unwrap_or(0).into()); + r.set_tracebusid(settings.bus_id.unwrap_or(0)); r }); -- cgit v1.2.3 From aa17958147ac57af6f10de170d869626397ba1d8 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:52:28 +0200 Subject: allow clippy::upper_case_acronyms --- src/peripheral/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 961f31d..7692f06 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -220,6 +220,7 @@ impl Peripherals { } /// Cache and branch predictor maintenance operations +#[allow(clippy::upper_case_acronyms)] pub struct CBP { _marker: PhantomData<*const ()>, } @@ -256,6 +257,7 @@ impl ops::Deref for CBP { } /// CPUID +#[allow(clippy::upper_case_acronyms)] pub struct CPUID { _marker: PhantomData<*const ()>, } @@ -283,6 +285,7 @@ impl ops::Deref for CPUID { } /// Debug Control Block +#[allow(clippy::upper_case_acronyms)] pub struct DCB { _marker: PhantomData<*const ()>, } @@ -310,6 +313,7 @@ impl ops::Deref for DCB { } /// Data Watchpoint and Trace unit +#[allow(clippy::upper_case_acronyms)] pub struct DWT { _marker: PhantomData<*const ()>, } @@ -337,6 +341,7 @@ impl ops::Deref for DWT { } /// Flash Patch and Breakpoint unit +#[allow(clippy::upper_case_acronyms)] pub struct FPB { _marker: PhantomData<*const ()>, } @@ -366,6 +371,7 @@ impl ops::Deref for FPB { } /// Floating Point Unit +#[allow(clippy::upper_case_acronyms)] pub struct FPU { _marker: PhantomData<*const ()>, } @@ -400,6 +406,7 @@ impl ops::Deref for FPU { /// `actlr`. It's called the "implementation control block" in the ARMv8-M /// standard, but earlier standards contained the registers, just without a /// name. +#[allow(clippy::upper_case_acronyms)] pub struct ICB { _marker: PhantomData<*const ()>, } @@ -434,6 +441,7 @@ impl ops::DerefMut for ICB { } /// Instrumentation Trace Macrocell +#[allow(clippy::upper_case_acronyms)] pub struct ITM { _marker: PhantomData<*const ()>, } @@ -471,6 +479,7 @@ impl ops::DerefMut for ITM { } /// Memory Protection Unit +#[allow(clippy::upper_case_acronyms)] pub struct MPU { _marker: PhantomData<*const ()>, } @@ -498,6 +507,7 @@ impl ops::Deref for MPU { } /// Nested Vector Interrupt Controller +#[allow(clippy::upper_case_acronyms)] pub struct NVIC { _marker: PhantomData<*const ()>, } @@ -525,6 +535,7 @@ impl ops::Deref for NVIC { } /// Security Attribution Unit +#[allow(clippy::upper_case_acronyms)] pub struct SAU { _marker: PhantomData<*const ()>, } @@ -554,6 +565,7 @@ impl ops::Deref for SAU { } /// System Control Block +#[allow(clippy::upper_case_acronyms)] pub struct SCB { _marker: PhantomData<*const ()>, } @@ -581,6 +593,7 @@ impl ops::Deref for SCB { } /// SysTick: System Timer +#[allow(clippy::upper_case_acronyms)] pub struct SYST { _marker: PhantomData<*const ()>, } @@ -608,6 +621,7 @@ impl ops::Deref for SYST { } /// Trace Port Interface Unit +#[allow(clippy::upper_case_acronyms)] pub struct TPIU { _marker: PhantomData<*const ()>, } -- cgit v1.2.3 From 0b4b0328f061ecbee6f716791de7e51e9010e935 Mon Sep 17 00:00:00 2001 From: gnxlxnxx Date: Fri, 12 Nov 2021 21:55:10 +0100 Subject: add note the same note as in https://github.com/rust-embedded/riscv/pull/87 --- src/macros.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/macros.rs b/src/macros.rs index b578370..66b75b1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,6 +30,9 @@ macro_rules! iprintln { /// `None` variant the caller must ensure that the macro is called from a function that's executed /// at most once in the whole lifetime of the program. /// +/// # Note +/// This macro is unsound on multi core systems. +/// /// # Example /// /// ``` no_run -- cgit v1.2.3 From 74e9bbe6811deb4888bf0c20157506ab06e4f957 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sat, 20 Nov 2021 00:05:42 +0100 Subject: scb: derive serde, Hash, PartialOrd for VectActive behind gates Exposes two new feature gates for VectActive serde::{Serialize, Deserialize} (via "serde") and Hash, PartialOrd (via "std-map") for use on host-side ITM tracing programs. While the struct itself is not received directly over ITM, its use greatly simplifies the implementation by allowing VectActive as keys in map collections and file/socket {,de}serialization to forward the structure elsewhere. These features are not enabled by default. Before this patch, serde functionality could be realized via [0], but this does not propagate down a dependency chain (i.e. if realized for crate B, which crate A depends on, serde functionality is not exposed in crate A unless VectActive is wrapped in a type from crate B). I am not aware of any method to realize PartialOrd, Hash derivation for a downstream crate. [0] https://serde.rs/remote-derive.html --- Cargo.toml | 6 ++++++ src/peripheral/scb.rs | 6 ++++++ xtask/Cargo.toml | 2 ++ xtask/src/lib.rs | 21 +++++++++++++++++++++ xtask/src/main.rs | 8 +++++--- xtask/tests/ci.rs | 5 ++++- 6 files changed, 44 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/Cargo.toml b/Cargo.toml index 19aa249..b7d377d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,11 +21,17 @@ volatile-register = "0.2.0" bitfield = "0.13.2" embedded-hal = "0.2.4" +[dependencies.serde] +version = "1" +features = [ "derive" ] +optional = true + [features] cm7 = [] cm7-r0p1 = ["cm7"] inline-asm = [] linker-plugin-lto = [] +std-map = [] [workspace] members = ["xtask", "cortex-m-semihosting", "panic-semihosting", "panic-itm"] diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index 688c431..28cfca8 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -11,6 +11,8 @@ use super::CBP; #[cfg(not(armv6m))] use super::CPUID; use super::SCB; +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; /// Register block #[repr(C)] @@ -194,6 +196,8 @@ impl SCB { /// Processor core exceptions (internal interrupts) #[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std-map", derive(PartialOrd, Hash))] pub enum Exception { /// Non maskable interrupt NonMaskableInt, @@ -259,6 +263,8 @@ impl Exception { /// Active exception number #[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "std-map", derive(PartialOrd, Hash))] pub enum VectActive { /// Thread mode ThreadMode, diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 06c5143..8742f9b 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -11,3 +11,5 @@ harness = false [dependencies] ar = "0.8.0" +cortex-m = { path = "../", features = ["serde", "std-map"] } +serde_json = "1" diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index a7b85e7..c3d8356 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -208,3 +208,24 @@ pub fn check_blobs() { println!("Blobs identical."); } + +// Check that serde and PartialOrd works with VectActive +pub fn check_host_side() { + use cortex_m::peripheral::scb::VectActive; + + // check serde + { + let v = VectActive::from(22).unwrap(); + let json = serde_json::to_string(&v).expect("Failed to serialize VectActive"); + let deser_v: VectActive = + serde_json::from_str(&json).expect("Failed to deserialize VectActive"); + assert_eq!(deser_v, v); + } + + // check PartialOrd + { + let a = VectActive::from(19).unwrap(); + let b = VectActive::from(20).unwrap(); + assert_eq!(a < b, true); + } +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index ec55bf8..3e4b394 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,17 +1,19 @@ use std::{env, process}; -use xtask::{assemble_blobs, check_blobs}; +use xtask::{assemble_blobs, check_blobs, check_host_side}; fn main() { let subcommand = env::args().skip(1).next(); match subcommand.as_ref().map(|s| &**s) { Some("assemble") => assemble_blobs(), Some("check-blobs") => check_blobs(), + Some("check-host-side") => check_host_side(), _ => { eprintln!("usage: cargo xtask "); eprintln!(); eprintln!("subcommands:"); - eprintln!(" assemble Reassemble the pre-built artifacts"); - eprintln!(" check-blobs Check that the pre-built artifacts are up-to-date and reproducible"); + eprintln!(" assemble Reassemble the pre-built artifacts"); + eprintln!(" check-blobs Check that the pre-built artifacts are up-to-date and reproducible"); + eprintln!(" check-host-side Build the crate in a non-Cortex-M host application and check host side usage of certain types"); process::exit(1); } } diff --git a/xtask/tests/ci.rs b/xtask/tests/ci.rs index a261783..37466e9 100644 --- a/xtask/tests/ci.rs +++ b/xtask/tests/ci.rs @@ -1,6 +1,6 @@ use std::process::Command; use std::{env, str}; -use xtask::{check_blobs, install_targets}; +use xtask::{check_blobs, check_host_side, install_targets}; /// List of all compilation targets we support. /// @@ -105,4 +105,7 @@ fn main() { let is_nightly = str::from_utf8(&output.stdout).unwrap().contains("nightly"); check_crates_build(is_nightly); + + // Check host-side applications of the crate. + check_host_side(); } -- cgit v1.2.3 From c470f8bc9a62fa6305fffca22ece972733739453 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:12:11 +0100 Subject: dwt, itm, tpiu: remove get_ prefix, as per Rust API guidelines --- src/peripheral/dwt.rs | 38 +++++++++++++++++++------------------- src/peripheral/itm.rs | 16 ++++++++-------- src/peripheral/tpiu.rs | 2 +- 3 files changed, 28 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 720511b..188681b 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -56,14 +56,14 @@ bitfield! { #[repr(C)] #[derive(Copy, Clone)] pub struct Ctrl(u32); - get_cyccntena, set_cyccntena: 0; - get_pcsamplena, set_pcsamplena: 12; - get_exctrcena, set_exctrcena: 16; - get_noprfcnt, _: 24; - get_nocyccnt, _: 25; - get_noexttrig, _: 26; - get_notrcpkt, _: 27; - u8, get_numcomp, _: 31, 28; + cyccntena, set_cyccntena: 0; + pcsamplena, set_pcsamplena: 12; + exctrcena, set_exctrcena: 16; + noprfcnt, _: 24; + nocyccnt, _: 25; + noexttrig, _: 26; + notrcpkt, _: 27; + u8, numcomp, _: 31, 28; } /// Comparator @@ -83,11 +83,11 @@ bitfield! { #[derive(Copy, Clone)] /// Comparator FUNCTIONn register. pub struct Function(u32); - u8, get_function, set_function: 3, 0; - get_emitrange, set_emitrange: 5; - get_cycmatch, set_cycmatch: 7; - get_datavmatch, set_datavmatch: 8; - get_matched, _: 24; + u8, function, set_function: 3, 0; + emitrange, set_emitrange: 5; + cycmatch, set_cycmatch: 7; + datavmatch, set_datavmatch: 8; + matched, _: 24; } impl DWT { @@ -96,35 +96,35 @@ impl DWT { /// A value of zero indicates no comparator support. #[inline] pub fn num_comp(&self) -> u8 { - self.ctrl.read().get_numcomp() + self.ctrl.read().numcomp() } /// Returns `true` if the the implementation supports sampling and exception tracing #[cfg(not(armv6m))] #[inline] pub fn has_exception_trace(&self) -> bool { - self.ctrl.read().get_notrcpkt() == false + self.ctrl.read().notrcpkt() == false } /// Returns `true` if the implementation includes external match signals #[cfg(not(armv6m))] #[inline] pub fn has_external_match(&self) -> bool { - self.ctrl.read().get_noexttrig() == false + self.ctrl.read().noexttrig() == false } /// Returns `true` if the implementation supports a cycle counter #[cfg(not(armv6m))] #[inline] pub fn has_cycle_counter(&self) -> bool { - self.ctrl.read().get_nocyccnt() == false + self.ctrl.read().nocyccnt() == false } /// Returns `true` if the implementation the profiling counters #[cfg(not(armv6m))] #[inline] pub fn has_profiling_counter(&self) -> bool { - self.ctrl.read().get_noprfcnt() == false + self.ctrl.read().noprfcnt() == false } /// Enables the cycle counter @@ -150,7 +150,7 @@ impl DWT { #[cfg(not(armv6m))] #[inline] pub fn cycle_counter_enabled(&self) -> bool { - self.ctrl.read().get_cyccntena() + self.ctrl.read().cyccntena() } /// Whether to enable exception tracing diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 24b926d..626fba2 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -36,14 +36,14 @@ bitfield! { #[repr(C)] #[derive(Copy, Clone)] pub struct Tcr(u32); - get_itmena, set_itmena: 0; - get_tsena, set_tsena: 1; - get_syncena, set_synena: 2; - get_txena, set_txena: 3; - get_swoena, set_swoena: 4; - u8, get_tsprescale, set_tsprescale: 9, 8; - u8, get_gtsfreq, set_gtsfreq: 11, 10; - u8, get_tracebusid, set_tracebusid: 22, 16; + itmena, set_itmena: 0; + tsena, set_tsena: 1; + syncena, set_synena: 2; + txena, set_txena: 3; + swoena, set_swoena: 4; + u8, tsprescale, set_tsprescale: 9, 8; + u8, gtsfreq, set_gtsfreq: 11, 10; + u8, tracebusid, set_tracebusid: 22, 16; busy, _: 23; } diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 5443fc0..9ff92d1 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -38,7 +38,7 @@ bitfield! { #[repr(C)] #[derive(Clone, Copy)] pub struct Ffcr(u32); - get_enfcont, set_enfcont: 1; + enfcont, set_enfcont: 1; } bitfield! { -- cgit v1.2.3 From 6ddc7463d5fcca98df23d7730deff04823eb6efb Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:14:46 +0100 Subject: dwt: fix clippy::bool_comparison --- src/peripheral/dwt.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 188681b..73f90ce 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -103,28 +103,28 @@ impl DWT { #[cfg(not(armv6m))] #[inline] pub fn has_exception_trace(&self) -> bool { - self.ctrl.read().notrcpkt() == false + !self.ctrl.read().notrcpkt() } /// Returns `true` if the implementation includes external match signals #[cfg(not(armv6m))] #[inline] pub fn has_external_match(&self) -> bool { - self.ctrl.read().noexttrig() == false + !self.ctrl.read().noexttrig() } /// Returns `true` if the implementation supports a cycle counter #[cfg(not(armv6m))] #[inline] pub fn has_cycle_counter(&self) -> bool { - self.ctrl.read().nocyccnt() == false + !self.ctrl.read().nocyccnt() } /// Returns `true` if the implementation the profiling counters #[cfg(not(armv6m))] #[inline] pub fn has_profiling_counter(&self) -> bool { - self.ctrl.read().noprfcnt() == false + !self.ctrl.read().noprfcnt() } /// Enables the cycle counter -- cgit v1.2.3 From 35bb481f462a4ed113bf9d562343da4922425de0 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:15:48 +0100 Subject: dwt: improve EmitOption docstring --- src/peripheral/dwt.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 73f90ce..597accd 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -322,7 +322,8 @@ pub enum EmitOption { /// Emit only trace address packet. Address, /// Emit only trace PC value packet - /// NOTE: only compatible with [AccessType::ReadWrite]. + /// + /// *NOTE* only compatible with [AccessType::ReadWrite]. PC, /// Emit trace address and data value packets. AddressData, -- cgit v1.2.3 From 021420b11fa7f51b5daae46fbfbcd19a370bc75d Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:16:39 +0100 Subject: dwt: don't inline Comparator::configure The function is a bit too large to warrant inlining. --- src/peripheral/dwt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 597accd..8bb063f 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -360,8 +360,8 @@ pub enum DWTError { impl Comparator { /// Configure the function of the comparator - #[inline] - pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DWTError> { + #[allow(clippy::missing_inline_in_public_items)] + pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DwtError> { match settings { ComparatorFunction::Address(settings) => unsafe { if settings.emit == EmitOption::PC && settings.access_type != AccessType::ReadWrite -- cgit v1.2.3 From 0e647743de4a87b4a04fb02178d3a76ef053fb42 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:20:57 +0100 Subject: dwt: refactor out unnecessary explicit panic --- src/peripheral/dwt.rs | 52 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 8bb063f..0b0d774 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -364,12 +364,32 @@ impl Comparator { pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DwtError> { match settings { ComparatorFunction::Address(settings) => unsafe { - if settings.emit == EmitOption::PC && settings.access_type != AccessType::ReadWrite - { - return Err(DWTError::InvalidFunction); - } + // FUNCTION, EMITRANGE + // See Table C1-14 + let (function, emit_range) = match (&settings.access_type, &settings.emit) { + (AccessType::ReadOnly, EmitOption::Data) => (0b1100, false), + (AccessType::ReadOnly, EmitOption::Address) => (0b1100, true), + (AccessType::ReadOnly, EmitOption::AddressData) => (0b1110, true), + (AccessType::ReadOnly, EmitOption::PCData) => (0b1110, false), + + (AccessType::WriteOnly, EmitOption::Data) => (0b1101, false), + (AccessType::WriteOnly, EmitOption::Address) => (0b1101, true), + (AccessType::WriteOnly, EmitOption::AddressData) => (0b1111, true), + (AccessType::WriteOnly, EmitOption::PCData) => (0b1111, false), + + (AccessType::ReadWrite, EmitOption::Data) => (0b0010, false), + (AccessType::ReadWrite, EmitOption::Address) => (0b0001, true), + (AccessType::ReadWrite, EmitOption::AddressData) => (0b0010, true), + (AccessType::ReadWrite, EmitOption::PCData) => (0b0011, false), + + (AccessType::ReadWrite, EmitOption::PC) => (0b0001, false), + (_, EmitOption::PC) => return Err(DWTError::InvalidFunction), + }; self.function.modify(|mut r| { + r.set_function(function); + r.set_emitrange(emit_range); + // don't compare data value r.set_datavmatch(false); @@ -377,30 +397,6 @@ impl Comparator { // NOTE: only needed for comparator 0, but is SBZP. r.set_cycmatch(false); - // FUNCTION, EMITRANGE - // See Table C1-14 - let (function, emit_range) = match (&settings.access_type, &settings.emit) { - (AccessType::ReadOnly, EmitOption::Data) => (0b1100, false), - (AccessType::ReadOnly, EmitOption::Address) => (0b1100, true), - (AccessType::ReadOnly, EmitOption::AddressData) => (0b1110, true), - (AccessType::ReadOnly, EmitOption::PCData) => (0b1110, false), - - (AccessType::WriteOnly, EmitOption::Data) => (0b1101, false), - (AccessType::WriteOnly, EmitOption::Address) => (0b1101, true), - (AccessType::WriteOnly, EmitOption::AddressData) => (0b1111, true), - (AccessType::WriteOnly, EmitOption::PCData) => (0b1111, false), - - (AccessType::ReadWrite, EmitOption::Data) => (0b0010, false), - (AccessType::ReadWrite, EmitOption::Address) => (0b0001, true), - (AccessType::ReadWrite, EmitOption::AddressData) => (0b0010, true), - (AccessType::ReadWrite, EmitOption::PCData) => (0b0011, false), - - (AccessType::ReadWrite, EmitOption::PC) => (0b0001, false), - (_, EmitOption::PC) => unreachable!(), // cannot return Err here; handled above - }; - r.set_function(function); - r.set_emitrange(emit_range); - r }); -- cgit v1.2.3 From d45bad7f6d2abdf7f1ea27868791987e87bd2876 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:22:27 +0100 Subject: tpiu: remove get_ prefix, as per Rust API guidelines --- src/peripheral/tpiu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 9ff92d1..69693f0 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -108,7 +108,7 @@ impl TPIU { /// Reads the supported trace output modes and the minimum size of /// the TPIU FIFO queue for trace data. #[inline] - pub fn get_swo_supports() -> SWOSupports { + pub fn swo_supports() -> SWOSupports { let _type = unsafe { (*Self::ptr())._type.read() }; SWOSupports { nrz_encoding: _type.nrzvalid(), -- cgit v1.2.3 From 633a631af6906421c087f1961c3880a93f69fd91 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:24:16 +0100 Subject: dwt: DWTError -> DwtError for in-crate consistency --- src/peripheral/dwt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 0b0d774..bf770d2 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -353,7 +353,7 @@ pub enum ComparatorFunction { /// Possible error values returned on [Comparator::configure]. #[derive(Debug)] -pub enum DWTError { +pub enum DwtError { /// Invalid combination of [AccessType] and [EmitOption]. InvalidFunction, } @@ -383,7 +383,7 @@ impl Comparator { (AccessType::ReadWrite, EmitOption::PCData) => (0b0011, false), (AccessType::ReadWrite, EmitOption::PC) => (0b0001, false), - (_, EmitOption::PC) => return Err(DWTError::InvalidFunction), + (_, EmitOption::PC) => return Err(DwtError::InvalidFunction), }; self.function.modify(|mut r| { -- cgit v1.2.3 From 09929b156b3919aefd640086de68517b00c43722 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:26:07 +0100 Subject: dwt: mark ComparatorFunction, DwtError as non-exhaustive A DWT unit can do much more than just comparing addresses. PC comparison, for example, which is only possible with the first DWT unit. --- src/peripheral/dwt.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index bf770d2..0769e96 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -346,6 +346,7 @@ pub struct ComparatorAddressSettings { /// The available functions of a DWT comparator. #[derive(Debug)] +#[non_exhaustive] pub enum ComparatorFunction { /// Compare accessed memory addresses. Address(ComparatorAddressSettings), @@ -353,6 +354,7 @@ pub enum ComparatorFunction { /// Possible error values returned on [Comparator::configure]. #[derive(Debug)] +#[non_exhaustive] pub enum DwtError { /// Invalid combination of [AccessType] and [EmitOption]. InvalidFunction, -- cgit v1.2.3 From c37f80bf35a9b81bbcdd9491abad0e550afb187b Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:28:27 +0100 Subject: itm: properly document ITMSettings --- src/peripheral/itm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 626fba2..f5f5935 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -133,7 +133,7 @@ pub enum TimestampClkSrc { AsyncTPIU, } -/// blah +/// Available settings for the ITM peripheral. #[derive(Debug)] pub struct ITMSettings { /// Whether to enable ITM. -- cgit v1.2.3 From 1efe31942b701d23a9d214f537adbfb471d25b9c Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 02:10:17 +0100 Subject: tpiu: use bitfield for SPPR --- src/peripheral/tpiu.rs | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 69693f0..e020b81 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -19,7 +19,7 @@ pub struct RegisterBlock { pub acpr: RW, reserved1: [u32; 55], /// Selected Pin Control - pub sppr: RW, + pub sppr: RW, reserved2: [u32; 132], /// Formatter and Flush Control pub ffcr: RW, @@ -52,7 +52,16 @@ bitfield! { nrzvalid, _: 11; } +bitfield! { + /// Selected pin protocol register. + #[repr(C)] + #[derive(Clone, Copy)] + pub struct Sppr(u32); + u8, txmode, set_txmode: 1, 0; +} + /// The available protocols for the trace output. +#[repr(u8)] pub enum TraceProtocol { /// Parallel trace port mode Parallel = 0b00, @@ -61,6 +70,21 @@ pub enum TraceProtocol { /// Asynchronous SWO, using NRZ encoding AsyncSWONRZ = 0b10, } +impl core::convert::TryFrom for TraceProtocol { + type Error = (); + + /// Tries to convert from a `TXMODE` field value. Fails if the set mode is + /// unknown (and thus unpredictable). + #[inline] + fn try_from(value: u8) -> Result { + match value { + x if x == Self::Parallel as u8 => Ok(Self::Parallel), + x if x == Self::AsyncSWOManchester as u8 => Ok(Self::AsyncSWOManchester), + x if x == Self::AsyncSWONRZ as u8 => Ok(Self::AsyncSWONRZ), + _ => Err(()), // unknown and unpredictable mode + } + } +} /// The SWO options supported by the TPIU. #[allow(dead_code)] @@ -86,10 +110,25 @@ impl TPIU { } } + /// The used protocol for the trace output. Return `None` if an + /// unknown (and thus unpredicable mode) is configured by means + /// other than + /// [`trace_output_protocol`](Self::set_trace_output_protocol). + #[inline] + pub fn trace_output_protocol(&self) -> Option { + use core::convert::TryInto; + self.sppr.read().txmode().try_into().ok() + } + /// Sets the used protocol for the trace output. #[inline] pub fn set_trace_output_protocol(&mut self, proto: TraceProtocol) { - unsafe { self.sppr.write(proto as u32) } + unsafe { + self.sppr.modify(|mut r| { + r.set_txmode(proto as u8); + r + }); + } } /// Whether to enable the formatter. If disabled, only ITM and DWT -- cgit v1.2.3 From 5a92298d9c12685214b12266357fe7c104035b59 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 02:11:06 +0100 Subject: tpiu: improve TYPE field documentation --- src/peripheral/tpiu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index e020b81..582544b 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -42,7 +42,7 @@ bitfield! { } bitfield! { - /// Type Register. + /// TPIU Type Register. #[repr(C)] #[derive(Clone, Copy)] pub struct Type(u32); -- cgit v1.2.3 From 92c15ed56da6331c1f7bc4bb1372b56e3fc93a05 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 02:20:51 +0100 Subject: dwt, itm, tpiu: derive common traits for structs/enums As per Rust API guidelines: . --- src/peripheral/dwt.rs | 10 +++++----- src/peripheral/itm.rs | 8 ++++---- src/peripheral/tpiu.rs | 3 ++- 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 0769e96..7fc9478 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -304,7 +304,7 @@ impl DWT { } /// Whether the comparator should match on read, write or read/write operations. -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum AccessType { /// Generate packet only when matched adress is read from. ReadOnly, @@ -315,7 +315,7 @@ pub enum AccessType { } /// The sequence of packet(s) that should be emitted on comparator match. -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum EmitOption { /// Emit only trace data value packet. Data, @@ -332,7 +332,7 @@ pub enum EmitOption { } /// Settings for address matching -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub struct ComparatorAddressSettings { /// The address to match against. pub address: u32, @@ -345,7 +345,7 @@ pub struct ComparatorAddressSettings { } /// The available functions of a DWT comparator. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[non_exhaustive] pub enum ComparatorFunction { /// Compare accessed memory addresses. @@ -353,7 +353,7 @@ pub enum ComparatorFunction { } /// Possible error values returned on [Comparator::configure]. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] #[non_exhaustive] pub enum DwtError { /// Invalid combination of [AccessType] and [EmitOption]. diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index f5f5935..4d0aa22 100644 --- a/src/peripheral/itm.rs +++ b/src/peripheral/itm.rs @@ -90,7 +90,7 @@ impl Stim { } /// The possible local timestamp options. -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum LocalTimestampOptions { /// Disable local timestamps. Disabled, @@ -108,7 +108,7 @@ pub enum LocalTimestampOptions { } /// The possible global timestamp options. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum GlobalTimestampOptions { /// Disable global timestamps. Disabled, @@ -121,7 +121,7 @@ pub enum GlobalTimestampOptions { } /// The possible clock sources for timestamp counters. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum TimestampClkSrc { /// Clock timestamp counters using the system processor clock. SystemClock, @@ -134,7 +134,7 @@ pub enum TimestampClkSrc { } /// Available settings for the ITM peripheral. -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub struct ITMSettings { /// Whether to enable ITM. pub enable: bool, diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 582544b..3ff5f55 100644 --- a/src/peripheral/tpiu.rs +++ b/src/peripheral/tpiu.rs @@ -62,6 +62,7 @@ bitfield! { /// The available protocols for the trace output. #[repr(u8)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum TraceProtocol { /// Parallel trace port mode Parallel = 0b00, @@ -87,7 +88,7 @@ impl core::convert::TryFrom for TraceProtocol { } /// The SWO options supported by the TPIU. -#[allow(dead_code)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] pub struct SWOSupports { /// Whether UART/NRZ encoding is supported for SWO. nrz_encoding: bool, -- cgit v1.2.3 From 360fb334c7cec241ca4e396b5ab23c58fb8905fe Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sat, 27 Nov 2021 10:32:37 +0100 Subject: dwt: refactor enable_exception_tracing into enable/disable funs --- src/peripheral/dwt.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 7fc9478..11dd545 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -153,13 +153,25 @@ impl DWT { self.ctrl.read().cyccntena() } - /// Whether to enable exception tracing + /// Enables exception tracing #[cfg(not(armv6m))] #[inline] - pub fn enable_exception_tracing(&mut self, bit: bool) { + pub fn enable_exception_tracing(&mut self) { unsafe { self.ctrl.modify(|mut r| { - r.set_exctrcena(bit); + r.set_exctrcena(true); + r + }); + } + } + + /// Disables exception tracing + #[cfg(not(armv6m))] + #[inline] + pub fn disable_exception_tracing(&mut self) { + unsafe { + self.ctrl.modify(|mut r| { + r.set_exctrcena(false); r }); } -- cgit v1.2.3 From c1d434a7e7ee1a04ce06c3e3bcdb9b65e048b8ba Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sat, 27 Nov 2021 13:34:28 +0100 Subject: bump MSRV Required to support the #[non_exhaustive] attribute. --- .github/bors.toml | 2 +- .github/workflows/ci.yml | 2 +- README.md | 2 +- src/lib.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/.github/bors.toml b/.github/bors.toml index 63d883f..0cf10c7 100644 --- a/.github/bors.toml +++ b/.github/bors.toml @@ -3,7 +3,7 @@ delete_merged_branches = true required_approvals = 1 status = [ "ci-linux (stable)", - "ci-linux (1.38.0)", + "ci-linux (1.40.0)", "rustfmt", "clippy", ] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7289085..8600054 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: include: # Test MSRV - - rust: 1.38.0 + - rust: 1.40.0 # Test nightly but don't fail - rust: nightly diff --git a/README.md b/README.md index 6bd8aed..6011ab2 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This project is developed and maintained by the [Cortex-M team][team]. ## Minimum Supported Rust Version (MSRV) -This crate is guaranteed to compile on stable Rust 1.38 and up. It might compile with older versions but that may change in any new patch release. +This crate is guaranteed to compile on stable Rust 1.40 and up. It might compile with older versions but that may change in any new patch release. ## License diff --git a/src/lib.rs b/src/lib.rs index 6a73692..a267750 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,7 +52,7 @@ //! //! # Minimum Supported Rust Version (MSRV) //! -//! This crate is guaranteed to compile on stable Rust 1.38 and up. It *might* +//! This crate is guaranteed to compile on stable Rust 1.40 and up. It *might* //! compile with older versions but that may change in any new patch release. #![cfg_attr(feature = "inline-asm", feature(asm))] -- cgit v1.2.3 From 46a3320d11cade9c9a5f2a914fb5a5bcb53b31d3 Mon Sep 17 00:00:00 2001 From: Robert Jördens Date: Thu, 16 Dec 2021 21:25:42 +0100 Subject: asm: silence warning about asm being stable --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index a267750..0914639 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,6 +76,8 @@ // - A generated #[derive(Debug)] function (in which case the attribute needs // to be applied to the struct). #![deny(clippy::missing_inline_in_public_items)] +// Don't warn about feature(asm) being stable on Rust >= 1.59.0 +#![allow(stable_features)] extern crate bare_metal; extern crate volatile_register; -- cgit v1.2.3 From 0da1028cbf4ae9d0accb3bb47f5d7341b31a1779 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Mon, 13 Dec 2021 16:25:36 -0800 Subject: add methods needed for cycle count comparisons --- src/peripheral/dcb.rs | 15 ++++++++++++ src/peripheral/dwt.rs | 66 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/peripheral/dcb.rs b/src/peripheral/dcb.rs index 056150b..b2bbd57 100644 --- a/src/peripheral/dcb.rs +++ b/src/peripheral/dcb.rs @@ -6,6 +6,7 @@ use crate::peripheral::DCB; use core::ptr; const DCB_DEMCR_TRCENA: u32 = 1 << 24; +const DCB_DEMCR_MON_EN: u32 = 1 << 16; /// Register block #[repr(C)] @@ -46,6 +47,20 @@ impl DCB { } } + /// Enables the [`DebugMonitor`](crate::peripheral::scb::Exception::DebugMonitor) exception + pub fn enable_debug_monitor(&mut self) { + unsafe { + self.demcr.modify(|w| w | DCB_DEMCR_MON_EN); + } + } + + /// Disables the [`DebugMonitor`](crate::peripheral::scb::Exception::DebugMonitor) exception + pub fn disable_debug_monitor(&mut self) { + unsafe { + self.demcr.modify(|w| w & !DCB_DEMCR_MON_EN); + } + } + /// Is there a debugger attached? (see note) /// /// Note: This function is [reported not to diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 11dd545..b827dce 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -356,12 +356,23 @@ pub struct ComparatorAddressSettings { pub access_type: AccessType, } +/// Settings for cycle count matching +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +pub struct CycleCountSettings { + /// The cycle count value to compare against. + pub compare: u32, + /// The cycle count mask value to use. + pub mask: u32, +} + /// The available functions of a DWT comparator. #[derive(Debug, Eq, PartialEq, Copy, Clone)] #[non_exhaustive] pub enum ComparatorFunction { /// Compare accessed memory addresses. Address(ComparatorAddressSettings), + /// Compare cycle count & target value. + CycleCount(CycleCountSettings), } /// Possible error values returned on [Comparator::configure]. @@ -376,8 +387,8 @@ impl Comparator { /// Configure the function of the comparator #[allow(clippy::missing_inline_in_public_items)] pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DwtError> { - match settings { - ComparatorFunction::Address(settings) => unsafe { + let (func, emit, data_match, cyc_match, comp, mask) = match settings { + ComparatorFunction::Address(settings) => { // FUNCTION, EMITRANGE // See Table C1-14 let (function, emit_range) = match (&settings.access_type, &settings.emit) { @@ -400,25 +411,50 @@ impl Comparator { (_, EmitOption::PC) => return Err(DwtError::InvalidFunction), }; - self.function.modify(|mut r| { - r.set_function(function); - r.set_emitrange(emit_range); - + ( + function, + emit_range, // don't compare data value - r.set_datavmatch(false); - + false, // don't compare cycle counter value // NOTE: only needed for comparator 0, but is SBZP. - r.set_cycmatch(false); + false, + settings.address, + settings.mask, + ) + } + ComparatorFunction::CycleCount(settings) => { + ( + // emit a Debug Watchpoint event, either halting execution or + // firing a `DebugMonitor` exception + 0b0111, + // don't emit (we're going to fire an exception not trace) + false, + // don't compare data + false, + // compare cyccnt + true, + settings.compare, + settings.mask, + ) + } + }; - r - }); + unsafe { + self.function.modify(|mut r| { + r.set_function(func); + r.set_emitrange(emit); + r.set_datavmatch(data_match); - self.comp.write(settings.address); - self.mask.write(settings.mask); - }, - } + // NOTE: only valid for comparator 0, but is SBZP. + r.set_cycmatch(cyc_match); + + r + }); + self.comp.write(comp); + self.mask.write(mask); + } Ok(()) } } -- cgit v1.2.3 From 1b9b2293cd72842902869bbfb22246817089b049 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Tue, 14 Dec 2021 08:21:09 -0800 Subject: inline --- src/peripheral/dcb.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/peripheral/dcb.rs b/src/peripheral/dcb.rs index b2bbd57..ef879ac 100644 --- a/src/peripheral/dcb.rs +++ b/src/peripheral/dcb.rs @@ -48,6 +48,7 @@ impl DCB { } /// Enables the [`DebugMonitor`](crate::peripheral::scb::Exception::DebugMonitor) exception + #[inline] pub fn enable_debug_monitor(&mut self) { unsafe { self.demcr.modify(|w| w | DCB_DEMCR_MON_EN); @@ -55,6 +56,7 @@ impl DCB { } /// Disables the [`DebugMonitor`](crate::peripheral::scb::Exception::DebugMonitor) exception + #[inline] pub fn disable_debug_monitor(&mut self) { unsafe { self.demcr.modify(|w| w & !DCB_DEMCR_MON_EN); -- cgit v1.2.3 From 12c4c8283cf8e4ad87be00434af4ac7308559383 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Tue, 14 Dec 2021 08:24:23 -0800 Subject: more correct comment --- src/peripheral/dwt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index b827dce..7c3e344 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -428,7 +428,7 @@ impl Comparator { // emit a Debug Watchpoint event, either halting execution or // firing a `DebugMonitor` exception 0b0111, - // don't emit (we're going to fire an exception not trace) + // emit_range is N/A for cycle count compare false, // don't compare data false, -- cgit v1.2.3 From 333584504479a15b788696befc6e1565f1646b5a Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Tue, 14 Dec 2021 09:06:38 -0800 Subject: review suggestions --- src/peripheral/dwt.rs | 77 ++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 7c3e344..54b28c8 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -387,7 +387,7 @@ impl Comparator { /// Configure the function of the comparator #[allow(clippy::missing_inline_in_public_items)] pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DwtError> { - let (func, emit, data_match, cyc_match, comp, mask) = match settings { + match settings { ComparatorFunction::Address(settings) => { // FUNCTION, EMITRANGE // See Table C1-14 @@ -411,50 +411,45 @@ impl Comparator { (_, EmitOption::PC) => return Err(DwtError::InvalidFunction), }; - ( - function, - emit_range, - // don't compare data value - false, - // don't compare cycle counter value - // NOTE: only needed for comparator 0, but is SBZP. - false, - settings.address, - settings.mask, - ) + unsafe { + self.function.modify(|mut r| { + r.set_function(function); + r.set_emitrange(emit_range); + // don't compare data value + r.set_datavmatch(false); + // don't compare cycle counter value + // NOTE: only needed for comparator 0, but is SBZP. + r.set_cycmatch(false); + + r + }); + + self.comp.write(settings.address); + self.mask.write(settings.mask); + } } ComparatorFunction::CycleCount(settings) => { - ( - // emit a Debug Watchpoint event, either halting execution or - // firing a `DebugMonitor` exception - 0b0111, - // emit_range is N/A for cycle count compare - false, - // don't compare data - false, - // compare cyccnt - true, - settings.compare, - settings.mask, - ) + unsafe { + self.function.modify(|mut r| { + // emit a Debug Watchpoint event, either halting execution or + // firing a `DebugMonitor` exception + // See Table C1-15 DWT cycle count comparison functions + r.set_function(0b0100); + // emit_range is N/A for cycle count compare + r.set_emitrange(false); + // don't compare data + r.set_datavmatch(false); + // compare cyccnt + r.set_cycmatch(true); + r + }); + + self.comp.write(settings.compare); + self.mask.write(settings.mask); + } } - }; - - unsafe { - self.function.modify(|mut r| { - r.set_function(func); - r.set_emitrange(emit); - r.set_datavmatch(data_match); - - // NOTE: only valid for comparator 0, but is SBZP. - r.set_cycmatch(cyc_match); - - r - }); - - self.comp.write(comp); - self.mask.write(mask); } + Ok(()) } } -- cgit v1.2.3 From 0e8bc7913f04e3aa19950e1f5bb7f1fe51f0174b Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Tue, 14 Dec 2021 11:15:19 -0800 Subject: further comments - factor out function selection and more documentation --- src/peripheral/dwt.rs | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 54b28c8..8bc44d3 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -318,15 +318,15 @@ impl DWT { /// Whether the comparator should match on read, write or read/write operations. #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum AccessType { - /// Generate packet only when matched adress is read from. + /// Generate packet only when matched address is read from. ReadOnly, - /// Generate packet only when matched adress is written to. + /// Generate packet only when matched address is written to. WriteOnly, - /// Generate packet when matched adress is both read from and written to. + /// Generate packet when matched address is both read from and written to. ReadWrite, } -/// The sequence of packet(s) that should be emitted on comparator match. +/// The sequence of packet(s) or events that should be emitted/generated on comparator match. #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub enum EmitOption { /// Emit only trace data value packet. @@ -341,6 +341,15 @@ pub enum EmitOption { AddressData, /// Emit trace PC value and data value packets. PCData, + /// Generate a watchpoint debug event. + /// + /// either halts execution or fires a `DebugMonitor` exception. + /// See more in section "Watchpoint debug event generation" page C1-729 + WatchpointDebugEvent, + /// Generate a `CMPMATCH[N]` event. + /// + /// See more in section "CMPMATCH[N] event generation" page C1-730 + CompareMatchEvent, } /// Settings for address matching @@ -359,6 +368,9 @@ pub struct ComparatorAddressSettings { /// Settings for cycle count matching #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub struct CycleCountSettings { + /// The function selection used. + /// See Table C1-15 DWT cycle count comparison functions + pub emit: EmitOption, /// The cycle count value to compare against. pub compare: u32, /// The cycle count mask value to use. @@ -396,16 +408,22 @@ impl Comparator { (AccessType::ReadOnly, EmitOption::Address) => (0b1100, true), (AccessType::ReadOnly, EmitOption::AddressData) => (0b1110, true), (AccessType::ReadOnly, EmitOption::PCData) => (0b1110, false), + (AccessType::ReadOnly, EmitOption::WatchpointDebugEvent) => (0b0101, false), + (AccessType::ReadOnly, EmitOption::CompareMatchEvent) => (0b1001, false), (AccessType::WriteOnly, EmitOption::Data) => (0b1101, false), (AccessType::WriteOnly, EmitOption::Address) => (0b1101, true), (AccessType::WriteOnly, EmitOption::AddressData) => (0b1111, true), (AccessType::WriteOnly, EmitOption::PCData) => (0b1111, false), + (AccessType::WriteOnly, EmitOption::WatchpointDebugEvent) => (0b0110, false), + (AccessType::WriteOnly, EmitOption::CompareMatchEvent) => (0b1010, false), (AccessType::ReadWrite, EmitOption::Data) => (0b0010, false), (AccessType::ReadWrite, EmitOption::Address) => (0b0001, true), (AccessType::ReadWrite, EmitOption::AddressData) => (0b0010, true), (AccessType::ReadWrite, EmitOption::PCData) => (0b0011, false), + (AccessType::ReadWrite, EmitOption::WatchpointDebugEvent) => (0b0111, false), + (AccessType::ReadWrite, EmitOption::CompareMatchEvent) => (0b1011, false), (AccessType::ReadWrite, EmitOption::PC) => (0b0001, false), (_, EmitOption::PC) => return Err(DwtError::InvalidFunction), @@ -429,12 +447,16 @@ impl Comparator { } } ComparatorFunction::CycleCount(settings) => { + let function = match &settings.emit { + EmitOption::PCData => 0b0001, + EmitOption::WatchpointDebugEvent => 0b0100, + EmitOption::CompareMatchEvent => 0b1000, + _ => return Err(DwtError::InvalidFunction), + }; + unsafe { self.function.modify(|mut r| { - // emit a Debug Watchpoint event, either halting execution or - // firing a `DebugMonitor` exception - // See Table C1-15 DWT cycle count comparison functions - r.set_function(0b0100); + r.set_function(function); // emit_range is N/A for cycle count compare r.set_emitrange(false); // don't compare data -- cgit v1.2.3 From 67835ae2270c82650423524518047e37c8922be3 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Tue, 14 Dec 2021 12:54:18 -0800 Subject: tidy up doc comments --- src/peripheral/dwt.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 8bc44d3..4101860 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -341,14 +341,13 @@ pub enum EmitOption { AddressData, /// Emit trace PC value and data value packets. PCData, - /// Generate a watchpoint debug event. + /// Generate a watchpoint debug event. Either halts execution or fires a `DebugMonitor` exception. /// - /// either halts execution or fires a `DebugMonitor` exception. - /// See more in section "Watchpoint debug event generation" page C1-729 + /// See more in section "Watchpoint debug event generation" page C1-729. WatchpointDebugEvent, /// Generate a `CMPMATCH[N]` event. /// - /// See more in section "CMPMATCH[N] event generation" page C1-730 + /// See more in section "CMPMATCH[N] event generation" page C1-730. CompareMatchEvent, } @@ -369,7 +368,7 @@ pub struct ComparatorAddressSettings { #[derive(Debug, Eq, PartialEq, Copy, Clone)] pub struct CycleCountSettings { /// The function selection used. - /// See Table C1-15 DWT cycle count comparison functions + /// See Table C1-15 for DWT cycle count comparison functions. pub emit: EmitOption, /// The cycle count value to compare against. pub compare: u32, -- cgit v1.2.3 From cd66d339cce732e6cea18441c7ae414209091340 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Wed, 15 Dec 2021 10:59:45 -0800 Subject: SBZ fields as needed, check if block supports cycle count compare --- src/peripheral/dwt.rs | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 4101860..a45032f 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -82,11 +82,17 @@ bitfield! { #[repr(C)] #[derive(Copy, Clone)] /// Comparator FUNCTIONn register. + /// + /// See C1.8.17 "Comparator Function registers, DWT_FUNCTIONn" pub struct Function(u32); u8, function, set_function: 3, 0; emitrange, set_emitrange: 5; cycmatch, set_cycmatch: 7; datavmatch, set_datavmatch: 8; + lnk1ena, set_lnk1ena: 9; + u8, datavsize, set_datavsize: 2, 10; + u8, datavaddr0, set_datavaddr0: 4, 12; + u8, datavaddr1, set_datavaddr1: 4, 16; matched, _: 24; } @@ -372,8 +378,6 @@ pub struct CycleCountSettings { pub emit: EmitOption, /// The cycle count value to compare against. pub compare: u32, - /// The cycle count mask value to use. - pub mask: u32, } /// The available functions of a DWT comparator. @@ -383,6 +387,8 @@ pub enum ComparatorFunction { /// Compare accessed memory addresses. Address(ComparatorAddressSettings), /// Compare cycle count & target value. + /// + /// **NOTE**: only supported by comparator 0. See C1.8.1. CycleCount(CycleCountSettings), } @@ -392,12 +398,14 @@ pub enum ComparatorFunction { pub enum DwtError { /// Invalid combination of [AccessType] and [EmitOption]. InvalidFunction, + /// The DWT block does not implement cycle count capabilities. + NoCycleCount, } impl Comparator { /// Configure the function of the comparator #[allow(clippy::missing_inline_in_public_items)] - pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DwtError> { + pub fn configure(&self, dwt: &DWT, settings: ComparatorFunction) -> Result<(), DwtError> { match settings { ComparatorFunction::Address(settings) => { // FUNCTION, EMITRANGE @@ -446,6 +454,10 @@ impl Comparator { } } ComparatorFunction::CycleCount(settings) => { + if !dwt.has_cycle_counter() { + return Err(DwtError::NoCycleCount); + } + let function = match &settings.emit { EmitOption::PCData => 0b0001, EmitOption::WatchpointDebugEvent => 0b0100, @@ -462,11 +474,16 @@ impl Comparator { r.set_datavmatch(false); // compare cyccnt r.set_cycmatch(true); + // SBZ as needed, see Page 784/C1-724 + r.set_datavsize(0); + r.set_datavaddr0(0); + r.set_datavaddr1(0); + r }); self.comp.write(settings.compare); - self.mask.write(settings.mask); + self.mask.write(0); // SBZ, see Page 784/C1-724 } } } -- cgit v1.2.3 From a77280cedc9b08e4b280445444fe4eab02d43ba7 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Wed, 15 Dec 2021 11:13:45 -0800 Subject: enable has_cycle_counter for all arches. armv6m always returns false --- src/peripheral/dwt.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index a45032f..24305ed 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -120,10 +120,13 @@ impl DWT { } /// Returns `true` if the implementation supports a cycle counter - #[cfg(not(armv6m))] #[inline] pub fn has_cycle_counter(&self) -> bool { - !self.ctrl.read().nocyccnt() + #[cfg(not(armv6m))] + return !self.ctrl.read().nocyccnt(); + + #[cfg(armv6m)] + return false; } /// Returns `true` if the implementation the profiling counters -- cgit v1.2.3 From a0ffab5ca628a98f691568aa43cbf437a3b7f925 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Wed, 15 Dec 2021 12:10:18 -0800 Subject: fix fields, SBZ as needed for address compare --- src/peripheral/dwt.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 24305ed..9751d7a 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -90,9 +90,9 @@ bitfield! { cycmatch, set_cycmatch: 7; datavmatch, set_datavmatch: 8; lnk1ena, set_lnk1ena: 9; - u8, datavsize, set_datavsize: 2, 10; - u8, datavaddr0, set_datavaddr0: 4, 12; - u8, datavaddr1, set_datavaddr1: 4, 16; + u8, datavsize, set_datavsize: 11, 10; + u8, datavaddr0, set_datavaddr0: 15, 12; + u8, datavaddr1, set_datavaddr1: 19, 16; matched, _: 24; } @@ -448,6 +448,10 @@ impl Comparator { // don't compare cycle counter value // NOTE: only needed for comparator 0, but is SBZP. r.set_cycmatch(false); + // SBZ as needed, see Page 784/C1-724 + r.set_datavsize(0); + r.set_datavaddr0(0); + r.set_datavaddr1(0); r }); -- cgit v1.2.3 From 1b5b39e5d9de9e8e715aeec71f8b0476b9aa9c8f Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Thu, 16 Dec 2021 09:28:54 -0800 Subject: change has_cycle_counter to a recommended end user call --- src/peripheral/dwt.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 9751d7a..e4845c7 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -389,9 +389,10 @@ pub struct CycleCountSettings { pub enum ComparatorFunction { /// Compare accessed memory addresses. Address(ComparatorAddressSettings), - /// Compare cycle count & target value. + /// Compare cycle count & target value. /// - /// **NOTE**: only supported by comparator 0. See C1.8.1. + /// **NOTE**: only supported by comparator 0 and if the HW supports the cycle counter. + /// Check `dwt.has_cycle_counter` for support. See C1.8.1 for more details. CycleCount(CycleCountSettings), } @@ -408,7 +409,7 @@ pub enum DwtError { impl Comparator { /// Configure the function of the comparator #[allow(clippy::missing_inline_in_public_items)] - pub fn configure(&self, dwt: &DWT, settings: ComparatorFunction) -> Result<(), DwtError> { + pub fn configure(&self, settings: ComparatorFunction) -> Result<(), DwtError> { match settings { ComparatorFunction::Address(settings) => { // FUNCTION, EMITRANGE @@ -461,10 +462,6 @@ impl Comparator { } } ComparatorFunction::CycleCount(settings) => { - if !dwt.has_cycle_counter() { - return Err(DwtError::NoCycleCount); - } - let function = match &settings.emit { EmitOption::PCData => 0b0001, EmitOption::WatchpointDebugEvent => 0b0100, -- cgit v1.2.3 From ec48cf3c24e7debb27770e31cec6ba54fb1484a0 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Thu, 16 Dec 2021 09:37:54 -0800 Subject: remove unused error --- src/peripheral/dwt.rs | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index e4845c7..3886b43 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -402,8 +402,6 @@ pub enum ComparatorFunction { pub enum DwtError { /// Invalid combination of [AccessType] and [EmitOption]. InvalidFunction, - /// The DWT block does not implement cycle count capabilities. - NoCycleCount, } impl Comparator { -- cgit v1.2.3 From 4d2c1989644cf628788073400ad1a263ab2de6c1 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Thu, 16 Dec 2021 10:00:39 -0800 Subject: make intra-doc link --- src/peripheral/dwt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 3886b43..db0398d 100644 --- a/src/peripheral/dwt.rs +++ b/src/peripheral/dwt.rs @@ -392,7 +392,7 @@ pub enum ComparatorFunction { /// Compare cycle count & target value. /// /// **NOTE**: only supported by comparator 0 and if the HW supports the cycle counter. - /// Check `dwt.has_cycle_counter` for support. See C1.8.1 for more details. + /// Check [`DWT::has_cycle_counter`] for support. See C1.8.1 for more details. CycleCount(CycleCountSettings), } -- cgit v1.2.3 From f0dc654951d7aa7910b662c4da61c06bab671729 Mon Sep 17 00:00:00 2001 From: Tyler Holmes Date: Wed, 15 Dec 2021 11:27:04 -0800 Subject: Switch "native" check from being x86_64 only to checking `HOST` If `HOST==TARGET`, we know we're compiling natively. Set a new `rustc` cfg for this and use it where we previously checked for `x86_64`. --- build.rs | 7 +++++-- src/peripheral/icb.rs | 6 +++--- src/peripheral/mod.rs | 8 ++++---- src/peripheral/scb.rs | 10 +++++----- 4 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/build.rs b/build.rs index dc9b3a0..be5b48a 100644 --- a/build.rs +++ b/build.rs @@ -3,9 +3,12 @@ use std::{env, fs}; fn main() { let target = env::var("TARGET").unwrap(); + let host_triple = env::var("HOST").unwrap(); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let name = env::var("CARGO_PKG_NAME").unwrap(); + let native_compilation = host_triple == target; + if target.starts_with("thumb") { let suffix = if env::var_os("CARGO_FEATURE_LINKER_PLUGIN_LTO").is_some() { "-lto" @@ -43,7 +46,7 @@ fn main() { println!("cargo:rustc-cfg=armv8m_main"); } - if target.ends_with("-eabihf") { - println!("cargo:rustc-cfg=has_fpu"); + if native_compilation { + println!("cargo:rustc-cfg=native"); } } diff --git a/src/peripheral/icb.rs b/src/peripheral/icb.rs index 9b29655..e1de33b 100644 --- a/src/peripheral/icb.rs +++ b/src/peripheral/icb.rs @@ -1,6 +1,6 @@ //! Implementation Control Block -#[cfg(any(armv7m, armv8m, target_arch = "x86_64"))] +#[cfg(any(armv7m, armv8m, native))] use volatile_register::RO; use volatile_register::RW; @@ -12,12 +12,12 @@ pub struct RegisterBlock { /// The bottom four bits of this register give the number of implemented /// interrupt lines, divided by 32. So a value of `0b0010` indicates 64 /// interrupts. - #[cfg(any(armv7m, armv8m, target_arch = "x86_64"))] + #[cfg(any(armv7m, armv8m, native))] pub ictr: RO, /// The ICTR is not defined in the ARMv6-M Architecture Reference manual, so /// we replace it with this. - #[cfg(not(any(armv7m, armv8m, target_arch = "x86_64")))] + #[cfg(not(any(armv7m, armv8m, native)))] _reserved: u32, /// Auxiliary Control Register diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 081aa0a..d1e119f 100644 --- a/src/peripheral/mod.rs +++ b/src/peripheral/mod.rs @@ -71,8 +71,8 @@ pub mod dcb; pub mod dwt; #[cfg(not(armv6m))] pub mod fpb; -// NOTE(target_arch) is for documentation purposes -#[cfg(any(has_fpu, target_arch = "x86_64"))] +// NOTE(native) is for documentation purposes +#[cfg(any(has_fpu, native))] pub mod fpu; pub mod icb; #[cfg(all(not(armv6m), not(armv8m_base)))] @@ -411,7 +411,7 @@ pub struct FPU { unsafe impl Send for FPU {} -#[cfg(any(has_fpu, target_arch = "x86_64"))] +#[cfg(any(has_fpu, native))] impl FPU { /// Pointer to the register block pub const PTR: *const fpu::RegisterBlock = 0xE000_EF30 as *const _; @@ -423,7 +423,7 @@ impl FPU { } } -#[cfg(any(has_fpu, target_arch = "x86_64"))] +#[cfg(any(has_fpu, native))] impl ops::Deref for FPU { type Target = self::fpu::RegisterBlock; diff --git a/src/peripheral/scb.rs b/src/peripheral/scb.rs index 28cfca8..b61c4ff 100644 --- a/src/peripheral/scb.rs +++ b/src/peripheral/scb.rs @@ -182,7 +182,7 @@ impl SCB { 5 => VectActive::Exception(Exception::BusFault), #[cfg(not(armv6m))] 6 => VectActive::Exception(Exception::UsageFault), - #[cfg(any(armv8m, target_arch = "x86_64"))] + #[cfg(any(armv8m, native))] 7 => VectActive::Exception(Exception::SecureFault), 11 => VectActive::Exception(Exception::SVCall), #[cfg(not(armv6m))] @@ -218,7 +218,7 @@ pub enum Exception { UsageFault, /// Secure fault interrupt (only on ARMv8-M) - #[cfg(any(armv8m, target_arch = "x86_64"))] + #[cfg(any(armv8m, native))] SecureFault, /// SV call interrupt @@ -250,7 +250,7 @@ impl Exception { Exception::BusFault => -11, #[cfg(not(armv6m))] Exception::UsageFault => -10, - #[cfg(any(armv8m, target_arch = "x86_64"))] + #[cfg(any(armv8m, native))] Exception::SecureFault => -9, Exception::SVCall => -5, #[cfg(not(armv6m))] @@ -293,7 +293,7 @@ impl VectActive { 5 => VectActive::Exception(Exception::BusFault), #[cfg(not(armv6m))] 6 => VectActive::Exception(Exception::UsageFault), - #[cfg(any(armv8m, target_arch = "x86_64"))] + #[cfg(any(armv8m, native))] 7 => VectActive::Exception(Exception::SecureFault), 11 => VectActive::Exception(Exception::SVCall), #[cfg(not(armv6m))] @@ -934,7 +934,7 @@ pub enum SystemHandler { UsageFault = 6, /// Secure fault interrupt (only on ARMv8-M) - #[cfg(any(armv8m, target_arch = "x86_64"))] + #[cfg(any(armv8m, native))] SecureFault = 7, /// SV call interrupt -- cgit v1.2.3 From 7df5de5347a245cad601aea86fca93c8581ee4d3 Mon Sep 17 00:00:00 2001 From: Ian McIntyre Date: Tue, 28 Dec 2021 22:20:53 -0500 Subject: Construct a SysTick delay with a clock source Helpful for users who prefer an external clock source for their system timer. Proposing this as a 0.7 backwards-compatible change. The constructor name tries to follow the "general constructors" recommendation in the Rust API naming guidelines. https://rust-lang.github.io/api-guidelines/naming.html#casing-conforms-to-rfc-430-c-case --- CHANGELOG.md | 2 ++ src/delay.rs | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e7d1e7..fdb8be9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - 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. +- Added `delay::Delay::with_source`, a constructor that lets you specify + the SysTick clock source (#374). ### Deprecated diff --git a/src/delay.rs b/src/delay.rs index 8ed1fea..66a63bf 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -6,7 +6,7 @@ use embedded_hal::blocking::delay::{DelayMs, DelayUs}; /// System timer (SysTick) as a delay provider. pub struct Delay { syst: SYST, - ahb_frequency: u32, + frequency: u32, } impl Delay { @@ -14,13 +14,19 @@ impl Delay { /// /// `ahb_frequency` is a frequency of the AHB bus in Hz. #[inline] - pub fn new(mut syst: SYST, ahb_frequency: u32) -> Self { - syst.set_clock_source(SystClkSource::Core); + pub fn new(syst: SYST, ahb_frequency: u32) -> Self { + Self::with_source(syst, ahb_frequency, SystClkSource::Core) + } - Delay { - syst, - ahb_frequency, - } + /// Configures the system timer (SysTick) as a delay provider + /// with a clock source. + /// + /// `frequency` is the frequency of your `clock_source` in Hz. + #[inline] + pub fn with_source(mut syst: SYST, frequency: u32, clock_source: SystClkSource) -> Self { + syst.set_clock_source(clock_source); + + Delay { syst, frequency } } /// Releases the system timer (SysTick) resource. @@ -32,7 +38,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; + let ticks = (u64::from(us)) * (u64::from(self.frequency)) / 1_000_000; let full_cycles = ticks >> 24; if full_cycles > 0 { -- cgit v1.2.3