diff --git a/CMakeLists.txt b/CMakeLists.txt
index 99553196cbd49ee7fced55cca5931001ec0dfef2..4307d22ebb9b8f788937234da5cbce6fb0a40d14 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -87,6 +87,9 @@ sbs_target(test-max485 stm32f407vg_stm32f4discovery)
 add_executable(test-pinobserver src/tests/test-pinobserver.cpp)
 sbs_target(test-pinobserver stm32f429zi_stm32f4discovery)
 
+add_executable(test-rtc src/tests/test-rtc.cpp)
+sbs_target(test-rtc stm32f767zi_compute_unit)
+
 add_executable(test-sensormanager src/tests/test-sensormanager.cpp)
 sbs_target(test-sensormanager stm32f429zi_skyward_death_stack_x)
 
diff --git a/src/tests/test-rtc.cpp b/src/tests/test-rtc.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7fc4242ae19797514767b6071fcd0c8d523140ee
--- /dev/null
+++ b/src/tests/test-rtc.cpp
@@ -0,0 +1,155 @@
+/* Copyright (c) 2015-2017 Skyward Experimental Rocketry
+ * Author: Luca Erbetta
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+// PA14 -> OSC32_IN
+// PA15 -> OSC32_OUT
+
+#include <miosix.h>
+
+using namespace miosix;
+
+typedef struct RTC_Date
+{
+    int day;
+    int month;
+    int year;
+} RTC_Date;
+typedef struct RTC_Time
+{
+    int hour;
+    int minutes;
+    int seconds;
+} RTC_Time;
+
+int main()
+{
+    for (int i = 5; i > 0; i--)
+    {
+        printf("Waiting... %d seconds left\n", i);
+        Thread::sleep(1000);
+    }
+
+    // Enable clock to RTC and PWR peripherals
+    RCC->APB1ENR |= RCC_APB1ENR_RTCEN;
+    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
+    RCC_SYNC();
+
+    // Disable backup domain write protection
+    PWR->CR1 |= PWR_CR1_DBP;
+
+    // Enable the LSE clock
+    RCC->BDCR |= RCC_BDCR_LSEDRV;    // High drive
+    RCC->BDCR |= RCC_BDCR_LSEON;     // Enable LSE clock
+    RCC->BDCR |= RCC_BDCR_RTCSEL_0;  // LSE as RTC clock
+    RCC->BDCR |= RCC_BDCR_RTCEN;     // Enable RTC clock
+    RCC_SYNC();
+
+    while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+    {
+        printf("LSE clock status %d\n", (RCC->BDCR & RCC_BDCR_LSERDY) != 0);
+        Thread::sleep(250);
+    }
+    printf("LSE clock now stable\n");
+
+    // Enable access to RTC registers
+    RTC->WPR = 0xCA;
+    RTC->WPR = 0x53;
+
+    // Enter RTC initialization mode
+    RTC->ISR |= RTC_ISR_INIT;
+    while (!(RTC->ISR & RTC_ISR_INITF))
+    {
+        printf("Waiting for RTC to enter initialization mode 0x%lx\n",
+               RTC->ISR);
+        Thread::sleep(250);
+    }
+
+    // The RTC prescalers are configured by default for a 32.768KHz clock
+    // f_CK_APRE = f_RTCCLK  / (PREDIV_A + 1) = f_RTCCLK / (127 + 1)
+    // f_CK_SPRE = f_CK_APRE / (PREDIV_B + 1) = f_RTCCLK / (255 + 1)
+
+    uint32_t ht, hu, mt, mu, st, su, yt, yu, wd, dt, du;
+
+    // Configure the time
+    ht      = 17 / 10;
+    hu      = 17 % 10;
+    mt      = 15 / 10;
+    mu      = 15 % 10;
+    st      = 30 / 10;
+    su      = 30 % 10;
+    RTC->TR = ht << RTC_TR_HT_Pos | hu << RTC_TR_HU_Pos | mt << RTC_TR_MNT_Pos |
+              mu << RTC_TR_MNU_Pos | st << RTC_TR_ST_Pos | su << RTC_TR_SU_Pos;
+
+    // Configure the date
+    yt      = 23 / 10;
+    yu      = 23 % 10;
+    wd      = 1;
+    mt      = 3 / 10;
+    mu      = 3 % 10;
+    dt      = 27 / 10;
+    du      = 27 % 10;
+    RTC->DR = yt << RTC_DR_YT_Pos | yu << RTC_DR_YU_Pos | wd << RTC_DR_WDU_Pos |
+              mt << RTC_DR_MT_Pos | mu << RTC_DR_MU_Pos | dt << RTC_DR_DT_Pos |
+              du << RTC_DR_DU_Pos;
+
+    // Exit RTC initialization mode
+    RTC->ISR &= ~RTC_ISR_INIT;
+
+    // Reactivate the write protection
+    RTC->WPR = 0xFF;
+    PWR->CR1 &= ~PWR_CR1_DBP;
+
+    Thread::sleep(1000);
+
+    RTC_Time time;
+    RTC_Date date;
+
+    while (true)
+    {
+        uint32_t rtc_tr = RTC->TR;
+        uint32_t rtc_dr = RTC->DR;
+
+        int hour_tens    = (rtc_tr & RTC_TR_HT_Msk) >> RTC_TR_HT_Pos;
+        int hour_units   = (rtc_tr & RTC_TR_HU_Msk) >> RTC_TR_HU_Pos;
+        time.hour        = (hour_tens * 10) + hour_units;
+        int mins_tens    = (rtc_tr & RTC_TR_MNT_Msk) >> RTC_TR_MNT_Pos;
+        int mins_units   = (rtc_tr & RTC_TR_MNU_Msk) >> RTC_TR_MNU_Pos;
+        time.minutes     = (mins_tens * 10) + mins_units;
+        int second_tens  = (rtc_tr & RTC_TR_ST_Msk) >> RTC_TR_ST_Pos;
+        int second_units = (rtc_tr & RTC_TR_SU_Msk) >> RTC_TR_SU_Pos;
+        time.seconds     = (second_tens * 10) + second_units;
+
+        int year_tens  = (rtc_dr & RTC_DR_YT_Msk) >> RTC_DR_YT_Pos;
+        int year_unit  = (rtc_dr & RTC_DR_YU_Msk) >> RTC_DR_YU_Pos;
+        date.year      = (year_tens * 10) + year_unit + 2000;
+        int month_tens = (rtc_dr & RTC_DR_MT_Msk) >> RTC_DR_MT_Pos;
+        int month_unit = (rtc_dr & RTC_DR_MU_Msk) >> RTC_DR_MU_Pos;
+        date.month     = (month_tens * 10) + month_unit;
+        int day_tens   = (rtc_dr & RTC_DR_DT_Msk) >> RTC_DR_DT_Pos;
+        int day_units  = (rtc_dr & RTC_DR_DU_Msk) >> RTC_DR_DU_Pos;
+        date.day       = (day_tens * 10) + day_units;
+
+        printf("%04d/%02d/%02d %02d:%02d:%02d\n", date.year, date.month,
+               date.day, time.hour, time.minutes, time.seconds);
+        Thread::sleep(1000);
+    }
+}
diff --git a/src/tests/test-serial.cpp b/src/tests/test-serial.cpp
index b1d27f59703eb56a8c43a8fb2abf2f036add5d3d..337f69a0075405d59fcfa50e36c02885c884563c 100644
--- a/src/tests/test-serial.cpp
+++ b/src/tests/test-serial.cpp
@@ -20,20 +20,155 @@
  * THE SOFTWARE.
  */
 
+// PA14 -> OSC32_IN
+// PA15 -> OSC32_OUT
+
 #include <miosix.h>
 
 using namespace miosix;
 
+GpioPin mco1(GPIOA_BASE, 8);
+GpioPin mco2(GPIOC_BASE, 9);
+
+typedef struct RTC_Date
+{
+    int day;
+    int month;
+    int year;
+} RTC_Date;
+typedef struct RTC_Time
+{
+    int hour;
+    int minutes;
+    int seconds;
+} RTC_Time;
+
 int main()
 {
-    while (true)
+    // RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
+    // RCC_SYNC();
+
+    // mco1.alternateFunction(0);
+    // mco1.speed(Speed::_100MHz);
+    // mco2.alternateFunction(0);
+    // mco2.speed(Speed::_100MHz);
+    // // mco1.mode(Mode::OUTPUT);
+    // // mco1.high();
+
+    // RCC->CFGR |= RCC_CFGR_MCO1;
+    // RCC->CFGR |= RCC_CFGR_MCO2_1;
+
+    for (int i = 5; i > 0; i--)
     {
-        ledOn();
-        printf("Serial is working!\n");
+        printf("Waiting... %d seconds left\n", i);
         Thread::sleep(1000);
-        ledOff();
+    }
+
+    // Enable clock to RTC and PWR peripherals
+    RCC->APB1ENR |= RCC_APB1ENR_RTCEN;
+    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
+    RCC_SYNC();
+
+    // Disable backup domain write protection
+    PWR->CR1 |= PWR_CR1_DBP;
+
+    // Enable the LSE clock
+    RCC->BDCR |= RCC_BDCR_LSEDRV;    // High drive
+    RCC->BDCR |= RCC_BDCR_LSEON;     // Enable LSE clock
+    RCC->BDCR |= RCC_BDCR_RTCSEL_0;  // LSE as RTC clock
+    RCC->BDCR |= RCC_BDCR_RTCEN;     // Enable RTC clock
+    RCC_SYNC();
+
+    while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0)
+    {
+        printf("LSE clock status %d\n", (RCC->BDCR & RCC_BDCR_LSERDY) != 0);
+        Thread::sleep(250);
+    }
+    printf("LSE clock now stable\n");
+
+    // Enable access to RTC registers
+    RTC->WPR = 0xCA;
+    RTC->WPR = 0x53;
+
+    // Enter RTC initialization mode
+    RTC->ISR |= RTC_ISR_INIT;
+    while (!(RTC->ISR & RTC_ISR_INITF))
+    {
+        printf("Waiting for RTC to enter initialization mode 0x%lx\n",
+               RTC->ISR);
+        Thread::sleep(250);
+    }
+
+    // The RTC prescalers are configured by default for a 32.768KHz clock
+    // f_CK_APRE = f_RTCCLK  / (PREDIV_A + 1) = f_RTCCLK / (127 + 1)
+    // f_CK_SPRE = f_CK_APRE / (PREDIV_B + 1) = f_RTCCLK / (255 + 1)
+    RTC->PRER |= 0x7f7fff;
+
+    // Configure the time
+    uint32_t ht = 17 / 10;
+    uint32_t hu = 17 % 10;
+    uint32_t mt = 15 / 10;
+    uint32_t mu = 15 % 10;
+    uint32_t st = 30 / 10;
+    uint32_t su = 30 % 10;
+    RTC->TR     = ht << 20 | hu << 16 | mt << 12 | mu << 8 | st << 4 | su << 0;
+
+    // Configure the date
+    uint32_t yt = 23 / 10;
+    uint32_t yu = 23 % 10;
+    uint32_t wd = 1;
+    mt          = 3 / 10;
+    mu          = 3 % 10;
+    uint32_t dt = 27 / 10;
+    uint32_t du = 27 % 10;
+    RTC->DR =
+        yt << 20 | yu << 16 | wd << 13 | mt << 12 | mu << 8 | dt << 4 | du << 0;
+
+    // Exit RTC initialization mode
+    RTC->ISR &= ~RTC_ISR_INIT;
+
+    // Reactivate the write protection
+    RTC->WPR = 0xFF;
+    PWR->CR1 &= ~PWR_CR1_DBP;
+
+    Thread::sleep(1000);
+
+    RTC_Time time;
+    RTC_Date date;
+
+    while (true)
+    {
+        uint32_t rtc_tr = RTC->TR;
+        uint32_t rtc_dr = RTC->DR;
+
+        int hour_tens    = (rtc_tr & RTC_TR_HT_Msk) >> RTC_TR_HT_Pos;
+        int hour_units   = (rtc_tr & RTC_TR_HU_Msk) >> RTC_TR_HU_Pos;
+        time.hour        = (hour_tens * 10) + hour_units;
+        int mins_tens    = (rtc_tr & RTC_TR_MNT_Msk) >> RTC_TR_MNT_Pos;
+        int mins_units   = (rtc_tr & RTC_TR_MNU_Msk) >> RTC_TR_MNU_Pos;
+        time.minutes     = (mins_tens * 10) + mins_units;
+        int second_tens  = (rtc_tr & RTC_TR_ST_Msk) >> RTC_TR_ST_Pos;
+        int second_units = (rtc_tr & RTC_TR_SU_Msk) >> RTC_TR_SU_Pos;
+        time.seconds     = (second_tens * 10) + second_units;
+
+        int day_tens   = (rtc_dr & RTC_DR_DT_Msk) >> RTC_DR_DT_Pos;
+        int day_units  = (rtc_dr & RTC_DR_DU_Msk) >> RTC_DR_DU_Pos;
+        date.day       = (day_tens * 10) + day_units;
+        int month_tens = (rtc_dr & RTC_DR_MT_Msk) >> RTC_DR_MT_Pos;
+        int month_unit = (rtc_dr & RTC_DR_MU_Msk) >> RTC_DR_MU_Pos;
+        date.month     = (month_tens * 10) + month_unit;
+        int year_tens  = (rtc_dr & RTC_DR_YT_Msk) >> RTC_DR_YT_Pos;
+        int year_unit  = (rtc_dr & RTC_DR_YU_Msk) >> RTC_DR_YU_Pos;
+        date.year      = (year_tens * 10) + year_unit + 2000;
+
+        printf("%04d/%02d/%02d %02d:%02d:%02d\n", date.year, date.month,
+               date.day, time.hour, time.minutes, time.seconds);
         Thread::sleep(1000);
     }
 
-    return 0;
+    // while (true)
+    // {
+    //     printf("I'm alive!\n");
+    //     Thread::sleep(1000);
+    // }
 }