diff --git a/miosix/arch/common/drivers/serial_stm32.cpp b/miosix/arch/common/drivers/serial_stm32.cpp
index 4ab54fd46b3ab8729f54c27f0eb4b9bf96363240..f6cb193ff031f88fb24a163f3d49b33161576fb1 100644
--- a/miosix/arch/common/drivers/serial_stm32.cpp
+++ b/miosix/arch/common/drivers/serial_stm32.cpp
@@ -32,7 +32,6 @@
 #include "kernel/sync.h"
 #include "kernel/scheduler/scheduler.h"
 #include "interfaces/portability.h"
-#include "interfaces/gpio.h"
 #include "filesystem/ioctl.h"
 #include "core/cache_cortexMx.h"
 
@@ -45,42 +44,20 @@ static const int numPorts=3; //Supporting only USART1, USART2, USART3
 //GPIOS in all families, stm32f1, f2, f4 and l1. Additionally, USART1 is
 //always connected to the APB2, while USART2 and USART3 are always on APB1
 //Unfortunately, this does not hold with DMA.
-#ifdef _BOARD_STM32H753XI_EVAL
-typedef Gpio<GPIOB_BASE,14> u1tx;
-typedef Gpio<GPIOB_BASE,15> u1rx;
-#else
 typedef Gpio<GPIOA_BASE,9>  u1tx;
 typedef Gpio<GPIOA_BASE,10> u1rx;
-#endif
 typedef Gpio<GPIOA_BASE,11> u1cts;
 typedef Gpio<GPIOA_BASE,12> u1rts;
 
-#if !defined(STM32_NO_SERIAL_2_3)
 typedef Gpio<GPIOA_BASE,2>  u2tx;
 typedef Gpio<GPIOA_BASE,3>  u2rx;
 typedef Gpio<GPIOA_BASE,0>  u2cts;
 typedef Gpio<GPIOA_BASE,1>  u2rts;
 
-//TODO: modify the class constructor so that it takes the gpiopins as
-//parameter, so as to allow each board to custom-remap usart pins,
-//otherwise this common driver will end up having even more ifdefs
-#ifdef _BOARD_STM3220G_EVAL
-//The STM3220G_EVAL board maps usart3 to different pins.
-typedef Gpio<GPIOC_BASE,10> u3tx;
-typedef Gpio<GPIOC_BASE,11> u3rx;
-#elif defined(_BOARD_STM32F746ZG_NUCLEO)
-//The STM32F746ZG_NUCLEO board maps usart3 to different pins.
-typedef Gpio<GPIOD_BASE,8> u3tx;
-typedef Gpio<GPIOD_BASE,9> u3rx;
-#else
-//Default placement
 typedef Gpio<GPIOB_BASE,10> u3tx;
 typedef Gpio<GPIOB_BASE,11> u3rx;
-#endif
-
 typedef Gpio<GPIOB_BASE,13> u3cts;
 typedef Gpio<GPIOB_BASE,14> u3rts;
-#endif //!defined(STM32_NO_SERIAL_2_3)
 
 /// Pointer to serial port classes to let interrupts access the classes
 static STM32Serial *ports[numPorts]={0};
@@ -389,8 +366,77 @@ static inline bool isInCCMarea(const void *x) { return false; }
 // 20ms of full data rate. In the 8N1 format one char is made of 10 bits.
 // So (baudrate/10)*0.02=baudrate/500
 STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl)
-        : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500), rxWaiting(0),
-        idle(true), flowControl(flowControl==RTSCTS), portId(id)
+        : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500),
+          flowControl(flowControl==RTSCTS), portId(id)
+{
+    #ifndef _ARCH_CORTEXM3_STM32
+    //stm32f2, f4, l1, f7, h7 require alternate function mapping
+    switch(id)
+    {
+        case 1:
+            u1tx::alternateFunction(7);
+            u1rx::alternateFunction(7);
+            if(flowControl)
+            {
+                u1rts::alternateFunction(7);
+                u1cts::alternateFunction(7);
+            }
+            break;
+        case 2:
+            u2tx::alternateFunction(7);
+            u2rx::alternateFunction(7);
+            if(flowControl)
+            {
+                u2rts::alternateFunction(7);
+                u2cts::alternateFunction(7);
+            }
+            break;
+        case 3:
+            u3tx::alternateFunction(7);
+            u3rx::alternateFunction(7);
+            if(flowControl)
+            {
+                u3rts::alternateFunction(7);
+                u3cts::alternateFunction(7);
+            }
+            break;
+    }
+    #endif //_ARCH_CORTEXM3_STM32
+    
+    switch(id)
+    {
+        case 1:
+            commonInit(id,baudrate,u1tx::getPin(),u1rx::getPin(),
+                       u1rts::getPin(),u1cts::getPin());
+            break;
+        case 2:
+            commonInit(id,baudrate,u2tx::getPin(),u2rx::getPin(),
+                       u2rts::getPin(),u3cts::getPin());
+            break;
+        case 3:
+            commonInit(id,baudrate,u3tx::getPin(),u2rx::getPin(),
+                       u2rts::getPin(),u3cts::getPin());
+            break;
+    }
+}
+
+STM32Serial::STM32Serial(int id, int baudrate, GpioPin tx, GpioPin rx)
+    : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500),
+      flowControl(false), portId(id)
+{
+    commonInit(id,baudrate,tx,rx,tx,rx); //The last two args will be ignored
+}
+
+STM32Serial::STM32Serial(int id, int baudrate, GpioPin tx, GpioPin rx,
+    miosix::GpioPin rts, miosix::GpioPin cts)
+    : Device(Device::TTY), rxQueue(rxQueueMin+baudrate/500),
+      flowControl(true), portId(id)
+{
+    commonInit(id,baudrate,tx,rx,rts,cts);
+}
+
+void STM32Serial::commonInit(int id, int baudrate, GpioPin tx, GpioPin rx,
+                             GpioPin rts, GpioPin cts)
 {
     #ifdef SERIAL_DMA
     dmaTx=0;
@@ -402,13 +448,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl)
     if(id<1|| id>numPorts || ports[id-1]!=0) errorHandler(UNEXPECTED);
     ports[id-1]=this;
     unsigned int freq=SystemCoreClock;
-    //Quirk: stm32f1 rx pin has to be in input mode, while stm32f2 and up want
-    //it in ALTERNATE mode. Go figure...
-    #ifdef _ARCH_CORTEXM3_STM32
-    Mode::Mode_ rxPinMode=Mode::INPUT;
-    #else //_ARCH_CORTEXM3_STM32
-    Mode::Mode_ rxPinMode=Mode::ALTERNATE;
-    #endif //_ARCH_CORTEXM3_STM32
     //Quirk the position of the PPRE1 and PPRE2 bitfields in RCC->CFGR changes
     #if defined(_ARCH_CORTEXM3_STM32) || defined(_ARCH_CORTEXM3_STM32L1)
     const unsigned int ppre1=8;
@@ -449,28 +488,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl)
             #endif
             port->CR3=USART_CR3_DMAT | USART_CR3_DMAR;
             #endif //SERIAL_1_DMA
-            #ifndef _ARCH_CORTEXM3_STM32
-            //Only stm32f2, f4 and l1 have the new alternate function mapping
-            #ifdef _BOARD_STM32H753XI_EVAL
-            u1tx::alternateFunction(4);
-            u1rx::alternateFunction(4);
-            #else
-            u1tx::alternateFunction(7);
-            u1rx::alternateFunction(7);
-            #endif
-            if(flowControl)
-            {
-                u1rts::alternateFunction(7);
-                u1cts::alternateFunction(7);
-            }
-            #endif //_ARCH_CORTEXM3_STM32
-            u1tx::mode(Mode::ALTERNATE);
-            u1rx::mode(rxPinMode);
-            if(flowControl)
-            {
-                u1rts::mode(Mode::ALTERNATE);
-                u1cts::mode(rxPinMode);
-            }
             NVIC_SetPriority(USART1_IRQn,15);//Lowest priority for serial
             NVIC_EnableIRQ(USART1_IRQn);
             #ifndef _ARCH_CORTEXM7_STM32H7
@@ -522,23 +539,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl)
             #endif
             port->CR3=USART_CR3_DMAT | USART_CR3_DMAR;
             #endif //SERIAL_2_DMA
-            #ifndef _ARCH_CORTEXM3_STM32
-            //Only stm32f2, f4 and l1 have the new alternate function mapping
-            u2tx::alternateFunction(7);
-            u2rx::alternateFunction(7);
-            if(flowControl)
-            {
-                u2rts::alternateFunction(7);
-                u2cts::alternateFunction(7);
-            }
-            #endif //_ARCH_CORTEXM3_STM32
-            u2tx::mode(Mode::ALTERNATE);
-            u2rx::mode(rxPinMode);
-            if(flowControl)
-            {
-                u2rts::mode(Mode::ALTERNATE);
-                u2cts::mode(rxPinMode);
-            }
             NVIC_SetPriority(USART2_IRQn,15);//Lowest priority for serial
             NVIC_EnableIRQ(USART2_IRQn);
             #ifndef _ARCH_CORTEXM7_STM32H7
@@ -589,23 +589,6 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl)
             #endif
             port->CR3=USART_CR3_DMAT | USART_CR3_DMAR;
             #endif //SERIAL_3_DMA
-            #ifndef _ARCH_CORTEXM3_STM32
-            //Only stm32f2, f4 and l1 have the new alternate function mapping
-            u3tx::alternateFunction(7);
-            u3rx::alternateFunction(7);
-            if(flowControl)
-            {
-                u3rts::alternateFunction(7);
-                u3cts::alternateFunction(7);
-            }
-            #endif //_ARCH_CORTEXM3_STM32
-            u3tx::mode(Mode::ALTERNATE);
-            u3rx::mode(rxPinMode);
-            if(flowControl)
-            {
-                u3rts::mode(Mode::ALTERNATE);
-                u3cts::mode(rxPinMode);
-            }
             NVIC_SetPriority(USART3_IRQn,15);//Lowest priority for serial
             NVIC_EnableIRQ(USART3_IRQn);
             #ifndef _ARCH_CORTEXM7_STM32H7
@@ -624,6 +607,20 @@ STM32Serial::STM32Serial(int id, int baudrate, FlowCtrl flowControl)
         #endif //!defined(STM32F411xE) && !defined(STM32F401xE) && !defined(STM32F401xC)
         #endif //!defined(STM32_NO_SERIAL_2_3)
     }
+    //Quirk: stm32f1 rx pin has to be in input mode, while stm32f2 and up want
+    //it in ALTERNATE mode. Go figure...
+    #ifdef _ARCH_CORTEXM3_STM32
+    Mode::Mode_ rxPinMode=Mode::INPUT;
+    #else //_ARCH_CORTEXM3_STM32
+    Mode::Mode_ rxPinMode=Mode::ALTERNATE;
+    #endif //_ARCH_CORTEXM3_STM32
+    tx.mode(Mode::ALTERNATE);
+    rx.mode(rxPinMode);
+    if(flowControl)
+    {
+        rts.mode(Mode::ALTERNATE);
+        cts.mode(rxPinMode);
+    }
     const unsigned int quot=2*freq/baudrate; //2*freq for round to nearest
     port->BRR=quot/2 + (quot & 1);           //Round to nearest
     if(flowControl==false) port->CR3 |= USART_CR3_ONEBIT;
diff --git a/miosix/arch/common/drivers/serial_stm32.h b/miosix/arch/common/drivers/serial_stm32.h
index 19249b8436b850c44388ed34082a7940cddf105c..12d55d0f410e66be5a5fbf2ce2329ac918a8d156 100644
--- a/miosix/arch/common/drivers/serial_stm32.h
+++ b/miosix/arch/common/drivers/serial_stm32.h
@@ -31,6 +31,7 @@
 #include "filesystem/console/console_device.h"
 #include "kernel/sync.h"
 #include "kernel/queue.h"
+#include "interfaces/gpio.h"
 #include "board_settings.h"
 
 #if defined(_ARCH_CORTEXM3_STM32) && defined(__ENABLE_XRAM)
@@ -67,7 +68,13 @@ public:
     };
     
     /**
-     * Constructor, initializes the serial port.
+     * Constructor, initializes the serial port using the default pins, which
+     * are:
+     * USART1: tx=PA9  rx=PA10 cts=PA11 rts=PA12
+     * USART2: tx=PA2  rx=PA3  cts=PA0  rts=PA1
+     * USART3: tx=PB10 rx=PB11 cts=PB13 rts=PB14
+     * If you board has a different mapping, use one of the other constructors.
+     * 
      * Calls errorHandler(UNEXPECTED) if id is not in the correct range, or when
      * attempting to construct multiple objects with the same id. That is,
      * it is possible to instantiate only one instance of this class for each
@@ -78,6 +85,46 @@ public:
      */
     STM32Serial(int id, int baudrate, FlowCtrl flowControl=NOFLOWCTRL);
     
+    /**
+     * Constructor, initializes the serial port using remapped pins and disables
+     * flow control.
+     * 
+     * NOTE: for stm32f2, f4, f7 and h7 you have to set the correct alternate
+     * function to the pins in order to connect then to the USART peripheral
+     * before passing them to this class.
+     * 
+     * Calls errorHandler(UNEXPECTED) if id is not in the correct range, or when
+     * attempting to construct multiple objects with the same id. That is,
+     * it is possible to instantiate only one instance of this class for each
+     * hardware USART.
+     * \param id a number 1 to 3 to select which USART
+     * \param baudrate serial port baudrate
+     * \param tx tx pin
+     * \param rx rx pin
+     */
+    STM32Serial(int id, int baudrate, miosix::GpioPin tx, miosix::GpioPin rx);
+    
+    /**
+     * Constructor, initializes the serial port using remapped pins and enables
+     * flow control.
+     * 
+     * NOTE: for stm32f2, f4, f7 and h7 you have to set the correct alternate
+     * function to the pins in order to connect then to the USART peripheral
+     * before passing them to this class.
+     * 
+     * Calls errorHandler(UNEXPECTED) if id is not in the correct range, or when
+     * attempting to construct multiple objects with the same id. That is,
+     * it is possible to instantiate only one instance of this class for each
+     * hardware USART.
+     * \param id a number 1 to 3 to select which USART
+     * \param tx tx pin
+     * \param rx rx pin
+     * \param rts rts pin
+     * \param cts cts pin
+     */
+    STM32Serial(int id, int baudrate, miosix::GpioPin tx, miosix::GpioPin rx,
+                miosix::GpioPin rts, miosix::GpioPin cts);
+    
     /**
      * Read a block of data
      * \param buffer buffer where read data will be stored
@@ -149,6 +196,12 @@ public:
     ~STM32Serial();
     
 private:
+    /**
+     * Code common for all constructors
+     */
+    void commonInit(int id, int baudrate, miosix::GpioPin tx, miosix::GpioPin rx,
+                    miosix::GpioPin rts, miosix::GpioPin cts);
+    
     #ifdef SERIAL_DMA
     /**
      * Wait until a pending DMA TX completes, if any
@@ -198,7 +251,7 @@ private:
     
     DynUnsyncQueue<char> rxQueue;     ///< Receiving queue
     static const unsigned int rxQueueMin=16; ///< Minimum queue size
-    Thread *rxWaiting;                ///< Thread waiting for rx, or 0
+    Thread *rxWaiting=0;              ///< Thread waiting for rx, or 0
     
     USART_TypeDef *port;              ///< Pointer to USART peripheral
     #ifdef SERIAL_DMA
@@ -221,7 +274,7 @@ private:
     char rxBuffer[rxQueueMin];
     bool dmaTxInProgress;             ///< True if a DMA tx is in progress
     #endif //SERIAL_DMA
-    bool idle;                        ///< Receiver idle
+    bool idle=true;                   ///< Receiver idle
     const bool flowControl;           ///< True if flow control GPIOs enabled
     const unsigned char portId;       ///< 1 for USART1, 2 for USART2, ...
 };
diff --git a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
index 863907ab976c68cdb35916787640e036b9e7cb30..375b99538347ae3eaeb66225c1911e97ac5385b5 100644
--- a/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
+++ b/miosix/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/interfaces-impl/bsp.cpp
@@ -77,13 +77,10 @@ void IRQbspInit()
     ledOn();
     delayMs(100);
     ledOff();
+    auto tx=Gpio<GPIOC_BASE,10>::getPin(); tx.alternateFunction(7);
+    auto rx=Gpio<GPIOC_BASE,11>::getPin(); rx.alternateFunction(7);
     DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>(
-    #ifndef STDOUT_REDIRECTED_TO_DCC
-        new STM32Serial(defaultSerial,defaultSerialSpeed,
-        defaultSerialFlowctrl ? STM32Serial::RTSCTS : STM32Serial::NOFLOWCTRL)));
-    #else //STDOUT_REDIRECTED_TO_DCC
-        new ARMDCC));
-    #endif //STDOUT_REDIRECTED_TO_DCC
+        new STM32Serial(3,defaultSerialSpeed,tx,rx)));
 }
 
 void bspInit2()
diff --git a/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp b/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp
index fc32a70c2a5eb220987faa2ea0ec131c9c5f985c..24bb3571ff11ec9fb8fde08c1a1604d675379e6a 100644
--- a/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp
+++ b/miosix/arch/cortexM7_stm32f7/stm32f746zg_nucleo/interfaces-impl/bsp.cpp
@@ -72,9 +72,10 @@ void IRQbspInit()
     ledOn();
     delayMs(100);
     ledOff();
+    auto tx=Gpio<GPIOD_BASE,8>::getPin(); tx.alternateFunction(7);
+    auto rx=Gpio<GPIOD_BASE,9>::getPin(); rx.alternateFunction(7);
     DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>(
-        new STM32Serial(defaultSerial,defaultSerialSpeed,
-        defaultSerialFlowctrl ? STM32Serial::RTSCTS : STM32Serial::NOFLOWCTRL)));
+        new STM32Serial(3,defaultSerialSpeed,tx,rx)));
 }
 
 void bspInit2()
diff --git a/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp b/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp
index 860a9227b6e0c72e9e5724289bbbc73aa72a452f..9dbc25d762aea61e8c8a743a7ba782ee17443604 100644
--- a/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp
+++ b/miosix/arch/cortexM7_stm32h7/stm32h753xi_eval/interfaces-impl/bsp.cpp
@@ -78,9 +78,10 @@ void IRQbspInit()
     ledOn();
     delayMs(100);
     ledOff();
+    auto tx=Gpio<GPIOB_BASE,14>::getPin(); tx.alternateFunction(4);
+    auto rx=Gpio<GPIOB_BASE,15>::getPin(); rx.alternateFunction(4);
     DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>(
-        new STM32Serial(defaultSerial,defaultSerialSpeed,
-        defaultSerialFlowctrl ? STM32Serial::RTSCTS : STM32Serial::NOFLOWCTRL)));
+        new STM32Serial(1,defaultSerialSpeed,tx,rx)));
 }
 
 void bspInit2()
diff --git a/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h b/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h
index 820ddea65eacf8e2f4165b3777efb0278169776a..4d1b7fe09b32c5be388818d924ad565ec0302493 100644
--- a/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h
+++ b/miosix/config/arch/cortexM3_stm32f2/stm32f207ig_stm3220g-eval/board_settings.h
@@ -63,9 +63,8 @@ const unsigned int AUX_TIMER_CLOCK=100000;
 const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits
 
 /// Serial port
-const unsigned int defaultSerial=3;
+//This board only exposes USART3, without flow control
 const unsigned int defaultSerialSpeed=19200;
-const bool defaultSerialFlowctrl=false;
 //#define SERIAL_1_DMA //Serial 1 is not used, so not enabling DMA
 //#define SERIAL_2_DMA //Serial 2 is not used, so not enabling DMA
 #define SERIAL_3_DMA
diff --git a/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h b/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h
index 8ce101684d0e957d37ede39b3b1b1c1b8fb742c3..5a70bc3995bee5d5f6d83270a2f69611cd7e73af 100644
--- a/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h
+++ b/miosix/config/arch/cortexM7_stm32f7/stm32f746zg_nucleo/board_settings.h
@@ -62,9 +62,8 @@ const unsigned int AUX_TIMER_CLOCK=100000;
 const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits
 
 /// Serial port
-const unsigned int defaultSerial=3;
+//This board only exposes USART3, without flow control, connected to an UART/USB
 const unsigned int defaultSerialSpeed=115200;
-const bool defaultSerialFlowctrl=false;
 // #define SERIAL_1_DMA
 // #define SERIAL_2_DMA
 #define SERIAL_3_DMA
diff --git a/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h b/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h
index cb4af9693756182c2022d1441b2b2effe7c18459..7466ebafb3cb7b7d0601d9b7dece5f0bd4f763de 100644
--- a/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h
+++ b/miosix/config/arch/cortexM7_stm32h7/stm32h753xi_eval/board_settings.h
@@ -62,9 +62,8 @@ const unsigned int AUX_TIMER_CLOCK=100000;
 const unsigned int AUX_TIMER_MAX=0xffff; ///<\internal Aux timer is 16 bits
 
 /// Serial port
-const unsigned int defaultSerial=1;
+//This board only exposes USART1, without flow control
 const unsigned int defaultSerialSpeed=115200;
-const bool defaultSerialFlowctrl=false;
 // #define SERIAL_1_DMA //TODO: serial port DMA
 // #define SERIAL_2_DMA
 // #define SERIAL_3_DMA