diff --git a/_examples/display_er_oledm015/main.cpp b/_examples/display_er_oledm015/main.cpp
index 33806c903bb83949553dcfffd9c44775b8a84e99..d399875274f486801a57add46226c3bee071ff8d 100644
--- a/_examples/display_er_oledm015/main.cpp
+++ b/_examples/display_er_oledm015/main.cpp
@@ -40,14 +40,14 @@ int main()
         dc.write(Point(0,0),"Miosix OS");
         dc.write(Point(0,tahoma.getHeight()),"MXGUI graphics library");
     }
-   for(int i=0;;i++)
-   {
-       {
-           DrawingContext dc(display);
-           char s[16];
-           sniprintf(s,15,"%02d:%02d",i/60,i%60);
-           dc.write(Point(0,2*tahoma.getHeight()),s);
-       }
-       Thread::sleep(1000);
-   }
+    for(int i=0;;i++)
+    {
+        {
+            DrawingContext dc(display);
+            char s[16];
+            sniprintf(s,15,"%02d:%02d",i/60,i%60);
+            dc.write(Point(0,2*tahoma.getHeight()),s);
+        }
+        Thread::sleep(1000);
+    }
 }
diff --git a/_examples/display_er_oledm024/display_er_oledm024.cpp b/_examples/display_er_oledm024/display_er_oledm024.cpp
index d346a3c93643e43d1cb7833ee823eb5b17d193f8..f9b22384518b92e600b24ca382293522da6ec28d 100644
--- a/_examples/display_er_oledm024/display_er_oledm024.cpp
+++ b/_examples/display_er_oledm024/display_er_oledm024.cpp
@@ -44,6 +44,11 @@ using mosi = Gpio<GPIOB_BASE,5>; //Used as HW SPI
 using dc   = Gpio<GPIOB_BASE,6>;
 using res  = Gpio<GPIOB_BASE,4>;
 
+/**
+ * Send and receive a byte, thus returning only after transmission is complete
+ * \param x byte to send
+ * \return the received byte
+ */
 static unsigned char spi1sendRecv(unsigned char x=0)
 {
     SPI1->DR=x;
@@ -51,11 +56,41 @@ static unsigned char spi1sendRecv(unsigned char x=0)
     return SPI1->DR;
 }
 
+/**
+ * Send a byte only.
+ * NOTE: this function requires special care to use as
+ * - it returns before the byte has been transmitted, and if this is the last
+ *   byte, you have to wait with spi1waitCompletion() before deasserting cs
+ * - as the received byte is ignored, the overrun flag gets set and it must be
+ *   cleared (spi1waitCompletion() does that as well)
+ */
+static void spi1sendOnly(unsigned char x)
+{
+    //NOTE: data is sent after the function returns, watch out!
+    while((SPI1->SR & SPI_SR_TXE)==0) ;
+    SPI1->DR=x;
+}
+
+/**
+ * Must be called after using spi1sendOnly(), complete the last byte transmission
+ */
+static void spi1waitCompletion()
+{
+    while(SPI1->SR & SPI_SR_BSY) ;
+    //Reading DR and then SR clears overrun flag
+    [[gnu::unused]] volatile int unused;
+    unused=SPI1->DR;
+    unused=SPI1->SR;
+}
+
+/**
+ * Send a command to the display
+ * \param c command
+ */
 static void cmd(unsigned char c)
 {
     dc::low();
     cs::low();
-    delayUs(1);
     spi1sendRecv(c);
     cs::high();
     delayUs(1);
@@ -84,7 +119,7 @@ DisplayErOledm024::DisplayErOledm024() : DisplayGeneric1BPP(128,64)
     SPI1->CR1=SPI_CR1_SSM  //No HW cs
             | SPI_CR1_SSI
             | SPI_CR1_SPE  //SPI enabled
-            | SPI_CR1_BR_1 //SPI clock 50/8=6.25 MHz
+            | SPI_CR1_BR_1 //SPI clock 50/8=6.25 MHz (Fmax=10MHz)
             | SPI_CR1_MSTR;//Master mode
 
     res::high();
@@ -138,8 +173,8 @@ void DisplayErOledm024::update()
     cmd(0x22); cmd(0); cmd(7);
     dc::high();
     cs::low();
-    delayUs(1);
-    for(int i=0;i<fbSize;i++) spi1sendRecv(backbuffer[i]);
+    for(int i=0;i<fbSize;i++) spi1sendOnly(backbuffer[i]);
+    spi1waitCompletion();
     cs::high();
     delayUs(1);
 }
diff --git a/_examples/display_er_oledm024/main.cpp b/_examples/display_er_oledm024/main.cpp
index 9a36eecaa9f9f4c638da4e29bc5aab881cd5a58a..5ba9972c3e63d3a4f5e609e6e3939fe50aa6538e 100644
--- a/_examples/display_er_oledm024/main.cpp
+++ b/_examples/display_er_oledm024/main.cpp
@@ -40,5 +40,14 @@ int main()
         dc.write(Point(0,0),"Miosix OS");
         dc.write(Point(0,tahoma.getHeight()),"MXGUI graphics library");
     }
-   for(;;) Thread::sleep(100);
+    for(int i=0;;i++)
+    {
+        {
+            DrawingContext dc(display);
+            char s[16];
+            sniprintf(s,15,"%02d:%02d",i/60,i%60);
+            dc.write(Point(0,2*tahoma.getHeight()),s);
+        }
+        Thread::sleep(1000);
+    }
 }
diff --git a/_examples/display_er_oledm028/display_er_oledm028.cpp b/_examples/display_er_oledm028/display_er_oledm028.cpp
index fb0ac0fe85efd1b9296d83878794a9ad78954d59..4ef23b3a2cc21c12aa1d8fe5458abb1913de6205 100644
--- a/_examples/display_er_oledm028/display_er_oledm028.cpp
+++ b/_examples/display_er_oledm028/display_er_oledm028.cpp
@@ -38,61 +38,74 @@ using namespace miosix;
 
 //Display connection
 
-typedef Gpio<GPIOB_BASE,3> sck;
-typedef Gpio<GPIOB_BASE,4> miso; //Not used
-typedef Gpio<GPIOB_BASE,5> mosi;
-typedef Gpio<GPIOB_BASE,7> cs;
-
-typedef Gpio<GPIOB_BASE,8> dc;
-typedef Gpio<GPIOB_BASE,15> reset;
-
-static void spiInit()
+using cs   = Gpio<GPIOB_BASE,7>; //Display pin 16
+using sck  = Gpio<GPIOB_BASE,3>; //Display pin  4, used as HW SPI
+using mosi = Gpio<GPIOB_BASE,5>; //Display pin  5, used as HW SPI
+using dc   = Gpio<GPIOB_BASE,8>; //Display pin 14
+using res = Gpio<GPIOB_BASE,15>; //Display pin 15
+//Display pin 2 is Vbat (3.3..5V), while display pins 1,7,8,9,10,11,12,13 are GND
+
+/**
+ * Send and receive a byte, thus returning only after transmission is complete
+ * \param x byte to send
+ * \return the received byte
+ */
+static unsigned char spi3sendRecv(unsigned char x=0)
 {
-    sck::mode(Mode::ALTERNATE);
-    sck::alternateFunction(6);
-    mosi::mode(Mode::ALTERNATE);
-    mosi::alternateFunction(6);
-    cs::mode(Mode::OUTPUT);
-    cs::high();
+    SPI3->DR=x;
+    while((SPI3->SR & SPI_SR_RXNE)==0) ;
+    return SPI3->DR;
+}
 
-    {
-        FastInterruptDisableLock dLock;
-        RCC->APB1ENR |= RCC_APB1ENR_SPI3EN;
-        RCC_SYNC();
-    }
-    //Master mode no hardware CS pin
-    //Note: SPI3 is attached on the 42MHz APB2 bus, so the clock is set
-    //to APB2/2/2=10.5MHz. This overclocking the SSD1332 by 500KHz
-    SPI3->CR1=SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_MSTR | SPI_CR1_BR_0;
-    SPI3->CR2=0;
-    SPI3->CR1 |= SPI_CR1_SPE; //Set enable bit
+/**
+ * Send a byte only.
+ * NOTE: this function requires special care to use as
+ * - it returns before the byte has been transmitted, and if this is the last
+ *   byte, you have to wait with spi3waitCompletion() before deasserting cs
+ * - as the received byte is ignored, the overrun flag gets set and it must be
+ *   cleared (spi1waitCompletion() does that as well)
+ */
+static void spi3sendOnly(unsigned char x)
+{
+    //NOTE: data is sent after the function returns, watch out!
+    while((SPI3->SR & SPI_SR_TXE)==0) ;
+    SPI3->DR=x;
 }
 
-static unsigned char spiSendRecv(unsigned char data)
+/**
+ * Must be called after using spi3sendOnly(), complete the last byte transmission
+ */
+static void spi3waitCompletion()
 {
-    SPI3->DR=data;
-    while((SPI3->SR & SPI_SR_RXNE)==0) ;
-    return SPI3->DR;
+    while(SPI3->SR & SPI_SR_BSY) ;
+    //Reading DR and then SR clears overrun flag
+    [[gnu::unused]] volatile int unused;
+    unused=SPI3->DR;
+    unused=SPI3->SR;
 }
 
+/**
+ * Send a command to the display
+ * \param c command
+ */
 static void cmd(unsigned char c)
 {
     dc::low();
-
     cs::low();
-    delayUs(1);
-    spiSendRecv(c);
+    spi3sendRecv(c);
     cs::high();
     delayUs(1);
 }
 
+/**
+ * Send data to the display
+ * \param d data
+ */
 static void data(unsigned char d)
 {
     dc::high();
-
     cs::low();
-    delayUs(1);
-    spiSendRecv(d);
+    spi3sendRecv(d);
     cs::high();
     delayUs(1);
 }
@@ -105,15 +118,29 @@ namespace mxgui {
 
 DisplayErOledm028::DisplayErOledm028() : DisplayGeneric4BPP(256,64)
 {
-    spiInit();
-    dc::mode(Mode::OUTPUT);
-    reset::mode(Mode::OUTPUT);
+    {
+        FastInterruptDisableLock dLock;
+        cs::mode(Mode::OUTPUT);      cs::high();
+        sck::mode(Mode::ALTERNATE);  sck::alternateFunction(6);
+        mosi::mode(Mode::ALTERNATE); mosi::alternateFunction(6);
+        dc::mode(Mode::OUTPUT);
+        res::mode(Mode::OUTPUT);
+        
+        RCC->APB1ENR |= RCC_APB1ENR_SPI3EN;
+        RCC_SYNC();
+    }
+
+    SPI3->CR1=SPI_CR1_SSM  //No HW cs
+            | SPI_CR1_SSI
+            | SPI_CR1_SPE  //SPI enabled
+            | SPI_CR1_BR_1 //SPI clock 42/8=5.25MHz (Fmax=10MHz)
+            | SPI_CR1_MSTR;//Master mode
 
-    reset::high();
+    res::high();
     Thread::sleep(1);
-    reset::low();
+    res::low();
     delayUs(100);
-    reset::high();
+    res::high();
     delayUs(100);
 
     cmd(0xfd); data(0x12);             // Disable command lock
@@ -167,8 +194,8 @@ void DisplayErOledm028::update()
 
     dc::high();
     cs::low();
-    delayUs(1);
-    for(int i=0;i<fbSize;i++) spiSendRecv(backbuffer[i]);
+    for(int i=0;i<fbSize;i++) spi3sendOnly(backbuffer[i]);
+    spi3waitCompletion();
     cs::high();
     delayUs(1);
 }
diff --git a/_examples/display_er_oledm028/main.cpp b/_examples/display_er_oledm028/main.cpp
index 3d56c86f9cef65d347dd42f329f0fea06b03b006..553893b92c90a138c4f1f80b322041523730944b 100644
--- a/_examples/display_er_oledm028/main.cpp
+++ b/_examples/display_er_oledm028/main.cpp
@@ -41,5 +41,14 @@ int main()
         dc.setFont(tahoma);
         dc.write(Point(0,droid21.getHeight()),"MXGUI graphics library");
     }
-   for(;;) Thread::sleep(100);
+    for(int i=0;;i++)
+    {
+        {
+            DrawingContext dc(display);
+            char s[16];
+            sniprintf(s,15,"%02d:%02d",i/60,i%60);
+            dc.write(Point(0,droid21.getHeight()+tahoma.getHeight()),s);
+        }
+        Thread::sleep(1000);
+    }
 }