cancel
Showing results for 
Search instead for 
Did you mean: 

usart.c

MLudw.1
Associate

I want to use the DMA for receiving data over USART. I have configured the DMA as a circular Buffer. To detect the end of the USART package I use the receiver time out.

My Problem is, that when the receiver time out interrupt is triggered, not all Bytes are copied from the USART to the DMA Buffer. A few random Bytes remain the same as before. I know, that the DMA still increment the address, because I send an image and the rest of the image is not shifted.

Does anybody know what problem this could be?

I use a STM32f MCU and I have generated the basic DMA and USART configuration with the CubeMX software.

My interrupt handler

void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
	/* check for receive timeout interrupt */
	if( huart3.Instance->ISR & USART_ISR_RTOF ) {
		/* clear interrupt */
		__HAL_UART_CLEAR_FLAG(&huart3, USART_ICR_RTOCF);
		ToF_Rx_Timeout_Callback( );
	}
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
}
/* UART rx callback */
void ToF_Rx_Timeout_Callback( void ) {
	static size_t old_pos;
	size_t pos;
	BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* Initialised to pdFALSE. */
	pos = sizeof(ucDmaRxBuffer) - huart3.hdmarx->Instance->NDTR;
	if(pos != old_pos)
	{
		if(pos > old_pos)
		{
			uint16_t xBytesSent = xMessageBufferSendFromISR( 	xRxMessageBuffer,(void*) &ucDmaRxBuffer[old_pos],	pos-old_pos, &xHigherPriorityTaskWoken );
		}
		else
		{
			memcpy(&ucMsgRxTemp[0],&ucDmaRxBuffer[old_pos],sizeof(ucDmaRxBuffer)-old_pos);
			memcpy(&ucMsgRxTemp[sizeof(ucDmaRxBuffer)-old_pos],&ucDmaRxBuffer[0],pos);
			uint16_t xBytesSent = xMessageBufferSendFromISR( 	xRxMessageBuffer,(void*) ucMsgRxTemp, pos+sizeof(ucDmaRxBuffer)-old_pos, &xHigherPriorityTaskWoken );
		}
	}
	old_pos = pos;
	if(old_pos == sizeof(ucDmaRxBuffer))
	{
		old_pos = 0;
	}
	/* switch context if higher priority task is waiting on data */
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken );	
}

Attached is the USART initialization.

1 ACCEPTED SOLUTION

Accepted Solutions

The cache should work consistently with ARM's implementation for all CM7, see TRM and other materials they publish. ST has a "Programming Manual", but most of this stuff is covered by classic CPU Design/Architecture texts. ARM doesn't spend any transistors to snoop bus traffic or protect the unwary.

The the F767 you have 128 KB of DTCM-RAM, that should work transparently. For other memories look at

SCB_InvalidateDCache_by_Addr() < Nuke CPU side cache/buffers

SCB_CleanDCache_by_Addr() <- Flush to memory

These operate on 32-BYTE blocks of memory, your buffer should be similarly aligned, and sized.

InvalidateDCache has very nasty side-effects/collateral damage if not paying attention

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

View solution in original post

3 REPLIES 3

What part?

On the CM7's you might need to manage the cache behaviour

Should probably yield out of the IRQHandler directly, otherwise the NVIC could block subsequent interrupts.

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

I use a STM32F769NI (oops the 7 got lost in the description).

When I disable the I- and D-Cache in the initialization process it works. Thank you for the hint with the cache.

How should I manage the cache? Do you have any recommended resources where I can look up how to manage the cache correctly?

I have no experience in using the cache.

Thank you for your help

The cache should work consistently with ARM's implementation for all CM7, see TRM and other materials they publish. ST has a "Programming Manual", but most of this stuff is covered by classic CPU Design/Architecture texts. ARM doesn't spend any transistors to snoop bus traffic or protect the unwary.

The the F767 you have 128 KB of DTCM-RAM, that should work transparently. For other memories look at

SCB_InvalidateDCache_by_Addr() < Nuke CPU side cache/buffers

SCB_CleanDCache_by_Addr() <- Flush to memory

These operate on 32-BYTE blocks of memory, your buffer should be similarly aligned, and sized.

InvalidateDCache has very nasty side-effects/collateral damage if not paying attention

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