changeset 916:4832981f9af8 Evo_2_23

External sensor UART: Switch to DMA TX transfers: The previous version used polling tx function to transfer data. Because of the short command length of the protocols supported this was no big issue. New protocolls (like GNSS) have longer command sequence which have an impact to the program flow. That's why the implementation has been changed to DMA transmission.
author Ideenmodellierer
date Mon, 28 Oct 2024 20:34:58 +0100
parents ff318ae65dd0
children 0d6c4b40fae4
files Small_CPU/Inc/uart.h Small_CPU/Src/externalInterface.c Small_CPU/Src/stm32f4xx_it_v3.c Small_CPU/Src/uart.c Small_CPU/Src/uartProtocol_Co2.c Small_CPU/Src/uartProtocol_O2.c
diffstat 6 files changed, 390 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/Small_CPU/Inc/uart.h	Sat Oct 19 20:10:56 2024 +0200
+++ b/Small_CPU/Inc/uart.h	Mon Oct 28 20:34:58 2024 +0100
@@ -25,8 +25,8 @@
 #include "stm32f4xx_hal.h"
 
 
-#define BUFFER_NODATA			(7u)		/* The read function needs a byte which indicated that no data for processing is available.*/
-											/* This byte shall never appear in a normal data steam */
+#define BUFFER_NODATA_LOW	('~')		/* The read function needs a signiture which indicates that no data for processing is available.*/
+#define BUFFER_NODATA_HIGH  (0xA5)
 
 
 UART_HandleTypeDef huart1, huart6;
@@ -46,6 +46,10 @@
 void UART_HandleCO2Data(void);
 void DigitalCO2_SendCmd(uint8_t CO2Cmd, uint8_t *cmdString, uint8_t *cmdLength);
 #endif
+
+#ifdef ENABLE_GNSS_SUPPORT
+void UART_HandleGnssData(void);
+#endif
 #ifdef ENABLE_SENTINEL_MODE
 void UART_HandleSentinelData(void);
 #endif
@@ -54,7 +58,9 @@
 void UART_setTargetChannel(uint8_t channel);
 void  UART_MUX_SelectAddress(uint8_t muxAddress);
 void UART_SendCmdString(uint8_t *cmdString);
+void UART_SendCmdUbx(uint8_t *cmd, uint8_t len);
 void UART_ReadData(uint8_t sensorType);
+void UART_WriteData(void);
 void UART_FlushRxBuffer(void);
 void UART_ChangeBaudrate(uint32_t newBaudrate);
 uint8_t UART_isComActive(uint8_t sensorId);
--- a/Small_CPU/Src/externalInterface.c	Sat Oct 19 20:10:56 2024 +0200
+++ b/Small_CPU/Src/externalInterface.c	Mon Oct 28 20:34:58 2024 +0100
@@ -35,6 +35,7 @@
 #include "uartProtocol_O2.h"
 #include "uartProtocol_Co2.h"
 #include "uartProtocol_Sentinel.h"
+#include "uartProtocol_GNSS.h"
 
 extern SGlobal global;
 extern UART_HandleTypeDef huart1;
@@ -92,7 +93,7 @@
 static float LookupCO2PressureCorrection[LOOKUP_CO2_CORR_TABLE_MAX / LOOKUP_CO2_CORR_TABLE_SCALE];		/* lookup table for pressure compensation values */
 
 static uint16_t externalInterfaceMuxReqIntervall = 0xffff;		/* delay between switching from one MUX channel to the next */
-static uint8_t activeUartChannel = 0;							/* Index of the sensor port which is selected by the mux or 0 if no mux is connected */
+static uint8_t activeUartChannel = 0xff;
 
 
 static void externalInface_MapUartToLegacyADC(uint8_t* pMap);
@@ -387,6 +388,10 @@
 #ifdef ENABLE_CO2_SUPPORT
 					|| ((externalAutoDetect >= DETECTION_CO2_0) && (externalAutoDetect <= DETECTION_CO2_3))
 #endif
+#ifdef ENABLE_GNSS_SUPPORT
+					|| ((externalAutoDetect >= DETECTION_GNSS_0) && (externalAutoDetect <= DETECTION_GNSS_3))
+#endif
+
 #ifdef ENABLE_SENTINEL_MODE
 														   || ((protocol == EXT_INTERFACE_UART_SENTINEL) && (externalAutoDetect == DETECTION_SENTINEL))
 #endif
@@ -608,6 +613,21 @@
 			}
 		}
 	}
+	for(index = 0; index < EXT_INTERFACE_SENSOR_CNT-1; index++)
+	{
+		if(pMap[index] == SENSOR_GNSS)
+		{
+			for(index2 = 0; index2 < MAX_ADC_CHANNEL; index2++)
+			{
+				if(pMap[index2] == SENSOR_NONE)
+				{
+					pMap[index2] = SENSOR_GNSSM;		/* store a mirror instance needed for visualization */
+					Mux2ADCMap[index2] = index;
+					break;
+				}
+			}
+		}
+	}
 #ifdef ENABLE_SENTINEL_MODE
 	if(pMap[EXT_INTERFACE_MUX_OFFSET] == SENSOR_SENTINEL)
 	{
@@ -640,6 +660,9 @@
 	static uint8_t sensorIndex = 0;
 	static uint8_t uartMuxChannel = 0;
 	uint8_t index = 0;
+#ifdef ENABLE_GNSS_SUPPORT
+	uint8_t detectionDelayCnt = 0;
+#endif
 	uint8_t cntSensor = 0;
 	uint8_t cntUARTSensor = 0;
 #ifdef ENABLE_CO2_SUPPORT
@@ -706,31 +729,32 @@
 									externalInterfaceMuxReqIntervall = 1100;
 									externalAutoDetect = DETECTION_UARTMUX;
 									externalInterface_SwitchUART(EXT_INTERFACE_UART_O2);
+									externalInterface_CheckBaudrate(SENSOR_DIGO2);
 									UART_MUX_SelectAddress(MAX_MUX_CHANNEL);
 									uartO2_SetChannel(MAX_MUX_CHANNEL);
 									activeUartChannel = MAX_MUX_CHANNEL;
 									tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
 				break;
-			case DETECTION_UARTMUX:  	if(uartO2_isSensorConnected())
-										{
-											uartMuxChannel = 1;
-											tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
-											foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
-										}
-										else
-										{
-											tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_NONE;
-										}
-										externalAutoDetect = DETECTION_DIGO2_0;
-										uartO2_SetChannel(0);
-										activeUartChannel = 0;
-										tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
-										externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
-										externalInterface_SwitchUART(EXT_INTERFACE_UART_O2);
-										if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
-										{
-											UART_MUX_SelectAddress(0);
-										}
+			case DETECTION_UARTMUX: if(uartO2_isSensorConnected())
+									{
+										uartMuxChannel = 1;
+										tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
+										foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_MUX;
+									}
+									else
+									{
+										tmpSensorMap[EXT_INTERFACE_SENSOR_CNT-1] = SENSOR_NONE;
+									}
+									externalAutoDetect = DETECTION_DIGO2_0;
+									uartO2_SetChannel(0);
+									activeUartChannel = 0;
+									tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_DIGO2;
+									externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
+									externalInterface_SwitchUART(EXT_INTERFACE_UART_O2);
+									if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
+									{
+										UART_MUX_SelectAddress(0);
+									}
 				break;
 			case DETECTION_DIGO2_0:
 			case DETECTION_DIGO2_1: 
@@ -791,7 +815,11 @@
 			case DETECTION_CO2_3:	if(uartCo2_isSensorConnected())
 									{
 										foundSensorMap[EXT_INTERFACE_MUX_OFFSET + activeUartChannel] = SENSOR_CO2;
+#ifdef ENABLE_GNSS_SUPPORT
+										externalAutoDetect = DETECTION_GNSS_0;	/* only one CO2 sensor supported */
+#else
 										externalAutoDetect = DETECTION_DONE;	/* only one CO2 sensor supported */
+#endif
 									}
 									else if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
 									{
@@ -808,13 +836,84 @@
 									}
 									else
 									{
+
+
+#if defined ENABLE_SENTINEL_MODE || defined ENABLE_GNSS_SUPPORT
+#ifdef ENABLE_GNSS_SUPPORT
+										externalAutoDetect = DETECTION_GNSS_0;
+#else
 #ifdef ENABLE_SENTINEL_MODE
 										externalAutoDetect = DETECTION_SENTINEL;
+#endif
+#endif
 #else
 										externalAutoDetect = DETECTION_DONE;
 #endif
 									}
 #endif
+
+#ifdef ENABLE_GNSS_SUPPORT
+									if(externalAutoDetect == DETECTION_GNSS_0)
+									{
+										tmpSensorMap[uartMuxChannel + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+										if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
+										{
+											externalInterface_CheckBaudrate(SENSOR_DIGO2);
+											UART_MUX_SelectAddress(0);
+										}
+										activeUartChannel = 0;
+										tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+										uartMuxChannel = 1;
+										tmpSensorMap[EXT_INTERFACE_MUX_OFFSET] = SENSOR_GNSS;
+										externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET] = UART_COMMON_INIT;
+										externalInterface_CheckBaudrate(SENSOR_GNSS);
+										externalInterfaceMuxReqIntervall = 200;	/* iterations needed for module config */
+										detectionDelayCnt = 3;
+		//								uartGnss_SendCmd(GNSSCMD_MODE_POLL, cmdString, &cmdLength);
+									}
+							break;
+			case DETECTION_GNSS_0:
+			case DETECTION_GNSS_1:
+			case DETECTION_GNSS_2:
+			case DETECTION_GNSS_3:	if(detectionDelayCnt == 0)
+									{
+										if(uartGnss_isSensorConnected())
+										{
+											foundSensorMap[EXT_INTERFACE_MUX_OFFSET + activeUartChannel] = SENSOR_GNSS;
+	#ifdef ENABLE_SENTINEL_MODE
+											externalAutoDetect = DETECTION_SENTINEL;	/* only one GNSS sensor supported */
+	#else
+											externalAutoDetect = DETECTION_DONE;		/* only one GNSS sensor supported */
+	#endif
+										}
+										else if(foundSensorMap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
+										{
+											externalInterface_CheckBaudrate(SENSOR_DIGO2);
+											UART_MUX_SelectAddress(uartMuxChannel);
+											activeUartChannel = uartMuxChannel;
+											tmpSensorMap[uartMuxChannel - 1 + EXT_INTERFACE_MUX_OFFSET] = SENSOR_NONE;
+											tmpSensorMap[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = SENSOR_CO2;
+											externalInterface_SensorState[EXT_INTERFACE_MUX_OFFSET + uartMuxChannel] = UART_COMMON_INIT;
+											externalInterface_CheckBaudrate(SENSOR_CO2);
+								//			uartGnss_SendCmd(GNSSCMD_MODE_POLL, cmdString, &cmdLength);
+											externalAutoDetect++;
+											detectionDelayCnt = 3;
+											uartMuxChannel++;
+										}
+										else
+										{
+	#ifdef ENABLE_SENTINEL_MODE
+											externalAutoDetect = DETECTION_SENTINEL;
+	#else
+											externalAutoDetect = DETECTION_DONE;
+	#endif
+										}
+									}
+									else
+									{
+										detectionDelayCnt--;
+									}
+	#endif
 #ifdef ENABLE_SENTINEL_MODE
 									if(externalAutoDetect == DETECTION_SENTINEL)
 									{
@@ -852,7 +951,7 @@
 											cntSensor++;
 										}
 
-										if((foundSensorMap[index] == SENSOR_DIGO2) || (foundSensorMap[index] == SENSOR_CO2))
+										if((foundSensorMap[index] == SENSOR_DIGO2) || (foundSensorMap[index] == SENSOR_CO2) || (foundSensorMap[index] == SENSOR_GNSS))
 										{
 											cntUARTSensor++;
 										}
@@ -919,7 +1018,7 @@
 												memcpy(SensorMap, MasterSensorMap, sizeof(MasterSensorMap));
 												for(index = 0; index < EXT_INTERFACE_SENSOR_CNT; index++)
 												{
-													if((SensorMap[index] == SENSOR_DIGO2) || (SensorMap[index] == SENSOR_CO2))
+													if((SensorMap[index] == SENSOR_DIGO2) || (SensorMap[index] == SENSOR_CO2) || (SensorMap[index] == SENSOR_GNSS))
 													{
 														cntUARTSensor++;
 													}
@@ -959,7 +1058,7 @@
 		{
 			index = 0;
 		}
-		if(((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2) || (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2))
+		if(((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2) || (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2) || (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_GNSS))
 				&& (index != activeUartChannel))
 		{
 			newChannel = index;
@@ -976,6 +1075,7 @@
 
 	switch(sensorType)
 	{
+			case SENSOR_GNSS:
 			case SENSOR_SENTINEL:
 			case SENSOR_CO2:		newBaudrate = 9600;
 				break;
@@ -998,12 +1098,11 @@
 	static uint8_t timeToTrigger = 0;
 	uint32_t tick =  HAL_GetTick();
 	uint8_t *pmap = externalInterface_GetSensorMapPointer(0);
+	uint8_t forceMuxChannel = 0;
 
 
 	if(externalInterfaceMuxReqIntervall != 0xFFFF)
 	{
-		UART_ReadData(pmap[activeSensorId]);
-
 		if(activeUartChannel == 0xFF)
 		{
 			MX_USART1_UART_Init();
@@ -1012,20 +1111,26 @@
 
 			switch(pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET])
 			{
-				case SENSOR_SENTINEL: externalInterface_CheckBaudrate(SENSOR_SENTINEL);
+				case SENSOR_DIGO2:
+				case SENSOR_GNSS:
+				case SENSOR_CO2:
+				case SENSOR_SENTINEL: externalInterface_CheckBaudrate(pmap[activeUartChannel + EXT_INTERFACE_MUX_OFFSET]);
 					break;
-				case SENSOR_CO2: externalInterface_CheckBaudrate(SENSOR_CO2);
-					break;
-				default:
-				case SENSOR_DIGO2: externalInterface_CheckBaudrate(SENSOR_DIGO2);
+				default: 			externalInterface_CheckBaudrate(SENSOR_DIGO2);
 					break;
 			}
 			if(pmap[EXT_INTERFACE_SENSOR_CNT-1] == SENSOR_MUX)
 			{
+				HAL_Delay(10);	/* make sure MUX is available for reception after wakeup */
 				UART_MUX_SelectAddress(activeUartChannel);
 			}
 		}
 
+		if(externalInterface_SensorState[activeSensorId] != UART_COMMON_INIT)
+		{
+			UART_ReadData(pmap[activeSensorId]);
+			UART_WriteData();
+		}
 		if(externalInterface_SensorState[activeSensorId] == UART_COMMON_INIT)
 		{
 			lastRequestTick = tick;
@@ -1056,6 +1161,7 @@
 					|| (externalInterface_SensorState[activeSensorId] == UART_O2_REQ_RAW)
 					|| (externalInterface_SensorState[activeSensorId] == UART_CO2_OPERATING))
 			{
+				forceMuxChannel = 1;
 				switch(pmap[activeSensorId])
 				{
 					case SENSOR_DIGO2: setExternalInterfaceChannel(activeSensorId,0.0);
@@ -1073,12 +1179,14 @@
 				if(activeUartChannel < MAX_MUX_CHANNEL)
 				{
 					index = ExternalInterface_SelectUsedMuxChannel(activeUartChannel);
-					if(index != activeUartChannel)
+					if((index != activeUartChannel) || (forceMuxChannel))
 					{
+						forceMuxChannel = 0;
 						timeToTrigger = 100;
 						activeUartChannel = index;
 						if((pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_DIGO2)
-								|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2))
+								|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_CO2)
+								|| (pmap[index + EXT_INTERFACE_MUX_OFFSET] == SENSOR_GNSS))
 						{
 							uartO2_SetChannel(activeUartChannel);
 							externalInterface_CheckBaudrate(SENSOR_MUX);
@@ -1105,6 +1213,10 @@
 				case SENSOR_CO2:	uartCo2_Control();
 					break;
 #endif
+#ifdef ENABLE_GNSS_SUPPORT
+				case SENSOR_GNSS:	uartGnss_Control();
+						break;
+#endif
 #ifdef ENABLE_SENTINEL_MODE
 				case SENSOR_SENTINEL: uartSentinel_Control();
 				break;
--- a/Small_CPU/Src/stm32f4xx_it_v3.c	Sat Oct 19 20:10:56 2024 +0200
+++ b/Small_CPU/Src/stm32f4xx_it_v3.c	Mon Oct 28 20:34:58 2024 +0100
@@ -60,6 +60,7 @@
 
 extern UART_HandleTypeDef huart1;
 extern DMA_HandleTypeDef  hdma_usart1_rx;
+extern DMA_HandleTypeDef  hdma_usart1_tx;
 
 /* Private function prototypes -----------------------------------------------*/
 /* Private functions ---------------------------------------------------------*/
@@ -241,6 +242,10 @@
   HAL_DMA_IRQHandler(&hdma_usart1_rx);
 }
 
+void DMA2_Stream7_IRQHandler(void)
+{
+  HAL_DMA_IRQHandler(&hdma_usart1_tx);
+}
 
 /******************************************************************************/
 /*                 STM32F4xx Peripherals Interrupt Handlers                   */
--- a/Small_CPU/Src/uart.c	Sat Oct 19 20:10:56 2024 +0200
+++ b/Small_CPU/Src/uart.c	Mon Oct 28 20:34:58 2024 +0100
@@ -37,27 +37,40 @@
 
 
 
-DMA_HandleTypeDef  hdma_usart1_rx, hdma_usart6_rx, hdma_usart6_tx;
+DMA_HandleTypeDef  hdma_usart1_rx, hdma_usart1_tx, hdma_usart6_rx, hdma_usart6_tx;
 
 uint8_t rxBuffer[CHUNK_SIZE * CHUNKS_PER_BUFFER];		/* The complete buffer has a X * chunk size to allow variations in buffer read time */
+uint8_t txBuffer[CHUNK_SIZE];							/* tx uses less bytes */
+uint8_t txBufferQue[CHUNK_SIZE];						/* In MUX mode command may be send shortly after each other => allow q 1 entry que */
+uint8_t txBufferQueLen;
+
 uint8_t rxBufferUart6[CHUNK_SIZE * CHUNKS_PER_BUFFER];		/* The complete buffer has a X * chunk size to allow variations in buffer read time */
 uint8_t txBufferUart6[CHUNK_SIZE * CHUNKS_PER_BUFFER];		/* The complete buffer has a X * chunk size to allow variations in buffer read time */
 
 static uint8_t rxWriteIndex;							/* Index of the data item which is analysed */
 static uint8_t rxReadIndex;								/* Index at which new data is stared */
 static uint8_t lastCmdIndex;							/* Index of last command which has not been completely received */
-static uint8_t dmaActive;								/* Indicator if DMA reception needs to be started */
+static uint8_t dmaRxActive;								/* Indicator if DMA reception needs to be started */
+static uint8_t dmaTxActive;								/* Indicator if DMA reception needs to be started */
 
 
 
 
 /* Exported functions --------------------------------------------------------*/
 
+void clearRxBuffer(void)
+{
+	uint16_t index = 0;
+	do
+	{
+		rxBuffer[index++] = BUFFER_NODATA_LOW;
+		rxBuffer[index++] = BUFFER_NODATA_HIGH;
+	} while (index < sizeof(rxBuffer));
+}
 
 void MX_USART1_UART_Init(void)
 {
 /* regular init */	
-
   huart1.Instance = USART1;
   huart1.Init.BaudRate = 19200;
   huart1.Init.WordLength = UART_WORDLENGTH_8B;
@@ -71,11 +84,16 @@
 
   MX_USART1_DMA_Init();
 
-  memset(rxBuffer,BUFFER_NODATA,sizeof(rxBuffer));
+  HAL_NVIC_SetPriority(USART1_IRQn, 1, 3);
+  HAL_NVIC_EnableIRQ(USART1_IRQn);
+
+  clearRxBuffer();
   rxReadIndex = 0;
   lastCmdIndex = 0;
   rxWriteIndex = 0;
-  dmaActive = 0;
+  dmaRxActive = 0;
+  dmaTxActive = 0;
+  txBufferQueLen = 0;
 }
 
 
@@ -84,8 +102,12 @@
 {
 	HAL_DMA_Abort(&hdma_usart1_rx);
 	HAL_DMA_DeInit(&hdma_usart1_rx);
+	HAL_DMA_Abort(&hdma_usart1_tx);
+	HAL_DMA_DeInit(&hdma_usart1_tx);
 	HAL_UART_DeInit(&huart1);
-	dmaActive = 0;
+	dmaRxActive = 0;
+	dmaTxActive = 0;
+	txBufferQueLen = 0;
 }
 
 void  MX_USART1_DMA_Init()
@@ -108,9 +130,26 @@
 
   __HAL_LINKDMA(&huart1,hdmarx,hdma_usart1_rx);
 
+  hdma_usart1_tx.Instance = DMA2_Stream7;
+  hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
+  hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
+  hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
+  hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
+  hdma_usart1_tx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
+  hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+  hdma_usart1_tx.Init.Mode = DMA_NORMAL;
+  hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
+  hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+  HAL_DMA_Init(&hdma_usart1_tx);
+
+  __HAL_LINKDMA(&huart1,hdmatx,hdma_usart1_tx);
+
+
   /* DMA interrupt init */
-  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
+  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 2, 2);
   HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
+  HAL_NVIC_SetPriority(DMA2_Stream7_IRQn, 2, 1);
+  HAL_NVIC_EnableIRQ(DMA2_Stream7_IRQn);
 }
 
 
@@ -136,7 +175,7 @@
 
 	/* USART6 DMA Init */
 	/* USART6_RX Init */
-	hdma_usart6_rx.Instance = DMA2_Stream2;
+	hdma_usart6_rx.Instance = DMA2_Stream1;
 	hdma_usart6_rx.Init.Channel = DMA_CHANNEL_5;
 	hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
 	hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
@@ -152,7 +191,7 @@
 
 	/* USART6_TX Init */
 	hdma_usart6_tx.Instance = DMA2_Stream6;
-	hdma_usart6_tx.Init.Channel = DMA_CHANNEL_5;
+	hdma_usart6_tx.Init.Channel = DMA_CHANNEL_6;
 	hdma_usart6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
 	hdma_usart6_tx.Init.PeriphInc = DMA_PINC_DISABLE;
 	hdma_usart6_tx.Init.MemInc = DMA_MINC_ENABLE;
@@ -219,8 +258,24 @@
 		indexstr[1] = muxAddress;
 		indexstr[2] = 0x0D;
 		indexstr[3] = 0x0A;
-
-		HAL_UART_Transmit(&huart1,indexstr,4,10);
+		if(!dmaTxActive)
+		{
+			memcpy(txBuffer, indexstr, 4);
+			dmaTxActive = 0;
+			if(HAL_OK == HAL_UART_Transmit_DMA(&huart1,txBuffer,4))
+			{
+				dmaTxActive = 1;
+				while(dmaTxActive)
+				{
+					HAL_Delay(1);
+				}
+			}
+		}
+		else
+		{
+			memcpy(txBufferQue, indexstr, 4);
+			txBufferQueLen = 4;
+		}
 	}
 }
 
@@ -229,13 +284,38 @@
 {
 	uint8_t cmdLength = strlen((char*)cmdString);
 
-	if(cmdLength < 20)		/* A longer string is an indication for a missing 0 termination */
+	if(dmaTxActive == 0)
 	{
-		if(dmaActive == 0)
+		if(cmdLength < CHUNK_SIZE)		/* A longer string is an indication for a missing 0 termination */
+		{
+			if(dmaRxActive == 0)
+			{
+				UART_StartDMA_Receiption();
+			}
+			memcpy(txBuffer, cmdString, cmdLength);
+			if(HAL_OK == HAL_UART_Transmit_DMA(&huart1,txBuffer,cmdLength))
+			{
+				dmaTxActive = 1;
+			}
+		}
+	}
+	else
+	{
+		memcpy(txBufferQue, cmdString, cmdLength);
+		txBufferQueLen = cmdLength;
+	}
+}
+
+void UART_SendCmdUbx(uint8_t *cmd, uint8_t len)
+{
+	if(len < CHUNK_SIZE)		/* A longer string is an indication for a missing 0 termination */
+	{
+		if(dmaRxActive == 0)
 		{
 			UART_StartDMA_Receiption();
 		}
-		HAL_UART_Transmit(&huart1,cmdString,cmdLength,10);
+		memcpy(txBuffer, cmd, len);
+		HAL_UART_Transmit_DMA(&huart1,txBuffer,len);
 	}
 }
 
@@ -268,18 +348,18 @@
 
 void UART_StartDMA_Receiption()
 {
-	if(dmaActive == 0)
+	if(dmaRxActive == 0)
 	{
 		if(HAL_OK == HAL_UART_Receive_DMA (&huart1, &rxBuffer[rxWriteIndex], CHUNK_SIZE))
 		{
-			dmaActive = 1;
+			dmaRxActive = 1;
 		}
 	}
 }
 
 void UART_ChangeBaudrate(uint32_t newBaudrate)
 {
-	uint8_t dmaWasActive = dmaActive;
+	uint8_t dmaWasActive = dmaRxActive;
 //	HAL_DMA_Abort(&hdma_usart1_rx);
 		MX_USART1_UART_DeInit();
 		//HAL_UART_Abort(&huart1);
@@ -290,12 +370,16 @@
 	huart1.Init.BaudRate = newBaudrate;
 	HAL_UART_Init(&huart1);
 	MX_USART1_DMA_Init();
+	HAL_NVIC_SetPriority(USART1_IRQn, 1, 3);
+	HAL_NVIC_EnableIRQ(USART1_IRQn);
+
 	if(dmaWasActive)
 	{
-		memset(rxBuffer,BUFFER_NODATA,sizeof(rxBuffer));
+		clearRxBuffer();
 		rxReadIndex = 0;
 		rxWriteIndex = 0;
-		dmaActive = 0;
+		dmaRxActive = 0;
+		txBufferQueLen = 0;
 		UART_StartDMA_Receiption();
 	}
 }
@@ -304,7 +388,7 @@
 {
     if(huart == &huart1)
     {
-    	dmaActive = 0;
+    	dmaRxActive = 0;
     	rxWriteIndex+=CHUNK_SIZE;
     	if(rxWriteIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
     	{
@@ -316,51 +400,143 @@
     	}
     }
 }
+void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
+{
+	if(huart == &huart1)
+	{
+		dmaTxActive = 0;
+		UART_WriteData();
+		if(txBufferQueLen)
+		{
+			memcpy(txBuffer, txBufferQue, txBufferQueLen);
+			HAL_UART_Transmit_DMA(&huart1,txBuffer,txBufferQueLen);
+			dmaTxActive = 1;
+			txBufferQueLen = 0;
+		}
+	}
+}
 
+uint8_t isEndIndication(uint8_t index)
+{
+	uint8_t ret = 0;
+	if(index % 2)
+	{
+		if(rxBuffer[index] == BUFFER_NODATA_HIGH)
+		{
+			ret = 1;
+		}
+	}
+	else
+	{
+		if(rxBuffer[index] == BUFFER_NODATA_LOW)
+		{
+			ret = 1;
+		}
+	}
+
+	return ret;
+}
 void UART_ReadData(uint8_t sensorType)
 {
 	uint8_t localRX = rxReadIndex;
+	uint8_t futureIndex = rxReadIndex + 1;
+	uint8_t moreData = 0;
 
-	while((rxBuffer[localRX]!=BUFFER_NODATA))
+	if(futureIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
 	{
-		switch (sensorType)
+		futureIndex = 0;
+	}
+
+	if((!isEndIndication(localRX)) || (!isEndIndication(futureIndex)))	do
+	{
+		while((!isEndIndication(localRX)) || (moreData))
 		{
-			case SENSOR_MUX:
-			case SENSOR_DIGO2:	uartO2_ProcessData(rxBuffer[localRX]);
-				break;
-#ifdef ENABLE_CO2_SUPPORT
-			case SENSOR_CO2:	uartCo2_ProcessData(rxBuffer[localRX]);
-				break;
-#endif
-#ifdef ENABLE_SENTINEL_MODE
-			case SENSOR_SENTINEL:	uartSentinel_ProcessData(rxBuffer[localRX]);
-				break;
-#endif
-			default:
-				break;
+			moreData = 0;
+			switch (sensorType)
+			{
+				case SENSOR_MUX:
+				case SENSOR_DIGO2:	uartO2_ProcessData(rxBuffer[localRX]);
+					break;
+	#ifdef ENABLE_CO2_SUPPORT
+				case SENSOR_CO2:	uartCo2_ProcessData(rxBuffer[localRX]);
+					break;
+	#endif
+	#ifdef ENABLE_GNSS_SUPPORT
+					case SENSOR_GNSS:	uartGnss_ProcessData(rxBuffer[localRX]);
+							break;
+	#endif
+	#ifdef ENABLE_SENTINEL_MODE
+				case SENSOR_SENTINEL:	uartSentinel_ProcessData(rxBuffer[localRX]);
+					break;
+	#endif
+				default:
+					break;
+			}
+			if(localRX % 2)
+			{
+				rxBuffer[localRX] = BUFFER_NODATA_HIGH;
+			}
+			else
+			{
+				rxBuffer[localRX] = BUFFER_NODATA_LOW;
+			}
+
+			localRX++;
+			rxReadIndex++;
+			if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+			{
+				localRX = 0;
+				rxReadIndex = 0;
+			}
+			futureIndex++;
+			if(futureIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+			{
+				futureIndex = 0;
+			}
 		}
+		if(!isEndIndication(futureIndex))
+		{
+			moreData = 1;
+		}
+	} while(moreData);
+}
 
-		rxBuffer[localRX] = BUFFER_NODATA;
-		localRX++;
-		rxReadIndex++;
-		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
-		{
-			localRX = 0;
-			rxReadIndex = 0;
-		}
+void UART_WriteData(void)
+{
+	if(huart1.hdmatx->State == HAL_DMA_STATE_READY)
+	{
+		huart1.gState = HAL_UART_STATE_READY;
+		dmaTxActive = 0;
 	}
 }
 
 void UART_FlushRxBuffer(void)
 {
-	while(rxBuffer[rxReadIndex] != BUFFER_NODATA)
+	uint8_t futureIndex = rxReadIndex + 1;
+
+	if(futureIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+	{
+		futureIndex = 0;
+	}
+	while((rxBuffer[rxReadIndex] != BUFFER_NODATA_LOW) && (rxBuffer[futureIndex] != BUFFER_NODATA_HIGH))
 	{
-		rxBuffer[rxReadIndex] = BUFFER_NODATA;
-		rxReadIndex++;
+		if(rxReadIndex % 2)
+		{
+			rxBuffer[rxReadIndex++] = BUFFER_NODATA_HIGH;
+		}
+		else
+		{
+			rxBuffer[rxReadIndex++] = BUFFER_NODATA_LOW;
+		}
 		if(rxReadIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
 		{
 			rxReadIndex = 0;
 		}
+		futureIndex++;
+		if(futureIndex >= CHUNK_SIZE * CHUNKS_PER_BUFFER)
+		{
+			futureIndex = 0;
+		}
 	}
 }
 
@@ -370,7 +546,7 @@
 
 	uint8_t ComState = externalInterface_GetSensorState(sensorId + EXT_INTERFACE_MUX_OFFSET);
 
-	if((ComState == UART_COMMON_INIT) || (ComState == UART_COMMON_IDLE) || (ComState == UART_COMMON_ERROR))
+	if((ComState == UART_COMMON_INIT) || (ComState == UART_COMMON_IDLE) || (ComState == UART_COMMON_ERROR) || (ComState == COMMON_SENSOR_STATE_INVALID))
 	{
 		active = 0;
 	}
--- a/Small_CPU/Src/uartProtocol_Co2.c	Sat Oct 19 20:10:56 2024 +0200
+++ b/Small_CPU/Src/uartProtocol_Co2.c	Mon Oct 28 20:34:58 2024 +0100
@@ -174,7 +174,7 @@
 			}
 		}
 	}
-	if((data == ' ') || (data == '\n'))	/* Abort data detection */
+	else if((data == ' ') || (data == '\n'))	/* Abort data detection */
 	{
 		if(rxState == CO2RX_DataComplete)
 		{
@@ -213,6 +213,13 @@
 			rxState = CO2RX_Ready;
 		}
 	}
+	else
+	{
+		if((rxState >= CO2RX_Data0) && (rxState <= CO2RX_Data4))
+		{
+			rxState = CO2RX_Ready; /* numerical data expected => abort */
+		}
+	}
 	externalInterface_SetSensorState(activeSensor + EXT_INTERFACE_MUX_OFFSET,localComState);
 }
 
--- a/Small_CPU/Src/uartProtocol_O2.c	Sat Oct 19 20:10:56 2024 +0200
+++ b/Small_CPU/Src/uartProtocol_O2.c	Mon Oct 28 20:34:58 2024 +0100
@@ -107,12 +107,10 @@
 		localComState = UART_O2_CHECK;
 		lastComState = UART_O2_CHECK;
 		uartO2_SetupCmd(localComState,cmdString,&cmdLength);
-
+		UART_SendCmdString(cmdString);
 		rxState = O2RX_CONFIRM;
 		respondErrorDetected = 0;
 		digO2Connected = 0;
-
-		UART_StartDMA_Receiption();
 	}
 	else
 	{