diff --git a/src/bsps/stm32f767zi_orion_motor/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_orion_motor/interfaces-impl/bsp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d189aa253aecac8cc6e1942ccb948db5c7b3c4c2
--- /dev/null
+++ b/src/bsps/stm32f767zi_orion_motor/interfaces-impl/bsp.cpp
@@ -0,0 +1,393 @@
+/* Copyright (c) 2023 Skyward Experimental Rocketry
+ * Authors: Alberto Nidasio, Davide Mor
+ *
+ * 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.
+ */
+
+/***********************************************************************
+ * 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/sd_stm32f2_f4_f7.h"
+#include "drivers/serial.h"
+#include "drivers/serial_stm32.h"
+#include "drivers/stm32_bsram.h"
+#include "filesystem/console/console_device.h"
+#include "filesystem/file_access.h"
+#include "hwmapping.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 gpios used by the ram
+    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN |
+                    RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN |
+                    RCC_AHB1ENR_GPIOFEN | RCC_AHB1ENR_GPIOGEN;
+    RCC_SYNC();
+
+    // On the compute unit with F767ZI, the SDRAM pins are:
+    // - PG8:  FMC_SDCLK  (sdram clock)
+    // - PB5:  FMC_SDCKE1 (sdram bank 2 clock enable)
+    // - PB6:  FMC_SDNE1  (sdram bank 2 chip enable)
+    // - 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    (used only by the 32MB ram, not by the 8MB one)
+    // - 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
+
+    // - PG4:  FMC_BA0
+    // - PG5:  FMC_BA1
+    // - PF11: FMC_SDNRAS
+    // - PG15: FMC_SDNCAS
+    // - PC0:  FMC_SDNWE
+    // - PE0:  FMC_NBL0
+    // - PE1:  FMC_NBL1
+
+    // All SDRAM GPIOs needs to be configured with alternate function 12 and
+    // maximum speed
+
+    // WARNING: The current configuration is for the 8MB ram
+
+    // Alternate functions
+    GPIOB->AFR[0] = 0x0cc00000;
+    GPIOC->AFR[0] = 0x0000000c;
+    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;
+
+    // Mode
+    GPIOB->MODER = 0x00002800;
+    GPIOC->MODER = 0x00000002;
+    GPIOD->MODER = 0xa02a000a;
+    GPIOE->MODER = 0xaaaa800a;
+    GPIOF->MODER = 0xaa800aaa;
+    GPIOG->MODER = 0x80020a2a;
+
+    // Speed (high speed for all, very high speed for SDRAM pins)
+    GPIOB->OSPEEDR = 0x00003c00;
+    GPIOC->OSPEEDR = 0x00000003;
+    GPIOD->OSPEEDR = 0xf03f000f;
+    GPIOE->OSPEEDR = 0xffffc00f;
+    GPIOF->OSPEEDR = 0xffc00fff;
+    GPIOG->OSPEEDR = 0xc0030f3f;
+
+    // Since we'we un-configured PB3 and PB4 (by default they are SWO and NJRST)
+    // finish the job and remove the default pull-up
+    GPIOB->PUPDR = 0;
+
+    // Enable the SDRAM controller clock
+    RCC->AHB3ENR |= RCC_AHB3ENR_FMCEN;
+    RCC_SYNC();
+
+    // The SDRAM is a AS4C16M16SA-6TIN
+    // 16Mx16bit = 256Mb = 32MB
+    // HCLK = 216MHz -> SDRAM clock = HCLK/2 = 108MHz
+
+    // 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
+    FMC_Bank5_6->SDCR[1] = 0                     // Write accesses allowed
+                           | FMC_SDCR2_CAS_1     // 2 cycles CAS latency
+                           | FMC_SDCR2_NB        // 4 internal banks
+                           | FMC_SDCR2_MWID_0    // 16 bit data bus
+                           | FMC_SDCR2_NR_1      // 13 bit row address
+                           | FMC_SDCR2_NC_0;     // 9 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_TRP_Pos     // 2 cycles TRP  (18.52ns > 18ns)
+        | (7 - 1) << FMC_SDTR1_TRC_Pos;  // 7 cycles TRC  (64.82ns > 60ns)
+    FMC_Bank5_6->SDTR[1] =
+        (2 - 1) << FMC_SDTR1_TRCD_Pos     // 2 cycles TRCD (18.52ns > 18ns)
+        | (2 - 1) << FMC_SDTR1_TWR_Pos    // 2 cycles TWR  (min 2cc > 12ns)
+        | (5 - 1) << FMC_SDTR1_TRAS_Pos   // 5 cycles TRAS (46.3ns  > 42ns)
+        | (7 - 1) << FMC_SDTR1_TXSR_Pos   // 7 cycles TXSR (74.08ns > 61.5ns)
+        | (2 - 1) << FMC_SDTR1_TMRD_Pos;  // 2 cycles TMRD (min 2cc > 12ns)
+#else
+#error No SDRAM timings for this clock
+#endif
+
+    // 3. Enable the bank 2 clock
+    FMC_Bank5_6->SDCMR =
+        0b001 << FMC_SDCMR_MODE_Pos  // Clock Configuration Enable
+        | FMC_SDCMR_CTB2;            // Bank 2
+    sdramCommandWait();
+
+    // 4. Wait during command execution
+    delayUs(100);
+
+    // 5. Issue a "Precharge All" command
+    FMC_Bank5_6->SDCMR = 0b010 << FMC_SDCMR_MODE_Pos  // Precharge all
+                         | FMC_SDCMR_CTB2;            // Bank 2
+    sdramCommandWait();
+
+    // 6. Issue Auto-Refresh commands
+    FMC_Bank5_6->SDCMR = 0b011 << FMC_SDCMR_MODE_Pos       // Auto-Refresh
+                         | FMC_SDCMR_CTB2                  // Bank 2
+                         | (8 - 1) << FMC_SDCMR_NRFS_Pos;  // 8 Auto-Refresh
+    sdramCommandWait();
+
+    // 7. Issue a Load Mode Register command
+    FMC_Bank5_6->SDCMR =
+        0b100 << FMC_SDCMR_MODE_Pos          // Load mode register
+        | FMC_SDCMR_CTB2                     // Bank 2
+        | 0 << FMC_SDCMR_MRD_Pos             // Burst length = 1
+        | (0b010 << 4) << FMC_SDCMR_MRD_Pos  // CAS = 2 clocks,
+        | (1 << 9) << FMC_SDCMR_MRD_Pos;     // Single bit write burst mode
+    sdramCommandWait();
+
+// 8. Program the refresh rate (4K / 32ms)
+// 64ms / 8192 = 7.8125us
+#ifdef SYSCLK_FREQ_216MHz
+    // 7.8125us * 133MHz = 1039 - 20 = 1019
+    FMC_Bank5_6->SDRTR = 1019 << FMC_SDRTR_COUNT_Pos;
+#else
+#error No SDRAM refresh timings for this clock
+#endif
+}
+
+void configureBackupSram()
+{
+    // Initialize the backup SRAM device
+    BSRAM::init();
+
+    // Defined in the linker script
+    extern unsigned char _preserve_start asm("_preserve_start");
+    extern unsigned char _preserve_end asm("_preserve_end");
+    extern unsigned char _preserve_load asm("_preserve_load");
+
+    unsigned char* preserve_start = &_preserve_start;
+    unsigned char* preserve_end   = &_preserve_end;
+    unsigned char* preserve_load  = &_preserve_load;
+
+    // Load the .preserve section from flash if not a software reset
+    if (miosix::lastResetReason() != miosix::ResetReason::SOFTWARE)
+    {
+        BSRAM::EnableWriteLock l;
+        memcpy(preserve_start, preserve_load, preserve_end - preserve_start);
+    }
+}
+
+void IRQbspInit()
+{
+    // Enable USART1 pins port
+    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
+
+    userLed1::mode(Mode::OUTPUT);
+    userLed2::mode(Mode::OUTPUT);
+    userLed3::mode(Mode::OUTPUT);
+    userLed4::mode(Mode::OUTPUT);
+
+    interfaces::spi1::sck::alternateFunction(5);
+    interfaces::spi1::sck::mode(Mode::ALTERNATE);
+    interfaces::spi1::miso::alternateFunction(5);
+    interfaces::spi1::miso::mode(Mode::ALTERNATE);
+    interfaces::spi1::mosi::alternateFunction(5);
+    interfaces::spi1::mosi::mode(Mode::ALTERNATE);
+
+    interfaces::spi3::sck::alternateFunction(6);
+    interfaces::spi3::sck::mode(Mode::ALTERNATE);
+    interfaces::spi3::miso::alternateFunction(6);
+    interfaces::spi3::miso::mode(Mode::ALTERNATE);
+    interfaces::spi3::mosi::alternateFunction(5);
+    interfaces::spi3::mosi::mode(Mode::ALTERNATE);
+
+    interfaces::spi4::sck::alternateFunction(5);
+    interfaces::spi4::sck::mode(Mode::ALTERNATE);
+    interfaces::spi4::miso::alternateFunction(5);
+    interfaces::spi4::miso::mode(Mode::ALTERNATE);
+    interfaces::spi4::mosi::alternateFunction(5);
+    interfaces::spi4::mosi::mode(Mode::ALTERNATE);
+
+    // We do not need to setup the miosix usart
+
+    interfaces::uart4::tx::alternateFunction(8);
+    interfaces::uart4::tx::mode(Mode::ALTERNATE);
+    interfaces::uart4::rx::alternateFunction(8);
+    interfaces::uart4::rx::mode(Mode::ALTERNATE);
+
+    interfaces::can1::tx::alternateFunction(9);
+    interfaces::can1::tx::mode(Mode::ALTERNATE);
+    interfaces::can1::rx::alternateFunction(9);
+    interfaces::can1::rx::mode(Mode::ALTERNATE);
+
+    interfaces::timers::tim1ch1::alternateFunction(1);
+    interfaces::timers::tim1ch1::mode(Mode::ALTERNATE);
+    interfaces::timers::tim3ch1::alternateFunction(2);
+    interfaces::timers::tim3ch1::mode(Mode::ALTERNATE);
+    interfaces::timers::tim4ch1::alternateFunction(2);
+    interfaces::timers::tim4ch1::mode(Mode::ALTERNATE);
+    interfaces::timers::tim8ch2::alternateFunction(3);
+    interfaces::timers::tim8ch2::mode(Mode::ALTERNATE);
+    interfaces::timers::tim9ch1::alternateFunction(3);
+    interfaces::timers::tim9ch1::mode(Mode::ALTERNATE);
+    interfaces::timers::tim11ch1::alternateFunction(3);
+    interfaces::timers::tim11ch1::mode(Mode::ALTERNATE);
+    interfaces::timers::tim12ch2::alternateFunction(9);
+    interfaces::timers::tim12ch2::mode(Mode::ALTERNATE);
+
+    interfaces::adcs::adc12in9::mode(Mode::INPUT_ANALOG);
+    interfaces::adcs::adc12in14::mode(Mode::INPUT_ANALOG);
+
+    sensors::ADS131M08::cs::mode(Mode::OUTPUT);
+    sensors::ADS131M08::cs::high();
+    sensors::LPS22DF::cs::mode(Mode::OUTPUT);
+    sensors::LPS22DF::cs::high();
+    sensors::LIS2MDL::cs::mode(Mode::OUTPUT);
+    sensors::LIS2MDL::cs::high();
+    sensors::H3LIS331DL::cs::mode(Mode::OUTPUT);
+    sensors::H3LIS331DL::cs::high();
+    sensors::LSM6DSRX::cs::mode(Mode::OUTPUT);
+    sensors::LSM6DSRX::cs::high();
+    // TODO: are there other sensors?
+
+    gpios::boardLed::mode(Mode::OUTPUT);
+    gpios::boardLed::low();
+
+    DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>(new STM32Serial(
+        defaultSerial, defaultSerialSpeed, STM32Serial::NOFLOWCTRL)));
+}
+
+void bspInit2()
+{
+#ifdef WITH_FILESYSTEM
+    basicFilesystemSetup(SDIODriver::instance());
+#endif  // WITH_FILESYSTEM
+
+#ifdef WITH_BACKUP_SRAM
+    // Print the reset reason
+    bootlog("Reset reson: ");
+    switch (SGM::instance().lastResetReason())
+    {
+        case ResetReason::RST_LOW_PWR:
+            bootlog("low power\n");
+            break;
+        case ResetReason::RST_WINDOW_WDG:
+            bootlog("window watchdog\n");
+            break;
+        case ResetReason::RST_INDEPENDENT_WDG:
+            bootlog("indeendent watchdog\n");
+            break;
+        case ResetReason::RST_SW:
+            bootlog("software reset\n");
+            break;
+        case ResetReason::RST_POWER_ON:
+            bootlog("power on\n");
+            break;
+        case ResetReason::RST_PIN:
+            bootlog("reset pin\n");
+            break;
+        case ResetReason::RST_UNKNOWN:
+            bootlog("unknown\n");
+            break;
+    }
+#endif  // WITH_BACKUP_SRAM
+}
+
+//
+// Shutdown and reboot
+//
+
+void shutdown()
+{
+    ioctl(STDOUT_FILENO, IOCTL_SYNC, 0);
+
+#ifdef WITH_FILESYSTEM
+    FilesystemManager::instance().umountAll();
+#endif  // WITH_FILESYSTEM
+
+    disableInterrupts();
+    for (;;)
+        ;
+}
+
+void reboot()
+{
+    ioctl(STDOUT_FILENO, IOCTL_SYNC, 0);
+
+#ifdef WITH_FILESYSTEM
+    FilesystemManager::instance().umountAll();
+#endif  // WITH_FILESYSTEM
+
+    disableInterrupts();
+    miosix_private::IRQsystemReboot();
+}
+
+}  // namespace miosix
diff --git a/src/bsps/stm32f767zi_orion_motor/interfaces-impl/bsp_impl.h b/src/bsps/stm32f767zi_orion_motor/interfaces-impl/bsp_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..6cbcdde743840c5890416a8aaffcf2b3d3d5eaca
--- /dev/null
+++ b/src/bsps/stm32f767zi_orion_motor/interfaces-impl/bsp_impl.h
@@ -0,0 +1,124 @@
+/* Copyright (c) 2023 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * 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.
+ */
+
+/***************************************************************************
+ * 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"
+
+/**
+ * Macro to place a variable in the backup SRAM. Variables are allowed to have a
+ * default value. The kernel initializes the variable to the provided value if
+ * the reset reason is not a software reset.
+ *
+ * Example usage: `PRESERVE int myVar = 0;`
+ */
+#define PRESERVE __attribute__((section(".preserve")))
+
+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
+ * Called by stage_1_boot.cpp to configure the backup SRAM and .preserve region
+ * Requires the CPU clock to be already configured (running from the PLL)
+ */
+void configureBackupSram();
+
+/**
+ * \internal
+ * Board pin definition
+ */
+typedef Gpio<GPIOC_BASE, 15> userLed1;
+typedef Gpio<GPIOC_BASE, 2> userLed2;
+typedef Gpio<GPIOC_BASE, 13> userLed3;
+typedef Gpio<GPIOC_BASE, 14> userLed4;
+
+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(); }
+
+inline void led4On() { userLed4::high(); }
+
+inline void led4Off() { userLed4::low(); }
+
+inline void ledOn()
+{
+    led1On();
+    led2On();
+    led3On();
+    led4On();
+}
+
+inline void ledOff()
+{
+    led1Off();
+    led2Off();
+    led3Off();
+    led4Off();
+}
+
+/**
+ * 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 true; }
+
+/**
+\}
+*/
+
+}  // namespace miosix
+
+#endif  // BSP_IMPL_H
diff --git a/src/bsps/stm32f767zi_orion_motor/interfaces-impl/hwmapping.h b/src/bsps/stm32f767zi_orion_motor/interfaces-impl/hwmapping.h
index 1e8e5a2096b2fad4b342ef80ce62509aba0e258e..0a4b7bb930277d33f95d501f1700b7b6dc302221 100644
--- a/src/bsps/stm32f767zi_orion_motor/interfaces-impl/hwmapping.h
+++ b/src/bsps/stm32f767zi_orion_motor/interfaces-impl/hwmapping.h
@@ -88,8 +88,8 @@ using rx = Gpio<GPIOA_BASE, 11>;
 namespace timers
 {
 using tim1ch1  = Gpio<GPIOA_BASE, 8>;
-using tim4ch1  = Gpio<GPIOD_BASE, 12>;
 using tim3ch1  = Gpio<GPIOC_BASE, 6>;
+using tim4ch1  = Gpio<GPIOD_BASE, 12>;
 using tim8ch2  = Gpio<GPIOC_BASE, 7>;
 using tim9ch1  = Gpio<GPIOA_BASE, 2>;
 using tim11ch1 = Gpio<GPIOB_BASE, 9>;