2024-08-26 02:07 PM
I am using the DMA to transfer data from UART 1 (Channel 2) and UART 2 (Channel 4). Every once and awhile the data seen on UART 2 which has a lower DMA priority will be "corrupted" by the UART 1 data. I know this because when I disable UART 1 routines, UART 2 receives perfectly everytime. This is never an issue with transmission on UART 2 even when UART 1 is enabled.
This is on the STM32F072CBU6 MCU. Both DMA protocols are initialized identically for UART 1 and UART 2.
I will post most of the code related to these functions.
Any ideas would be greatly appreciated!
NOTE: This is a repost because the last post was marked as spam...
UART Initializations:
uint32_t Tmp;
huart1.Instance = USART1;
STM32_GPIO_Init(RS485_TXD_GPIO_Port, RS485_TXD_Pin, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_HIGH, GPIO_AF1_USART1, 0);
STM32_GPIO_Init(RS485_RXD_GPIO_Port, RS485_RXD_Pin, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_HIGH, GPIO_AF1_USART1, 0);
hdma_usart1_tx.Instance = DMA1_Channel2;
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_tx.Init.Mode = DMA_NORMAL;
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
Tmp = hdma_usart1_tx.Instance->CCR;
Tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | DMA_CCR_DIR));
Tmp |= DMA_MEMORY_TO_PERIPH | DMA_PINC_DISABLE | DMA_MINC_ENABLE |
DMA_PDATAALIGN_BYTE | DMA_MDATAALIGN_BYTE | DMA_NORMAL | DMA_PRIORITY_LOW;
hdma_usart1_tx.Instance->CCR = Tmp;
hdma_usart1_tx.ChannelIndex = (((uint32_t)hdma_usart1_tx.Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2u;
hdma_usart1_tx.DmaBaseAddress = DMA1;
hdma_usart1_tx.XferCpltCallback = NULL;
huart1.hdmatx = &hdma_usart1_tx;
hdma_usart1_tx.Parent = &huart1;
STM32_NVIC_SetPriority(USART1_IRQn, 0, 0);
STM32_NVIC_EnableIRQ(USART1_IRQn);
USART1->CR1 &= ~USART_CR1_UE;
USART1->CR1 = 0x0C;
USART1->CR2 = 0x00;
USART1->CR3 = 0x3000;
USART1->BRR = 417;
USART1->CR1 = 0x2D;
UART IRQ Handler:
uint32_t ISRFlags;
uint32_t ControlReg1its;
ISRFlags = huart->Instance->ISR;
ControlReg1its = huart->Instance->CR1;
//
// Clear Errors - even if there aren't any
//
huart->Instance->ICR = UART_CLEAR_PEF | UART_CLEAR_FEF | UART_CLEAR_NEF | UART_CLEAR_OREF;
/* UART in mode Receiver */
if (huart->Instance == USART1) {
if (((ISRFlags & USART_ISR_RXNE) != 0) && ((ControlReg1its & USART_CR1_RXNEIE) != 0)) {
SerialUsart1.DmaRingBuffer[SerialUsart1.RingBufferIn++] = (uint8_t)huart->Instance->RDR;
return;
}
}
else if (huart->Instance == USART2) {
if (((ISRFlags & USART_ISR_RXNE) != 0) && ((ControlReg1its & USART_CR1_RXNEIE) != 0)) {
SerialUsart2.DmaRingBuffer[SerialUsart2.RingBufferIn++] = (uint8_t)huart->Instance->RDR;
return;
}
}
/* UART in mode Transmitter (transmission end) -----------------------------*/
if (((ISRFlags & USART_ISR_TC) != 0) && ((ControlReg1its & USART_CR1_TCIE) != 0)) {
UART_EndTransmit_IT(huart);
}
DMA Initialization:
uint32_t Tmp;
Tmp = hdma->Instance->CCR;
Tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | DMA_CCR_DIR));
Tmp |= hdma->Init.Direction |
hdma->Init.PeriphInc | hdma->Init.MemInc |
hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
hdma->Init.Mode | hdma->Init.Priority;
hdma->Instance->CCR = Tmp;
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2u;
hdma->DmaBaseAddress = DMA1;
hdma->XferCpltCallback = NULL;
DMA Interrupt Handler:
uint32_t FlagIt = hdma->DmaBaseAddress->ISR;
uint32_t SourceIt = hdma->Instance->CCR;
/* Transfer Complete Interrupt management ***********************************/
if ((RESET != (FlagIt & (DMA_FLAG_TC1 << hdma->ChannelIndex))) && (RESET != (SourceIt & DMA_IT_TC))) {
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0u) {
/* Disable the transfer complete & transfer error interrupts */
/* if the DMA mode is not CIRCULAR */
hdma->Instance->CCR &= ~(DMA_IT_TC | DMA_IT_TE);
}
/* Clear the transfer complete flag */
hdma->DmaBaseAddress->IFCR = DMA_FLAG_TC1 << hdma->ChannelIndex;
if (hdma->XferCpltCallback != NULL) {
/* Transfer complete callback */
hdma->XferCpltCallback(hdma);
}
/* Transfer Error Interrupt management ***************************************/
} else if ((RESET != (FlagIt & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (SourceIt & DMA_IT_TE))) {
/* When a DMA transfer error occurs */
/* reset the processor */
Error_Handler(FILE_DMA, __LINE__);
} else {
}