@@ -16,7 +16,7 @@ pub struct RegisterBlock {
16
16
pub cspsr : RW < u32 > ,
17
17
reserved0 : [ u32 ; 2 ] ,
18
18
/// Asynchronous Clock Prescaler
19
- pub acpr : RW < u32 > ,
19
+ pub acpr : RW < Acpr > ,
20
20
reserved1 : [ u32 ; 55 ] ,
21
21
/// Selected Pin Control
22
22
pub sppr : RW < Sppr > ,
@@ -41,6 +41,14 @@ bitfield! {
41
41
enfcont, set_enfcont: 1 ;
42
42
}
43
43
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
+
44
52
bitfield ! {
45
53
/// TPIU Type Register.
46
54
#[ repr( C ) ]
@@ -101,15 +109,54 @@ pub struct SWOSupports {
101
109
pub min_queue_size : u8 ,
102
110
}
103
111
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
+
104
123
impl TPIU {
105
124
/// Sets the prescaler value for a wanted baud rate of the Serial
106
125
/// 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".
108
130
#[ 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
+
110
148
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 ) ;
112
157
}
158
+
159
+ Ok ( ( ) )
113
160
}
114
161
115
162
/// The used protocol for the trace output. Return `None` if an
0 commit comments