@@ -145,6 +145,10 @@ pub trait RegisterBlockImpl: crate::Sealed {
145
145
146
146
// PeriAddress
147
147
fn peri_address ( & self ) -> u32 ;
148
+
149
+ fn enable_dma ( & self , dc : config:: DmaConfig ) ;
150
+
151
+ fn calculate_brr ( pclk_freq : u32 , baud : u32 ) -> Result < ( bool , u32 ) , config:: InvalidConfig > ;
148
152
}
149
153
150
154
macro_rules! uartCommon {
@@ -259,6 +263,67 @@ macro_rules! uartCommon {
259
263
fn peri_address( & self ) -> u32 {
260
264
self . dr( ) . as_ptr( ) as u32
261
265
}
266
+
267
+ fn enable_dma( & self , dc: config:: DmaConfig ) {
268
+ use config:: DmaConfig ;
269
+ match dc {
270
+ DmaConfig :: Tx => self . cr3( ) . write( |w| w. dmat( ) . enabled( ) ) ,
271
+ DmaConfig :: Rx => self . cr3( ) . write( |w| w. dmar( ) . enabled( ) ) ,
272
+ DmaConfig :: TxRx => self . cr3( ) . write( |w| w. dmar( ) . enabled( ) . dmat( ) . enabled( ) ) ,
273
+ DmaConfig :: None => { }
274
+ }
275
+ }
276
+
277
+ fn calculate_brr( pclk_freq: u32 , baud: u32 ) -> Result <( bool , u32 ) , config:: InvalidConfig > {
278
+ // The frequency to calculate USARTDIV is this:
279
+ //
280
+ // (Taken from STM32F411xC/E Reference Manual,
281
+ // Section 19.3.4, Equation 1)
282
+ //
283
+ // 16 bit oversample: OVER8 = 0
284
+ // 8 bit oversample: OVER8 = 1
285
+ //
286
+ // USARTDIV = (pclk)
287
+ // ------------------------
288
+ // 8 x (2 - OVER8) x (baud)
289
+ //
290
+ // BUT, the USARTDIV has 4 "fractional" bits, which effectively
291
+ // means that we need to "correct" the equation as follows:
292
+ //
293
+ // USARTDIV = (pclk) * 16
294
+ // ------------------------
295
+ // 8 x (2 - OVER8) x (baud)
296
+ //
297
+ // When OVER8 is enabled, we can only use the lowest three
298
+ // fractional bits, so we'll need to shift those last four bits
299
+ // right one bit
300
+
301
+ // Calculate correct baudrate divisor on the fly
302
+ if ( pclk_freq / 16 ) >= baud {
303
+ // We have the ability to oversample to 16 bits, take
304
+ // advantage of it.
305
+ //
306
+ // We also add `baud / 2` to the `pclk_freq` to ensure
307
+ // rounding of values to the closest scale, rather than the
308
+ // floored behavior of normal integer division.
309
+ let div = ( pclk_freq + ( baud / 2 ) ) / baud;
310
+ Ok ( ( false , div) )
311
+ } else if ( pclk_freq / 8 ) >= baud {
312
+ // We are close enough to pclk where we can only
313
+ // oversample 8.
314
+ //
315
+ // See note above regarding `baud` and rounding.
316
+ let div = ( ( pclk_freq * 2 ) + ( baud / 2 ) ) / baud;
317
+
318
+ // Ensure the the fractional bits (only 3) are
319
+ // right-aligned.
320
+ let frac = div & 0xF ;
321
+ let div = ( div & !0xF ) | ( frac >> 1 ) ;
322
+ Ok ( ( true , div) )
323
+ } else {
324
+ Err ( config:: InvalidConfig )
325
+ }
326
+ }
262
327
} ;
263
328
}
264
329
@@ -282,66 +347,11 @@ where {
282
347
let pclk_freq = UART :: clock ( clocks) . raw ( ) ;
283
348
let baud = config. baudrate . 0 ;
284
349
285
- // The frequency to calculate USARTDIV is this:
286
- //
287
- // (Taken from STM32F411xC/E Reference Manual,
288
- // Section 19.3.4, Equation 1)
289
- //
290
- // 16 bit oversample: OVER8 = 0
291
- // 8 bit oversample: OVER8 = 1
292
- //
293
- // USARTDIV = (pclk)
294
- // ------------------------
295
- // 8 x (2 - OVER8) x (baud)
296
- //
297
- // BUT, the USARTDIV has 4 "fractional" bits, which effectively
298
- // means that we need to "correct" the equation as follows:
299
- //
300
- // USARTDIV = (pclk) * 16
301
- // ------------------------
302
- // 8 x (2 - OVER8) x (baud)
303
- //
304
- // When OVER8 is enabled, we can only use the lowest three
305
- // fractional bits, so we'll need to shift those last four bits
306
- // right one bit
307
- //
308
- // In IrDA Smartcard, LIN, and IrDA modes, OVER8 is always disabled.
309
- //
310
- // (Taken from STM32F411xC/E Reference Manual,
311
- // Section 19.3.4, Equation 2)
312
- //
313
- // USARTDIV = pclk
314
- // ---------
315
- // 16 x baud
316
- //
317
- // With reference to the above, OVER8 == 0 when in Smartcard, LIN, and
318
- // IrDA modes, so the register value needed for USARTDIV is the same
319
- // as for 16 bit oversampling.
320
-
321
- // Calculate correct baudrate divisor on the fly
322
- let ( over8, div) = if ( pclk_freq / 16 ) >= baud || config. irda != IrdaMode :: None {
323
- // We have the ability to oversample to 16 bits, take
324
- // advantage of it.
325
- //
326
- // We also add `baud / 2` to the `pclk_freq` to ensure
327
- // rounding of values to the closest scale, rather than the
328
- // floored behavior of normal integer division.
350
+ let ( over8, div) = if config. irda != IrdaMode :: None {
329
351
let div = ( pclk_freq + ( baud / 2 ) ) / baud;
330
352
( false , div)
331
- } else if ( pclk_freq / 8 ) >= baud {
332
- // We are close enough to pclk where we can only
333
- // oversample 8.
334
- //
335
- // See note above regarding `baud` and rounding.
336
- let div = ( ( pclk_freq * 2 ) + ( baud / 2 ) ) / baud;
337
-
338
- // Ensure the the fractional bits (only 3) are
339
- // right-aligned.
340
- let frac = div & 0xF ;
341
- let div = ( div & !0xF ) | ( frac >> 1 ) ;
342
- ( true , div)
343
353
} else {
344
- return Err ( config :: InvalidConfig ) ;
354
+ Self :: calculate_brr ( pclk_freq , baud ) ?
345
355
} ;
346
356
347
357
uart. brr ( ) . write ( |w| unsafe { w. bits ( div) } ) ;
@@ -384,12 +394,7 @@ where {
384
394
w. ps ( ) . bit ( config. parity == Parity :: ParityOdd )
385
395
} ) ;
386
396
387
- match config. dma {
388
- DmaConfig :: Tx => uart. cr3 ( ) . write ( |w| w. dmat ( ) . enabled ( ) ) ,
389
- DmaConfig :: Rx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) ) ,
390
- DmaConfig :: TxRx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) . dmat ( ) . enabled ( ) ) ,
391
- DmaConfig :: None => { }
392
- }
397
+ uart. enable_dma ( config. dma ) ;
393
398
394
399
let serial = Serial {
395
400
tx : Tx :: new ( uart, pins. 0 . into ( ) ) ,
@@ -423,54 +428,7 @@ where {
423
428
let pclk_freq = UART :: clock ( clocks) . raw ( ) ;
424
429
let baud = config. baudrate . 0 ;
425
430
426
- // The frequency to calculate USARTDIV is this:
427
- //
428
- // (Taken from STM32F411xC/E Reference Manual,
429
- // Section 19.3.4, Equation 1)
430
- //
431
- // 16 bit oversample: OVER8 = 0
432
- // 8 bit oversample: OVER8 = 1
433
- //
434
- // USARTDIV = (pclk)
435
- // ------------------------
436
- // 8 x (2 - OVER8) x (baud)
437
- //
438
- // BUT, the USARTDIV has 4 "fractional" bits, which effectively
439
- // means that we need to "correct" the equation as follows:
440
- //
441
- // USARTDIV = (pclk) * 16
442
- // ------------------------
443
- // 8 x (2 - OVER8) x (baud)
444
- //
445
- // When OVER8 is enabled, we can only use the lowest three
446
- // fractional bits, so we'll need to shift those last four bits
447
- // right one bit
448
-
449
- // Calculate correct baudrate divisor on the fly
450
- let ( over8, div) = if ( pclk_freq / 16 ) >= baud {
451
- // We have the ability to oversample to 16 bits, take
452
- // advantage of it.
453
- //
454
- // We also add `baud / 2` to the `pclk_freq` to ensure
455
- // rounding of values to the closest scale, rather than the
456
- // floored behavior of normal integer division.
457
- let div = ( pclk_freq + ( baud / 2 ) ) / baud;
458
- ( false , div)
459
- } else if ( pclk_freq / 8 ) >= baud {
460
- // We are close enough to pclk where we can only
461
- // oversample 8.
462
- //
463
- // See note above regarding `baud` and rounding.
464
- let div = ( ( pclk_freq * 2 ) + ( baud / 2 ) ) / baud;
465
-
466
- // Ensure the the fractional bits (only 3) are
467
- // right-aligned.
468
- let frac = div & 0xF ;
469
- let div = ( div & !0xF ) | ( frac >> 1 ) ;
470
- ( true , div)
471
- } else {
472
- return Err ( config:: InvalidConfig ) ;
473
- } ;
431
+ let ( over8, div) = Self :: calculate_brr ( pclk_freq, baud) ?;
474
432
475
433
uart. brr ( ) . write ( |w| unsafe { w. bits ( div) } ) ;
476
434
@@ -491,12 +449,7 @@ where {
491
449
w. ps ( ) . bit ( config. parity == Parity :: ParityOdd )
492
450
} ) ;
493
451
494
- match config. dma {
495
- DmaConfig :: Tx => uart. cr3 ( ) . write ( |w| w. dmat ( ) . enabled ( ) ) ,
496
- DmaConfig :: Rx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) ) ,
497
- DmaConfig :: TxRx => uart. cr3 ( ) . write ( |w| w. dmar ( ) . enabled ( ) . dmat ( ) . enabled ( ) ) ,
498
- DmaConfig :: None => { }
499
- }
452
+ uart. enable_dma ( config. dma ) ;
500
453
501
454
let serial = Serial {
502
455
tx : Tx :: new ( uart, pins. 0 . into ( ) ) ,
0 commit comments