UART DMA TX FIFO sends only single buffer worth of data
Hi,
I'm trying to send data via UART6 TX DMA on STM32F429-Discovery board. All is well, if I send packets of size less than 16 bytes (FIFO buffer size). However, if packet size is larger than 16 bytes, only first 16 are sent and the rest of the data is replaced by 0x00. I.e.
CB 00 01 00 28 00 29 35 32 47 0C 36 34 30 32 15 00 00 00 00
instead of
CB 00 01 00 28 00 29 35 32 47 0C 36 34 30 32 15 16 17 18 89
The initialization code is reasonably straight-forward:
void MX_USART6_UART_Init(void) {
huart6.Instance = USART6;
huart6.Init.BaudRate = 256000;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart6) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {
GPIO_InitTypeDef GPIO_InitStruct;
if (uartHandle->Instance == USART6) {
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_RCC_USART6_CLK_ENABLE();
/**USART6 GPIO Configuration
PC6 ------> USART6_TX
PC7 ------> USART6_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* USART6 DMA Init */
/* USART6_RX Init */
hdma_usart6_rx.Instance = USARTx_RX_DMA_STREAM;
hdma_usart6_rx.Init.Channel = USARTx_RX_DMA_CHANNEL;
hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart6_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart6_rx.Init.Mode = DMA_NORMAL;
hdma_usart6_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_usart6_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
if (HAL_DMA_Init(&hdma_usart6_rx) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(uartHandle, hdmarx, hdma_usart6_rx);
/* USART6_TX Init */
hdma_usart6_tx.Instance = USARTx_TX_DMA_STREAM;
hdma_usart6_tx.Init.Channel = USARTx_TX_DMA_CHANNEL;
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;
hdma_usart6_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart6_tx.Init.Mode = DMA_NORMAL;
hdma_usart6_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_usart6_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
if (HAL_DMA_Init(&hdma_usart6_tx) != HAL_OK) {
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(uartHandle, hdmatx, hdma_usart6_tx);
/* NVIC configuration for DMA transfer complete interrupt (USARTx_TX) */
HAL_NVIC_SetPriority(USARTx_DMA_TX_IRQn, 4, 1);
HAL_NVIC_EnableIRQ(USARTx_DMA_TX_IRQn);
/* NVIC configuration for DMA transfer complete interrupt (USARTx_RX) */
HAL_NVIC_SetPriority(USARTx_DMA_RX_IRQn, 3, 2);
HAL_NVIC_EnableIRQ(USARTx_DMA_RX_IRQn);
/* NVIC configuration for USART TC interrupt */
HAL_NVIC_SetPriority(USARTx_IRQn, 3, 1);
HAL_NVIC_EnableIRQ(USARTx_IRQn);
/* Idle line detection interrupt for packets smaller than RX_BUFFER_SIZE */
__HAL_UART_ENABLE_IT(&huart6, UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart6, UART_IT_RXNE);
__HAL_UART_CLEAR_IDLEFLAG(&huart6);
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) {
if (uartHandle->Instance == USART6) {
__HAL_RCC_USART1_CLK_DISABLE();
/**USART6 GPIO Configuration
PC6 ------> USART6_TX
PC7 ------> USART6_RX
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_6 | GPIO_PIN_7);
/* USART6 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmarx);
HAL_DMA_DeInit(uartHandle->hdmatx);
}
}
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) {
__asm("nop");
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
__asm("nop");
}After assembling the packet, I tried sending it in blocking, followed by DMA mode, using:
HAL_UART_Transmit(&huart6, packet, len, 100);
HAL_UART_Transmit_DMA(&huart6, packet, len);And response is, as always:
CB 00 01 00 28 00 29 35 32 47 0C 36 34 30 32 15 16 17 18 89
CB 00 01 00 28 00 29 35 32 47 0C 36 34 30 32 15 00 00 00 00
I checked the values passed to TransmitDMA(), they seem correct. Even the memory at addresses used is correct.
What is interesting, that if I step into SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); in stm32f4xx_hal_uart.c:919, it transmits just fine. If I break there and just resume, it still loses trailing bits.
