From 2e0eebb47a695a8f67d02b6aa17103f39612cd9a Mon Sep 17 00:00:00 2001 From: EmanuelFeru Date: Tue, 23 Jun 2020 19:56:16 +0200 Subject: [PATCH] Improved UART error recovery - In case of an Rx error instead of stopping the complete UART, only the Rx DMA is aborted and restarted. --- Inc/config.h | 3 +-- Inc/defines.h | 4 +--- Inc/util.h | 33 ++++++++++++++++++--------------- Src/util.c | 25 +++++++++++++++++++++---- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/Inc/config.h b/Inc/config.h index c5d8bd2..6c47410 100644 --- a/Inc/config.h +++ b/Inc/config.h @@ -73,9 +73,8 @@ #define USART_MAIN_BAUD 38400 // [bit/s] MAIN Serial Tx/Rx baud rate #endif #define SERIAL_START_FRAME 0xABCD // [-] Start frame definition for reliable serial communication -#define SERIAL_TIMEOUT 500 // [-] Number of wrong received data for Serial timeout detection. Depends on DELAY_IN_MAIN_LOOP #define SERIAL_BUFFER_SIZE 64 // [bytes] Size of Serial Rx buffer. Make sure it is always larger than the 'Feedback' structure size - +#define SERIAL_TIMEOUT 600 // [-] Number of wrong received data for Serial timeout detection. Depends on DELAY_IN_MAIN_LOOP /* ==================================== VALIDATE SETTINGS ==================================== */ #if defined(SERIAL_DEBUG) && defined(SERIAL_CONTROL) diff --git a/Inc/defines.h b/Inc/defines.h index 04560e8..dde9dad 100644 --- a/Inc/defines.h +++ b/Inc/defines.h @@ -27,8 +27,6 @@ #include "config.h" #include "util.h" -#define UART_DMA_CHANNEL_TX DMA1_Channel7 -#define UART_DMA_CHANNEL_RX DMA1_Channel6 #if defined(PRINTF_FLOAT_SUPPORT) && defined(SERIAL_DEBUG) && defined(__GNUC__) asm(".global _printf_float"); // this is the magic trick for printf to support float. Warning: It will increase code considerably! Better to avoid! @@ -135,4 +133,4 @@ typedef struct { int16_t temp; } MPU_Data; -#endif +#endif // DEFINES_H diff --git a/Inc/util.h b/Inc/util.h index dc2f377..3725a78 100644 --- a/Inc/util.h +++ b/Inc/util.h @@ -22,23 +22,9 @@ #define UTIL_H #include -#include "defines.h" -/* general functions */ -void consoleLog(char *message); -void get_tick_count_ms(unsigned long *count); -void intro_demo_led(uint32_t tDelay); - -/* input initialization function */ -void input_init(void); - -/* usart read functions */ -void usart_rx_check(void); - -#ifdef SERIAL_DEBUG -void usart_process_debug(uint8_t *userCommand, uint32_t len); -#endif +/* Rx Structures USART */ #ifdef SERIAL_CONTROL typedef struct{ uint16_t start; @@ -61,8 +47,25 @@ typedef struct{ uint16_t cmdLed; uint16_t checksum; } SerialFeedback; +#endif + +/* general functions */ +void consoleLog(char *message); +void get_tick_count_ms(unsigned long *count); +void intro_demo_led(uint32_t tDelay); + +/* input initialization function */ +void input_init(void); + +/* usart read functions */ +void usart_rx_check(void); +#ifdef SERIAL_DEBUG +void usart_process_debug(uint8_t *userCommand, uint32_t len); +#endif +#ifdef SERIAL_FEEDBACK void usart_process_data(SerialFeedback *Feedback_in, SerialFeedback *Feedback_out); #endif +void UART_EndRxTransfer(UART_HandleTypeDef *huart); /* i2c write/read functions */ int8_t i2c_writeBytes(uint8_t slaveAddr, uint8_t regAddr, uint8_t length, uint8_t *data); diff --git a/Src/util.c b/Src/util.c index 400163a..669e340 100644 --- a/Src/util.c +++ b/Src/util.c @@ -39,6 +39,7 @@ SerialSideboard Sideboard; #if defined(SERIAL_DEBUG) || defined(SERIAL_FEEDBACK) static uint8_t rx_buffer[SERIAL_BUFFER_SIZE]; // USART Rx DMA circular buffer static uint32_t rx_buffer_len = ARRAY_LEN(rx_buffer); +static uint32_t old_pos; #endif #ifdef SERIAL_FEEDBACK @@ -155,7 +156,6 @@ void input_init(void) { void usart_rx_check(void) { #ifdef SERIAL_DEBUG - static uint32_t old_pos; uint32_t pos; pos = rx_buffer_len - __HAL_DMA_GET_COUNTER(huart2.hdmarx); // Calculate current position in buffer, Rx: DMA1_Channel6->CNDTR, Tx: DMA1_Channel7 @@ -170,14 +170,12 @@ void usart_rx_check(void) } } old_pos = pos; // Updated old position - if (old_pos == rx_buffer_len) { // Check and manually update if we reached end of buffer old_pos = 0; } #endif // SERIAL_DEBUG #ifdef SERIAL_FEEDBACK - static uint32_t old_pos; uint32_t pos; uint8_t *ptr; pos = rx_buffer_len - __HAL_DMA_GET_COUNTER(huart2.hdmarx); // Calculate current position in buffer, Rx: DMA1_Channel6->CNDTR, Tx: DMA1_Channel7 @@ -247,11 +245,30 @@ void usart_process_data(SerialFeedback *Feedback_in, SerialFeedback *Feedback_ou void HAL_UART_ErrorCallback(UART_HandleTypeDef *uartHandle) { #if defined(SERIAL_DEBUG) || defined(SERIAL_FEEDBACK) if(uartHandle->Instance == USART2) { - HAL_UART_Receive_DMA (uartHandle, (uint8_t *)rx_buffer, sizeof(rx_buffer)); + HAL_DMA_Abort(uartHandle->hdmarx); + UART_EndRxTransfer(uartHandle); + HAL_UART_Receive_DMA(uartHandle, (uint8_t *)rx_buffer, sizeof(rx_buffer)); + old_pos = 0; } #endif } +/** + * @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion). + * @param huart: UART handle. + * @retval None + */ +void UART_EndRxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable RXNE (Interrupt Enable) and PE (Parity Error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + /* Disable EIE (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; +} + /* =========================== I2C WRITE Functions =========================== */ /*