diff --git a/src/shared/drivers/i2c/I2CDriver-f7.cpp b/src/shared/drivers/i2c/I2CDriver-f7.cpp
index 080277ab4cb67a47c2b9c2d10cf666c030e0f6cd..c98c0de14282e6bcb5b33ee2bf633cee51f2acfb 100644
--- a/src/shared/drivers/i2c/I2CDriver-f7.cpp
+++ b/src/shared/drivers/i2c/I2CDriver-f7.cpp
@@ -40,43 +40,34 @@ static const int N_SCL_BITBANG =
     16;  ///< Number of clocks created for slave locked bus recovery
 static const uint8_t I2C_PIN_ALTERNATE_FUNCTION =
     4;  ///< Alternate Function number of the I2C peripheral pins
-
-static uint8_t PRESC_STD;   ///< PRESC for STANDARD speed
-static uint8_t SCLH_STD;    ///< SCLH for STANDARD speed
-static uint8_t SCLL_STD;    ///< SCLL for STANDARD speed
-static uint8_t SCLDEL_STD;  ///< SCLDEL for STANDARD speed
-static uint8_t SDADEL_STD;  ///< SDADEL for STANDARD speed
-
-static uint8_t PRESC_F;   ///< PRESC for FAST speed
-static uint8_t SCLH_F;    ///< SCLH for FAST speed
-static uint8_t SCLL_F;    ///< SCLL for FAST speed
-static uint8_t SCLDEL_F;  ///< SCLDEL for FAST speed
-static uint8_t SDADEL_F;  ///< SDADEL for FAST speed
-
-static uint8_t PRESC_FP;   ///< PRESC for FAST PLUS speed
-static uint8_t SCLH_FP;    ///< SCLH for FAST PLUS speed
-static uint8_t SCLL_FP;    ///< SCLL for FAST PLUS speed
-static uint8_t SCLDEL_FP;  ///< SCLDEL for FAST PLUS speed
-static uint8_t SDADEL_FP;  ///< SDADEL for FAST PLUS speed
 }  // namespace I2CConsts
 
+/**
+ * @brief Struct that collects all the timing parameters for the clock
+ * generation.
+ */
+typedef struct
+{
+    uint8_t presc;   ///< Timing prescaler
+    uint8_t sclh;    ///< SCL high period
+    uint8_t scll;    ///< SCL low period
+    uint8_t scldel;  ///< Data setup time
+    uint8_t sdadel;  ///< Data hold time
+} I2CTimings;
+
 /**
  * @brief Helper function for calculating the timing parameters for the
  * peripheral
  *
  * The formula for the clock is:
  * t_SCL = [(SCLL + 1) + (SCLH + 1)] * (PRESC + 1) * t_I2CCLK + t_sync
- * @param f Peripheral timer clock frequency in kHz
- * @param fi2c I2C clock frequency in kHz
- * @param presc pointer to the prescaler variable to set
- * @param sclh pointer to the sclh variable to set
- * @param scll pointer to the scll variable to set
- * @param scldel pointer to the scldel variable to set
- * @param sdadel pointer to the sdadel variable to set
+ * @param f Peripheral timer clock frequency in kHz.
+ * @param fi2c I2C clock frequency in kHz.
+ * @return Struct with the timings for the wanted i2c frequency.
  */
-void calculateTimings(uint32_t f, uint32_t fi2c, uint8_t *presc, uint8_t *sclh,
-                      uint8_t *scll, uint8_t *scldel, uint8_t *sdadel)
+I2CTimings calculateTimings(uint32_t f, uint32_t fi2c)
 {
+    I2CTimings i2cTimings;
     // calculating the "smallest" prescaler so that we can handle in a more
     // refined way (with SCLL and SCLH) the length of high and low phases. We
     // "limit" SCLL and SCLH to 64 because like so we can have acceptable values
@@ -86,21 +77,23 @@ void calculateTimings(uint32_t f, uint32_t fi2c, uint8_t *presc, uint8_t *sclh,
     // presc is 4 bit long, so avoiding overflow
     if (temp_presc >= 16)
     {
-        *presc = 15;
+        i2cTimings.presc = 15;
     }
     else if (temp_presc == 0)
     {
-        *presc = 0;
+        i2cTimings.presc = 0;
     }
     else
     {
-        *presc = temp_presc - 1;
+        i2cTimings.presc = temp_presc - 1;
     }
 
     // calculating SCLL and SCLH in order to have duty cycle of 50%. Also,
     // correcting for the 250ns delay of the peripheral (250ns = 12 I2C clocks)
     // distributing the correction on SCLL and SCLH
-    *sclh = *scll = (f / (fi2c * 2 * (*presc + 1)) - 1) - (7 / (*presc + 1));
+    i2cTimings.sclh = i2cTimings.scll =
+        (f / (fi2c * 2 * (i2cTimings.presc + 1)) - 1) -
+        (7 / (i2cTimings.presc + 1));
 
     // SCLDEL >= (t_r + t_su) / ((PRESC+1)*t_i2c) - 1 ; approximated without
     // subtracting 1. scldly and sdadly are calculated using values taken from
@@ -108,25 +101,63 @@ void calculateTimings(uint32_t f, uint32_t fi2c, uint8_t *presc, uint8_t *sclh,
     uint32_t scldly = 0, sdadly = 0;
     if (fi2c == 100)
     {
-        scldly = 1250 * f / (*presc + 1) / 1000000;
-        sdadly = (3450 - 1000 - 260) * f / (*presc + 1) / 1000000;
+        scldly = 1250 * f / (i2cTimings.presc + 1) / 1000000;
+        sdadly = (3450 - 1000 - 260) * f / (i2cTimings.presc + 1) / 1000000;
     }
     else if (fi2c == 400)
     {
-        scldly = 400 * f / (*presc + 1) / 1000000;
-        sdadly = (900 - 300 - 260) * f / (*presc + 1) / 1000000;
+        scldly = 400 * f / (i2cTimings.presc + 1) / 1000000;
+        sdadly = (900 - 300 - 260) * f / (i2cTimings.presc + 1) / 1000000;
     }
     else if (fi2c == 1000)
     {
-        scldly = 170 * f / (*presc + 1) / 1000000;
-        sdadly = (450 - 120 - 260) * f / (*presc + 1) / 1000000;
+        scldly = 170 * f / (i2cTimings.presc + 1) / 1000000;
+        sdadly = (450 - 120 - 260) * f / (i2cTimings.presc + 1) / 1000000;
     }
 
     // max value of scldel is 15
-    *scldel = ((scldly < 16) ? (scldly - 1) : 15);
+    i2cTimings.scldel = ((scldly < 16) ? (scldly - 1) : 15);
 
     // max value of sdadel is 15
-    *sdadel = ((sdadly < 16) ? (sdadly - 1) : 15);
+    i2cTimings.sdadel = ((sdadly < 16) ? (sdadly - 1) : 15);
+
+    return i2cTimings;
+}
+
+/**
+ * @brief Used to get the timing parameters for each speed mode. If the speed
+ * mode isn't supported, communication in release mode will take place with
+ * minimum speed (standard mode).
+ * @param speed Speed mode for which we want the timing parameters.
+ * @return The struct with the timing parameters for the speed mode passed.
+ */
+const I2CTimings &getTimings(Boardcore::I2CDriver::Speed speed)
+{
+    // Retrieving the frequency of the APB relative to the I2C peripheral
+    // [kHz] (I2C peripherals are always connected to APB1, Low speed bus). In
+    // fact by default the I2C peripheral is clocked by the APB1 bus; anyway HSI
+    // and SYSCLK can be chosen.
+    static const uint32_t f = Boardcore::ClockUtils::getAPBPeripheralsClock(
+                                  Boardcore::ClockUtils::APB::APB1) /
+                              1000;
+    static const I2CTimings i2cTimingsStd      = calculateTimings(f, 100);
+    static const I2CTimings i2cTimingsFast     = calculateTimings(f, 400);
+    static const I2CTimings i2cTimingsFastPlus = calculateTimings(f, 1000);
+
+    // Calculating for all the speed modes the clock parameters (so we won't
+    // have to calculate them again for every transaction)
+    switch (speed)
+    {
+        case Boardcore::I2CDriver::Speed::STANDARD:;
+            return i2cTimingsStd;
+        case Boardcore::I2CDriver::Speed::FAST:
+            return i2cTimingsFast;
+        case Boardcore::I2CDriver::Speed::FAST_PLUS:
+            return i2cTimingsFastPlus;
+        default:
+            D(assert(false && "Speed mode not supported!"));
+            return i2cTimingsStd;
+    }
 }
 
 #ifdef I2C1
@@ -413,30 +444,6 @@ void I2CDriver::init()
     // bit resets the peripheral)
     i2c->CR1 = 0;
 
-    // Retrieving the frequency of the APB relative to the I2C peripheral
-    // [kHz] (I2C peripherals are always connected to APB1, Low speed bus). In
-    // fact by default the I2C peripheral is clocked by the APB1 bus; anyway HSI
-    // and SYSCLK can be chosen.
-    uint32_t f =
-        ClockUtils::getAPBPeripheralsClock(ClockUtils::APB::APB1) / 1000;
-
-    // Calculating for all the speed modes the clock parameters (so we won't
-    // have to calculate them again for every transaction)
-    // Standard mode (100 kHz)
-    calculateTimings(f, 100, &I2CConsts::PRESC_STD, &I2CConsts::SCLH_STD,
-                     &I2CConsts::SCLL_STD, &I2CConsts::SCLDEL_STD,
-                     &I2CConsts::SDADEL_STD);
-
-    // Fast mode (400 kHz)
-    calculateTimings(f, 400, &I2CConsts::PRESC_F, &I2CConsts::SCLH_F,
-                     &I2CConsts::SCLL_F, &I2CConsts::SCLDEL_F,
-                     &I2CConsts::SDADEL_F);
-
-    // Fast mode plus (1000 kHz)
-    calculateTimings(f, 1000, &I2CConsts::PRESC_FP, &I2CConsts::SCLH_FP,
-                     &I2CConsts::SCLL_FP, &I2CConsts::SCLDEL_FP,
-                     &I2CConsts::SDADEL_FP);
-
     // Enabling the peripheral after initialization
     i2c->CR1 |= I2C_CR1_PE;
 }
@@ -566,39 +573,15 @@ void I2CDriver::setupPeripheral(const I2CSlaveConfig &slaveConfig)
     // state machines and flags in order to start with a clear environment
     i2c->CR1 &= ~I2C_CR1_PE;
 
+    const auto i2cTimings = getTimings(slaveConfig.speed);
+
     // Setting PRESC, SCLH, SCLL, SCLDEL and SDADEL bits in I2C_TIMINGR register
     // to generate correct timings for each speed mode
-    if (slaveConfig.speed == Speed::STANDARD)
-    {
-        i2c->TIMINGR =
-            (I2CConsts::PRESC_STD << I2C_TIMINGR_PRESC_Pos) |    // PRESC
-            (I2CConsts::SCLL_STD << I2C_TIMINGR_SCLL_Pos) |      // SCLL
-            (I2CConsts::SCLH_STD << I2C_TIMINGR_SCLH_Pos) |      // SCLH
-            (I2CConsts::SCLDEL_STD << I2C_TIMINGR_SCLDEL_Pos) |  // SCLDEL
-            (I2CConsts::SDADEL_STD << I2C_TIMINGR_SDADEL_Pos);   // SDADEL
-    }
-    else if (slaveConfig.speed == Speed::FAST)
-    {
-        i2c->TIMINGR =
-            (I2CConsts::PRESC_F << I2C_TIMINGR_PRESC_Pos) |    // PRESC
-            (I2CConsts::SCLL_F << I2C_TIMINGR_SCLL_Pos) |      // SCLL
-            (I2CConsts::SCLH_F << I2C_TIMINGR_SCLH_Pos) |      // SCLH
-            (I2CConsts::SCLDEL_F << I2C_TIMINGR_SCLDEL_Pos) |  // SCLDEL
-            (I2CConsts::SDADEL_F << I2C_TIMINGR_SDADEL_Pos);   // SDADEL
-    }
-    else if (slaveConfig.speed == Speed::FAST_PLUS)
-    {
-        i2c->TIMINGR =
-            (I2CConsts::PRESC_FP << I2C_TIMINGR_PRESC_Pos) |    // PRESC
-            (I2CConsts::SCLL_FP << I2C_TIMINGR_SCLL_Pos) |      // SCLL
-            (I2CConsts::SCLH_FP << I2C_TIMINGR_SCLH_Pos) |      // SCLH
-            (I2CConsts::SCLDEL_FP << I2C_TIMINGR_SCLDEL_Pos) |  // SCLDEL
-            (I2CConsts::SDADEL_FP << I2C_TIMINGR_SDADEL_Pos);   // SDADEL
-    }
-    else
-    {
-        D(assert(false && "speed not supported"));
-    }
+    i2c->TIMINGR = (i2cTimings.presc << I2C_TIMINGR_PRESC_Pos) |    // PRESC
+                   (i2cTimings.scll << I2C_TIMINGR_SCLL_Pos) |      // SCLL
+                   (i2cTimings.sclh << I2C_TIMINGR_SCLH_Pos) |      // SCLH
+                   (i2cTimings.scldel << I2C_TIMINGR_SCLDEL_Pos) |  // SCLDEL
+                   (i2cTimings.sdadel << I2C_TIMINGR_SDADEL_Pos);   // SDADEL
 
     // setting addressing mode and slave address (for 7-Bit addressing the 7
     // bits have to be set on SADD[7:1])