From 326814784b4528257165e289ec654435a87db122 Mon Sep 17 00:00:00 2001
From: Rahix <rahix@rahix.de>
Date: Sat, 24 Aug 2019 00:32:40 +0200
Subject: [PATCH] fix(serial): Perform serial prints in a critical section

Sometimes during initialization, one `log_msg()` intercepts another one,
leading to a whole lot of weird issues in other modules (like I2C).  I
suspect this to be memory corruption of some kind.  The issues can be
fixed by performing serial prints in a critical section, thus ensuring
atomicity of prints.  Note that this does not mean log messages will not
interleave.

The CDC-ACM and BLE-Serial writes cannot be put into a critical section
and are thus a point where this code can still fail.  For now, however,
this fix ensures the race-conditions during startup, where USB and BLE
are not yet running, don't happen anymore.

Signed-off-by: Rahix <rahix@rahix.de>
---
 epicardium/modules/serial.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/epicardium/modules/serial.c b/epicardium/modules/serial.c
index a7392056..b7be0594 100644
--- a/epicardium/modules/serial.c
+++ b/epicardium/modules/serial.c
@@ -27,7 +27,21 @@ static QueueHandle_t read_queue;
  */
 void epic_uart_write_str(const char *str, intptr_t length)
 {
+	uint32_t basepri = __get_BASEPRI();
+	if (xPortIsInsideInterrupt()) {
+		taskENTER_CRITICAL_FROM_ISR();
+	} else {
+		taskENTER_CRITICAL();
+	}
+
 	UART_Write(ConsoleUart, (uint8_t *)str, length);
+
+	if (xPortIsInsideInterrupt()) {
+		taskEXIT_CRITICAL_FROM_ISR(basepri);
+	} else {
+		taskEXIT_CRITICAL();
+	}
+
 	cdcacm_write((uint8_t *)str, length);
 	ble_uart_write((uint8_t *)str, length);
 }
-- 
GitLab