cancel
Showing results for 
Search instead for 
Did you mean: 

UART+DMA sends data disordered or resends it. Is it a variable type problem?

SGonz.2
Associate II

Hello!

I'm working this UART+DMA with idle detection and ring buffer. My STM32F4707VET6 receives data from a sensor and then sends it by USB, the data received by USB should look like this:

$1651500,-5,-228,-988,-3,-217,-976,-102

$1651510,-4,-228,-987,-3,-216,-975,-105

$1651520,-6,-229,-988,-5,-217,-976,-114

$1651530,-5,-229,-987,-4,-217,-975,-110

$1651540,-6,-227,-987,-5,-215,-975,-129

$1651550,-6,-229,-988,-4,-218,-976,-119

But I receive this:

$1651500,-5,-228,-988,-3,-217,-976,-102

$1651510,-4,-228,-987,-3,-216,-975,-105

$1651520,-6,-229,-988,-5,-217,-976,-114

-987,-3,-216,-975,-105

$1651520,-6,-229,-988,-5,-217,-976,-114

$1651530,-5,-229,-987,-4,-217,-975,-110

$1651510,-4,-228,-987,-3,-216,-975,-105

$1651520,-6,-229,-988,-5,-217,-976,-114

I truncated the data because every sample is around 250-300 characters(variable), 50 samples every second at 115200 baudrate. And I checked that the sensor sends its data properly.

I wonder what may be causing this problem. I think maybe is some type of data I'm using on my code but I can't find it.

This is my ring buffer or callback snippet. I post this code because this is how my STM32 receives(possible the problem is here) and sends data:

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
	// Timer and RX indicator LEDs
	__HAL_TIM_SetCounter(&htim2, 0);						// Reset Timer2
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);	// Turn on LED 2 - UART Rx LED
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET);     // Turn off LED 3 - Timer LED
	if(huart->Instance == USART1){	// In USART 1
		static uint8_t old_pos1 = 0;
		uint8_t *ptemp1;
		uint32_t i;
		// Ring buffer management
		if (Size != old_pos1){  	// If buffer changed
			if (Size > old_pos1){
				ReceivedChars1 = Size - old_pos1;
				for (i = 0; i < ReceivedChars1; i++){
					pBufferReadyForUser1[i] = RXBufferUser1[old_pos1 + i];
				}
			}else{					// Buffer overflows
				ReceivedChars1 = RX_BUFFER_SIZE - old_pos1;
				for (i = 0; i < ReceivedChars1; i++){
					pBufferReadyForUser1[i] = RXBufferUser1[old_pos1 + i];
				}
				if (Size > 0){
					for (i = 0; i < Size; i++){
						pBufferReadyForUser1[ReceivedChars1 + i] = RXBufferUser1[i];
					}
					ReceivedChars1 += Size;
				}
			}
			// User data process and buffer & pointers update
			UserDataTreatment(huart, pBufferReadyForUser1, ReceivedChars1);
			ptemp1 = pBufferReadyForUser1;
			pBufferReadyForUser1 = pBufferReadyForReception1;
			pBufferReadyForReception1 = ptemp1;
		}
	  // Buffer position(pointer) update
	  old_pos1 = Size;
	}
	// Turn off Rx indicator LED
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);	// Turn off LED 2 - UART Rx LED
}

And my user data treatment function, once the data is received it sends by USB:

void UserDataTreatment(UART_HandleTypeDef *huart, uint8_t* pData, uint16_t Size){
	if(huart->Instance == USART1){			// If USART1
		__HAL_TIM_SetCounter(&htim2, 0);	// Reset Timer2
		CDC_Transmit_FS(pData, Size);		// Send USB data
	}
}

I'm using the example from: https://github.com/STMicroelectronics/STM32CubeF4/tree/master/Projects/STM32446E-Nucleo/Examples/UART/UART_ReceptionToIdle_CircularDMA

I also added some features like activity LEDs and a timer to send a special message if no UART messages are received in a few seconds, but I think they are not relevant in the problem. Anyways, tell me to upload them If you think you need them.

Thank you!

2 REPLIES 2

You say Send, and then show Rx code. Not really looking to unpack the logic of others code/implementations.

For Tx, you'd need to be aware that the buffer can be changed whilst the DMA is active, so typically one uses a ping-pong buffer, or locks the active buffer, and release/reuse only when completed. DMA IRQs can service the HT (Half Transfer) and TC (Transfer Complete) interrupts.

For Rx, watch for the data being "volatile", as it is changed outside of program flow/execution, and beyond the view of the processor.

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

Sorry, because I'm echoing data maybe my choice of words wasn't good. I posted the Rx because possibly the problem is there in how I receive and prepare the data to be sent. The Tx part is very simple and relies on the Rx.

Thank you for your answer! I will try the volatile data and then lock the active buffer.