@@ -16,7 +16,7 @@ pub struct RegisterBlock {
1616 pub cspsr : RW < u32 > ,
1717 reserved0 : [ u32 ; 2 ] ,
1818 /// Asynchronous Clock Prescaler
19- pub acpr : RW < u32 > ,
19+ pub acpr : RW < Acpr > ,
2020 reserved1 : [ u32 ; 55 ] ,
2121 /// Selected Pin Control
2222 pub sppr : RW < Sppr > ,
@@ -41,6 +41,14 @@ bitfield! {
4141 enfcont, set_enfcont: 1 ;
4242}
4343
44+ bitfield ! {
45+ /// TPIU ACPR Register.
46+ #[ repr( C ) ]
47+ #[ derive( Clone , Copy ) ]
48+ pub struct Acpr ( u32 ) ;
49+ u16 , swoscaler, set_swoscaler: 15 , 0 ;
50+ }
51+
4452bitfield ! {
4553 /// TPIU Type Register.
4654 #[ repr( C ) ]
@@ -101,15 +109,54 @@ pub struct SWOSupports {
101109 pub min_queue_size : u8 ,
102110}
103111
112+ /// Possible errors on [`TPIU::set_swo_baud_rate`].
113+ #[ derive( Debug , Eq , PartialEq , Copy , Clone ) ]
114+ pub enum ACPRError {
115+ /// The reference clock frequency divided by the requested baud rate
116+ /// did not yield an integer.
117+ NonInteger ,
118+ /// Required prescaler value is too large. Largest supported
119+ /// prescaler value is [`u16::MAX`].
120+ TooLarge ,
121+ }
122+
104123impl TPIU {
105124 /// Sets the prescaler value for a wanted baud rate of the Serial
106125 /// Wire Output (SWO) in relation to a given asynchronous refernce
107- /// clock rate.
126+ /// clock rate. Returns `true` if a prescaler was correctly
127+ /// calculated and applied, `false` otherwise.
128+ ///
129+ /// See C1.10.4 "Asynchronous Clock Prescaler Register, TPIU_ACPR".
108130 #[ inline]
109- pub fn set_swo_baud_rate ( & mut self , ref_clk_rate : u32 , baud_rate : u32 ) {
131+ pub fn set_swo_baud_rate (
132+ & mut self ,
133+ ref_clk_rate : u32 ,
134+ baud_rate : u32 ,
135+ ) -> Result < ( ) , ACPRError > {
136+ use ACPRError as Error ;
137+
138+ if ref_clk_rate % baud_rate != 0 {
139+ return Err ( Error :: NonInteger ) ;
140+ }
141+
142+ use core:: convert:: TryInto ;
143+ let prescaler: u16 = match { ( ( ref_clk_rate / baud_rate) - 1 ) . try_into ( ) } {
144+ Ok ( ps) => ps,
145+ Err ( _) => return Err ( Error :: TooLarge ) ,
146+ } ;
147+
110148 unsafe {
111- self . acpr . write ( ( ref_clk_rate / baud_rate) - 1 ) ;
149+ self . acpr . modify ( |mut r| {
150+ r. set_swoscaler ( prescaler) ;
151+ r
152+ } ) ;
153+ }
154+
155+ if self . acpr . read ( ) . swoscaler ( ) != prescaler {
156+ return Err ( Error :: TooLarge ) ;
112157 }
158+
159+ Ok ( ( ) )
113160 }
114161
115162 /// The used protocol for the trace output. Return `None` if an
0 commit comments