@@ -12,7 +12,12 @@ use core::{convert::Infallible, ops::Deref};
12
12
use crate :: {
13
13
gpio:: { gpioa, gpiob, gpioc, AF7 } ,
14
14
hal:: { blocking, serial} ,
15
- pac:: { self , rcc:: cfgr3:: USART1SW_A , usart1:: RegisterBlock , USART1 , USART2 , USART3 } ,
15
+ pac:: {
16
+ self ,
17
+ rcc:: cfgr3:: USART1SW_A ,
18
+ usart1:: { cr1:: M_A , cr1:: PCE_A , cr1:: PS_A , RegisterBlock } ,
19
+ USART1 , USART2 , USART3 ,
20
+ } ,
16
21
rcc:: { Clocks , APB1 , APB2 } ,
17
22
time:: rate:: * ,
18
23
} ;
@@ -111,6 +116,100 @@ cfg_if! {
111
116
}
112
117
}
113
118
119
+ /// Types for configuring a serial interface.
120
+ pub mod config {
121
+ use crate :: time:: rate:: { Baud , Extensions } ;
122
+
123
+ // Reexport stop bit enum from PAC. In case there is a breaking change,
124
+ // provide a compatible enum from this HAL.
125
+ pub use crate :: pac:: usart1:: cr2:: STOP_A as StopBits ;
126
+
127
+ /// Parity generation and checking. If odd or even parity is selected, the
128
+ /// underlying USART will be configured to send/receive the parity bit in
129
+ /// addtion to the data bits.
130
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
131
+ #[ derive( Clone , Copy , PartialEq ) ]
132
+ pub enum Parity {
133
+ /// No parity bit will be added/checked.
134
+ None ,
135
+ /// The MSB transmitted/received will be generated/checked to have a
136
+ /// even number of bits set.
137
+ Even ,
138
+ /// The MSB transmitted/received will be generated/checked to have a
139
+ /// odd number of bits set.
140
+ Odd ,
141
+ }
142
+
143
+ /// Configuration struct for [`Serial`](super::Serial) providing all
144
+ /// communication-related / parameters. `Serial` always uses eight data
145
+ /// bits plus the parity bit - if selected.
146
+ ///
147
+ /// Create a configuration by using `default` in combination with the
148
+ /// builder methods. The following snippet shows creating a configuration
149
+ /// for 19,200 Baud, 8N1 by deriving it from the default value:
150
+ /// ```
151
+ /// # use stm32f3xx_hal::serial::config::*;
152
+ /// # use stm32f3xx_hal::time::rate::{Baud, Extensions};
153
+ /// let config = Config::default().baudrate(19_200.Bd());
154
+ ///
155
+ /// assert!(config.baudrate == 19_200.Bd());
156
+ /// assert!(config.parity == Parity::None);
157
+ /// assert!(config.stopbits == StopBits::STOP1);
158
+ /// ```
159
+ #[ derive( Clone , Copy , PartialEq ) ]
160
+ #[ non_exhaustive]
161
+ pub struct Config {
162
+ /// Serial interface baud rate
163
+ pub baudrate : Baud ,
164
+ /// Whether and how to generate/check a parity bit
165
+ pub parity : Parity ,
166
+ /// The number of stop bits to follow the last data bit or the parity
167
+ /// bit
168
+ pub stopbits : StopBits ,
169
+ }
170
+
171
+ impl Config {
172
+ /// Sets the given baudrate.
173
+ pub fn baudrate ( mut self , baudrate : impl Into < Baud > ) -> Self {
174
+ self . baudrate = baudrate. into ( ) ;
175
+ self
176
+ }
177
+
178
+ /// Sets the given parity.
179
+ pub fn parity ( mut self , parity : Parity ) -> Self {
180
+ self . parity = parity;
181
+ self
182
+ }
183
+
184
+ /// Sets the stop bits to `stopbits`.
185
+ pub fn stopbits ( mut self , stopbits : StopBits ) -> Self {
186
+ self . stopbits = stopbits;
187
+ self
188
+ }
189
+ }
190
+
191
+ impl Default for Config {
192
+ /// Creates a new configuration with typically used parameters: 115,200
193
+ /// Baud 8N1.
194
+ fn default ( ) -> Config {
195
+ Config {
196
+ baudrate : 115_200 . Bd ( ) ,
197
+ parity : Parity :: None ,
198
+ stopbits : StopBits :: STOP1 ,
199
+ }
200
+ }
201
+ }
202
+
203
+ impl < T : Into < Baud > > From < T > for Config {
204
+ fn from ( b : T ) -> Config {
205
+ Config {
206
+ baudrate : b. into ( ) ,
207
+ ..Default :: default ( )
208
+ }
209
+ }
210
+ }
211
+ }
212
+
114
213
/// Serial abstraction
115
214
pub struct Serial < Usart , Pins > {
116
215
usart : Usart ,
@@ -211,30 +310,55 @@ where
211
310
Usart : Instance ,
212
311
{
213
312
/// Configures a USART peripheral to provide serial communication
214
- pub fn new (
313
+ pub fn new < Config > (
215
314
usart : Usart ,
216
315
pins : ( Tx , Rx ) ,
217
- baud_rate : Baud ,
316
+ config : Config ,
218
317
clocks : Clocks ,
219
318
apb : & mut <Usart as Instance >:: APB ,
220
319
) -> Self
221
320
where
222
321
Usart : Instance ,
223
322
Tx : TxPin < Usart > ,
224
323
Rx : RxPin < Usart > ,
324
+ Config : Into < config:: Config > ,
225
325
{
326
+ use self :: config:: * ;
327
+
328
+ let config = config. into ( ) ;
329
+
330
+ // Enable USART peripheral for any further interaction.
226
331
Usart :: enable_clock ( apb) ;
332
+ // Disable USART because some configuration bits could only be written
333
+ // in this state.
334
+ usart. cr1 . modify ( |_, w| w. ue ( ) . disabled ( ) ) ;
227
335
228
- let brr = Usart :: clock ( & clocks) . integer ( ) / baud_rate . integer ( ) ;
336
+ let brr = Usart :: clock ( & clocks) . integer ( ) / config . baudrate . integer ( ) ;
229
337
crate :: assert!( brr >= 16 , "impossible baud rate" ) ;
230
338
usart. brr . write ( |w| w. brr ( ) . bits ( brr as u16 ) ) ;
231
339
340
+ // We currently support only eight data bits as supporting a full-blown
341
+ // configuration gets complicated pretty fast. The USART counts data
342
+ // and partiy bits together so the actual amount depends on the parity
343
+ // selection.
344
+ let ( m0, ps, pce) = match config. parity {
345
+ Parity :: None => ( M_A :: BIT8 , PS_A :: EVEN , PCE_A :: DISABLED ) ,
346
+ Parity :: Even => ( M_A :: BIT9 , PS_A :: EVEN , PCE_A :: ENABLED ) ,
347
+ Parity :: Odd => ( M_A :: BIT9 , PS_A :: ODD , PCE_A :: ENABLED ) ,
348
+ } ;
349
+
350
+ usart. cr2 . modify ( |_, w| w. stop ( ) . variant ( config. stopbits ) ) ;
232
351
usart. cr1 . modify ( |_, w| {
233
- w. ue ( ) . enabled ( ) ; // enable USART
352
+ w. ps ( ) . variant ( ps) ; // set parity mode
353
+ w. pce ( ) . variant ( pce) ; // enable parity checking/generation
354
+ w. m ( ) . variant ( m0) ; // set data bits
234
355
w. re ( ) . enabled ( ) ; // enable receiver
235
356
w. te ( ) . enabled ( ) // enable transmitter
236
357
} ) ;
237
358
359
+ // Finally enable the configured UART.
360
+ usart. cr1 . modify ( |_, w| w. ue ( ) . enabled ( ) ) ;
361
+
238
362
Self { usart, pins }
239
363
}
240
364
0 commit comments