2017-02-28 01:28 PM
Hello! I have a problem with using usart transmit function twice in main program on STM32F4/
STM32
F0. First transmition should be with DMA and after it data should be send in blocking mode without using DMA. Problem is that I have to use the same usart module for each of transmitions and there is a conflict because using DMA requires USART global interrupts to be enabled and transmition in blocking mode doesn't work properly when the interrupts are enabled. I would be very grateful if you coud give me some information or any suggestions what I couls do to resolve my problem.#stm32f4-usart #stm32f4-discovery #stm32f4 #stm32f0-discovery #stm32f4-dma-usart #stm32f0-usart2017-03-01 02:47 PM
I don't quite understand your description. Please try to restate it.
Why do you think DMA requires USART interrupts to be enabled?
JW
2017-03-01 03:20 PM
Can you post your USART configuration?
Do you use circular buffer in DMA configuration?
2017-03-02 01:26 AM
The problem is that when I don't enable usart global interrupts, the transmit DMA function doesn't work, I mean there is no transmited data.
Only if I enable it, I can transmit data to my PC. Another problem is that if I enable the interrupts
HAL_UART_Transmit function leaves out some of data to send which it has already received, beacause the performing time is much longer (about 1ms).
I would like to make such a program:
HAL_UART_Receive(&huart1,UART1TX_Buffer,16,10);
HAL_UART_Transmit_DMA(&huart3,UART3TX_Buffer,16);
.
.
.
HAL_UART_Transmit(&huart3,UART3TX_Buffer,16,10);
In this configuration the performing time seems to be much longer then 1ms (I can see it on a scope in MATLAB.
I don't have any idea why it happens like that.
2017-03-02 01:30 AM
For
HAL_UART_Transmit_DMA I use normal DMA mode.
My USART configuration:
static void MX_USART1_UART_Init(void)
{huart1.Instance = USART1;
huart1.Init.BaudRate = 512000; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT; huart1.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); }}
and DMA for USART TX configuration:
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; if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK) { Error_Handler(); }__HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);
2017-03-03 09:40 AM
Hi all,
I could try to explain requirement for having USARTx interrupt to be enabled at NVIC level in case of TX DMA (normal mode), (for example by calling : HAL_NVIC_EnableIRQ(USARTx_IRQn); )
From DMA point of view, a transmit DMA sequence is considered as completed once last data is pushed in TDR. Then, DMA notifies USART of this transfer completion. Prior calling user DMA transfer complete callback (HAL_UART_TxCpltCallback), HAL usart code needs to ensure that in addition to have been loaded into TDR, data has also been transmitted. TC interrupt is used for that, instead of having a blocking wait on TC flag to be set.
This does not mean that user code has to enable some interrupts in USART registers to be able to use HAL DMA Transmit services, it is all handled within HAL code.
Now, regarding your use case, nothing prevents in my opinion, to perform USART transmit in blocking mode, after having used the DMA. it should be able to work. Just need to ensure that DMA transmit is complete (HAL_UART_TxCpltCallback has been called), prior calling HAL_UART_Transmit(&huart3,UART3TX_Buffer,16,10);
It is sure that use of HAL_UART_Transmit() might require more time than using HAL_UART_Transmit_DMA(), but there should be no problem of loss data or similar issues.
Hope this helps.
Regards
Guenael
2017-03-06 04:46 AM
Thank you for your answer but what if when I don't enable usart interrupts and it is the only one modification and DMA transmition doesn't work?
Moreover if I wait for TC flag in DMA ISR register it takes much more time to send data in DMA mode because it wait long time for this flag.
Have you any ideas why it happens?
2017-03-06 04:58 AM
Writing that DMA mode doesn't work, I mean that if I make suche a program, for example:
uint8_t tx_buff[]={0,1,2,3,4,5,6,7,8,9};
uint8_t rx_buff[10];while(1){
HAL_UART_Receive_DMA(&huart1,rx_buff,10);
HAL_UART_Transmit_DMA(&huart1,tx_buff,10);}
and don't enable global usart interrupts it sends me only one frame and nothing else.
2017-03-06 05:54 AM
Hi
Bartnik.Katarzyna
,This is corresponding to what I tried to explain in my previous posts : Transmission in DMA mode on USARTx, requires USARTx IRQ to be enabled. Tranmission process will enable TC interrupt when last data has been loaded in TDR by DMA, and then, on TC interrupt, transmission will be considered as complete.
If USART IRQ is not enabled, no interrupt will occur, and the, DMA process will remain in Busy state, i.e. not able to start a new process.
HAL_UART_Transmit_DMA (and HAL_UART_Receive_DMA) proces are not blocking : this means that when function code is executed (when you exit function code), transfer is programmed, maybe started, but not executed yet.
In above code section you wrote, if USARTx IRQ is not enabled :
What you need is :
For more details, you could have a look to code examples provided in STM32Cube firmware packages. (for example, for F0 serie, please look into Firmware\Projects\STM32F072B-Discovery\Examples\UART\UART_TwoBoards_ComDMA projects, for having an example of code using USART/UART DMA services). Example highlights the fact that DMA transmit process is conly considered as completed in main(), when a global variable is set. setting of this variable is done in HAL_UART_TxCpltCallback() Tx complete callback.
This example should be available for other targets/series.
Hope this helps.
Regards
Guenael
2017-03-07 02:09 AM
Hi,
Sorry I didn't understand at the first time. I tried to use callback but it turned out that that
HAL_UART_TxCpltCallback() is not called in dma normal mode. There is only USART_DMATransmitCplt() called and there is cleared this bit:
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
So in this case I tried to use such a loop after dma transmit function:
while ((huart1.Instance->CR3 & USART_CR3_DMAT)!=0);Now, my program looks like that (in TIM_IRQhandler):
/sin wave calculating/
/some memcpy functions/
HAL_UART_Transmit_DMA(&huart1,UART1TX_Buffer,16);
while ((huart1.Instance->CR3 & USART_CR3_DMAT)!=0); UART2Rx_Receive(UART3_RX_temp_buffer, 8);/some memcpy functions/
HAL_UART_Transmit_DMA(&huart1,UART1TX_Buffer,16);
while ((huart1.Instance->CR3 & USART_CR3_DMAT)!=0);
As a result, I get such figures in MATLAB host:
These are sin waves get from another stm. Something like that happens only if I use blocking mode with usart global interrupts (which are not necessary for blocking mode but I need them for DMA and if I have each of modes used in one main program I have to enable the interrupts) or if I wait for clearing one of flags behind the information about transmit complete.