diff --git a/CMakeLists.txt b/CMakeLists.txt
index 07850a8b5ec88a9efc3c68736ecacaa79bee2b2e..b616d14adabf0f084f6d66a9c970769eedea8ce9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,7 +49,7 @@ add_executable(mxgui-helloworld src/entrypoints/examples/mxgui-helloworld.cpp)
 sbs_target(mxgui-helloworld stm32f429zi_stm32f4discovery)
 
 add_executable(kernel-testsuite src/entrypoints/kernel-testsuite.cpp)
-sbs_target(kernel-testsuite stm32f205rc_skyward_ciuti)
+sbs_target(kernel-testsuite stm32f769ni_discovery)
 
 add_executable(runcam-settings src/entrypoints/runcam-settings.cpp)
 sbs_target(runcam-settings stm32f407vg_stm32f4discovery)
@@ -91,7 +91,7 @@ add_executable(test-sensormanager src/tests/test-sensormanager.cpp)
 sbs_target(test-sensormanager stm32f429zi_skyward_death_stack_x)
 
 add_executable(test-serial src/tests/test-serial.cpp)
-sbs_target(test-serial stm32f429zi_stm32f4discovery)
+sbs_target(test-serial stm32f769ni_discovery)
 
 add_executable(test-taskscheduler src/tests/scheduler/test-taskscheduler.cpp)
 sbs_target(test-taskscheduler stm32f407vg_stm32f4discovery)
diff --git a/cmake/boardcore.cmake b/cmake/boardcore.cmake
index 9aeb3c2e55c60eecdff7637ad8640054eea9b961..2ddcb8dd831cae9f1db139f84484e882f42374ff 100644
--- a/cmake/boardcore.cmake
+++ b/cmake/boardcore.cmake
@@ -122,11 +122,15 @@ foreach(OPT_BOARD ${BOARDS})
     target_include_directories(${BOARDCORE_LIBRARY} PUBLIC ${SBS_BASE}/src/shared)
     target_link_libraries(${BOARDCORE_LIBRARY} PUBLIC
         Miosix::Miosix::${OPT_BOARD}
-        Mxgui::Mxgui::${OPT_BOARD}
         TSCPP::TSCPP
         Eigen3::Eigen
         fmt::fmt-header-only
         Catch2::Catch2
         Mavlink::Mavlink
     )
+
+    # Link MxGui only if supported by the target
+    if(${OPT_BOARD} IN_LIST MXGUI_BOARDS)
+        target_link_libraries(${BOARDCORE_LIBRARY} PUBLIC Mxgui::Mxgui::${OPT_BOARD})
+    endif()
 endforeach()
diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake
index d77b06c6888e6b171328204c83a08c347729fc59..7a4f691a0b7e31a97e6bce06bad6713bf2c4d437 100644
--- a/cmake/dependencies.cmake
+++ b/cmake/dependencies.cmake
@@ -30,6 +30,7 @@ add_subdirectory(${SBS_BASE}/libs/miosix-host EXCLUDE_FROM_ALL)
 
 set(KPATH ${KPATH} CACHE PATH "Path to kernel directory")
 add_subdirectory(${SBS_BASE}/libs/mxgui EXCLUDE_FROM_ALL)
+include(${SBS_BASE}/libs/mxgui/cmake/boards.cmake)
 
 add_subdirectory(${SBS_BASE}/libs/tscpp EXCLUDE_FROM_ALL)
 
diff --git a/src/entrypoints/kernel-testsuite.cpp b/src/entrypoints/kernel-testsuite.cpp
index 89c3260272c61d4c0e2e4247573fc97362176ce3..b6c1073cb41b3f98b95e7d4e2478ccd66a2f8727 100644
--- a/src/entrypoints/kernel-testsuite.cpp
+++ b/src/entrypoints/kernel-testsuite.cpp
@@ -4196,7 +4196,7 @@ static Thread *waiting = nullptr;  /// Thread waiting on DMA completion IRQ
 /**
  * DMA completion IRQ
  */
-void __attribute__((naked)) DMA2_Stream0_IRQHandler()
+void __attribute__((naked)) DMA2_Stream1_IRQHandler()
 {
     saveContext();
     asm volatile("bl _Z9dma2s0irqv");
@@ -4208,7 +4208,7 @@ void __attribute__((naked)) DMA2_Stream0_IRQHandler()
  */
 void dma2s0irq()
 {
-    DMA2->LIFCR = 0b111101;
+    DMA2->LIFCR = 0b1111010000000;
     if (waiting)
         waiting->IRQwakeup();
     if (waiting->IRQgetPriority() >
@@ -4225,10 +4225,10 @@ void dmaMemcpy(void *dest, const void *source, int size, void *slackBeforeDest,
                void *slackAfterDest, void *slackAfterSource, int slackAfterSize)
 {
     FastInterruptDisableLock dLock;
-    DMA2_Stream0->NDTR = size;
-    DMA2_Stream0->PAR  = reinterpret_cast<unsigned int>(source);
-    DMA2_Stream0->M0AR = reinterpret_cast<unsigned int>(dest);
-    DMA2_Stream0->CR   = 0               // Select channel 0
+    DMA2_Stream1->NDTR = size;
+    DMA2_Stream1->PAR  = reinterpret_cast<unsigned int>(source);
+    DMA2_Stream1->M0AR = reinterpret_cast<unsigned int>(dest);
+    DMA2_Stream1->CR   = 0               // Select channel 0
                        | DMA_SxCR_MINC   // Increment RAM pointer
                        | DMA_SxCR_PINC   // Increment RAM pointer
                        | DMA_SxCR_DIR_1  // Memory to memory
@@ -4320,8 +4320,8 @@ void testCacheAndDMA()
         FastInterruptDisableLock dLock;
         RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
         RCC_SYNC();
-        NVIC_SetPriority(DMA2_Stream0_IRQn, 15);  // Lowest priority for serial
-        NVIC_EnableIRQ(DMA2_Stream0_IRQn);
+        NVIC_SetPriority(DMA2_Stream1_IRQn, 15);  // Lowest priority for serial
+        NVIC_EnableIRQ(DMA2_Stream1_IRQn);
     }
 
     // Testing cache-aligned transactions
diff --git a/src/shared/drivers/adc/InternalTemp.cpp b/src/shared/drivers/adc/InternalTemp.cpp
index 0032b645886af1b994812a87b8f7e9af9e0ce564..a1b6765e54c845a3e7bc0095ef2732cc86ef5a28 100644
--- a/src/shared/drivers/adc/InternalTemp.cpp
+++ b/src/shared/drivers/adc/InternalTemp.cpp
@@ -22,11 +22,19 @@
 
 #include "InternalTemp.h"
 
-#ifdef _ARCH_CORTEXM4_STM32F4
+#if defined(STM32F407xx) || defined(STM32F429xx)
 #define TEMP30_CAL_VALUE ((uint16_t*)((uint32_t)0x1FFF7A2C))
 #define TEMP110_CAL_VALUE ((uint16_t*)((uint32_t)0x1FFF7A2E))
 #define TEMP30 30
 #define TEMP110 110
+#elif defined(STM32F767xx) || defined(STM32F769xx)
+#define TEMP30_CAL_VALUE ((uint16_t*)((uint32_t)0x1FF0F44C))
+#define TEMP110_CAL_VALUE ((uint16_t*)((uint32_t)0x1FF0F44E))
+#define TEMP30 30
+#define TEMP110 110
+#else
+#warning This microcontroller does not have a calibrated temperature sensor or is not currently supported by this driver
+#define WITHOUT_CALIBRATION
 #endif
 
 namespace Boardcore
@@ -42,9 +50,9 @@ bool InternalTemp::init()
 {
     bool result = adc.init();
 
-#if defined(_BOARD_STM32F4DISCOVERY) || defined(_ARCH_CORTEXM3_STM32F2)
+#if defined(STM32F407xx) || defined(STM32F205xx)
     adc.addRegularChannel(InternalADC::CH16);
-#else
+#elif defined(STM32F429xx) || defined(STM32F767xx) || defined(STM32F769xx)
     adc.addRegularChannel(InternalADC::CH18);
 #endif
 
@@ -58,16 +66,16 @@ bool InternalTemp::selfTest() { return adc.selfTest(); }
 
 InternalTempData InternalTemp::sampleImpl()
 {
-#if defined(_BOARD_STM32F4DISCOVERY) || defined(_ARCH_CORTEXM3_STM32F2)
+#if defined(STM32F407xx) || defined(STM32F205xx)
     auto adcData = adc.readChannel(InternalADC::CH16, sampleTime);
-#else
+#elif defined(STM32F429xx) || defined(STM32F767xx) || defined(STM32F769xx)
     auto adcData = adc.readChannel(InternalADC::CH18, sampleTime);
 #endif
 
     InternalTempData data;
     data.temperatureTimestamp = adcData.voltageTimestamp;
 
-#ifdef _ARCH_CORTEXM3_STM32F2
+#ifdef WITHOUT_CALIBRATION
     // Default conversion
     data.temperature = ((adcData.voltage - 0.76) / 0.0025) + 25;
 #else
diff --git a/src/shared/drivers/spi/SPIBus.h b/src/shared/drivers/spi/SPIBus.h
index e7c4d4923de360de4b66300b23b02908b0d73586..d1b8d0288c5722f78df3f15fa53fa5a6054ca37b 100644
--- a/src/shared/drivers/spi/SPIBus.h
+++ b/src/shared/drivers/spi/SPIBus.h
@@ -303,9 +303,15 @@ inline void SPIBus::enable() { spi->CR1 |= SPI_CR1_SPE; }
 
 inline void SPIBus::disable() { spi->CR1 &= ~SPI_CR1_SPE; }
 
+#ifndef _ARCH_CORTEXM7_STM32F7
 inline void SPIBus::set8BitFrameFormat() { spi->CR1 &= ~SPI_CR1_DFF; }
 
 inline void SPIBus::set16BitFrameFormat() { spi->CR1 |= SPI_CR1_DFF; }
+#else
+inline void SPIBus::set8BitFrameFormat() { spi->CR1 &= ~SPI_CR1_CRCL; }
+
+inline void SPIBus::set16BitFrameFormat() { spi->CR1 |= SPI_CR1_CRCL; }
+#endif
 
 inline void SPIBus::enableSoftwareSlaveManagement() { spi->CR1 |= SPI_CR1_SSM; }
 
diff --git a/src/shared/drivers/timer/TimerUtils.h b/src/shared/drivers/timer/TimerUtils.h
index 09ecfdc14f1af783d3bfb8e71e46fa1a0bf5a7d4..16693ece4d52b54daa315f5bd11369e97bad5ef5 100644
--- a/src/shared/drivers/timer/TimerUtils.h
+++ b/src/shared/drivers/timer/TimerUtils.h
@@ -185,7 +185,7 @@ enum class SlaveMode : uint16_t
      *
      * Rising edges of the selected trigger (TRGI) clock the counter
      */
-    EXTERNAL_CLOCK_MODE_1 = TIM_SMCR_SMS
+    EXTERNAL_CLOCK_MODE_1 = TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_2
 };
 
 enum class OutputCompareMode : uint16_t
diff --git a/src/shared/drivers/usart/USART.cpp b/src/shared/drivers/usart/USART.cpp
index 05d9e5f24ad7bceb9ea82359a5bc41a23e6bf5e7..00a6485273e5353d3b08a1c2523b4a1a3711a865 100644
--- a/src/shared/drivers/usart/USART.cpp
+++ b/src/shared/drivers/usart/USART.cpp
@@ -255,6 +255,7 @@ void USART::IRQhandleInterrupt()
 {
     char c;
 
+#ifndef _ARCH_CORTEXM7_STM32F7
     // If read data register is empty then read data
     if (usart->SR & USART_SR_RXNE)
     {
@@ -282,6 +283,35 @@ void USART::IRQhandleInterrupt()
             rxWaiting = 0;
         }
     }
+#else
+    // If read data register is empty then read data
+    if (usart->ISR & USART_ISR_RXNE)
+    {
+        // Always read data
+        c = usart->RDR;
+        // If no error put data in buffer
+        if (!(usart->ISR & USART_ISR_FE))
+            if (rxQueue.tryPut(c) == false)  // FIFO overflow
+                ;
+
+        idle = false;
+    }
+
+    if (usart->ISR & USART_ISR_IDLE)
+        idle = true;
+
+    if (usart->ISR & USART_ISR_IDLE || rxQueue.size() >= rxQueue.capacity() / 2)
+    {
+        usart->ICR = USART_ICR_IDLECF;  // Clears interrupt flags
+
+        // Enough data in buffer or idle line, awake thread
+        if (rxWaiting)
+        {
+            rxWaiting->IRQwakeup();
+            rxWaiting = 0;
+        }
+    }
+#endif
 }
 
 USART::USART(USARTType *usart, Baudrate baudrate, unsigned int queueLen)
@@ -521,11 +551,15 @@ int USART::write(void *buffer, size_t nBytes)
     size_t i;
     for (i = 0; i < nBytes; i++)
     {
+#ifndef _ARCH_CORTEXM7_STM32F7
         while ((usart->SR & USART_SR_TXE) == 0)
             ;
-
-        usart->DR = *buf;
-        buf++;
+        usart->DR = *buf++;
+#else
+        while ((usart->ISR & USART_ISR_TXE) == 0)
+            ;
+        usart->TDR = *buf++;
+#endif
     }
 
     return i;
@@ -537,15 +571,28 @@ int USART::writeString(const char *buffer)
     miosix::Lock<miosix::FastMutex> l(txMutex);
 
     // Send everything, also the ending '\0' character
+#ifndef _ARCH_CORTEXM7_STM32F7
     usart->DR = *buffer;
+#else
+    usart->TDR = *buffer;
+#endif
+
     i++;
+
     while (*buffer != '\0')
     {
         buffer++;
+
+#ifndef _ARCH_CORTEXM7_STM32F7
         while (!(usart->SR & USART_SR_TXE))
             ;
-
         usart->DR = *buffer;
+#else
+        while ((usart->ISR & USART_ISR_TXE) == 0)
+            ;
+        usart->TDR = *buffer;
+#endif
+
         i++;
     };