diff --git a/epicardium/main.c b/epicardium/main.c
index e6ac3ea9081fcdb9a8a8fd609c89afefeaeb4688..b7ab34198baad2f018a6434379c77441eb5ec3ef 100644
--- a/epicardium/main.c
+++ b/epicardium/main.c
@@ -60,6 +60,7 @@ int main(void)
 	fatfs_init();
 	api_interrupt_init();
 	stream_init();
+	i2c_init();
 
 	LOG_INFO("startup", "Initializing tasks ...");
 
diff --git a/epicardium/modules/bhi.c b/epicardium/modules/bhi.c
index 5e05e67236250323473771fbba2615560b53c728..79ce0a724fcf9e11c14d0c6185d116a293f77cad 100644
--- a/epicardium/modules/bhi.c
+++ b/epicardium/modules/bhi.c
@@ -115,7 +115,8 @@ int epic_bhi160_enable_sensor(
 		return -ENODEV;
 	}
 
-	if (xSemaphoreTake(bhi160_mutex, LOCK_WAIT) == pdTRUE) {
+	if (i2c_lock() == 0 &&
+	    xSemaphoreTake(bhi160_mutex, LOCK_WAIT) == pdTRUE) {
 		struct stream_info *stream = &bhi160_streams[sensor_type];
 		stream->item_size = bhi160_lookup_data_size(sensor_type);
 		/* TODO: Sanity check length */
@@ -138,6 +139,7 @@ int epic_bhi160_enable_sensor(
 			0,
 			config->dynamic_range /* dynamic range is sensor dependent */
 		);
+		i2c_unlock();
 		xSemaphoreGive(bhi160_mutex);
 	} else {
 		return -EBUSY;
@@ -153,13 +155,15 @@ int epic_bhi160_disable_sensor(enum bhi160_sensor_type sensor_type)
 		return -ENODEV;
 	}
 
-	if (xSemaphoreTake(bhi160_mutex, LOCK_WAIT) == pdTRUE) {
+	if (i2c_lock() == 0 &&
+	    xSemaphoreTake(bhi160_mutex, LOCK_WAIT) == pdTRUE) {
 		struct stream_info *stream = &bhi160_streams[sensor_type];
 		stream_deregister(bhi160_lookup_sd(sensor_type), stream);
 		vQueueDelete(stream->queue);
 		stream->queue = NULL;
 
 		bhy_disable_virtual_sensor(vs_id, VS_WAKEUP);
+		i2c_unlock();
 		xSemaphoreGive(bhi160_mutex);
 	} else {
 		return -EBUSY;
@@ -233,7 +237,8 @@ static int bhi160_fetch_fifo(void)
 	/* Number of bytes left in BHI160's FIFO buffer */
 	uint16_t bytes_left_in_fifo = 1;
 
-	if (xSemaphoreTake(bhi160_mutex, LOCK_WAIT) != pdTRUE) {
+	if (i2c_lock() < 0 ||
+	    xSemaphoreTake(bhi160_mutex, LOCK_WAIT) != pdTRUE) {
 		return -EBUSY;
 	}
 
@@ -282,6 +287,7 @@ static int bhi160_fetch_fifo(void)
 	}
 
 	xSemaphoreGive(bhi160_mutex);
+	i2c_unlock();
 	return 0;
 }
 
@@ -310,8 +316,8 @@ void vBhi160Task(void *pvParameters)
 	bhi160_mutex   = xSemaphoreCreateMutexStatic(&bhi160_mutex_data);
 
 	/* Take Mutex during initialization, just in case */
-	if (xSemaphoreTake(bhi160_mutex, 0) != pdTRUE) {
-		LOG_CRIT("bhi160", "Failed to acquire BHI160 mutex!");
+	if (i2c_lock() < 0 || xSemaphoreTake(bhi160_mutex, 0) != pdTRUE) {
+		LOG_CRIT("bhi160", "Failed to acquire BHI160/i2c mutex!");
 		vTaskDelay(portMAX_DELAY);
 	}
 
@@ -336,8 +342,7 @@ void vBhi160Task(void *pvParameters)
 		vTaskDelay(portMAX_DELAY);
 	}
 
-	/* Wait for first two interrupts */
-	ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100));
+	/* Wait for first interrupt */
 	ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(100));
 
 	/* Remap axes to match card10 layout */
@@ -356,6 +361,8 @@ void vBhi160Task(void *pvParameters)
 
 	xSemaphoreGive(bhi160_mutex);
 
+	i2c_unlock();
+
 	/* ----------------------------------------- */
 
 	while (1) {
diff --git a/epicardium/modules/i2c.c b/epicardium/modules/i2c.c
new file mode 100644
index 0000000000000000000000000000000000000000..f7ba63e373943c13ba36a0f7c3d1145721866dfe
--- /dev/null
+++ b/epicardium/modules/i2c.c
@@ -0,0 +1,33 @@
+#include "modules/log.h"
+#include "modules/modules.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+
+#include <errno.h>
+
+static StaticSemaphore_t i2c_mutex_data;
+static SemaphoreHandle_t i2c_mutex;
+
+int i2c_init(void)
+{
+	i2c_mutex = xSemaphoreCreateMutexStatic(&i2c_mutex_data);
+	return 0;
+}
+
+int i2c_lock(void)
+{
+	if (xSemaphoreTake(i2c_mutex, pdMS_TO_TICKS(100)) != pdTRUE) {
+		LOG_WARN("i2c", "Mutex is busy");
+		return -EBUSY;
+	}
+	return 0;
+}
+
+void i2c_unlock(void)
+{
+	if (xSemaphoreGive(i2c_mutex) != pdTRUE) {
+		LOG_ERR("i2c", "Mutex was not acquired correctly");
+	}
+}
diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build
index e59aeaee83dd5c3579391bc0706a4598c8dd1576..0732576c33c0f2285cadfe394361ca69eb127a46 100644
--- a/epicardium/modules/meson.build
+++ b/epicardium/modules/meson.build
@@ -3,6 +3,7 @@ module_sources = files(
   'display.c',
   'fatfs.c',
   'fatfs_fileops.c',
+  'i2c.c',
   'leds.c',
   'log.c',
   'pmic.c',
diff --git a/epicardium/modules/modules.h b/epicardium/modules/modules.h
index f09caa398fed0cdf7af7288d20bb175ab62d47e6..d1e92dcd5654d5c96d812bfe0751e0b95ef32662 100644
--- a/epicardium/modules/modules.h
+++ b/epicardium/modules/modules.h
@@ -26,6 +26,11 @@ void vPmicTask(void *pvParameters);
 #define BHI160_MUTEX_WAIT_MS          50
 void vBhi160Task(void *pvParameters);
 
+/* ---------- I2C ---------------------------------------------------------- */
+int i2c_init(void);
+int i2c_lock(void);
+void i2c_unlock(void);
+
 // Forces an unlock of the display. Only to be used in epicardium
 void disp_forcelock();
 #endif /* MODULES_H */
diff --git a/epicardium/modules/pmic.c b/epicardium/modules/pmic.c
index a41b38aae24e5268c57471ea6841a4e59e509acd..64f6526f5fd1f231d79c81ae8033ca98f110b088 100644
--- a/epicardium/modules/pmic.c
+++ b/epicardium/modules/pmic.c
@@ -27,9 +27,9 @@ void pmic_interrupt_callback(void *_)
 
 void vPmicTask(void *pvParameters)
 {
-	int count = 0;
+	int count          = 0;
 	portTickType delay = portMAX_DELAY;
-	pmic_task_id = xTaskGetCurrentTaskHandle();
+	pmic_task_id       = xTaskGetCurrentTaskHandle();
 
 	while (1) {
 		ulTaskNotifyTake(pdTRUE, delay);
@@ -43,7 +43,13 @@ void vPmicTask(void *pvParameters)
 			MAX77650_setSFT_RST(0x2);
 		}
 
+		while (i2c_lock() < 0) {
+			LOG_WARN("pmic", "Failed to acquire i2c. Retrying.");
+			vTaskDelay(pdMS_TO_TICKS(500));
+		}
+
 		uint8_t int_flag = MAX77650_getINT_GLBL();
+		i2c_unlock();
 
 		if (int_flag & MAX77650_INT_nEN_F) {
 			/* Button was pressed */
@@ -62,8 +68,11 @@ void vPmicTask(void *pvParameters)
 
 		/* TODO: Remove when all interrupts are handled */
 		if (int_flag & ~(MAX77650_INT_nEN_F | MAX77650_INT_nEN_R)) {
-			LOG_WARN("pmic", "Unhandled PMIC Interrupt: %x",
-			         int_flag);
+			LOG_WARN(
+				"pmic",
+				"Unhandled PMIC Interrupt: %x",
+				int_flag
+			);
 		}
 
 		if (delay != portMAX_DELAY) {