cancel
Showing results for 
Search instead for 
Did you mean: 

Full duplex usart data corruption

alexpabouct9
Associate II
Posted on August 12, 2016 at 09:52

I'm currently working on a system with 2 STM32, which communicate with each other via a full duplex USART.

The chips are a STM32F746VG (we'll call MCU1) and STM32F411CE (MCU2). MCU1 uses the DMA for both Tx and Rx. The Rx DMA is configured as a circular buffer. It periodically sends a packet (~30bytes) at 1Khz. MCU2 Rx parsing is done entirely in the interrupt handler, and it uses the DMA for the Tx. It periodically sends a packet (~30 bytes) at 100Hz. I'm currently using the HAL Libraries on both MCU's. The issue i'm having is if the upstream and downstream packets start to overlap (as seen on a oscilloscope). My packets start getting corrupted on both MCU's. Packet corruption is detected by verifying a 16 bit CRC.

Here are extracts of the code on the MCU2

USART+DMA config:


static
void
hw_avionics_usart_init(
void
)

{

__USART1_CLK_ENABLE() ;

__HAL_RCC_DMA2_CLK_ENABLE() ;


// Configure USART PINs

GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_PULLUP;

GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;

GPIO_InitStruct.Alternate = USART_LB2_AF;


GPIO_InitStruct.Pin = USART_LB2_RX_PIN;

HAL_GPIO_Init(USART_LB2_RX_PORT, &GPIO_InitStruct);


GPIO_InitStruct.Pin = USART_LB2_TX_PIN;

HAL_GPIO_Init(USART_LB2_TX_PORT, &GPIO_InitStruct);


// Configure LB2 USART

g_huart_avionics.Instance = USART_AVIONICS;

g_huart_avionics.Init.BaudRate = 1000000;

g_huart_avionics.Init.WordLength = UART_WORDLENGTH_8B;

g_huart_avionics.Init.StopBits = UART_STOPBITS_1;

g_huart_avionics.Init.Parity = UART_PARITY_NONE;

g_huart_avionics.Init.Mode = UART_MODE_TX_RX;

g_huart_avionics.Init.HwFlowCtl = UART_HWCONTROL_NONE;

g_huart_avionics.Init.OverSampling = UART_OVERSAMPLING_16;

HAL_UART_Init(&g_huart_avionics);


// Configure DMA for TX

g_hdma_usart_avionics_tx.Instance = USART_AVIONICS_DMA_STREAM_TX;

g_hdma_usart_avionics_tx.Init.Channel = USART_AVIONICS_DMA_CHANNEL_TX;

g_hdma_usart_avionics_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

g_hdma_usart_avionics_tx.Init.PeriphInc = DMA_PINC_DISABLE;

g_hdma_usart_avionics_tx.Init.MemInc = DMA_MINC_ENABLE;

g_hdma_usart_avionics_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

g_hdma_usart_avionics_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

g_hdma_usart_avionics_tx.Init.Mode = DMA_NORMAL;

g_hdma_usart_avionics_tx.Init.Priority = DMA_PRIORITY_LOW;

g_hdma_usart_avionics_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;

HAL_DMA_Init(&g_hdma_usart_avionics_tx);


__HAL_LINKDMA(&g_huart_avionics, hdmatx, g_hdma_usart_avionics_tx);


// Enable NVIC Interrupt

HAL_NVIC_SetPriority(USART_AVIONICS_IRQ, 0, 0);

HAL_NVIC_EnableIRQ(USART_AVIONICS_IRQ);


HAL_NVIC_SetPriority(USART_AVIONICS_DMA_IRQ_TX, 10, 0);

HAL_NVIC_EnableIRQ(USART_AVIONICS_DMA_IRQ_TX);


// Enable Rx Interrupt request

__HAL_UART_ENABLE_IT(&g_huart_avionics, UART_IT_RXNE);


ge_uart_avionics_tx_semaphore = xSemaphoreCreateBinary();

}

USART and DMA Tx Interrupt handlers:


void
USART_AVIONICS_DMA_IRQ_HANDLER_TX(
void
)

{

BaseType_t xHigherPriorityTaskWoken;

if
(__HAL_DMA_GET_IT_SOURCE(g_huart_avionics.hdmatx, DMA_IT_TC) != RESET)

{

xHigherPriorityTaskWoken = pdFALSE;


// return semaphore

xSemaphoreGiveFromISR(ge_uart_avionics_tx_semaphore,

&xHigherPriorityTaskWoken);


// force context switch

portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}

// Avionics USART TX

HAL_DMA_IRQHandler(g_huart_avionics.hdmatx);

}

void
USART_AVIONICS_IRQ_HANDER(
void
)

{

// AV USART RX Interrupt

uint8_t rx_byte;


bcmd_error_flag_t bcmd_flag;


// check if new rx data interrupt

if
(__HAL_UART_GET_FLAG(&g_huart_avionics, UART_FLAG_RXNE))

{

//read byte

rx_byte = g_huart_avionics.Instance->DR;


//call lightbrdige rx interrupt handler

bcmd_flag = bcmd_parse_byte(&ge_avl_bcmd_obj, rx_byte);


// increment counter if bad crc

if
(bcmd_flag == BCMD_BAD_CRC_FLAG)

{

avl_bcmd_increment_bad_crc();

}

}

else
if
(__HAL_UART_GET_FLAG(&g_huart_avionics, UART_FLAG_ORE))

{

// clear any overrun errors by reading DR

rx_byte = g_huart_avionics.Instance->DR;

}

else

{

HAL_UART_IRQHandler(&g_huart_avionics);

}

}

USART send function (called periodically at 100Hz in a FreeRTOS Task)

1.
static
void
avl_usart_send(
const
uint8_t* tx_buffer, uint8_t size)
2.
{
3.
HAL_UART_Transmit_DMA(&g_huart_avionics, (uint8_t*) tx_buffer, size);
4.
xSemaphoreTake(ge_uart_avionics_tx_semaphore, portMAX_DELAY);
5.
}

The signals as seen on a oscilloscope look clean, which is why im currently focused on the software side. I've also tested the code using the polling USART Tx ''HAL_UART_Transmit'', with the same results. Any help would be very much appreciated! Thanks, Alex #stm32f4-stm32f7-hal-usart
1 REPLY 1
Posted on August 12, 2016 at 14:25

Do  you use multiple transmit buffers or keep using the same one?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..