diff --git a/Makefile b/Makefile
index ac00c36f1c83f9dbb2b6a08ba855aa54f642a327..1d5d4bcec620efcddcef7c0f436728d90ead7b1c 100644
--- a/Makefile
+++ b/Makefile
@@ -11,14 +11,6 @@ KPATH := miosix
 CONFPATH := $(KPATH)
 include $(CONFPATH)/config/Makefile.inc
 
-ifeq ("$(BUILD_VERBOSE)","1")
-Q := @
-ECHO := @echo
-else
-Q :=
-ECHO := @true
-endif
-
 ##
 ## List here subdirectories which contains makefiles
 ##
@@ -106,19 +98,19 @@ main: main.elf
 	$(Q)$(SZ) main.elf
 
 main.elf: $(OBJ) all-recursive
-	$(ECHO) "[LD]   main.elf"
+	$(ECHO) "[LD  ] main.elf"
 	$(Q)$(CXX) $(LFLAGS) -o main.elf $(OBJ) $(KPATH)/$(BOOT_FILE) $(LINK_LIBS)
 
 %.o: %.s
-	$(ECHO) "[AS]   $<"
+	$(ECHO) "[AS  ] $<"
 	$(Q)$(AS)  $(AFLAGS) $< -o $@
 
 %.o : %.c
-	$(ECHO) "[CC]   $<"
+	$(ECHO) "[CC  ] $<"
 	$(Q)$(CC)  $(DFLAGS) $(CFLAGS) $< -o $@
 
 %.o : %.cpp
-	$(ECHO) "[CXX]  $<"
+	$(ECHO) "[CXX ] $<"
 	$(Q)$(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@
 
 #pull in dependecy info for existing .o files
diff --git a/miosix/Makefile b/miosix/Makefile
index 31cd85e580e24d92d7c0315efeffcb114521b494..afb5aff8f0affff738950ab673b26428954b24f9 100644
--- a/miosix/Makefile
+++ b/miosix/Makefile
@@ -9,14 +9,6 @@ GCCMAJOR := $(shell arm-miosix-eabi-gcc --version | \
 ## KPATH and CONFPATH are forwarded by the parent Makefile
 include $(CONFPATH)/config/Makefile.inc
 
-ifeq ("$(BUILD_VERBOSE)","1")
-Q :=
-ECHO := @true
-else
-Q := @
-ECHO := @echo
-endif
-
 ## List of all Miosix OS source files that have no special requirements
 ## and that must be built for each architecture (both .c and .cpp)
 ## These files will end up in libmiosix.a
@@ -68,7 +60,6 @@ Q := @
 ECHO := @echo
 endif
 
-BINDIR := bin/$(OPT_BOARD)
 ## Replaces both "foo.cpp"-->"foo.o" and "foo.c"-->"foo.o"
 OBJ := $(addsuffix .o, $(basename $(SRC)))
 
@@ -84,33 +75,27 @@ DFLAGS    := -MMD -MP
 ## Build libmiosix.a and stage_1_boot.o (whose path is in BOOT_FILE)
 ## The file stage_1_boot.o is compiled separately because
 ## it must not end up in libmiosix.a
-all: makedir $(OBJ) $(BOOT_FILE)
+all: $(OBJ) $(BOOT_FILE)
 	$(ECHO) "[PERL] Checking global objects"
 	$(Q)perl _tools/kernel_global_objects.pl $(OBJ)
 	$(ECHO) "[AR  ] libmiosix.a"
-	$(Q)$(AR) rcs $(BINDIR)/libmiosix.a $(OBJ)
-
-makedir:
-	$(Q) mkdir -p $(BINDIR)
+	$(Q)$(AR) rcs libmiosix.a $(OBJ)
 
 clean:
-	-rm -f $(OBJ) $(BOOT_FILE) $(BINDIR)/libmiosix.a $(OBJ:.o=.d)
+	-rm -f $(OBJ) $(BOOT_FILE) libmiosix.a $(OBJ:.o=.d)
 	-rm -f $(BOOT_FILE:.o=.d)
 
 %.o: %.s
-	$(ECHO) "[AS]   $<"
+	$(ECHO) "[AS  ] $<"
 	$(Q)$(AS)  $(AFLAGS) $< -o $@
 
 %.o : %.c
-	$(ECHO) "[CC]   $<"
+	$(ECHO) "[CC  ] $<"
 	$(Q)$(CC)  $(DFLAGS) $(CFLAGS) $< -o $@
 
 %.o : %.cpp
-	$(ECHO) "[CXX]  $<"
+	$(ECHO) "[CXX ] $<"
 	$(Q)$(CXX) $(DFLAGS) $(CXXFLAGS) $< -o $@
 
 #pull in dependecy info for existing .o files
 -include $(OBJ:.o=.d)
-
-.PHONY: clean makedir
-.NOTPARALLEL: clean makedir
diff --git a/miosix/arch/common/CMSIS/Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c b/miosix/arch/common/CMSIS/Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c
index b8faf8a9803be8c34f02f288f7f0e5d9bae8414b..29c0603ee17c9ec5eb03119e3f123d83cc047e5d 100644
--- a/miosix/arch/common/CMSIS/Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c
+++ b/miosix/arch/common/CMSIS/Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c
@@ -98,6 +98,22 @@
                                    This value must be a multiple of 0x200. */
 /******************************************************************************/
 
+// By Alberto Nidasio -- begin
+
+// Divide the input clock
+#define PLL_M (HSE_VALUE/1000000)
+
+#ifdef SYSCLK_FREQ_216MHz
+#define PLL_Q      9
+#define PLL_R      7
+#define PLL_N      432
+#define PLL_P      2
+#else
+#error Clock not selected
+#endif
+
+// By Alberto Nidasio -- end
+
 /**
   * @}
   */
@@ -237,7 +253,7 @@ void SystemInit(void)
   */
 void SystemCoreClockUpdate(void)
 {
-  uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
+  uint32_t tmp = 0, pllvco = 0, pllp = 2, pllSource = 0, pllm = 2;
   
   /* Get SYSCLK source -------------------------------------------------------*/
   tmp = RCC->CFGR & RCC_CFGR_SWS;
@@ -255,10 +271,10 @@ void SystemCoreClockUpdate(void)
       /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
          SYSCLK = PLL_VCO / PLL_P
          */    
-      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
+      pllSource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
       pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
       
-      if (pllsource != 0)
+      if (pllSource != 0)
       {
         /* HSE used as PLL clock source */
         pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
@@ -286,21 +302,12 @@ void SystemCoreClockUpdate(void)
 //By TFT: added PLL initialization that was not present in the CMSIS code
 void SetSysClk(void)
 {
-  register uint32_t tmpreg = 0, timeout = 0xFFFF;
+  register uint32_t tmpReg = 0, timeout = 0xFFFF;
   
 /******************************************************************************/
 /*            PLL (clocked by HSE) used as System clock source                */
 /******************************************************************************/
   
-/************************* PLL Parameters for clock at 216MHz******************/
-  //By TFT: the original settings were for a boar with a 25MHz clock, not 8MHz
-  //They also mention a PLL_R that doesn't exist in the datasheet and maps to
-  //reseved bits. Finally, the PLL input frequency was set to 2MHz to reduce
-  //PLL jitter as suggested by the datasheet.
-  
-  //uint32_t PLL_M = 25,PLL_Q = 9, PLL_R = 7, PLL_N = 432, PLL_P = 2;
-  uint32_t PLL_M = 4,PLL_Q = 9, PLL_R = 7, PLL_N = 216, PLL_P = 2;
-  
   /* Enable Power Control clock */
   RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  
@@ -313,8 +320,8 @@ void SetSysClk(void)
   /* Wait till HSE is ready and if Time out is reached exit */
   do
   {
-    tmpreg = RCC->CR & RCC_CR_HSERDY;
-  } while((tmpreg != RCC_CR_HSERDY) && (timeout-- > 0));
+    tmpReg = RCC->CR & RCC_CR_HSERDY;
+  } while((tmpReg != RCC_CR_HSERDY) && (timeout-- > 0));
   
   if(timeout != 0)
   {  
@@ -330,8 +337,8 @@ void SetSysClk(void)
     /* Wait till ODR is ready and if Time out is reached exit */
     do
     {
-      tmpreg = PWR->CSR1 & PWR_CSR1_ODRDY;
-    } while((tmpreg != PWR_CSR1_ODRDY) && (timeout-- > 0));
+      tmpReg = PWR->CSR1 & PWR_CSR1_ODRDY;
+    } while((tmpReg != PWR_CSR1_ODRDY) && (timeout-- > 0));
     
     /* Enable ODSW */
     PWR->CR1 |= 0x00020000;
@@ -339,8 +346,8 @@ void SetSysClk(void)
     /* Wait till ODR is ready and if Time out is reached exit */
     do
     {
-      tmpreg = PWR->CSR1 & PWR_CSR1_ODSWRDY;
-    } while((tmpreg != PWR_CSR1_ODSWRDY) && (timeout-- > 0)); 
+      tmpReg = PWR->CSR1 & PWR_CSR1_ODSWRDY;
+    } while((tmpReg != PWR_CSR1_ODSWRDY) && (timeout-- > 0)); 
    
     /* HCLK = SYSCLK / 1*/
     RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
@@ -362,8 +369,8 @@ void SetSysClk(void)
   timeout = 0xFFFF;
   do
   {
-    tmpreg = (RCC->CR & RCC_CR_PLLRDY); 
-  } while((tmpreg != RCC_CR_PLLRDY) && (timeout-- > 0));
+    tmpReg = (RCC->CR & RCC_CR_PLLRDY); 
+  } while((tmpReg != RCC_CR_PLLRDY) && (timeout-- > 0));
   
   if(timeout != 0)
   {
@@ -377,8 +384,8 @@ void SetSysClk(void)
     timeout = 0xFFFF;
     do
     {
-      tmpreg = (RCC->CFGR & RCC_CFGR_SWS); 
-    } while((tmpreg != RCC_CFGR_SWS) && (timeout-- > 0));
+      tmpReg = (RCC->CFGR & RCC_CFGR_SWS); 
+    } while((tmpReg != RCC_CFGR_SWS) && (timeout-- > 0));
   }   
 }
 
diff --git a/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/core/stage_1_boot.cpp b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/core/stage_1_boot.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c7c0042ba586117742d47b4452ff35c34fd7b834
--- /dev/null
+++ b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/core/stage_1_boot.cpp
@@ -0,0 +1,479 @@
+#include <string.h>
+
+#include "core/cache_cortexMx.h"
+#include "core/interrupts.h"  //For the unexpected interrupt call
+#include "core/interrupts_cortexMx.h"
+#include "interfaces/arch_registers.h"
+#include "interfaces/bsp.h"
+#include "kernel/stage_2_boot.h"
+
+/*
+ * startup.cpp
+ * STM32 C++ startup.
+ * NOTE: for stm32f769 devices ONLY.
+ * Supports interrupt handlers in C++ without extern "C"
+ * Developed by Terraneo Federico, based on ST startup code.
+ * Additionally modified to boot Miosix.
+ */
+
+/**
+ * Called by Reset_Handler, performs initialization and calls main.
+ * Never returns.
+ */
+void program_startup() __attribute__((noreturn));
+void program_startup() {
+    // Cortex M7 core appears to get out of reset with interrupts already
+    // enabled
+    __disable_irq();
+
+    miosix::IRQconfigureCache();
+
+    // These are defined in the linker script
+    extern unsigned char _etext asm("_etext");
+    extern unsigned char _data asm("_data");
+    extern unsigned char _edata asm("_edata");
+    extern unsigned char _bss_start asm("_bss_start");
+    extern unsigned char _bss_end asm("_bss_end");
+
+    // Initialize .data section, clear .bss section
+    unsigned char *etext = &_etext;
+    unsigned char *data = &_data;
+    unsigned char *edata = &_edata;
+    unsigned char *bss_start = &_bss_start;
+    unsigned char *bss_end = &_bss_end;
+    memcpy(data, etext, edata - data);
+    memset(bss_start, 0, bss_end - bss_start);
+
+    // Move on to stage 2
+    _init();
+
+    // If main returns, reboot
+    NVIC_SystemReset();
+    for (;;)
+        ;
+}
+
+/**
+ * Reset handler, called by hardware immediately after reset
+ */
+void Reset_Handler() __attribute__((__interrupt__, noreturn));
+void Reset_Handler() {
+    /**
+     * SystemInit() is called *before* initializing .data and zeroing .bss
+     * Despite all startup files provided by ST do the opposite, there are three
+     * good reasons to do so:
+     * 1. First, the CMSIS specifications say that SystemInit() must not access
+     *    global variables, so it is actually possible to call it before
+     * 2. Second, when running Miosix with the xram linker scripts .data and
+     *    .bss are placed in the external RAM, so we *must* call SystemInit(),
+     *    which enables xram, before touching .data and .bss
+     * 3. Third, this is a performance improvement since the loops that
+     *    initialize .data and zeros .bss now run with the CPU at full speed
+     *    instead of 8MHz
+     */
+    SystemInit();
+
+    /**
+     * ST does not provide code to initialize the SDRAM at boot.
+     * Put after SystemInit() as SDRAM is timing-sensitive and needs the full
+     * clock speed.
+     */
+#ifdef __ENABLE_XRAM
+    miosix::configureSdram();
+#endif  //__ENABLE_XRAM
+
+    /*
+     * Load into the program stack pointer the heap end address and switch from
+     * the msp to sps.
+     * This is required for booting Miosix, a small portion of the top of the
+     * heap area will be used as stack until the first thread starts. After,
+     * this stack will be abandoned and the process stack will point to the
+     * current thread's stack.
+     */
+    asm volatile(
+        "ldr r0,  =_heap_end          \n\t"
+        "msr psp, r0                  \n\t"
+        "movw r0, #2                  \n\n"  // Set the control register to use
+        "msr control, r0              \n\t"  // the process stack
+        "isb                          \n\t" ::
+            : "r0");
+
+    program_startup();
+}
+
+/**
+ * All unused interrupts call this function.
+ */
+extern "C" void Default_Handler() { unexpectedInterrupt(); }
+
+// System handlers
+void /*__attribute__((weak))*/ Reset_Handler();      // These interrupts are not
+void /*__attribute__((weak))*/ NMI_Handler();        // weak because they are
+void /*__attribute__((weak))*/ HardFault_Handler();  // surely defined by Miosix
+void /*__attribute__((weak))*/ MemManage_Handler();
+void /*__attribute__((weak))*/ BusFault_Handler();
+void /*__attribute__((weak))*/ UsageFault_Handler();
+void /*__attribute__((weak))*/ SVC_Handler();
+void /*__attribute__((weak))*/ DebugMon_Handler();
+void /*__attribute__((weak))*/ PendSV_Handler();
+void /*__attribute__((weak))*/ SysTick_Handler();
+
+// Interrupt handlers
+void __attribute__((weak)) WWDG_IRQHandler();
+void __attribute__((weak)) PVD_IRQHandler();
+void __attribute__((weak)) TAMP_STAMP_IRQHandler();
+void __attribute__((weak)) RTC_WKUP_IRQHandler();
+void __attribute__((weak)) FLASH_IRQHandler();
+void __attribute__((weak)) RCC_IRQHandler();
+void __attribute__((weak)) EXTI0_IRQHandler();
+void __attribute__((weak)) EXTI1_IRQHandler();
+void __attribute__((weak)) EXTI2_IRQHandler();
+void __attribute__((weak)) EXTI3_IRQHandler();
+void __attribute__((weak)) EXTI4_IRQHandler();
+void __attribute__((weak)) DMA1_Stream0_IRQHandler();
+void __attribute__((weak)) DMA1_Stream1_IRQHandler();
+void __attribute__((weak)) DMA1_Stream2_IRQHandler();
+void __attribute__((weak)) DMA1_Stream3_IRQHandler();
+void __attribute__((weak)) DMA1_Stream4_IRQHandler();
+void __attribute__((weak)) DMA1_Stream5_IRQHandler();
+void __attribute__((weak)) DMA1_Stream6_IRQHandler();
+void __attribute__((weak)) ADC_IRQHandler();
+void __attribute__((weak)) CAN1_TX_IRQHandler();
+void __attribute__((weak)) CAN1_RX0_IRQHandler();
+void __attribute__((weak)) CAN1_RX1_IRQHandler();
+void __attribute__((weak)) CAN1_SCE_IRQHandler();
+void __attribute__((weak)) EXTI9_5_IRQHandler();
+void __attribute__((weak)) TIM1_BRK_TIM9_IRQHandler();
+void __attribute__((weak)) TIM1_UP_TIM10_IRQHandler();
+void __attribute__((weak)) TIM1_TRG_COM_TIM11_IRQHandler();
+void __attribute__((weak)) TIM1_CC_IRQHandler();
+void __attribute__((weak)) TIM2_IRQHandler();
+void __attribute__((weak)) TIM3_IRQHandler();
+void __attribute__((weak)) TIM4_IRQHandler();
+void __attribute__((weak)) I2C1_EV_IRQHandler();
+void __attribute__((weak)) I2C1_ER_IRQHandler();
+void __attribute__((weak)) I2C2_EV_IRQHandler();
+void __attribute__((weak)) I2C2_ER_IRQHandler();
+void __attribute__((weak)) SPI1_IRQHandler();
+void __attribute__((weak)) SPI2_IRQHandler();
+void __attribute__((weak)) USART1_IRQHandler();
+void __attribute__((weak)) USART2_IRQHandler();
+void __attribute__((weak)) USART3_IRQHandler();
+void __attribute__((weak)) EXTI15_10_IRQHandler();
+void __attribute__((weak)) RTC_Alarm_IRQHandler();
+void __attribute__((weak)) OTG_FS_WKUP_IRQHandler();
+void __attribute__((weak)) TIM8_BRK_TIM12_IRQHandler();
+void __attribute__((weak)) TIM8_UP_TIM13_IRQHandler();
+void __attribute__((weak)) TIM8_TRG_COM_TIM14_IRQHandler();
+void __attribute__((weak)) TIM8_CC_IRQHandler();
+void __attribute__((weak)) DMA1_Stream7_IRQHandler();
+void __attribute__((weak)) FMC_IRQHandler();
+void __attribute__((weak)) SDMMC1_IRQHandler();
+void __attribute__((weak)) TIM5_IRQHandler();
+void __attribute__((weak)) SPI3_IRQHandler();
+void __attribute__((weak)) UART4_IRQHandler();
+void __attribute__((weak)) UART5_IRQHandler();
+void __attribute__((weak)) TIM6_DAC_IRQHandler();
+void __attribute__((weak)) TIM7_IRQHandler();
+void __attribute__((weak)) DMA2_Stream0_IRQHandler();
+void __attribute__((weak)) DMA2_Stream1_IRQHandler();
+void __attribute__((weak)) DMA2_Stream2_IRQHandler();
+void __attribute__((weak)) DMA2_Stream3_IRQHandler();
+void __attribute__((weak)) DMA2_Stream4_IRQHandler();
+void __attribute__((weak)) ETH_IRQHandler();
+void __attribute__((weak)) ETH_WKUP_IRQHandler();
+void __attribute__((weak)) CAN2_TX_IRQHandler();
+void __attribute__((weak)) CAN2_RX0_IRQHandler();
+void __attribute__((weak)) CAN2_RX1_IRQHandler();
+void __attribute__((weak)) CAN2_SCE_IRQHandler();
+void __attribute__((weak)) OTG_FS_IRQHandler();
+void __attribute__((weak)) DMA2_Stream5_IRQHandler();
+void __attribute__((weak)) DMA2_Stream6_IRQHandler();
+void __attribute__((weak)) DMA2_Stream7_IRQHandler();
+void __attribute__((weak)) USART6_IRQHandler();
+void __attribute__((weak)) I2C3_EV_IRQHandler();
+void __attribute__((weak)) I2C3_ER_IRQHandler();
+void __attribute__((weak)) OTG_HS_EP1_OUT_IRQHandler();
+void __attribute__((weak)) OTG_HS_EP1_IN_IRQHandler();
+void __attribute__((weak)) OTG_HS_WKUP_IRQHandler();
+void __attribute__((weak)) OTG_HS_IRQHandler();
+void __attribute__((weak)) DCMI_IRQHandler();
+void __attribute__((weak)) CRYP_IRQHandler();
+void __attribute__((weak)) RNG_IRQHandler();
+void __attribute__((weak)) FPU_IRQHandler();
+void __attribute__((weak)) UART7_IRQHandler();
+void __attribute__((weak)) UART8_IRQHandler();
+void __attribute__((weak)) SPI4_IRQHandler();
+void __attribute__((weak)) SPI5_IRQHandler();
+void __attribute__((weak)) SPI6_IRQHandler();
+void __attribute__((weak)) SAI1_IRQHandler();
+void __attribute__((weak)) LTDC_IRQHandler();
+void __attribute__((weak)) LTDC_ER_IRQHandler();
+void __attribute__((weak)) DMA2D_IRQHandler();
+void __attribute__((weak)) SAI2_IRQHandler();
+void __attribute__((weak)) QUADSPI_IRQHandler();
+void __attribute__((weak)) LPTIM1_IRQHandler();
+void __attribute__((weak)) CEC_IRQHandler();
+void __attribute__((weak)) I2C4_EV_IRQHandler();
+void __attribute__((weak)) I2C4_ER_IRQHandler();
+void __attribute__((weak)) SPDIF_RX_IRQHandler();
+void __attribute__((weak)) DSIHOST_IRQHandler();
+void __attribute__((weak)) DFSDM1_FLT0_IRQHandler();
+void __attribute__((weak)) DFSDM1_FLT1_IRQHandler();
+void __attribute__((weak)) DFSDM1_FLT2_IRQHandler();
+void __attribute__((weak)) DFSDM1_FLT3_IRQHandler();
+void __attribute__((weak)) SDMMC2_IRQHandler();
+void __attribute__((weak)) CAN3_TX_IRQHandler();
+void __attribute__((weak)) CAN3_RX0_IRQHandler();
+void __attribute__((weak)) CAN3_RX1_IRQHandler();
+void __attribute__((weak)) CAN3_SCE_IRQHandler();
+void __attribute__((weak)) JPEG_IRQHandler();
+void __attribute__((weak)) MDIOS_IRQHandler();
+
+// Stack top, defined in the linker script
+extern char _main_stack_top asm("_main_stack_top");
+
+// Interrupt vectors, must be placed @ address 0x00000000
+// The extern declaration is required otherwise g++ optimizes it out
+extern void (*const __Vectors[])();
+void (*const __Vectors[])() __attribute__((section(".isr_vector"))) = {
+    reinterpret_cast<void (*)()>(&_main_stack_top), /* Stack pointer*/
+    Reset_Handler,                                  /* Reset Handler */
+    NMI_Handler,                                    /* NMI Handler */
+    HardFault_Handler,                              /* Hard Fault Handler */
+    MemManage_Handler,                              /* MPU Fault Handler */
+    BusFault_Handler,                               /* Bus Fault Handler */
+    UsageFault_Handler,                             /* Usage Fault Handler */
+    0,                                              /* Reserved */
+    0,                                              /* Reserved */
+    0,                                              /* Reserved */
+    0,                                              /* Reserved */
+    SVC_Handler,                                    /* SVCall Handler */
+    DebugMon_Handler,                               /* Debug Monitor Handler */
+    0,                                              /* Reserved */
+    PendSV_Handler,                                 /* PendSV Handler */
+    SysTick_Handler,                                /* SysTick Handler */
+
+    /* External Interrupts */
+    WWDG_IRQHandler,
+    PVD_IRQHandler,
+    TAMP_STAMP_IRQHandler,
+    RTC_WKUP_IRQHandler,
+    FLASH_IRQHandler,
+    RCC_IRQHandler,
+    EXTI0_IRQHandler,
+    EXTI1_IRQHandler,
+    EXTI2_IRQHandler,
+    EXTI3_IRQHandler,
+    EXTI4_IRQHandler,
+    DMA1_Stream0_IRQHandler,
+    DMA1_Stream1_IRQHandler,
+    DMA1_Stream2_IRQHandler,
+    DMA1_Stream3_IRQHandler,
+    DMA1_Stream4_IRQHandler,
+    DMA1_Stream5_IRQHandler,
+    DMA1_Stream6_IRQHandler,
+    ADC_IRQHandler,
+    CAN1_TX_IRQHandler,
+    CAN1_RX0_IRQHandler,
+    CAN1_RX1_IRQHandler,
+    CAN1_SCE_IRQHandler,
+    EXTI9_5_IRQHandler,
+    TIM1_BRK_TIM9_IRQHandler,
+    TIM1_UP_TIM10_IRQHandler,
+    TIM1_TRG_COM_TIM11_IRQHandler,
+    TIM1_CC_IRQHandler,
+    TIM2_IRQHandler,
+    TIM3_IRQHandler,
+    TIM4_IRQHandler,
+    I2C1_EV_IRQHandler,
+    I2C1_ER_IRQHandler,
+    I2C2_EV_IRQHandler,
+    I2C2_ER_IRQHandler,
+    SPI1_IRQHandler,
+    SPI2_IRQHandler,
+    USART1_IRQHandler,
+    USART2_IRQHandler,
+    USART3_IRQHandler,
+    EXTI15_10_IRQHandler,
+    RTC_Alarm_IRQHandler,
+    OTG_FS_WKUP_IRQHandler,
+    TIM8_BRK_TIM12_IRQHandler,
+    TIM8_UP_TIM13_IRQHandler,
+    TIM8_TRG_COM_TIM14_IRQHandler,
+    TIM8_CC_IRQHandler,
+    DMA1_Stream7_IRQHandler,
+    FMC_IRQHandler,
+    SDMMC1_IRQHandler,
+    TIM5_IRQHandler,
+    SPI3_IRQHandler,
+    UART4_IRQHandler,
+    UART5_IRQHandler,
+    TIM6_DAC_IRQHandler,
+    TIM7_IRQHandler,
+    DMA2_Stream0_IRQHandler,
+    DMA2_Stream1_IRQHandler,
+    DMA2_Stream2_IRQHandler,
+    DMA2_Stream3_IRQHandler,
+    DMA2_Stream4_IRQHandler,
+    ETH_IRQHandler,
+    ETH_WKUP_IRQHandler,
+    CAN2_TX_IRQHandler,
+    CAN2_RX0_IRQHandler,
+    CAN2_RX1_IRQHandler,
+    CAN2_SCE_IRQHandler,
+    OTG_FS_IRQHandler,
+    DMA2_Stream5_IRQHandler,
+    DMA2_Stream6_IRQHandler,
+    DMA2_Stream7_IRQHandler,
+    USART6_IRQHandler,
+    I2C3_EV_IRQHandler,
+    I2C3_ER_IRQHandler,
+    OTG_HS_EP1_OUT_IRQHandler,
+    OTG_HS_EP1_IN_IRQHandler,
+    OTG_HS_WKUP_IRQHandler,
+    OTG_HS_IRQHandler,
+    DCMI_IRQHandler,
+    CRYP_IRQHandler,
+    RNG_IRQHandler,
+    FPU_IRQHandler,
+    UART7_IRQHandler,
+    UART8_IRQHandler,
+    SPI4_IRQHandler,
+    SPI5_IRQHandler,
+    SPI6_IRQHandler,
+    SAI1_IRQHandler,
+    LTDC_IRQHandler,
+    LTDC_ER_IRQHandler,
+    DMA2D_IRQHandler,
+    SAI2_IRQHandler,
+    QUADSPI_IRQHandler,
+    LPTIM1_IRQHandler,
+    CEC_IRQHandler,
+    I2C4_EV_IRQHandler,
+    I2C4_ER_IRQHandler,
+    SPDIF_RX_IRQHandler,
+    DSIHOST_IRQHandler,
+    DFSDM1_FLT0_IRQHandler,
+    DFSDM1_FLT1_IRQHandler,
+    DFSDM1_FLT2_IRQHandler,
+    DFSDM1_FLT3_IRQHandler,
+    SDMMC2_IRQHandler,
+    CAN3_TX_IRQHandler,
+    CAN3_RX0_IRQHandler,
+    CAN3_RX1_IRQHandler,
+    CAN3_SCE_IRQHandler,
+    JPEG_IRQHandler,
+    MDIOS_IRQHandler,
+};
+
+#pragma weak WWDG_IRQHandler = Default_Handler
+#pragma weak PVD_IRQHandler = Default_Handler
+#pragma weak TAMP_STAMP_IRQHandler = Default_Handler
+#pragma weak RTC_WKUP_IRQHandler = Default_Handler
+#pragma weak FLASH_IRQHandler = Default_Handler
+#pragma weak RCC_IRQHandler = Default_Handler
+#pragma weak EXTI0_IRQHandler = Default_Handler
+#pragma weak EXTI1_IRQHandler = Default_Handler
+#pragma weak EXTI2_IRQHandler = Default_Handler
+#pragma weak EXTI3_IRQHandler = Default_Handler
+#pragma weak EXTI4_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream0_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream1_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream2_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream3_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream4_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream5_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream6_IRQHandler = Default_Handler
+#pragma weak ADC_IRQHandler = Default_Handler
+#pragma weak CAN1_TX_IRQHandler = Default_Handler
+#pragma weak CAN1_RX0_IRQHandler = Default_Handler
+#pragma weak CAN1_RX1_IRQHandler = Default_Handler
+#pragma weak CAN1_SCE_IRQHandler = Default_Handler
+#pragma weak EXTI9_5_IRQHandler = Default_Handler
+#pragma weak TIM1_BRK_TIM9_IRQHandler = Default_Handler
+#pragma weak TIM1_UP_TIM10_IRQHandler = Default_Handler
+#pragma weak TIM1_TRG_COM_TIM11_IRQHandler = Default_Handler
+#pragma weak TIM1_CC_IRQHandler = Default_Handler
+#pragma weak TIM2_IRQHandler = Default_Handler
+#pragma weak TIM3_IRQHandler = Default_Handler
+#pragma weak TIM4_IRQHandler = Default_Handler
+#pragma weak I2C1_EV_IRQHandler = Default_Handler
+#pragma weak I2C1_ER_IRQHandler = Default_Handler
+#pragma weak I2C2_EV_IRQHandler = Default_Handler
+#pragma weak I2C2_ER_IRQHandler = Default_Handler
+#pragma weak SPI1_IRQHandler = Default_Handler
+#pragma weak SPI2_IRQHandler = Default_Handler
+#pragma weak USART1_IRQHandler = Default_Handler
+#pragma weak USART2_IRQHandler = Default_Handler
+#pragma weak USART3_IRQHandler = Default_Handler
+#pragma weak EXTI15_10_IRQHandler = Default_Handler
+#pragma weak RTC_Alarm_IRQHandler = Default_Handler
+#pragma weak OTG_FS_WKUP_IRQHandler = Default_Handler
+#pragma weak TIM8_BRK_TIM12_IRQHandler = Default_Handler
+#pragma weak TIM8_UP_TIM13_IRQHandler = Default_Handler
+#pragma weak TIM8_TRG_COM_TIM14_IRQHandler = Default_Handler
+#pragma weak TIM8_CC_IRQHandler = Default_Handler
+#pragma weak DMA1_Stream7_IRQHandler = Default_Handler
+#pragma weak FMC_IRQHandler = Default_Handler
+#pragma weak SDMMC1_IRQHandler = Default_Handler
+#pragma weak TIM5_IRQHandler = Default_Handler
+#pragma weak SPI3_IRQHandler = Default_Handler
+#pragma weak UART4_IRQHandler = Default_Handler
+#pragma weak UART5_IRQHandler = Default_Handler
+#pragma weak TIM6_DAC_IRQHandler = Default_Handler
+#pragma weak TIM7_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream0_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream1_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream2_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream3_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream4_IRQHandler = Default_Handler
+#pragma weak ETH_IRQHandler = Default_Handler
+#pragma weak ETH_WKUP_IRQHandler = Default_Handler
+#pragma weak CAN2_TX_IRQHandler = Default_Handler
+#pragma weak CAN2_RX0_IRQHandler = Default_Handler
+#pragma weak CAN2_RX1_IRQHandler = Default_Handler
+#pragma weak CAN2_SCE_IRQHandler = Default_Handler
+#pragma weak OTG_FS_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream5_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream6_IRQHandler = Default_Handler
+#pragma weak DMA2_Stream7_IRQHandler = Default_Handler
+#pragma weak USART6_IRQHandler = Default_Handler
+#pragma weak I2C3_EV_IRQHandler = Default_Handler
+#pragma weak I2C3_ER_IRQHandler = Default_Handler
+#pragma weak OTG_HS_EP1_OUT_IRQHandler = Default_Handler
+#pragma weak OTG_HS_EP1_IN_IRQHandler = Default_Handler
+#pragma weak OTG_HS_WKUP_IRQHandler = Default_Handler
+#pragma weak OTG_HS_IRQHandler = Default_Handler
+#pragma weak DCMI_IRQHandler = Default_Handler
+#pragma weak CRYP_IRQHandler = Default_Handler
+#pragma weak RNG_IRQHandler = Default_Handler
+#pragma weak FPU_IRQHandler = Default_Handler
+#pragma weak UART7_IRQHandler = Default_Handler
+#pragma weak UART8_IRQHandler = Default_Handler
+#pragma weak SPI4_IRQHandler = Default_Handler
+#pragma weak SPI5_IRQHandler = Default_Handler
+#pragma weak SPI6_IRQHandler = Default_Handler
+#pragma weak SAI1_IRQHandler = Default_Handler
+#pragma weak LTDC_IRQHandler = Default_Handler
+#pragma weak LTDC_ER_IRQHandler = Default_Handler
+#pragma weak DMA2D_IRQHandler = Default_Handler
+#pragma weak SAI2_IRQHandler = Default_Handler
+#pragma weak QUADSPI_IRQHandler = Default_Handler
+#pragma weak LPTIM1_IRQHandler = Default_Handler
+#pragma weak CEC_IRQHandler = Default_Handler
+#pragma weak I2C4_EV_IRQHandler = Default_Handler
+#pragma weak I2C4_ER_IRQHandler = Default_Handler
+#pragma weak SPDIF_RX_IRQHandler = Default_Handler
+#pragma weak DSIHOST_IRQHandler = Default_Handler
+#pragma weak DFSDM1_FLT0_IRQHandler = Default_Handler
+#pragma weak DFSDM1_FLT1_IRQHandler = Default_Handler
+#pragma weak DFSDM1_FLT2_IRQHandler = Default_Handler
+#pragma weak DFSDM1_FLT3_IRQHandler = Default_Handler
+#pragma weak SDMMC2_IRQHandler = Default_Handler
+#pragma weak CAN3_TX_IRQHandler = Default_Handler
+#pragma weak CAN3_RX0_IRQHandler = Default_Handler
+#pragma weak CAN3_RX1_IRQHandler = Default_Handler
+#pragma weak CAN3_SCE_IRQHandler = Default_Handler
+#pragma weak JPEG_IRQHandler = Default_Handler
+#pragma weak MDIOS_IRQHandler = Default_Handler
diff --git a/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/arch_registers_impl.h b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/arch_registers_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..29cb8822fc174d5c16b01deaa92358fc456d38e5
--- /dev/null
+++ b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/arch_registers_impl.h
@@ -0,0 +1,17 @@
+#ifndef ARCH_REGISTERS_IMPL_H
+#define ARCH_REGISTERS_IMPL_H
+
+// stm32f7xx.h defines a few macros like __ICACHE_PRESENT, __DCACHE_PRESENT and
+// includes core_cm7.h. Do not include core_cm7.h before.
+#define STM32F769xx
+#include "CMSIS/Device/ST/STM32F7xx/Include/stm32f7xx.h"
+
+#if (__ICACHE_PRESENT != 1) || (__DCACHE_PRESENT != 1)
+#error "Wrong include order"
+#endif
+
+#include "CMSIS/Device/ST/STM32F7xx/Include/system_stm32f7xx.h"
+
+#define RCC_SYNC() __DSB()  // TODO: can this dsb be removed?
+
+#endif  // ARCH_REGISTERS_IMPL_H
diff --git a/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/bsp.cpp b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/bsp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c6ea2f5066c50543546d0ab0c8c35da52a23ef1e
--- /dev/null
+++ b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/bsp.cpp
@@ -0,0 +1,287 @@
+/***************************************************************************
+ *   Copyright (C) 2018 by Terraneo Federico                               *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   As a special exception, if other files instantiate templates or use   *
+ *   macros or inline functions from this file, or you compile this file   *
+ *   and link it with other works to produce a work based on this file,    *
+ *   this file does not by itself cause the resulting work to be covered   *
+ *   by the GNU General Public License. However the source code for this   *
+ *   file must still be made available in accordance with the GNU General  *
+ *   Public License. This exception does not invalidate any other reasons  *
+ *   why a work based on this file might be covered by the GNU General     *
+ *   Public License.                                                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
+ ***************************************************************************/
+
+/***********************************************************************
+ * bsp.cpp Part of the Miosix Embedded OS.
+ * Board support package, this file initializes hardware.
+ ************************************************************************/
+
+#include "interfaces/bsp.h"
+
+#include <inttypes.h>
+#include <sys/ioctl.h>
+
+#include <cstdlib>
+
+#include "board_settings.h"
+#include "config/miosix_settings.h"
+#include "drivers/serial.h"
+#include "drivers/serial_stm32.h"
+#include "filesystem/console/console_device.h"
+#include "filesystem/file_access.h"
+#include "interfaces/arch_registers.h"
+#include "interfaces/delays.h"
+#include "interfaces/portability.h"
+#include "kernel/kernel.h"
+#include "kernel/logging.h"
+#include "kernel/sync.h"
+
+namespace miosix {
+
+//
+// Initialization
+//
+
+static void sdramCommandWait() {
+    for (int i = 0; i < 0xffff; i++)
+        if ((FMC_Bank5_6->SDSR & FMC_SDSR_BUSY) == 0)
+            return;
+}
+
+void configureSdram() {
+    // Enable all gpios, passing clock
+    RCC->AHB1ENR |=
+        RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN |
+        RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN |
+        RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN | RCC_AHB1ENR_GPIOIEN |
+        RCC_AHB1ENR_GPIOJEN | RCC_AHB1ENR_GPIOKEN;
+    RCC_SYNC();
+
+    // On the Discovery F769NI, the SDRAM pins are:
+    // - PG8:  FMC_SDCLK
+    // - PH2:  FMC_SDCKE0
+    // - PH3:  FMC_SDNE0
+    // - PF0:  FMC_A0
+    // - PF1:  FMC_A1
+    // - PF2:  FMC_A2
+    // - PF3:  FMC_A3
+    // - PF4:  FMC_A4
+    // - PF5:  FMC_A5
+    // - PF12: FMC_A6
+    // - PF13: FMC_A7
+    // - PF14: FMC_A8
+    // - PF15: FMC_A9
+    // - PG0:  FMC_A10
+    // - PG1:  FMC_A11
+    // - PG2:  FMC_A12
+    // - PD14: FMC_D0
+    // - PD15: FMC_D1
+    // - PD0:  FMC_D2
+    // - PD1:  FMC_D3
+    // - PE7:  FMC_D4
+    // - PE8:  FMC_D5
+    // - PE9:  FMC_D6
+    // - PE10: FMC_D7
+    // - PE11: FMC_D8
+    // - PE12: FMC_D9
+    // - PE13: FMC_D10
+    // - PE14: FMC_D11
+    // - PE15: FMC_D12
+    // - PD8:  FMC_D13
+    // - PD9:  FMC_D14
+    // - PD10: FMC_D15
+    // - PH8:  FMC_D16
+    // - PH9:  FMC_D17
+    // - PH10: FMC_D18
+    // - PH11: FMC_D19
+    // - PH12: FMC_D20
+    // - PH13: FMC_D21
+    // - PH14: FMC_D22
+    // - PH15: FMC_D23
+    // - PI0:  FMC_D24
+    // - PI1:  FMC_D25
+    // - PI2:  FMC_D26
+    // - PI3:  FMC_D27
+    // - PI6:  FMC_D28
+    // - PI7:  FMC_D29
+    // - PI9:  FMC_D30
+    // - PI10: FMC_D31
+    // - PG4:  FMC_BA0
+    // - PG5:  FMC_BA1
+    // - PF11: FMC_SDNRAS
+    // - PG15: FMC_SDNCAS
+    // - PH5:  FMC_SDNWE
+    // - PE0:  FMC_NBL0
+    // - PE1:  FMC_NBL1
+    // - PI4:  FMC_NBL2
+    // - PI5:  FMC_NBL3
+
+    // All SDRAM GPIOs needs to be configured with alternate function 12 and
+    // maximum speed
+
+    // Alternate functions
+    GPIOD->AFR[0] = 0x000000cc;
+    GPIOD->AFR[1] = 0xcc000ccc;
+    GPIOE->AFR[0] = 0xc00000cc;
+    GPIOE->AFR[1] = 0xcccccccc;
+    GPIOF->AFR[0] = 0x00cccccc;
+    GPIOF->AFR[1] = 0xccccc000;
+    GPIOG->AFR[0] = 0x00cc0ccc;
+    GPIOG->AFR[1] = 0xc000000c;
+    GPIOH->AFR[0] = 0x00c0cc00;
+    GPIOH->AFR[1] = 0xcccccccc;
+    GPIOI->AFR[0] = 0xcccccccc;
+    GPIOI->AFR[1] = 0x00000cc0;
+
+    // Mode
+    GPIOD->MODER = 0xa02a000a;
+    GPIOE->MODER = 0xaaaa800a;
+    GPIOF->MODER = 0xaa800aaa;
+    GPIOG->MODER = 0x80020a2a;
+    GPIOH->MODER = 0xaaaa08a0;
+    GPIOI->MODER = 0x0028aaaa;
+
+    // Speed (high speed for all, very high speed for SDRAM pins)
+    GPIOA->OSPEEDR = 0xaaaaaaaa;
+    GPIOB->OSPEEDR = 0xaaaaaaaa;
+    GPIOC->OSPEEDR = 0xaaaaaaaa;
+    GPIOD->OSPEEDR = 0xaaaaaaaa | 0xf03f000f;
+    GPIOE->OSPEEDR = 0xaaaaaaaa | 0xffffc00f;
+    GPIOF->OSPEEDR = 0xaaaaaaaa | 0xffc00fff;
+    GPIOG->OSPEEDR = 0xaaaaaaaa | 0xc0030f3f;
+    GPIOH->OSPEEDR = 0xaaaaaaaa | 0xffff0cf0;
+    GPIOI->OSPEEDR = 0xaaaaaaaa | 0x003cffff;
+    GPIOJ->OSPEEDR = 0xaaaaaaaa;
+    GPIOK->OSPEEDR = 0xaaaaaaaa;
+
+    // Enable the SDRAM controller clock
+    RCC->AHB3ENR |= RCC_AHB3ENR_FMCEN;
+    RCC_SYNC();
+
+    // The SDRAM is a IS42S32400F-6BL
+    // HCLK = 216MHz -> SDRAM clock = HCLK/2 = 133MHz
+
+    // 1. Memory device features
+    FMC_Bank5_6->SDCR[0] = 0                    // 0 delay after CAS latency
+                           | FMC_SDCR1_RBURST   // Enable read bursts
+                           | FMC_SDCR1_SDCLK_1  // SDCLK = HCLK / 2
+                           | 0                  // Write accesses allowed
+                           | FMC_SDCR1_CAS_1    // 2 cycles CAS latency
+                           | FMC_SDCR1_NB       // 4 internal banks
+                           | FMC_SDCR1_MWID_1   // 32 bit data bus
+                           | FMC_SDCR1_NR_0     // 12 bit row address
+                           | 0;                 // 8 bit column address
+
+    // 2. Memory device timings
+#ifdef SYSCLK_FREQ_216MHz
+    // SDRAM timings. One clock cycle is 9.26ns
+    FMC_Bank5_6->SDTR[0] =
+        (2 - 1) << FMC_SDTR1_TRCD_Pos     // 2 cycles TRCD (18.52ns > 18ns)
+        | (2 - 1) << FMC_SDTR1_TRP_Pos    // 2 cycles TRP  (18.52ns > 18ns)
+        | (2 - 1) << FMC_SDTR1_TWR_Pos    // 2 cycles TWR  (18.52ns > 12ns)
+        | (7 - 1) << FMC_SDTR1_TRC_Pos    // 7 cycles TRC  (64.82ns > 60ns)
+        | (5 - 1) << FMC_SDTR1_TRAS_Pos   // 5 cycles TRAS (46.3ns  > 42ns)
+        | (8 - 1) << FMC_SDTR1_TXSR_Pos   // 8 cycles TXSR (74.08ns > 70ns)
+        | (2 - 1) << FMC_SDTR1_TMRD_Pos;  // 2 cycles TMRD (18.52ns > 12ns)
+#else
+#error No SDRAM timings for this clock
+#endif
+
+    // 3. Enable the bank 1 clock
+    FMC_Bank5_6->SDCMR = FMC_SDCMR_MODE_0   // Clock Configuration Enable
+                         | FMC_SDCMR_CTB1;  // Bank 1
+    sdramCommandWait();
+
+    // 4. Wait during command execution
+    delayUs(100);
+
+    // 5. Issue a "Precharge All" command
+    FMC_Bank5_6->SDCMR = FMC_SDCMR_MODE_1   // Precharge all
+                         | FMC_SDCMR_CTB1;  // Bank 1
+    sdramCommandWait();
+
+    // 6. Issue Auto-Refresh commands
+    FMC_Bank5_6->SDCMR = FMC_SDCMR_MODE_1 | FMC_SDCMR_MODE_0  // Auto-Refresh
+                         | FMC_SDCMR_CTB1                     // Bank 1
+                         | (8 - 1) << FMC_SDCMR_NRFS_Pos;     // 2 Auto-Refresh
+    sdramCommandWait();
+
+    // 7. Issue a Load Mode Register command
+    FMC_Bank5_6->SDCMR = FMC_SDCMR_MODE_2               /// Load mode register
+                         | FMC_SDCMR_CTB1               // Bank 1
+                         | 0x220 << FMC_SDCMR_MRD_Pos;  // CAS = 2, burst = 1
+    sdramCommandWait();
+
+    // 8. Program the refresh rate (4K / 64ms)
+    // 64ms / 4096 = 15.625us
+#ifdef SYSCLK_FREQ_216MHz
+    // 15.625us * 108MHz = 1687 - 20 = 1667
+    FMC_Bank5_6->SDRTR = 1667 << FMC_SDRTR_COUNT_Pos;
+#else
+#error No SDRAM refresh timings for this clock
+#endif
+}
+
+void IRQbspInit() {
+// If using SDRAM GPIOs are enabled by configureSdram(), else enable them here
+#ifndef __ENABLE_XRAM
+    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN |
+                    RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN |
+                    RCC_AHB1ENR_GPIOEEN | RCC_AHB1ENR_GPIOFEN |
+                    RCC_AHB1ENR_GPIOGEN | RCC_AHB1ENR_GPIOHEN |
+                    RCC_AHB1ENR_GPIOIEN | RCC_AHB1ENR_GPIOJEN;
+    RCC_SYNC();
+#endif  //__ENABLE_XRAM
+
+    userLed1::mode(Mode::OUTPUT);
+    userLed2::mode(Mode::OUTPUT);
+    userLed3::mode(Mode::OUTPUT);
+    userBtn::mode(Mode::INPUT);
+    sdCardDetect::mode(Mode::INPUT);
+
+    ledOn();
+    delayMs(100);
+    ledOff();
+
+    DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>(new STM32Serial(
+        defaultSerial, defaultSerialSpeed, STM32Serial::NOFLOWCTRL)));
+}
+
+void bspInit2() {
+    // Nothing to do
+}
+
+//
+// Shutdown and reboot
+//
+
+void shutdown() {
+    ioctl(STDOUT_FILENO, IOCTL_SYNC, 0);
+
+    disableInterrupts();
+    for (;;)
+        ;
+}
+
+void reboot() {
+    ioctl(STDOUT_FILENO, IOCTL_SYNC, 0);
+
+    disableInterrupts();
+    miosix_private::IRQsystemReboot();
+}
+
+}  // namespace miosix
diff --git a/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/bsp_impl.h b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/bsp_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b276803f54778927355ecd47e50083efe647b96
--- /dev/null
+++ b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/interfaces-impl/bsp_impl.h
@@ -0,0 +1,105 @@
+/***************************************************************************
+ *   Copyright (C) 2018 by Terraneo Federico                               *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   As a special exception, if other files instantiate templates or use   *
+ *   macros or inline functions from this file, or you compile this file   *
+ *   and link it with other works to produce a work based on this file,    *
+ *   this file does not by itself cause the resulting work to be covered   *
+ *   by the GNU General Public License. However the source code for this   *
+ *   file must still be made available in accordance with the GNU General  *
+ *   Public License. This exception does not invalidate any other reasons  *
+ *   why a work based on this file might be covered by the GNU General     *
+ *   Public License.                                                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
+ ***************************************************************************/
+
+/***************************************************************************
+ * bsp_impl.h Part of the Miosix Embedded OS.
+ * Board support package, this file initializes hardware.
+ ***************************************************************************/
+
+#ifndef BSP_IMPL_H
+#define BSP_IMPL_H
+
+#include "config/miosix_settings.h"
+#include "interfaces/gpio.h"
+
+namespace miosix {
+
+/**
+\addtogroup Hardware
+\{
+*/
+
+/**
+ * \internal
+ * Called by stage_1_boot.cpp to enable the SDRAM before initializing .data/.bss
+ * Requires the CPU clock to be already configured (running from the PLL)
+ */
+void configureSdram();
+
+/**
+ * \internal
+ * Board pin definition
+ */
+typedef Gpio<GPIOJ_BASE, 13> userLed1;
+typedef Gpio<GPIOJ_BASE, 5> userLed2;
+typedef Gpio<GPIOA_BASE, 12> userLed3;
+typedef Gpio<GPIOA_BASE, 0> userBtn;
+typedef Gpio<GPIOI_BASE, 15> sdCardDetect;
+
+inline void ledOn() {
+    userLed1::high();
+    userLed2::high();
+    userLed3::high();
+}
+
+inline void ledOff() {
+    userLed1::low();
+    userLed2::low();
+    userLed3::low();
+}
+
+inline void led1On() { userLed1::high(); }
+
+inline void led1Off() { userLed1::low(); }
+
+inline void led2On() { userLed2::high(); }
+
+inline void led2Off() { userLed2::low(); }
+
+inline void led3On() { userLed3::high(); }
+
+inline void led3Off() { userLed3::low(); }
+
+/**
+ * Polls the SD card sense GPIO.
+ *
+ * This board has no SD card whatsoever, but a card can be connected to the
+ * following GPIOs:
+ * TODO: never tested
+ *
+ * \return true. As there's no SD card sense switch, let's pretend that
+ * the card is present.
+ */
+inline bool sdCardSense() { return sdCardDetect::value() == 0; }
+
+/**
+\}
+*/
+
+}  // namespace miosix
+
+#endif  // BSP_IMPL_H
diff --git a/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/stm32_2m+16m_xram.ld b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/stm32_2m+16m_xram.ld
new file mode 100644
index 0000000000000000000000000000000000000000..683956e89517d0cc9dbecaf59bcea5d0690644d8
--- /dev/null
+++ b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/stm32_2m+16m_xram.ld
@@ -0,0 +1,179 @@
+/*
+ * C++ enabled linker script for stm32f769ni (2M FLASH, 512K RAM, 16MB XRAM)
+ * Developed by TFT: Terraneo Federico Technologies
+ * Optimized for use with the Miosix kernel
+ */
+
+/*
+ * This linker script puts:
+ * - read only data and code (.text, .rodata, .eh_*) in FLASH
+ * - the 512Byte main (IRQ) stack, .data and .bss in the DTCM 128KB RAM
+ * - .data, .bss, stacks and heap in the external 16MB SDRAM.
+ */
+
+/*
+ * The main stack is used for interrupt handling by the kernel.
+ *
+ * *** Readme ***
+ * This linker script places the main stack (used by the kernel for interrupts)
+ * at the bottom of the ram, instead of the top. This is done for two reasons:
+ *
+ * - as an optimization for microcontrollers with little ram memory. In fact
+ *   the implementation of malloc from newlib requests memory to the OS in 4KB
+ *   block (except the first block that can be smaller). This is probably done
+ *   for compatibility with OSes with an MMU and paged memory. To see why this
+ *   is bad, consider a microcontroller with 8KB of ram: when malloc finishes
+ *   up the first 4KB it will call _sbrk_r asking for a 4KB block, but this will
+ *   fail because the top part of the ram is used by the main stack. As a
+ *   result, the top part of the memory will not be used by malloc, even if
+ *   available (and it is nearly *half* the ram on an 8KB mcu). By placing the
+ *   main stack at the bottom of the ram, the upper 4KB block will be entirely
+ *   free and available as heap space.
+ *
+ * - In case of main stack overflow the cpu will fault because access to memory
+ *   before the beginning of the ram faults. Instead with the default stack
+ *   placement the main stack will silently collide with the heap.
+ * Note: if increasing the main stack size also increase the ORIGIN value in
+ * the MEMORY definitions below accordingly.
+ */
+
+_main_stack_size = 512;                             /* main stack = 512Bytes */
+_main_stack_top  = 0x20000000 + _main_stack_size;
+ASSERT(_main_stack_size   % 8 == 0, "MAIN stack size error");
+
+/* Mapping the heap into XRAM */
+_heap_end = 0xc0000000 + 16M;                        /* end of available ram */
+
+/* Identify the Entry Point  */
+ENTRY(_Z13Reset_Handlerv)
+
+/*
+ * Specify the memory areas
+ *
+ * NOTE: starting at 0x20000000 there's 128KB of DTCM (Data Tightly Coupled
+ * Memory). Technically, we could use this as normal RAM as there's a way for
+ * the DMA to access it, but the datasheet is unclear about performance
+ * penalties for doing so. To avoid nonuniform DMA memory access latencies,
+ * we leave this 128KB DTCM unused except for the first 512Bytes which are for
+ * the interrupt stack. This leaves us with 384KB of RAM
+ */
+MEMORY
+{
+    xram(wx)  : ORIGIN = 0xc0000000, LENGTH =  16M
+    sram(wx)  : ORIGIN = 0x20020000, LENGTH = 384K
+    dtcm(wx)  : ORIGIN = 0x20000000, LENGTH = 128K    /* Used for main stack */
+    flash(rx) : ORIGIN = 0x08000000, LENGTH =   2M
+}
+
+/* now define the output sections  */
+SECTIONS
+{
+    . = 0;
+    
+    /* .text section: code goes to flash */
+    .text :
+    {
+        /* Startup code must go at address 0 */
+        KEEP(*(.isr_vector))
+        
+        *(.text)
+        *(.text.*)
+        *(.gnu.linkonce.t.*)
+        /* these sections for thumb interwork? */
+        *(.glue_7)
+        *(.glue_7t)
+        /* these sections for C++? */
+        *(.gcc_except_table)
+        *(.gcc_except_table.*)
+        *(.ARM.extab*)
+        *(.gnu.linkonce.armextab.*)
+
+        . = ALIGN(4);
+        /* .rodata: constant data */
+        *(.rodata)
+        *(.rodata.*)
+        *(.gnu.linkonce.r.*)
+
+        /* C++ Static constructors/destructors (eabi) */
+        . = ALIGN(4);
+        KEEP(*(.init))
+        
+        . = ALIGN(4);
+        __miosix_init_array_start = .;
+        KEEP (*(SORT(.miosix_init_array.*)))
+        KEEP (*(.miosix_init_array))
+        __miosix_init_array_end = .;
+
+        . = ALIGN(4);
+        __preinit_array_start = .;
+        KEEP (*(.preinit_array))
+        __preinit_array_end = .;
+
+        . = ALIGN(4);
+        __init_array_start = .;
+        KEEP (*(SORT(.init_array.*)))
+        KEEP (*(.init_array))
+        __init_array_end = .;
+
+        . = ALIGN(4);
+        KEEP(*(.fini))
+
+        . = ALIGN(4);
+        __fini_array_start = .;
+        KEEP (*(.fini_array))
+        KEEP (*(SORT(.fini_array.*)))
+        __fini_array_end = .;
+
+        /* C++ Static constructors/destructors (elf)  */
+        . = ALIGN(4);
+        _ctor_start = .;
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*crtend.o(.ctors))
+       _ctor_end = .;
+
+        . = ALIGN(4);
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*crtend.o(.dtors))
+    } > flash
+
+    /* .ARM.exidx is sorted, so has to go in its own output section.  */
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > flash
+    __exidx_end = .;
+
+	/*
+     * .data section: global variables go to xram, but also store a copy to
+     * flash to initialize them
+     */
+    .data : ALIGN(8)
+    {
+        _data = .;
+        *(.data)
+        *(.data.*)
+        *(.gnu.linkonce.d.*)
+        . = ALIGN(8);
+        _edata = .;
+    } > xram AT > flash
+    _etext = LOADADDR(.data);
+
+    /* .bss section: uninitialized global variables go to xram */
+    _bss_start = .;
+    .bss :
+    {
+        *(.bss)
+        *(.bss.*)
+        *(.gnu.linkonce.b.*)
+        . = ALIGN(8);
+    } > xram
+    _bss_end = .;
+
+    _end = .;
+    PROVIDE(end = .);
+}
diff --git a/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/stm32_2m+384k_ram.ld b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/stm32_2m+384k_ram.ld
new file mode 100644
index 0000000000000000000000000000000000000000..5c82915f3727b667011636ead66f46d120e4315a
--- /dev/null
+++ b/miosix/arch/cortexM7_stm32f7/stm32f769ni_discovery/stm32_2m+384k_ram.ld
@@ -0,0 +1,178 @@
+/*
+ * C++ enabled linker script for stm32f769ni (2M FLASH, 384K RAM)
+ * Developed by TFT: Terraneo Federico Technologies
+ * Optimized for use with the Miosix kernel
+ */
+
+/*
+ * This linker script puts:
+ * - read only data and code (.text, .rodata, .eh_*) in FLASH
+ * - the 512Byte main (IRQ) stack, .data and .bss in the DTCM 128KB RAM
+ * - .data, .bss, stacks and heap in the internal RAM.
+ */
+
+/*
+ * The main stack is used for interrupt handling by the kernel.
+ *
+ * *** Readme ***
+ * This linker script places the main stack (used by the kernel for interrupts)
+ * at the bottom of the ram, instead of the top. This is done for two reasons:
+ *
+ * - as an optimization for microcontrollers with little ram memory. In fact
+ *   the implementation of malloc from newlib requests memory to the OS in 4KB
+ *   block (except the first block that can be smaller). This is probably done
+ *   for compatibility with OSes with an MMU and paged memory. To see why this
+ *   is bad, consider a microcontroller with 8KB of ram: when malloc finishes
+ *   up the first 4KB it will call _sbrk_r asking for a 4KB block, but this will
+ *   fail because the top part of the ram is used by the main stack. As a
+ *   result, the top part of the memory will not be used by malloc, even if
+ *   available (and it is nearly *half* the ram on an 8KB mcu). By placing the
+ *   main stack at the bottom of the ram, the upper 4KB block will be entirely
+ *   free and available as heap space.
+ *
+ * - In case of main stack overflow the cpu will fault because access to memory
+ *   before the beginning of the ram faults. Instead with the default stack
+ *   placement the main stack will silently collide with the heap.
+ * Note: if increasing the main stack size also increase the ORIGIN value in
+ * the MEMORY definitions below accordingly.
+ */
+
+_main_stack_size = 512;                             /* main stack = 512Bytes */
+_main_stack_top  = 0x20000000 + _main_stack_size;
+ASSERT(_main_stack_size   % 8 == 0, "MAIN stack size error");
+
+/* Mapping the heap to the end of SRAM2 */
+_heap_end = 0x20000000 + 512K;                       /* end of available ram */
+
+/* Identify the Entry Point  */
+ENTRY(_Z13Reset_Handlerv)
+
+/*
+ * Specify the memory areas
+ *
+ * NOTE: starting at 0x20000000 there's 128KB of DTCM (Data Tightly Coupled
+ * Memory). Technically, we could use this as normal RAM as there's a way for
+ * the DMA to access it, but the datasheet is unclear about performance
+ * penalties for doing so. To avoid nonuniform DMA memory access latencies,
+ * we leave this 128KB DTCM unused except for the first 512Bytes which are for
+ * the interrupt stack. This leaves us with 384KB of RAM
+ */
+MEMORY
+{
+    sram(wx)  : ORIGIN = 0x20020000, LENGTH = 384K
+    dtcm(wx)  : ORIGIN = 0x20000000, LENGTH = 128K    /* Used for main stack */
+    flash(rx) : ORIGIN = 0x08000000, LENGTH =   2M
+}
+
+/* now define the output sections  */
+SECTIONS
+{
+    . = 0;
+    
+    /* .text section: code goes to flash */
+    .text :
+    {
+        /* Startup code must go at address 0 */
+        KEEP(*(.isr_vector))
+        
+        *(.text)
+        *(.text.*)
+        *(.gnu.linkonce.t.*)
+        /* these sections for thumb interwork? */
+        *(.glue_7)
+        *(.glue_7t)
+        /* these sections for C++? */
+        *(.gcc_except_table)
+        *(.gcc_except_table.*)
+        *(.ARM.extab*)
+        *(.gnu.linkonce.armextab.*)
+
+        . = ALIGN(4);
+        /* .rodata: constant data */
+        *(.rodata)
+        *(.rodata.*)
+        *(.gnu.linkonce.r.*)
+
+        /* C++ Static constructors/destructors (eabi) */
+        . = ALIGN(4);
+        KEEP(*(.init))
+        
+        . = ALIGN(4);
+        __miosix_init_array_start = .;
+        KEEP (*(SORT(.miosix_init_array.*)))
+        KEEP (*(.miosix_init_array))
+        __miosix_init_array_end = .;
+
+        . = ALIGN(4);
+        __preinit_array_start = .;
+        KEEP (*(.preinit_array))
+        __preinit_array_end = .;
+
+        . = ALIGN(4);
+        __init_array_start = .;
+        KEEP (*(SORT(.init_array.*)))
+        KEEP (*(.init_array))
+        __init_array_end = .;
+
+        . = ALIGN(4);
+        KEEP(*(.fini))
+
+        . = ALIGN(4);
+        __fini_array_start = .;
+        KEEP (*(.fini_array))
+        KEEP (*(SORT(.fini_array.*)))
+        __fini_array_end = .;
+
+        /* C++ Static constructors/destructors (elf)  */
+        . = ALIGN(4);
+        _ctor_start = .;
+        KEEP (*crtbegin.o(.ctors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
+        KEEP (*(SORT(.ctors.*)))
+        KEEP (*crtend.o(.ctors))
+       _ctor_end = .;
+
+        . = ALIGN(4);
+        KEEP (*crtbegin.o(.dtors))
+        KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
+        KEEP (*(SORT(.dtors.*)))
+        KEEP (*crtend.o(.dtors))
+    } > flash
+
+    /* .ARM.exidx is sorted, so has to go in its own output section.  */
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > flash
+    __exidx_end = .;
+
+	/*
+     * .data section: global variables go to sram, but also store a copy to
+     * flash to initialize them
+     */
+    .data : ALIGN(8)
+    {
+        _data = .;
+        *(.data)
+        *(.data.*)
+        *(.gnu.linkonce.d.*)
+        . = ALIGN(8);
+        _edata = .;
+    } > sram AT > flash
+    _etext = LOADADDR(.data);
+
+    /* .bss section: uninitialized global variables go to sram */
+    _bss_start = .;
+    .bss :
+    {
+        *(.bss)
+        *(.bss.*)
+        *(.gnu.linkonce.b.*)
+        . = ALIGN(8);
+    } > sram
+    _bss_end = .;
+
+    _end = .;
+    PROVIDE(end = .);
+}
diff --git a/miosix/config/Makefile.inc b/miosix/config/Makefile.inc
index fe137259bd74dc9fa51ed65ae229cdebc3a869cc..772820630aa8e29a042fff98678738287bc1927f 100644
--- a/miosix/config/Makefile.inc
+++ b/miosix/config/Makefile.inc
@@ -63,6 +63,7 @@
 #OPT_BOARD := stm32l476rg_nucleo
 #OPT_BOARD := atsam4lc2aa_generic
 #OPT_BOARD := stm32f411ce_blackpill
+OPT_BOARD := stm32f769ni_discovery
 
 ##
 ## Optimization flags, choose one.
@@ -1071,6 +1072,8 @@ else ifeq ($(OPT_BOARD),atsam4lc2aa_generic)
     ARCH := cortexM4_atsam4l
 else ifeq ($(OPT_BOARD),stm32f411ce_blackpill)
     ARCH := cortexM4_stm32f4
+else ifeq ($(OPT_BOARD),stm32f769ni_discovery)
+    ARCH := cortexM7_stm32f7
 else
     $(info Error: no board specified in miosix/config/Makefile.inc)
     $(error Error)
@@ -2959,6 +2962,45 @@ else ifeq ($(ARCH),cortexM7_stm32f7)
         ## board.
         PROGRAM_CMDLINE := echo 'make program not supported.'
 
+    ##-------------------------------------------------------------------------
+    ## BOARD: stm32f769ni_discovery
+    ##
+    else ifeq ($(OPT_BOARD),stm32f769ni_discovery)
+        ## Select appropriate compiler flags for both ASM/C/C++/linker
+        ## The stm32f769 has the double precision FPU, so we will build for m7
+        ARCHOPTS := -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16
+    
+        ## Base directory with header files for this board
+        BOARD_INC := arch/cortexM7_stm32f7/stm32f769ni_discovery
+
+        ## Select linker script and boot file
+        ## Their path must be relative to the miosix directory.
+        BOOT_FILE := $(BOARD_INC)/core/stage_1_boot.o
+        # LINKER_SCRIPT := $(BOARD_INC)/stm32_2m+384k_ram.ld
+        LINKER_SCRIPT := $(BOARD_INC)/stm32_2m+16m_xram.ld
+
+        ## Select architecture specific files
+        ## These are the files in arch/<arch name>/<board name>
+        ARCH_SRC := $(BOARD_INC)/interfaces-impl/bsp.cpp
+
+        ## Add a #define to allow querying board name
+        CFLAGS_BASE   += -D_BOARD_STM32F769NI_DISCO
+        CXXFLAGS_BASE += -D_BOARD_STM32F769NI_DISCO
+
+        ## Enables the initialization of the external 16MB SDRAM memory
+        XRAM := -D__ENABLE_XRAM
+
+        ## Select clock frequency (HSE_VALUE is the xtal on board, fixed)
+        CLOCK_FREQ := -DHSE_VALUE=25000000 -DSYSCLK_FREQ_216MHz=216000000
+
+        ## Select programmer command line
+        ## This is the program that is invoked when the user types
+        ## 'make program'
+        ## The command must provide a way to program the board, or print an
+        ## error message saying that 'make program' is not supported for that
+        ## board.
+        PROGRAM_CMDLINE := st-flash --reset write "main.bin" 0x8000000
+
     ##-------------------------------------------------------------------------
     ## End of board list
     ##
@@ -2993,7 +3035,6 @@ else ifeq ($(ARCH),cortexM7_stm32f7)
     arch/common/core/mpu_cortexMx.cpp                        \
     arch/common/core/cache_cortexMx.cpp                      \
     arch/common/drivers/serial_stm32.cpp                     \
-    arch/common/drivers/sd_stm32f2_f4.cpp                    \
     arch/common/drivers/dcc.cpp                              \
     $(ARCH_INC)/interfaces-impl/portability.cpp              \
     $(ARCH_INC)/interfaces-impl/delays.cpp                   \
diff --git a/miosix/config/arch/cortexM7_stm32f7/stm32f769ni_discovery/board_settings.h b/miosix/config/arch/cortexM7_stm32f7/stm32f769ni_discovery/board_settings.h
new file mode 100644
index 0000000000000000000000000000000000000000..ca505da47fdf4b794f1eb4fb53ffd3eb67a7a102
--- /dev/null
+++ b/miosix/config/arch/cortexM7_stm32f7/stm32f769ni_discovery/board_settings.h
@@ -0,0 +1,73 @@
+/***************************************************************************
+ *   Copyright (C) 2018 by Terraneo Federico                               *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   As a special exception, if other files instantiate templates or use   *
+ *   macros or inline functions from this file, or you compile this file   *
+ *   and link it with other works to produce a work based on this file,    *
+ *   this file does not by itself cause the resulting work to be covered   *
+ *   by the GNU General Public License. However the source code for this   *
+ *   file must still be made available in accordance with the GNU General  *
+ *   Public License. This exception does not invalidate any other reasons  *
+ *   why a work based on this file might be covered by the GNU General     *
+ *   Public License.                                                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
+ ***************************************************************************/
+
+#pragma once
+
+#include "util/version.h"
+
+/**
+ * \internal
+ * Versioning for board_settings.h for out of git tree projects
+ */
+#define BOARD_SETTINGS_VERSION 100
+
+namespace miosix {
+
+/**
+ * \addtogroup Settings
+ * \{
+ */
+
+/// Size of stack for main().
+/// The C standard library is stack-heavy (iprintf requires 1KB)
+const unsigned int MAIN_STACK_SIZE = 4 * 1024;
+
+/// Frequency of tick (in Hz). For the priority scheduler this is also the
+/// context switch frequency
+const unsigned int TICK_FREQ = 1000;
+
+///\internal Aux timer run @ 100KHz
+/// Note that since the timer is only 16 bits this imposes a limit on the
+/// burst measurement of 655ms. If due to a pause_kernel() or
+/// disable_interrupts() section a thread runs for more than that time, a wrong
+/// burst value will be measured
+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;
+const unsigned int defaultSerialSpeed = 115200;
+// #define SERIAL_1_DMA
+
+// SD card driver
+static const unsigned char sdVoltage = 33;  // Board powered @ 3.3V
+
+/**
+ * \}
+ */
+
+}  // namespace miosix
diff --git a/miosix/config/boards.cmake b/miosix/config/boards.cmake
index 83bf1a482795be3171d38eb35e63267d2d446f8c..83154f5bec12fb8d92d2ce198db8ef1d2cffc9a7 100644
--- a/miosix/config/boards.cmake
+++ b/miosix/config/boards.cmake
@@ -75,4 +75,5 @@ set(BOARDS
     stm32f429zi_skyward_groundstation_parafoil
     stm32f429zi_skyward_pyxis_auxiliary
     stm32f429zi_skyward_parafoil
+    stm32f769ni_discovery
 )
diff --git a/miosix/config/options.cmake b/miosix/config/options.cmake
index 73797abac23c399c8cffaaf6f912ea80be693308..5cdb573a3bee373e504307a26e7a676e7df41beb 100644
--- a/miosix/config/options.cmake
+++ b/miosix/config/options.cmake
@@ -1147,6 +1147,8 @@ elseif(${OPT_BOARD} STREQUAL stm32f429zi_hre_test_stand)
     set(ARCH cortexM4_stm32f4)
 elseif(${OPT_BOARD} STREQUAL stm32f429zi_skyward_parafoil)
     set(ARCH cortexM4_stm32f4)
+elseif(${OPT_BOARD} STREQUAL stm32f769ni_discovery)
+    set(ARCH cortexM7_stm32f7)
 else()
     message(FATAL_ERROR "no board specified in miosix/config/options.cmake")
 endif()
@@ -3053,6 +3055,46 @@ elseif(${ARCH} STREQUAL cortexM7_stm32f7)
         ## board.
         set(PROGRAM_CMDLINE echo "make program not supported.")
 
+    ##-------------------------------------------------------------------------
+    ## BOARD: stm32f769ni_discovery
+    ##
+    elseif(${OPT_BOARD} STREQUAL stm32f769ni_discovery)
+        ## Select appropriate compiler flags for both ASM/C/C++/linker
+        ## Not all stm32f7 have the double precision FPU. Those that only
+        ## support single precision are built as cortex m4
+        set(ARCHOPTS -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16)
+
+        ## Base directory with header files for this board
+        set(BOARD_INC arch/cortexM7_stm32f7/stm32f769ni_discovery)
+
+        ## Select linker script and boot file
+        ## Their path must be relative to the miosix directory.
+        set(BOOT_FILE ${KPATH}/${BOARD_INC}/core/stage_1_boot.cpp)
+        #set(LINKER_SCRIPT ${LINKER_SCRIPT_PATH}stm32_2m+384k_ram.ld)
+        set(LINKER_SCRIPT ${LINKER_SCRIPT_PATH}stm32_2m+16m_xram.ld)
+
+        ## Select architecture specific files
+        ## These are the files in arch/<arch name>/<board name>
+        set(ARCH_SRC ${KPATH}/${BOARD_INC}/interfaces-impl/bsp.cpp)
+
+        ## Add a #define to allow querying board name
+        list(APPEND CFLAGS_BASE -D_BOARD_STM32F769NI_DISCO)
+        list(APPEND CXXFLAGS_BASE -D_BOARD_STM32F769NI_DISCO)
+
+        ## Enables the initialization of the external 16MB SDRAM memory
+        set(XRAM -D__ENABLE_XRAM)
+
+        ## Select clock frequency (HSE_VALUE is the xtal on board, fixed)
+        set(CLOCK_FREQ -DHSE_VALUE=25000000 -DSYSCLK_FREQ_216MHz=216000000)
+
+        ## Select programmer command line
+        ## This is the program that is invoked when the user types
+        ## 'make program'
+        ## The command must provide a way to program the board, or print an
+        ## error message saying that 'make program' is not supported for that
+        ## board.
+        set(PROGRAM_CMDLINE st-flash --reset write "main.bin" 0x8000000)
+
     ##-------------------------------------------------------------------------
     ## End of board list
     ##
@@ -3070,7 +3112,6 @@ elseif(${ARCH} STREQUAL cortexM7_stm32f7)
         ${KPATH}/arch/common/core/mpu_cortexMx.cpp
         ${KPATH}/arch/common/core/cache_cortexMx.cpp
         ${KPATH}/arch/common/drivers/serial_stm32.cpp
-        ${KPATH}/arch/common/drivers/sd_stm32f2_f4.cpp
         ${KPATH}/arch/common/drivers/dcc.cpp
         ${KPATH}/${ARCH_INC}/interfaces-impl/portability.cpp
         ${KPATH}/${ARCH_INC}/interfaces-impl/delays.cpp