2017-06-15 04:00 AM
Dear community,
I used CubeMX to setup a project for UART DMA transfers RX and TX. Apart from my protocol logic, I added two callbacks:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
rx_cplt=true;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *UartHandle)
{
tx_cplt=true;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
and start transfers with calls to
HAL_UART_Receive_DMA(&huart2, (uint8_t *)buf, len);
HAL_UART_Transmit_DMA(&huart2, (uint8_t *)x, len)�?�?�?�?
Both work fine in the sense that the data is transmitted, as I can see from logic analyzer and host side. But the problem is, that only the Rx Callback is called after transfer has finished.
I walked through the source code with debugger and found that the interrupt for TX complete is actually triggered, but the callback function is never called from HAL implementation. I checked the file 'stm32l4xx_hal_uart.c' and found the following function, which is called after the UART DMA TX transfer has completed:
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent);
/* DMA Normal mode */
if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) )
{
huart->TxXferCount = 0;
/* Disable the DMA transfer for transmit request by resetting the DMAT bit
in the UART CR3 register */
CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
/* Enable the UART Transmit Complete Interrupt */
SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
}
/* DMA Circular mode */
else
{
HAL_UART_TxCpltCallback(huart);
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
Essentially, this tells me, that when in normal mode (not circular), the registered callback is never executed. Is this a bug in the HAL implementation?
After adding the callback in the code executed if normal mode is activated, everything works like a charm. I would prefer not to change the HAL library code, though.
Has anybody experienced this problem before? Am I using the driver correctly?
You can find the complete source code of my application in the attachment.
Cheers,
Malte
#uart-tx #uart #dmaSolved! Go to Solution.
2018-02-25 01:21 PM
ganderson
, great for sharingthis!Anyway, yes, I've found my workaround a long time ago. Here it is: I used Low Layer drivers. I found that (UART specifically) HAL drivers are much to complicated and 'undeterministic', and since Low Layer is actually very simple and straight forward, I managed to rewrite whole communication part of my project in a matter of few hours. I even made my own simple data protocol for communication with PC master.
Here you can read more about it:
https://damogranlabs.com/2017/12/sdp-simple-data-protocol/
Note: If I conclude by myself, there might be a certain 'fear' of Low Layer drivers - since they are described and recommended only for experienced users... Well, good news, I think they are even simpler than HAL - simpler in terms of transparency and what is actually going on with peripheral. Really straightforward... So, to all of you who are not sure if LL is the right path: GO FOR IT! You can always return to HAL.
2018-03-09 07:47 AM
What was your solution? I think I am facing the same thing, though the code I had worked for years using the 1.1.2 version of the HAL. After updating to the current one, we started having UART issues.
2018-03-09 08:56 AM
I suggest you read my last reply, I switched to LL. At the time the problem was recognised, I also realised, I don't really need DMA. Anyway, if I would have to do it know, I wouldn't hesitate to use LL.
Good luck!2018-03-09 09:02 AM
Oops. I saw that reply and didn't realize it was from you. Thanks! I'll have to check out the LL_ stuff.
2018-03-09 09:10 AM
Are you aware of any HAL changed in the UART code that required altering program code? We had code in use for 3 years running the 1.1.2 HAL, but after updating to the current one, it no longer works. (If I swap out the .c/.h UART file to the old ones, it works again, so I expect some new steps are just required now to set it up.)
From debugging, I think the IRQ is just not firing. We have four UARTs in user, and two work fine, but USART1/USART2 seem to get one TX IRQ on init, then nothing after that.
My code seems to mirror the example code from the current CUBE zip file for an F2 eval board.
2018-03-12 08:10 AM
,
,
I am trying to track down something that changed after the 1.1.2 version of the HAL which makes our existing UART code (DMA_NORMAL) not work.
In the old UART code, it was:
, , , /* Enable the UART Transmit Complete Interrupt */
,
, , , __HAL_UART_ENABLE_IT(huart, UART_IT_TC),And currently it is the code you mention.
♯ define UART_IT_TC , , , , , , , , , , , , , , , , , , , , , , ((uint32_t)(UART_CR1_REG_INDEX <,<, 28U | USART_CR1_TCIE))
versus
♯ define USART_CR1_TCIE_Pos , , , , , , , , , , , (6U) , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
,
♯ define USART_CR1_TCIE_Msk , , , , , , , , , , , (0x1U <,<, USART_CR1_TCIE_Pos) , , , , , , , , , , , , /*!<, 0x00000040 */,
♯ define USART_CR1_TCIE , , , , , , , , , , , , , , , USART_CR1_TCIE_Msk , , , , , , , , , , , , , , , , , , , , , , /*!<,Transmission Complete Interrupt Enable */Since the situation we are seeing involves the IRQ handler never getting called, I have been looking specifically at UART and DMA IRQ code changes. I will look into this one further. Thanks.
We can get our code working (seemingly) fine just by using the old versions of ,stm32f2xx_hal_uart.h and stm32f2xx_hal_uart.c. There is something in the 1.1.3 Release notes that says '
The following changes done on the HAL drivers require an update on the application code based on HAL V1.1.2
' with specific notes for UART, but the steps they describe seem to be what was already being done. There are notes regarding DMA and UART, so I expect I am just not understanding something. My code matches an F2 eval board DMA example, as well.Or we are the only folks ever to use this particular UART/DMA config.
Any pointers would be greatly appreciated.
2021-07-26 06:57 AM
Thank you , this is indeed a bug in the HAL, and I just ran into it myself. Setting
SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
Just after the HAL_UART_Transmit_DMA() call fixed it for me.
I do have many high priority interrupts going on, so your analysis is spot on. I wish ST would fix this bug as it has wasted a day of my time tracking it down.
Note my test program, that was standalone, of course worked perfectly as there were no other interrupts to delay it.