2016-08-12 12:52 AM
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
2016-08-12 05:25 AM
Do you use multiple transmit buffers or keep using the same one?