2020-11-13 03:10 AM
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.
Solved! Go to Solution.
2020-11-13 01:19 PM
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
2020-11-13 05:11 AM
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.
2020-11-13 07:44 AM
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
2020-11-13 01:19 PM
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