From 720282fb8ee406a14c56f67ed1595c24133f7e5d Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 28 Apr 2021 18:23:03 +0200 Subject: [PATCH 01/28] tpiu: impl functions related to trace data output --- src/peripheral/tpiu.rs | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 11cb79e9..ab8f7103 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 + } + } +} From f75f17f764bded9a75475683ac12a55ed1925d67 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 28 Apr 2021 18:46:39 +0200 Subject: [PATCH 02/28] dwt: impl functions related to trace generation --- src/peripheral/dwt.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 043223a7..4684f75f 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] From 8c53e6069b319d8d7e2c9b4a5bb58eba6dd31226 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 00:35:15 +0200 Subject: [PATCH 03/28] tpiu: fix always-zero field-comparison --- src/peripheral/tpiu.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index ab8f7103..694204de 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 } } From be983a3cb4c46646172e92a1b8abaf872faed58b Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 02:23:16 +0200 Subject: [PATCH 04/28] dwt: configure address comparison using struct --- src/peripheral/dwt.rs | 143 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 4684f75f..fd2c6d68 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(()) + } +} From 930558078e32bff74c101e2f1725f4d94f8c6902 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 02:26:51 +0200 Subject: [PATCH 05/28] dwt: add missing #[inline] --- src/peripheral/dwt.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index fd2c6d68..77be0ccd 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 { From 9285dccd332e2f14f2dfa7c2eacda652717fc1e0 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 30 Apr 2021 03:00:42 +0200 Subject: [PATCH 06/28] dcb: add note about vendor-specific trace options --- src/peripheral/dcb.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/peripheral/dcb.rs b/src/peripheral/dcb.rs index 5689cb4f..056150bc 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 From 859f9d848d4a0cb9ffcd36b8fec9f14e846921b2 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 12:38:57 +0200 Subject: [PATCH 07/28] dwt: reimplement with bitfield --- src/peripheral/dwt.rs | 141 +++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 76 deletions(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 77be0ccd..84ea6a77 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 }); From b533eb60c3a90d0eac38f142f942aaa1d3bd5256 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 13:15:35 +0200 Subject: [PATCH 08/28] itm: impl functions related to trace generation --- src/peripheral/itm.rs | 124 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index c0d560f5..b23ce8e9 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 + }); + } + } +} From fb604a76148f8756c3fe4d12458984024d80324d Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 13:27:44 +0200 Subject: [PATCH 09/28] tpiu: fix flipped SWOSupports field, reimplement with bitfield --- src/peripheral/tpiu.rs | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 694204de..5443fc0f 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(), } } } From 085e738359d03c7a72ecb6e8c1b05c2ad27e982f Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Wed, 5 May 2021 13:29:25 +0200 Subject: [PATCH 10/28] itm, dwt: limit some bitfields to u8 --- src/peripheral/dwt.rs | 2 +- src/peripheral/itm.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 84ea6a77..4097c8d9 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 b23ce8e9..83d891f2 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; } From 669c872a29921260e1e9f03f7592397c60fdbc07 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:41:35 +0200 Subject: [PATCH 11/28] dwt: feature gate trace and PC samples out of armv6m --- src/peripheral/dwt.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 4097c8d9..57c90635 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 From 362ad2df6034aea26f7f5d7fe6615e9b1436f997 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:42:29 +0200 Subject: [PATCH 12/28] itm: fix field spelling --- src/peripheral/itm.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 83d891f2..946f71ce 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, From 02853a4f03f6028b8998fc8909d9b13306dd5d11 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:51:53 +0200 Subject: [PATCH 13/28] itm: remove useless conversion --- src/peripheral/itm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 946f71ce..24b926df 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 }); From aa17958147ac57af6f10de170d869626397ba1d8 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Fri, 24 Sep 2021 05:52:28 +0200 Subject: [PATCH 14/28] allow clippy::upper_case_acronyms --- src/peripheral/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/peripheral/mod.rs b/src/peripheral/mod.rs index 961f31d0..7692f06b 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 ()>, } From c470f8bc9a62fa6305fffca22ece972733739453 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:12:11 +0100 Subject: [PATCH 15/28] 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(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 720511b5..188681be 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 24b926df..626fba21 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 5443fc0f..9ff92d10 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! { From 6ddc7463d5fcca98df23d7730deff04823eb6efb Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:14:46 +0100 Subject: [PATCH 16/28] dwt: fix clippy::bool_comparison --- src/peripheral/dwt.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 188681be..73f90cec 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 From 35bb481f462a4ed113bf9d562343da4922425de0 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:15:48 +0100 Subject: [PATCH 17/28] dwt: improve EmitOption docstring --- src/peripheral/dwt.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 73f90cec..597accd5 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, From 021420b11fa7f51b5daae46fbfbcd19a370bc75d Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:16:39 +0100 Subject: [PATCH 18/28] 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(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 597accd5..8bb063f4 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 From 0e647743de4a87b4a04fb02178d3a76ef053fb42 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:20:57 +0100 Subject: [PATCH 19/28] dwt: refactor out unnecessary explicit panic --- src/peripheral/dwt.rs | 52 ++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 8bb063f4..0b0d774a 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 }); From d45bad7f6d2abdf7f1ea27868791987e87bd2876 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:22:27 +0100 Subject: [PATCH 20/28] tpiu: remove get_ prefix, as per Rust API guidelines --- src/peripheral/tpiu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 9ff92d10..69693f05 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(), From 633a631af6906421c087f1961c3880a93f69fd91 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:24:16 +0100 Subject: [PATCH 21/28] dwt: DWTError -> DwtError for in-crate consistency --- src/peripheral/dwt.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 0b0d774a..bf770d2f 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| { From 09929b156b3919aefd640086de68517b00c43722 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:26:07 +0100 Subject: [PATCH 22/28] 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(+) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index bf770d2f..0769e965 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, From c37f80bf35a9b81bbcdd9491abad0e550afb187b Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 01:28:27 +0100 Subject: [PATCH 23/28] itm: properly document ITMSettings --- src/peripheral/itm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peripheral/itm.rs b/src/peripheral/itm.rs index 626fba21..f5f5935a 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. From 1efe31942b701d23a9d214f537adbfb471d25b9c Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 02:10:17 +0100 Subject: [PATCH 24/28] tpiu: use bitfield for SPPR --- src/peripheral/tpiu.rs | 43 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index 69693f05..e020b811 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 From 5a92298d9c12685214b12266357fe7c104035b59 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 02:11:06 +0100 Subject: [PATCH 25/28] tpiu: improve TYPE field documentation --- src/peripheral/tpiu.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/peripheral/tpiu.rs b/src/peripheral/tpiu.rs index e020b811..582544bc 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); From 92c15ed56da6331c1f7bc4bb1372b56e3fc93a05 Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sun, 21 Nov 2021 02:20:51 +0100 Subject: [PATCH 26/28] 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(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 0769e965..7fc9478e 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 f5f5935a..4d0aa220 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 582544bc..3ff5f550 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, From 360fb334c7cec241ca4e396b5ab23c58fb8905fe Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sat, 27 Nov 2021 10:32:37 +0100 Subject: [PATCH 27/28] dwt: refactor enable_exception_tracing into enable/disable funs --- src/peripheral/dwt.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/peripheral/dwt.rs b/src/peripheral/dwt.rs index 7fc9478e..11dd5455 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 }); } From c1d434a7e7ee1a04ce06c3e3bcdb9b65e048b8ba Mon Sep 17 00:00:00 2001 From: Viktor Sonesten Date: Sat, 27 Nov 2021 13:34:28 +0100 Subject: [PATCH 28/28] 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(-) diff --git a/.github/bors.toml b/.github/bors.toml index 63d883fd..0cf10c79 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 72890855..86000548 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 6bd8aedd..6011ab2b 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 6a736924..a2677503 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))]