diff --git a/src/bsps/CMakeLists.txt b/src/bsps/CMakeLists.txt
index c91f328f42181b40da0c6053795863e3e9f6c994..051cd0a7d90e33a75bc916ca20ce3cec15ba6eb6 100644
--- a/src/bsps/CMakeLists.txt
+++ b/src/bsps/CMakeLists.txt
@@ -28,6 +28,7 @@ set(MIOSIX_KPATH ${BOARDCORE_PATH}/libs/miosix-kernel/miosix)
 set(BSPS_PATH ${BOARDCORE_PATH}/src/bsps)
 
 set(BOARDCORE_BOARDS
+    stm32f767zi_gemini_motor
     stm32f767zi_lyra_biscotto
     stm32f767zi_compute_unit
     stm32f767zi_compute_unit_v2
@@ -59,7 +60,9 @@ endif()
 if(
     BOARDCORE_OPT_BOARD STREQUAL stm32f767zi_lyra_biscotto OR
     BOARDCORE_OPT_BOARD STREQUAL stm32f767zi_compute_unit OR
-    BOARDCORE_OPT_BOARD STREQUAL stm32f767zi_compute_unit_v2
+    BOARDCORE_OPT_BOARD STREQUAL stm32f767zi_compute_unit_v2 OR
+    BOARDCORE_OPT_BOARD STREQUAL stm32f767zi_gemini_motor
+
 )
     set(MIOSIX_ARCH_NAME cortexM7_stm32f7)
 # elseif(
diff --git a/src/bsps/stm32f767zi_gemini_motor/CMakeLists.txt b/src/bsps/stm32f767zi_gemini_motor/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..90f293a976cfa4601dde05e271db487f8c05e5a2
--- /dev/null
+++ b/src/bsps/stm32f767zi_gemini_motor/CMakeLists.txt
@@ -0,0 +1,109 @@
+# Copyright (C) 2024 by Skyward
+#
+# This program is free software; you can redistribute it and/or
+# it under the terms of the GNU General Public License as published
+# 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
+# Public License. This exception does not invalidate any other
+# 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/>
+
+# The stm32f767 has the double precision FPU, so we will build for m7
+set(MIOSIX_CPU_FLAGS -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16)
+
+# Directory with header files for this board
+set(MIOSIX_BOARD_INC ${BSPS_PATH}/${BOARDCORE_OPT_BOARD})
+
+# The user can set a custom path for board_settings.h
+set(MIOSIX_CUSTOM_BOARD_SETTINGS_INC "" CACHE PATH "Include directory for custom board_settings.h")
+mark_as_advanced(MIOSIX_CUSTOM_BOARD_SETTINGS_INC)
+if(MIOSIX_CUSTOM_BOARD_SETTINGS_INC)
+    set(MIOSIX_BOARD_SETTINGS_INC ${MIOSIX_CUSTOM_BOARD_SETTINGS_INC})
+    message(NOTICE "You have set a custom path for board_settings.h")
+else()
+    set(MIOSIX_BOARD_SETTINGS_INC ${MIOSIX_BOARD_INC}/config)
+endif()
+
+# Linker script type, there are three options
+# 1) Code in FLASH, stack + heap in internal RAM (file *_rom.ld)
+#    the most common choice, available for all microcontrollers
+# 2) Code in FLASH, stack + heap in external RAM (file *8m_xram.ld)
+#    You must uncomment -D__ENABLE_XRAM below in this case.
+# 3) Code in FLASH, stack + heap in external RAM (file *6m_xram.ld)
+#    Same as above, but leaves the upper 2MB of RAM for the LCD.
+set(MIOSIX_LINKER_SCRIPT_LIST
+    stm32_2m+16m_xram.ld
+    stm32_2m+384k_ram.ld
+)
+if(NOT MIOSIX_LINKER_SCRIPT IN_LIST MIOSIX_LINKER_SCRIPT_LIST)
+    # If there is no cached value, or the cached value is not in the list, set a default value
+    set(MIOSIX_LINKER_SCRIPT stm32_2m+16m_xram.ld CACHE STRING "Linker script" FORCE)
+endif()
+set_property(CACHE MIOSIX_LINKER_SCRIPT PROPERTY STRINGS ${MIOSIX_LINKER_SCRIPT_LIST})
+
+# Uncommenting __ENABLE_XRAM enables the initialization of the external
+# 8MB SDRAM memory. Do not uncomment this even if you don't use a linker
+# script that requires it, as it is used for the LCD framebuffer.
+option(MIOSIX_ENABLE_XRAM "Enables the initialization of the external 16MB SDRAM memory" ON)
+if(MIOSIX_ENABLE_XRAM)
+    set(XRAM -D__ENABLE_XRAM) # TODO: Change to an always defined flag
+else()
+    message(NOTICE "You have disabled the XRAM, make sure that the selected linker script does not use it")
+endif()
+
+# Select HSE clock frequency (external clock on board, fixed)
+set(MIOSIX_HSE_VALUE -DHSE_VALUE=25000000)
+
+# Select clock frequency.
+# Warning: due to a limitation in the PLL, it is not possible to generate
+# a precise 48MHz output when running the core at 180MHz. If 180MHz is
+# chosen the SDIO and RNG will run ~6% slower (45MHz insteand of 48MHz)
+set(MIOSIX_SYSCLK_FREQ_LIST
+    -DSYSCLK_FREQ_216MHz=216000000
+)
+if(NOT MIOSIX_SYSCLK_FREQ IN_LIST MIOSIX_SYSCLK_FREQ_LIST)
+    # If there is no cached value, or the cached value is not in the list, set a default value
+    set(MIOSIX_SYSCLK_FREQ -DSYSCLK_FREQ_216MHz=216000000 CACHE STRING "Clock frenquency" FORCE)
+endif()
+set_property(CACHE MIOSIX_SYSCLK_FREQ PROPERTY STRINGS ${MIOSIX_SYSCLK_FREQ_LIST})
+
+if(MIOSIX_SYSCLK_FREQ STREQUAL -DSYSCLK_FREQ_180MHz=180000000)
+    message(NOTICE "The clock frequency has been set to 180MHz, the SDIO and RNG will run ~6% slower (45MHz insteand of 48MHz)")
+endif()
+
+# Select architecture specific files
+set(MIOSIX_ARCH_SRC
+    ${BSPS_PATH}/${BOARDCORE_OPT_BOARD}/core/stage_1_boot.cpp
+    ${BSPS_PATH}/${BOARDCORE_OPT_BOARD}/interfaces-impl/bsp.cpp
+)
+
+# Add a #define to allow querying board name
+list(APPEND MIOSIX_C_FLAGS -D_BOARD_STM32F767ZI_GEMINI_MOTOR)
+list(APPEND MIOSIX_CXX_FLAGS -D_BOARD_STM32F767ZI_GEMINI_MOTOR)
+
+
+list(APPEND MIOSIX_ARCH_SRC
+    ${MIOSIX_KPATH}/arch/common/drivers/stm32_bsram.cpp
+)
+
+# Specify a custom flash command
+# This is the program that is invoked when the program-<target_name> target is
+# built. Use <binary> or <hex> as placeolders, they will be replaced by the
+# build systems with the binary or hex file path repectively.
+# If a command is not specified, the build system will fallback to st-flash
+# set(PROGRAM_CMDLINE st-flash --connect-under-reset --reset write <binary> 0x8000000)
diff --git a/src/bsps/stm32f767zi_gemini_motor/config/board_options.cmake b/src/bsps/stm32f767zi_gemini_motor/config/board_options.cmake
deleted file mode 100644
index c9eb1bdc64f2a17d4a9d2742d51b7e1fb27960a5..0000000000000000000000000000000000000000
--- a/src/bsps/stm32f767zi_gemini_motor/config/board_options.cmake
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright (C) 2023 by Skyward
-#
-# This program is free software; you can redistribute it and/or 
-# it under the terms of the GNU General Public License as published 
-# 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 
-# Public License. This exception does not invalidate any other 
-# 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/>
-
-set(BOARD_NAME stm32f767zi_gemini_motor)
-set(ARCH_NAME cortexM7_stm32f7)
-
-# Base directories with header files for this board
-set(ARCH_PATH ${KPATH}/arch/${ARCH_NAME}/common)
-set(BOARD_PATH ${BOARDCORE_PATH}/src/bsps/${BOARD_NAME})
-set(BOARD_CONFIG_PATH ${BOARDCORE_PATH}/src/bsps/${BOARD_NAME}/config)
-
-# Specify where to find the board specific config/miosix_settings.h
-set(BOARD_MIOSIX_SETTINGS_PATH ${BOARD_PATH})
-
-# Specify where to find the board specific config/mxgui_settings.h
-set(BOARD_MXGUI_SETTINGS_PATH ${BOARD_PATH})
-
-# Optimization flags:
-# -O0 do no optimization, the default if no optimization level is specified
-# -O or -O1 optimize minimally
-# -O2 optimize more
-# -O3 optimize even more
-# -Ofast optimize very aggressively to the point of breaking the standard
-# -Og Optimize debugging experience, enables optimizations that do not
-# interfere with debugging
-# -Os Optimize for size with -O2 optimizations that do not increase code size
-set(OPT_OPTIMIZATION
-    $<$<CONFIG:Debug>:-O2>
-    $<$<CONFIG:Release>:-O2>
-)
-
-# Boot file and linker script
-set(BOOT_FILE ${BOARD_PATH}/core/stage_1_boot.cpp)
-# set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+384k_ram.ld)
-set(LINKER_SCRIPT ${BOARD_PATH}/stm32_2m+16m_xram.ld)
-
-# 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)
-
-# C++ Exception/rtti support disable flags.
-# To save code size if not using C++ exceptions (nor some STL code which
-# implicitly uses it) uncomment this option.
-# -D__NO_EXCEPTIONS is used by Miosix to know if exceptions are used.
-# set(OPT_EXCEPT -fno-exceptions -fno-rtti -D__NO_EXCEPTIONS)
-
-# Specify a custom flash command
-# This is the program that is invoked when the flash flag (-f or --flash) is
-# used with the Miosix Build System. Use $binary or $hex as placeolders, they
-# will be replaced by the build systems with the binary or hex file repectively.
-# If a command is not specified, the build system will use st-flash if found
-# set(PROGRAM_CMDLINE "here your custom flash command")
-
-# Basic flags
-set(FLAGS_BASE -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-d16)
-set(LINK_PATH_ARCH thumb/cm7/hardfp/fpv5)
-
-# Flags for ASM and linker
-set(AFLAGS_BASE ${FLAGS_BASE})
-set(LFLAGS_BASE ${FLAGS_BASE} -Wl,--gc-sections,-Map,main.map -Wl,-T${LINKER_SCRIPT} ${OPT_EXCEPT} ${OPT_OPTIMIZATION} -nostdlib)
-
-# Flags for C/C++
-string(TOUPPER ${BOARD_NAME} BOARD_UPPER)
-set(CFLAGS_BASE
-    -D_BOARD_${BOARD_UPPER} -D_MIOSIX_BOARDNAME=\"${BOARD_NAME}\"
-    -D_DEFAULT_SOURCE=1 -ffunction-sections -Wall -Werror=return-type -g
-    -D_ARCH_CORTEXM7_STM32F7
-    ${CLOCK_FREQ} ${XRAM} ${SRAM_BOOT} ${FLAGS_BASE} ${OPT_OPTIMIZATION} -c
-)
-set(CXXFLAGS_BASE ${CFLAGS_BASE} ${OPT_EXCEPT})
-
-# Select architecture specific files
-set(ARCH_SRC
-    ${ARCH_PATH}/interfaces-impl/delays.cpp
-    ${ARCH_PATH}/interfaces-impl/gpio_impl.cpp
-    ${ARCH_PATH}/interfaces-impl/portability.cpp
-    ${BOARD_PATH}/interfaces-impl/bsp.cpp
-    ${KPATH}/arch/common/CMSIS/Device/ST/STM32F7xx/Source/Templates/system_stm32f7xx.c
-    ${KPATH}/arch/common/core/cache_cortexMx.cpp
-    ${KPATH}/arch/common/core/interrupts_cortexMx.cpp
-    ${KPATH}/arch/common/core/mpu_cortexMx.cpp
-    ${KPATH}/arch/common/core/stm32f2_f4_l4_f7_h7_os_timer.cpp
-    ${KPATH}/arch/common/drivers/sd_stm32f2_f4_f7.cpp
-    ${KPATH}/arch/common/drivers/serial_stm32.cpp
-    ${KPATH}/arch/common/drivers/stm32_hardware_rng.cpp
-)
diff --git a/src/bsps/stm32f767zi_gemini_motor/config/miosix_settings.h b/src/bsps/stm32f767zi_gemini_motor/config/miosix_settings.h
index 64b0670cab5f4cdfc3d8e06db7cc06e913deae15..f592c28ef8b73649efce20292dfadb37352bb2bc 100644
--- a/src/bsps/stm32f767zi_gemini_motor/config/miosix_settings.h
+++ b/src/bsps/stm32f767zi_gemini_motor/config/miosix_settings.h
@@ -93,6 +93,33 @@ namespace miosix
 /// By default it is defined (DevFs is enabled)
 #define WITH_DEVFS
 
+/// \def WITH_FATFS
+/// Allows to enable/disable FATFS support to save code size
+/// By default it is defined (FATFS is enabled)
+#define WITH_FATFS
+/// Maxium number of files that can be opened on a mounted FATFS partition.
+/// Must be greater than 0
+constexpr unsigned char FATFS_MAX_OPEN_FILES = 8;
+/// The truncate/ftruncate operations, and seeking past the end of the file are
+/// two patterns for zero-filling a file. This requires a buffer to be done
+/// efficiently, and the size of the buffer impacts performance. To save RAM the
+/// suggested value is 512 byte, for performance 4096 or even 16384 are better.
+/// Note that no buffer is allocated unless required, the buffer is deallocated
+/// afterwards, and the worst case memory required is one buffer per mounted
+/// FATFS partition if one concurrent truncate/write past the end per partition
+/// occurs.
+constexpr unsigned int FATFS_EXTEND_BUFFER = 512;
+
+/// \def WITH_LITTLEFS
+/// Allows to enable/disable LittleFS support to save code size
+/// By default it is not defined (LittleFS is disabled)
+// #define WITH_LITTLEFS
+
+/// \def WITH_ROMFS
+/// Allows to enable/disable RomFS support to save code size
+/// By default it is not defined (RomFS is disabled)
+// #define WITH_ROMFS
+
 /// \def SYNC_AFTER_WRITE
 /// Increases filesystem write robustness. After each write operation the
 /// filesystem is synced so that a power failure happens data is not lost
@@ -101,8 +128,10 @@ namespace miosix
 /// By default it is defined (slow but safe)
 #define SYNC_AFTER_WRITE
 
-/// Maximum number of open files. Trying to open more will fail.
-/// Cannot be lower than 3, as the first three are stdin, stdout, stderr
+/// Maximum number of files a single process (or the kernel) can open. This
+/// constant is used to size file descriptor tables. Individual filesystems can
+/// introduce futher limitations. Cannot be less than 3, as the first three are
+/// stdin, stdout, stderr, and in this case no additional files can be opened.
 const unsigned char MAX_OPEN_FILES = 8;
 
 /// \def WITH_PROCESSES
@@ -110,19 +139,12 @@ const unsigned char MAX_OPEN_FILES = 8;
 /// This enables the dynamic loader to load elf programs, the extended system
 /// call service and, if the hardware supports it, the MPU to provide memory
 /// isolation of processes
-//#define WITH_PROCESSES
-
-#if defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS)
-#error Processes require C++ exception support
-#endif  // defined(WITH_PROCESSES) && defined(__NO_EXCEPTIONS)
-
-#if defined(WITH_PROCESSES) && !defined(WITH_FILESYSTEM)
-#error Processes require filesystem support
-#endif  // defined(WITH_PROCESSES) && !defined(WITH_FILESYSTEM)
-
-#if defined(WITH_PROCESSES) && !defined(WITH_DEVFS)
-#error Processes require devfs support
-#endif  // defined(WITH_PROCESSES) && !defined(WITH_DEVFS)
+// #define WITH_PROCESSES
+/// RomFS is enabled by default when using processes. Comment the following
+/// lines if you want to use processes without RomFS.
+#if defined(WITH_PROCESSES) && !defined(WITH_ROMFS)
+#define WITH_ROMFS
+#endif
 
 //
 // C/C++ standard library I/O (stdin, stdout and stderr related)
@@ -168,7 +190,7 @@ const unsigned int STACK_IDLE = 256;
 
 /// Default stack size for pthread_create.
 /// The chosen value is enough to call C standard library functions
-/// such as printf/fopen which are stack-heavy
+/// such as printf/fopen which are stack-heavy (MUST be divisible by 4)
 const unsigned int STACK_DEFAULT_FOR_PTHREAD = 2048;
 
 /// Maximum size of the RAM image of a process. If a program requires more
@@ -177,13 +199,28 @@ const unsigned int MAX_PROCESS_IMAGE_SIZE = 64 * 1024;
 
 /// Minimum size of the stack for a process. If a program specifies a lower
 /// size the kernel will not run it (MUST be divisible by 4)
-const unsigned int MIN_PROCESS_STACK_SIZE = STACK_MIN;
+const unsigned int MIN_PROCESS_STACK_SIZE = 1024;
 
 /// Every userspace thread has two stacks, one for when it is running in
 /// userspace and one for when it is running in kernelspace (that is, while it
 /// is executing system calls). This is the size of the stack for when the
 /// thread is running in kernelspace (MUST be divisible by 4)
-const unsigned int SYSTEM_MODE_PROCESS_STACK_SIZE = 2 * 1024;
+const unsigned int SYSTEM_MODE_PROCESS_STACK_SIZE = 2048;
+
+/// Maximum number of arguments passed through argv to a process
+/// Also maximum number of environment variables passed through envp to a
+/// process
+const unsigned int MAX_PROCESS_ARGS = 16;
+
+/// Maximum size of the memory area at the top of the stack for arguments and
+/// environment variables. This area is not considered part of the stack and
+/// does not contribute to the stack size.
+const unsigned int MAX_PROCESS_ARGS_BLOCK_SIZE = 512;
+
+static_assert(STACK_IDLE >= STACK_MIN, "");
+static_assert(STACK_DEFAULT_FOR_PTHREAD >= STACK_MIN, "");
+static_assert(MIN_PROCESS_STACK_SIZE >= STACK_MIN, "");
+static_assert(SYSTEM_MODE_PROCESS_STACK_SIZE >= STACK_MIN, "");
 
 /// Number of priorities (MUST be >1)
 /// PRIORITY_MAX-1 is the highest priority, 0 is the lowest. -1 is reserved as
diff --git a/src/bsps/stm32f767zi_gemini_motor/core/stage_1_boot.cpp b/src/bsps/stm32f767zi_gemini_motor/core/stage_1_boot.cpp
index 83eac53b4b0b56309c0a9c26aacb7ff4289558d0..fbb0d866b2c7a33561b939a84ea8eae5b118ef89 100644
--- a/src/bsps/stm32f767zi_gemini_motor/core/stage_1_boot.cpp
+++ b/src/bsps/stm32f767zi_gemini_motor/core/stage_1_boot.cpp
@@ -68,6 +68,8 @@ void program_startup()
     memcpy(data, etext, edata - data);
     memset(bss_start, 0, bss_end - bss_start);
 
+    miosix::configureBackupSram();
+    
     // Move on to stage 2
     _init();
 
diff --git a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp
index 12303cae3b797c729cba634123b21caabee0afb1..3c0257fc683b61c4d0520da468fcd1887f7c0e1a 100644
--- a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp
+++ b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp.cpp
@@ -37,7 +37,7 @@
 #include "drivers/sd_stm32f2_f4_f7.h"
 #include "drivers/serial.h"
 #include "drivers/serial_stm32.h"
-#include "drivers/stm32_sgm.h"
+#include "drivers/stm32_bsram.h"
 #include "filesystem/console/console_device.h"
 #include "filesystem/file_access.h"
 #include "interfaces/arch_registers.h"
@@ -61,6 +61,28 @@ static void sdramCommandWait()
             return;
 }
 
+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 configureSdram()
 {
     // Enable all gpios
@@ -245,6 +267,11 @@ void IRQbspInit()
     interfaces::spi4::mosi::mode(Mode::ALTERNATE);
     interfaces::spi4::mosi::alternateFunction(5);
 
+    interfaces::i2c1::sda::mode(Mode::ALTERNATE);
+    interfaces::i2c1::sda::alternateFunction(4);
+    interfaces::i2c1::scl::mode(Mode::ALTERNATE);
+    interfaces::i2c1::scl::alternateFunction(4);
+
     // USART1 configured by the miosix serial driver
 
     interfaces::usart2::tx::mode(Mode::ALTERNATE);
@@ -265,38 +292,41 @@ void IRQbspInit()
 
     peripherals::switches::userSwitch1::mode(Mode::INPUT);
 
-    peripherals::lsm6dsrx::cs::mode(Mode::OUTPUT);
-    peripherals::lsm6dsrx::cs::high();
-    peripherals::lsm6dsrx::int1::mode(Mode::INPUT);
-    peripherals::lsm6dsrx::int2::mode(Mode::INPUT);
+    sensors::LSM6DSRX::cs::mode(Mode::OUTPUT);
+    sensors::LSM6DSRX::cs::high();
+    sensors::LSM6DSRX::int1::mode(Mode::INPUT);
+    sensors::LSM6DSRX::int2::mode(Mode::INPUT);
 
-    peripherals::h3lis331dl::cs::mode(Mode::OUTPUT);
-    peripherals::h3lis331dl::cs::high();
-    peripherals::h3lis331dl::int1::mode(Mode::INPUT);
+    sensors::H3LIS331DL::cs::mode(Mode::OUTPUT);
+    sensors::H3LIS331DL::cs::high();
+    sensors::H3LIS331DL::int1::mode(Mode::INPUT);
 
-    peripherals::lis2mdl::cs::mode(Mode::OUTPUT);
-    peripherals::lis2mdl::cs::high();
+    sensors::LIS2MDL::cs::mode(Mode::OUTPUT);
+    sensors::LIS2MDL::cs::high();
 
-    peripherals::lps22df::cs::mode(Mode::OUTPUT);
-    peripherals::lps22df::cs::high();
-    peripherals::lps22df::int1::mode(Mode::INPUT);
+    sensors::LPS22DF::cs::mode(Mode::OUTPUT);
+    sensors::LPS22DF::cs::high();
+    sensors::LPS22DF::int1::mode(Mode::INPUT);
 
-    peripherals::ads131m08::cs::mode(Mode::OUTPUT);
-    peripherals::ads131m08::cs::high();
+    sensors::ADS131M08::cs::mode(Mode::OUTPUT);
+    sensors::ADS131M08::cs::high();
 
-    peripherals::max31856::cs::mode(Mode::OUTPUT);
-    peripherals::max31856::cs::high();
+    // sensors::max31856::cs::mode(Mode::OUTPUT);
+    // sensors::max31856::cs::high();
 
     peripherals::servos::servo1::mode(Mode::ALTERNATE);
     peripherals::servos::servo1::alternateFunction(3);
     peripherals::servos::servo2::mode(Mode::ALTERNATE);
     peripherals::servos::servo2::alternateFunction(3);
 
-    peripherals::tank_level::lvl1::mode(Mode::INPUT);
-    peripherals::tank_level::lvl2::mode(Mode::INPUT);
-    peripherals::tank_level::lvl3::mode(Mode::INPUT);
+    sensors::tank_level::lvl1::mode(Mode::INPUT);
+    sensors::tank_level::lvl2::mode(Mode::INPUT);
+    sensors::tank_level::lvl3::mode(Mode::INPUT);
+
+    sensors::battery_voltage::ch15::mode(Mode::INPUT_ANALOG);
 
-    peripherals::battery_voltage::ch15::mode(Mode::INPUT_ANALOG);
+    gpios::mainDeploy::mode(Mode::OUTPUT);
+    gpios::mainDeploy::low();
 
     DefaultConsole::instance().IRQset(intrusive_ref_ptr<Device>(new STM32Serial(
         defaultSerial, defaultSerialSpeed, STM32Serial::NOFLOWCTRL)));
diff --git a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp_impl.h b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp_impl.h
index 5c82116ba88d1de2ae3aec23c73f5389905a5337..2def89862e00fcd87ce4e544057285f0f3dbe23b 100644
--- a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp_impl.h
+++ b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/bsp_impl.h
@@ -32,6 +32,15 @@
 #include "hwmapping.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
 {
 
@@ -47,6 +56,13 @@ namespace miosix
  */
 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();
+
 inline void ledOn()
 {
     peripherals::leds::userLed1::high();
@@ -85,6 +101,10 @@ inline void led3Off()
     peripherals::leds::userLed3_2::low();
 }
 
+inline void led4On() { peripherals::leds::userLed4::high(); }
+
+inline void led4Off() { peripherals::leds::userLed4::low(); }
+
 /**
  * Polls the SD card sense GPIO.
  *
diff --git a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/hwmapping.h b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/hwmapping.h
index 6e563e2e97ded420db3b10e5b08f11894607a923..02cc9c1eb44ce412229f9f3544df8acc8e6cfd0d 100644
--- a/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/hwmapping.h
+++ b/src/bsps/stm32f767zi_gemini_motor/interfaces-impl/hwmapping.h
@@ -24,6 +24,42 @@
 
 #include "interfaces/gpio.h"
 
+#define MIOSIX_SENSOR_H3LIS331DL_SPI SPI1
+#define MIOSIX_SENSOR_LPS22DF_SPI SPI1
+#define MIOSIX_SENSOR_LSM6DSRX_SPI SPI3
+#define MIOSIX_SENSOR_LIS2MDL_SPI SPI3
+#define MIOSIX_SENSOR_UBXGPS_SPI SPI3
+#define MIOSIX_SENSOR_ADS131M08_SPI SPI4
+
+#define MIOSIX_SENSOR_LPS28DFW_I2C I2C1
+
+#define MIOSIX_SENSOR_VN100_SYNC_IN EXTI7_IRQHandlerImpl
+#define MIOSIX_SENSOR_VN100_SPI SPI1
+
+#define MIOSIX_RADIO_DIO0_IRQ EXTI11_IRQHandlerImpl
+#define MIOSIX_RADIO_DIO1_IRQ EXTI3_IRQHandlerImpl
+#define MIOSIX_RADIO_DIO3_IRQ EXTI6_IRQHandlerImpl
+#define MIOSIX_RADIO_SPI SPI6
+
+#define MIOSIX_SERVOS_1_TIM TIM4
+#define MIOSIX_SERVOS_1_CHANNEL CHANNEL_2
+#define MIOSIX_SERVOS_2_TIM TIM3
+#define MIOSIX_SERVOS_2_CHANNEL CHANNEL_1
+#define MIOSIX_SERVOS_3_TIM TIM9
+#define MIOSIX_SERVOS_3_CHANNEL CHANNEL_1
+#define MIOSIX_BUZZER_TIM TIM1
+#define MIOSIX_BUZZER_CHANNEL CHANNEL_1
+
+#define MIOSIX_PARAFOIL_SERVO_1_TIM MIOSIX_SERVOS_1_TIM
+#define MIOSIX_PARAFOIL_SERVO_1_CHANNEL MIOSIX_SERVOS_1_CHANNEL
+#define MIOSIX_PARAFOIL_SERVO_2_TIM MIOSIX_SERVOS_2_TIM
+#define MIOSIX_PARAFOIL_SERVO_2_CHANNEL MIOSIX_SERVOS_2_CHANNEL
+#define MIOSIX_AIRBRAKES_TIM MIOSIX_SERVOS_2_TIM
+#define MIOSIX_AIRBRAKES_CHANNEL MIOSIX_SERVOS_2_CHANNEL
+#define MIOSIX_EXPULSION_TIM MIOSIX_SERVOS_3_TIM
+#define MIOSIX_EXPULSION_CHANNEL MIOSIX_SERVOS_3_CHANNEL
+
+
 namespace miosix
 {
 
@@ -51,6 +87,12 @@ using miso = Gpio<GPIOE_BASE, 5>;
 using mosi = Gpio<GPIOE_BASE, 6>;
 }  // namespace spi4
 
+namespace i2c1
+{
+using sda = Gpio<GPIOB_BASE, 9>;
+using scl = Gpio<GPIOB_BASE, 8>;
+}  // namespace i2c1
+
 namespace usart1
 {
 using tx = Gpio<GPIOA_BASE, 9>;
@@ -88,45 +130,56 @@ namespace switches
 using userSwitch1 = Gpio<GPIOB_BASE, 2>;
 }
 
-namespace lsm6dsrx
+namespace servos
+{
+using servo1 = Gpio<GPIOC_BASE, 6>;  // TIM8 CH1
+using servo2 = Gpio<GPIOC_BASE, 7>;  // TIM8 CH2
+}  // namespace servos
+
+}  // namespace peripherals
+
+namespace sensors
+{
+namespace LSM6DSRX
 {
 using cs   = Gpio<GPIOC_BASE, 4>;
 using int1 = Gpio<GPIOD_BASE, 13>;
 using int2 = Gpio<GPIOG_BASE, 7>;
-}  // namespace lsm6dsrx
+}  // namespace LSM6DSRX
 
-namespace h3lis331dl
+namespace H3LIS331DL
 {
 using cs   = Gpio<GPIOD_BASE, 3>;
 using int1 = Gpio<GPIOC_BASE, 3>;
-}  // namespace h3lis331dl
+}  // namespace H3LIS331DL
 
-namespace lis2mdl
+namespace LIS2MDL
 {
 using cs = Gpio<GPIOD_BASE, 5>;
-}  // namespace lis2mdl
+}  // namespace LIS2MDL
 
-namespace lps22df
+namespace LPS22DF
 {
 using cs   = Gpio<GPIOD_BASE, 7>;
 using int1 = Gpio<GPIOB_BASE, 11>;
-}  // namespace lps22df
+}  // namespace LPS22DF
 
-namespace ads131m08
+namespace ADS131M08
 {
 using cs = Gpio<GPIOG_BASE, 10>;
-}  // namespace ads131m08
+}  // namespace ADS131M08
 
-namespace max31856
+namespace UBXGps
 {
-using cs = Gpio<GPIOD_BASE, 4>;
-}  // namespace max31856
+using cs = Gpio<GPIOG_BASE, 7>;
+}
 
-namespace servos
+namespace VN100
 {
-using servo1 = Gpio<GPIOC_BASE, 6>;  // TIM8 CH1
-using servo2 = Gpio<GPIOC_BASE, 7>;  // TIM8 CH2
-}  // namespace servos
+using cs      = Gpio<GPIOA_BASE, 15>;
+using syncIn  = Gpio<GPIOB_BASE, 7>;
+using syncOut = Gpio<GPIOE_BASE, 3>;
+}  // namespace VN100
 
 namespace tank_level
 {
@@ -140,6 +193,32 @@ namespace battery_voltage
 using ch15 = Gpio<GPIOC_BASE, 5>;
 }
 
-}  // namespace peripherals
+}  // namespace sensors
+
+
+namespace radio
+{
+using cs   = Gpio<GPIOC_BASE, 4>;
+using txEn = Gpio<GPIOC_BASE, 5>;
+using rxEn = Gpio<GPIOB_BASE, 15>;
+using dio0 = Gpio<GPIOD_BASE, 11>;
+using dio1 = Gpio<GPIOG_BASE, 3>;
+using dio3 = Gpio<GPIOG_BASE, 6>;
+using nrst = Gpio<GPIOE_BASE, 4>;
+}  // namespace radio
+
+namespace sense
+{
+using detachPayload  = Gpio<GPIOC_BASE, 3>;
+using detachMain     = Gpio<GPIOA_BASE, 4>;
+using detachRamp     = Gpio<GPIOB_BASE, 11>;
+using expulsionSense = Gpio<GPIOA_BASE, 3>;
+using cutterSense    = Gpio<GPIOC_BASE, 1>;
+}  // namespace sense
+
+namespace gpios
+{
+using mainDeploy = Gpio<GPIOD_BASE, 4>;
+}  // namespace gpios
 
 }  // namespace miosix
diff --git a/src/bsps/stm32f767zi_gemini_motor/stm32_2m+16m_xram.ld b/src/bsps/stm32f767zi_gemini_motor/stm32_2m+16m_xram.ld
index 5b3545abd6f3007072b8ff00a978242d74503d79..c3439827b34e3beec55cd27c14b7a70b8aa44606 100644
--- a/src/bsps/stm32f767zi_gemini_motor/stm32_2m+16m_xram.ld
+++ b/src/bsps/stm32f767zi_gemini_motor/stm32_2m+16m_xram.ld
@@ -187,4 +187,15 @@ SECTIONS
         . = ALIGN(4);
         _preserve_end = .;
     } > bram
+
+    .preserve : ALIGN(4)
+    {
+        _preserve_start = .;
+        . = ALIGN(4);
+        *(.preserve);
+        *(.preserve*);
+        . = ALIGN(4);
+        _preserve_end = .;
+    } > bram AT > flash
+    _preserve_load = LOADADDR(.preserve);
 }
diff --git a/src/bsps/stm32f767zi_gemini_motor/stm32_2m+384k_ram.ld b/src/bsps/stm32f767zi_gemini_motor/stm32_2m+384k_ram.ld
index 497bd5198760b9637c774bf3900fd9dfbc01a2b2..b25d3fe8e93d1fad0573ec2067b3e703040b7eba 100644
--- a/src/bsps/stm32f767zi_gemini_motor/stm32_2m+384k_ram.ld
+++ b/src/bsps/stm32f767zi_gemini_motor/stm32_2m+384k_ram.ld
@@ -177,7 +177,7 @@ SECTIONS
     _end = .;
     PROVIDE(end = .);
     
-    .preserve(NOLOAD) : ALIGN(4)
+    .preserve : ALIGN(4)
     {
         _preserve_start = .;
         . = ALIGN(4);
@@ -185,5 +185,6 @@ SECTIONS
         *(.preserve*);
         . = ALIGN(4);
         _preserve_end = .;
-    } > bram
+    } > bram AT > flash
+    _preserve_load = LOADADDR(.preserve);
 }