@@ -12,11 +12,14 @@ use core::{convert::Infallible, ops::Deref};
1212use crate :: {
1313 gpio:: { gpioa, gpiob, gpioc, AF7 } ,
1414 hal:: { blocking, serial} ,
15- pac:: { self , rcc:: cfgr3:: USART1SW_A , usart1:: RegisterBlock , RCC , USART1 , USART2 , USART3 } ,
15+ pac:: { self , rcc:: cfgr3:: USART1SW_A , usart1:: RegisterBlock , USART1 , USART2 , USART3 } ,
1616 rcc:: { Clocks , APB1 , APB2 } ,
1717 time:: rate:: * ,
1818} ;
1919
20+ #[ allow( unused_imports) ]
21+ use crate :: pac:: RCC ;
22+
2023use cfg_if:: cfg_if;
2124
2225cfg_if ! {
@@ -492,35 +495,32 @@ pub trait Instance: Deref<Target = RegisterBlock> + private::Sealed {
492495}
493496
494497macro_rules! usart {
495- ( $( $USARTX: ident: ( $usartXen: ident, $APB: ident, $pclkX: ident, $usartXrst: ident, $usartXsw: ident) , ) +) => {
498+ (
499+ $(
500+ $USARTX: ident: (
501+ $usartXen: ident,
502+ $APB: ident,
503+ $pclkX: ident,
504+ $usartXrst: ident,
505+ $usartXsw: ident,
506+ $usartXclock: ident
507+ ) ,
508+ ) +
509+ ) => {
496510 $(
497511 impl private:: Sealed for $USARTX { }
498512 impl Instance for $USARTX {
499513 type APB = $APB;
500514 fn enable_clock( apb: & mut Self :: APB ) {
501515 apb. enr( ) . modify( |_, w| w. $usartXen( ) . enabled( ) ) ;
502516 apb. rstr( ) . modify( |_, w| w. $usartXrst( ) . reset( ) ) ;
503- apb. rstr( ) . modify( |_, w| w. $usartXrst( ) . clear_bit( ) ) ;
504517 }
505518
506519 fn clock( clocks: & Clocks ) -> Hertz {
507- // NOTE(unsafe) atomic read with no side effects
508-
509- // This is only partly sovable by this. The macro has to be adjusted, to give
510- // information about, if sw is avalible for the uart implementation or not
511- cfg_if:: cfg_if! {
512- if #[ cfg( any( feature = "svd-f301" , feature = "svd-f3x4" ) ) ] {
513- clocks. $pclkX( )
514- } else {
515- // FIXME usart2sw() is not avalible for stm32f318x8 for example
516- match unsafe { ( * RCC :: ptr( ) ) . cfgr3. read( ) . $usartXsw( ) . variant( ) } {
517- USART1SW_A :: PCLK => clocks. $pclkX( ) ,
518- USART1SW_A :: HSI => crate :: rcc:: HSI ,
519- USART1SW_A :: SYSCLK => clocks. sysclk( ) ,
520- USART1SW_A :: LSE => crate :: rcc:: LSE ,
521- }
522- }
523- }
520+ // Use the function created via another macro outside of this one,
521+ // because the implementation is dependend on the type $USARTX.
522+ // But macros can not differentiate between types.
523+ $usartXclock( clocks)
524524 }
525525 }
526526
@@ -552,12 +552,79 @@ macro_rules! usart {
552552 ( [ $( ( $X: literal, $APB: literal) ) ,+ ] ) => {
553553 paste:: paste! {
554554 usart!(
555- $( [ <USART $X>] : ( [ <usart $X en>] , [ <APB $APB>] , [ <pclk $APB>] , [ <usart $X rst>] , [ <usart $X sw>] ) , ) +
555+ $(
556+ [ <USART $X>] : (
557+ [ <usart $X en>] ,
558+ [ <APB $APB>] ,
559+ [ <pclk $APB>] ,
560+ [ <usart $X rst>] ,
561+ [ <usart $X sw>] ,
562+ [ <usart $X clock>]
563+ ) ,
564+ ) +
565+ ) ;
566+ }
567+ } ;
568+ }
569+
570+ /// Generates a clock function for UART Peripherals, where
571+ /// the only clock source can be the peripheral clock
572+ #[ allow( unused_macros) ]
573+ macro_rules! usart_static_clock {
574+ ( $( $usartXclock: ident, $pclkX: ident) ,+) => {
575+ $(
576+ /// Return the currently set source frequency the UART peripheral
577+ /// depending on the clock source.
578+ fn $usartXclock( clocks: & Clocks ) -> Hertz {
579+ clocks. $pclkX( )
580+ }
581+ ) +
582+ } ;
583+ ( [ $( ( $X: literal, $APB: literal) ) ,+ ] ) => {
584+ paste:: paste! {
585+ usart_static_clock!(
586+ $( [ <usart $X clock>] , [ <pclk $APB>] ) ,+
556587 ) ;
557588 }
558589 } ;
559590}
560591
561- usart ! ( [ ( 1 , 2 ) ] ) ;
562- usart ! ( [ ( 2 , 1 ) ] ) ;
563- usart ! ( [ ( 3 , 1 ) ] ) ;
592+ /// Generates a clock function for UART Peripherals, where
593+ /// the clock source can vary.
594+ macro_rules! usart_var_clock {
595+ ( $( $usartXclock: ident, $usartXsw: ident, $pclkX: ident) ,+) => {
596+ $(
597+ /// Return the currently set source frequency the UART peripheral
598+ /// depending on the clock source.
599+ fn $usartXclock( clocks: & Clocks ) -> Hertz {
600+ // NOTE(unsafe): atomic read with no side effects
601+ match unsafe { ( * RCC :: ptr( ) ) . cfgr3. read( ) . $usartXsw( ) . variant( ) } {
602+ USART1SW_A :: PCLK => clocks. $pclkX( ) ,
603+ USART1SW_A :: HSI => crate :: rcc:: HSI ,
604+ USART1SW_A :: SYSCLK => clocks. sysclk( ) ,
605+ USART1SW_A :: LSE => crate :: rcc:: LSE ,
606+ }
607+ }
608+ ) +
609+ } ;
610+ ( [ $( ( $X: literal, $APB: literal) ) ,+ ] ) => {
611+ paste:: paste! {
612+ usart_var_clock!(
613+ $( [ <usart $X clock>] , [ <usart $X sw>] , [ <pclk $APB>] ) ,+
614+ ) ;
615+ }
616+ } ;
617+ }
618+
619+ cfg_if:: cfg_if! {
620+ if #[ cfg( any( feature = "svd-f301" , feature = "svd-f3x4" ) ) ] {
621+ usart_var_clock!( [ ( 1 , 2 ) ] ) ;
622+ // These are uart peripherals, where the only clock source
623+ // is the PCLK (peripheral clock).
624+ usart_static_clock!( [ ( 2 , 1 ) , ( 3 , 1 ) ] ) ;
625+ } else {
626+ usart_var_clock!( [ ( 1 , 2 ) , ( 2 , 1 ) , ( 3 , 1 ) ] ) ;
627+ }
628+ }
629+ // TODO: what about uart 4 and uart 5?
630+ usart ! ( [ ( 1 , 2 ) , ( 2 , 1 ) , ( 3 , 1 ) ] ) ;
0 commit comments