Jelajahi Sumber

UART receive with Circular ring buffer

Juraj Ďuďák 2 hari lalu
induk
melakukan
3772b57248
6 mengubah file dengan 91 tambahan dan 62 penghapusan
  1. 2 2
      .cproject
  2. 5 0
      Core/Inc/main.h
  3. 76 51
      Core/Src/main.c
  4. 2 3
      Core/Src/stm32l0xx_hal_msp.c
  5. 1 1
      Modules/nbus
  6. 5 5
      baModule-slave.ioc

+ 2 - 2
.cproject

@@ -21,7 +21,7 @@
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid.2016087764" name="CPU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid" useByScannerDiscovery="false" value="0" valueType="string"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid.423721789" name="Core" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid" useByScannerDiscovery="false" value="0" valueType="string"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.1415206628" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
-							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.949399491" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32L082KZTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32L0xx/Include | ../Drivers/CMSIS/Include ||  ||  || USE_HAL_DRIVER | STM32L082xx ||  || Drivers | Core/Startup | Core ||  ||  || ${workspace_loc:/${ProjName}/STM32L082KZTX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  || " valueType="string"/>
+							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.949399491" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Debug || true || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32L082KZTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32L0xx/Include | ../Drivers/CMSIS/Include ||  ||  || USE_HAL_DRIVER | STM32L082xx ||  || Drivers | Core/Startup | Core ||  ||  || ${workspace_loc:/${ProjName}/STM32L082KZTX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  ||  || ::" valueType="string"/>
 							<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.546024625" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="32" valueType="string"/>
 							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.922562106" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
 							<builder buildPath="${workspace_loc:/baModule-slave}/Debug" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1586147119" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
@@ -131,7 +131,7 @@
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid.562557773" name="CPU" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_cpuid" useByScannerDiscovery="false" value="0" valueType="string"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid.1525837965" name="Core" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid" useByScannerDiscovery="false" value="0" valueType="string"/>
 							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.1112811640" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
-							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.324250348" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32L082KZTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32L0xx/Include | ../Drivers/CMSIS/Include ||  ||  || USE_HAL_DRIVER | STM32L082xx ||  || Drivers | Core/Startup | Core ||  ||  || ${workspace_loc:/${ProjName}/STM32L082KZTX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  || " valueType="string"/>
+							<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.324250348" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.6 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.option.toolchain.value.workspace || STM32L082KZTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Core/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc/Legacy | ../Drivers/CMSIS/Device/ST/STM32L0xx/Include | ../Drivers/CMSIS/Include ||  ||  || USE_HAL_DRIVER | STM32L082xx ||  || Drivers | Core/Startup | Core ||  ||  || ${workspace_loc:/${ProjName}/STM32L082KZTX_FLASH.ld} || true || NonSecure ||  || secure_nsclib.o ||  || None ||  ||  ||  || ::" valueType="string"/>
 							<option id="com.st.stm32cube.ide.mcu.debug.option.cpuclock.1585210253" name="Cpu clock frequence" superClass="com.st.stm32cube.ide.mcu.debug.option.cpuclock" useByScannerDiscovery="false" value="32" valueType="string"/>
 							<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.552215938" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
 							<builder buildPath="${workspace_loc:/baModule-slave}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1764690039" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>

+ 5 - 0
Core/Inc/main.h

@@ -37,6 +37,11 @@ extern "C" {
 /* Exported types ------------------------------------------------------------*/
 /* USER CODE BEGIN ET */
 
+typedef enum {
+    STATE_WAIT_LEN,
+    STATE_PAYLOAD,
+} ProtocolState;
+
 /* USER CODE END ET */
 
 /* Exported constants --------------------------------------------------------*/

+ 76 - 51
Core/Src/main.c

@@ -89,11 +89,18 @@ static void MX_USART1_UART_Init(void);
 /* Private user code ---------------------------------------------------------*/
 /* USER CODE BEGIN 0 */
 #define MAX_SYSTICK  0xFFFFFFFF
-uint8_t data[BUFF_SIZE];	// tmp read buffer
+
+uint8_t rx_ring_buffer[BUFF_SIZE];
 uint8_t *dataUART;  // pointee for rx_buffer
-volatile uint8_t dataL;
-volatile uint8_t dataI;
+
+// UART DMA related variables
 volatile uint32_t uart_timeout = MAX_SYSTICK;
+volatile uint16_t rx_read_pos = 0; // DAM UART CIRCULAR - tail
+volatile uint8_t msg_len = 0;
+volatile uint8_t msg_idx = 0;
+
+ProtocolState state = STATE_WAIT_LEN;
+
 
 #if MODULE == MODULE_IMU || MODULE == MODULE_DMP
 volatile uint8_t icm_data_ready = 0;
@@ -111,13 +118,12 @@ inline void uart_send(uint8_t *data, int n)
 inline void uart_receive(uint8_t *dataNBUS, int n)
 {
 	dataUART = dataNBUS;
-	dataL = 0;
-	dataI = 0;
-	data[0] = 0;
+	rx_ring_buffer[0] = 0;
 	uart_timeout = HAL_GetTick();
-	HAL_UARTEx_ReceiveToIdle_DMA(&huart1, data, n);
+	HAL_UART_Receive_DMA(&huart1, rx_ring_buffer, n);
 }
 
+
 inline void led_on(){
 	HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
 }
@@ -134,13 +140,73 @@ inline void app_delay(uint8_t ms){
 	HAL_Delay(ms);
 }
 
+
+static uint8_t Parse_Protocol_Byte(uint8_t b) {
+
+	uint8_t packet_finished = 0;
+	// Timeout reset logic
+	if (state != STATE_WAIT_LEN) {
+		if ((HAL_GetTick() - uart_timeout) > NBUS_UART_FRAME_TIMEOUT){
+			state = STATE_WAIT_LEN;
+			msg_len = 0;
+			msg_idx = 0;
+		}
+	}
+
+    switch (state) {
+        case STATE_WAIT_LEN:
+            // Validácia dĺžky (max 128 bajtov, min 4 bajty)
+            if (b > 3 && b < PAYLOAD_SIZE) {
+                msg_len = b;
+                msg_idx = 0;
+                state = STATE_PAYLOAD;
+                uart_timeout = HAL_GetTick(); // Reset timeoutu
+            }
+            break;
+
+
+        case STATE_PAYLOAD:
+        	dataUART[msg_idx++] = b;
+        	uart_timeout = HAL_GetTick(); // Aktualizácia timeoutu pri každom bajte
+
+            if (msg_idx >= msg_len) { // Koniec paketu (podľa definície dĺžky)
+            	nbus_cb_UART_RX(msg_idx);	// callback to nBus, notify message length
+                state = STATE_WAIT_LEN;
+                packet_finished = 1;
+            }
+            break;
+    }
+
+    return packet_finished;
+
+
+}
+
+static void Process_UART_RingBuffer(void) {
+	// Zistíme, kde sa aktuálne nachádza DMA (Head)
+    // CNDTR register obsahuje počet ZOSTÁVAJÚCICH bajtov do konca buffra
+    uint16_t rx_dma_pos = BUFF_SIZE - __HAL_DMA_GET_COUNTER(huart1.hdmarx);
+
+    while (rx_read_pos != rx_dma_pos) {
+        uint8_t byte = rx_ring_buffer[rx_read_pos];
+        rx_read_pos++;
+        if (rx_read_pos >= BUFF_SIZE) {
+            rx_read_pos = 0;
+        }
+
+        if( Parse_Protocol_Byte(byte) != 0){
+        	return;
+        }
+    }
+}
+
 static inline uint8_t loop_callback(nBusStateCallbackType_t state_check) {
 // treba kontrolovat kazdy stav (state_check) zvlast. Moznost doplnit dalsie kontroly
 	if (state_check == CallbackType_SENSOR) {
 #if MODULE == MODULE_IMU || MODULE == MODULE_DMP
 		if(icm_data_ready == 1){
 			icm_data_ready = 0;
-			return 0;  // TEMPORARY DISABLED STATE. interrupt from external sensor: data ready
+			return 0;  // TODO!!!!!!  TEMPORARY DISABLED STATE. interrupt from external sensor: data ready
 		}
 #endif
 
@@ -148,55 +214,16 @@ static inline uint8_t loop_callback(nBusStateCallbackType_t state_check) {
 	}
 
 	if (state_check == CallbackType_UART) {
-		// timeout: 1 - 2 ms
-		if(HAL_GetTick() - 1 > uart_timeout) {
-			dataL = 0;
-			dataI = 0;
-			data[0] = 0;
-			uart_timeout = MAX_SYSTICK;
-			HAL_UARTEx_ReceiveToIdle_DMA(&huart1, data, BUFF_SIZE);
-			return 1;  // UART receive timeout
-		}
-		return 0;
+		Process_UART_RingBuffer();
 	}
 
 	return 0;
 }
 
 //  Application callbacks
-void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
-	HAL_UARTEx_ReceiveToIdle_DMA(huart, data, BUFF_SIZE);
-	uint8_t copy_offset = 0;
-	if (dataL == 0) {
-		uart_timeout = HAL_GetTick();
-		dataL = data[0];
-		dataI = 0;
-		if (Size == 1) {
-			return;
-		}
-
-		Size--;
-		copy_offset = 1;
-	}
-
-	memcpy(&dataUART[dataI], &data[copy_offset], Size);
-
-	dataI += Size;
-	if(dataI >= dataL){
-		nbus_cb_UART_RX(dataI);
-		dataL=0;
-		dataI=0;
-		data[0]=0;
-		uart_timeout = MAX_SYSTICK;
-	}
-}
-
 void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){
-	dataL=0;
-	dataI=0;
-	data[0]=0;
 	uart_timeout = MAX_SYSTICK;
-	HAL_UARTEx_ReceiveToIdle_DMA(huart, data, BUFF_SIZE);
+	HAL_UART_Receive_DMA(huart, rx_ring_buffer, BUFF_SIZE);
 }
 
 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
@@ -244,8 +271,6 @@ int main(void)
   MX_SPI1_Init();
   MX_USART1_UART_Init();
   /* USER CODE BEGIN 2 */
-  dataI=0;
-  dataL=0;
 
 #ifdef MODULE_INIT_IP_ADC
   MX_ADC_Init();

+ 2 - 3
Core/Src/stm32l0xx_hal_msp.c

@@ -17,7 +17,6 @@
   ******************************************************************************
   */
 /* USER CODE END Header */
-
 /* Includes ------------------------------------------------------------------*/
 #include "main.h"
 /* USER CODE BEGIN Includes */
@@ -361,8 +360,8 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
     hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
     hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
     hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
-    hdma_usart1_rx.Init.Mode = DMA_NORMAL;
-    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
+    hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
+    hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
     if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
     {
       Error_Handler();

+ 1 - 1
Modules/nbus

@@ -1 +1 @@
-Subproject commit 219ca744699b12ed7f4a9d51ec05092fe0a433e4
+Subproject commit 61b9ad932d04e24942a86b8378a7baae95e3dd03

+ 5 - 5
baModule-slave.ioc

@@ -37,10 +37,10 @@ Dma.USART1_RX.1.Direction=DMA_PERIPH_TO_MEMORY
 Dma.USART1_RX.1.Instance=DMA1_Channel3
 Dma.USART1_RX.1.MemDataAlignment=DMA_MDATAALIGN_BYTE
 Dma.USART1_RX.1.MemInc=DMA_MINC_ENABLE
-Dma.USART1_RX.1.Mode=DMA_NORMAL
+Dma.USART1_RX.1.Mode=DMA_CIRCULAR
 Dma.USART1_RX.1.PeriphDataAlignment=DMA_PDATAALIGN_BYTE
 Dma.USART1_RX.1.PeriphInc=DMA_PINC_DISABLE
-Dma.USART1_RX.1.Priority=DMA_PRIORITY_LOW
+Dma.USART1_RX.1.Priority=DMA_PRIORITY_MEDIUM
 Dma.USART1_RX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority
 Dma.USART1_TX.2.Direction=DMA_MEMORY_TO_PERIPH
 Dma.USART1_TX.2.Instance=DMA1_Channel2
@@ -97,8 +97,8 @@ Mcu.PinsNb=26
 Mcu.ThirdPartyNb=0
 Mcu.UserConstants=
 Mcu.UserName=STM32L082KZTx
-MxCube.Version=6.16.1
-MxDb.Version=DB.6.0.161
+MxCube.Version=6.17.0
+MxDb.Version=DB.6.0.170
 NVIC.ADC1_COMP_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
 NVIC.DMA1_Channel1_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
 NVIC.DMA1_Channel2_3_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
@@ -198,7 +198,7 @@ ProjectManager.CustomerFirmwarePackage=
 ProjectManager.DefaultFWLocation=true
 ProjectManager.DeletePrevious=true
 ProjectManager.DeviceId=STM32L082KZTx
-ProjectManager.FirmwarePackage=STM32Cube FW_L0 V1.12.3
+ProjectManager.FirmwarePackage=STM32Cube FW_L0 V1.12.4
 ProjectManager.FreePins=false
 ProjectManager.FreePinsContext=
 ProjectManager.HalAssertFull=false