2021-06-17 09:02 AM
Hello,
I am trying to set the UART5 TX with the DMA. I am using Cube, and in the GUI I selected UART5 to asynchronous, and added DMA for UART5_TX. Then, in the generated code, I added this part as I didn't see initialization for the DMA (inside the MX_DMA_Init()):
/* Peripheral DMA init*/
hdma_uart5_tx.Instance = DMA1_Stream0;
//hdma_uart5_tx.Init.Channel = DMA_CHANNEL_4;
hdma_uart5_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_uart5_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_uart5_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_uart5_tx.Init.PeriphDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart5_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_uart5_tx.Init.Mode = DMA_NORMAL;
hdma_uart5_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_uart5_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_uart5_tx);
__HAL_LINKDMA(&huart5,hdmatx,hdma_uart5_tx);
The Main function, I didn't do much except I added this code in the while(1):
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if (HAL_UART_Transmit_DMA(&huart5,au8ch, 1) == HAL_OK)
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_SET);
}
else
{
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_1, GPIO_PIN_RESET);
}
HAL_Delay(1000);
}
/* USER CODE END 3 */
Which is a code to transmit the first byte of an array. I connected the Nucleo-H753ZI board pins to a terminal software, and I didn't get anything. (Note that I was able to get something without using the DMA). The LED turned ON, which means the function is returning HAL_OK, but still nothing on the screen.
I tried to debug the code, I put a breakpoint in the function "void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)" and it stops there, which means it got the interrupt to send something, but then it goes into this autogenerated code:
if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
{
/* Transfer Error Interrupt management ***************************************/
if ((tmpisr_dma & (DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU))) != 0U)
{
if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != 0U)
{
/* Disable the transfer error interrupt */
((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TE);
/* Clear the transfer error flag */
regs_dma->IFCR = DMA_FLAG_TEIF0_4 << (hdma->StreamIndex & 0x1FU);
/* Update error code */
hdma->ErrorCode |= HAL_DMA_ERROR_TE;
}
}
...
...
...
/* manage error case */
if(hdma->ErrorCode != HAL_DMA_ERROR_NONE)
{
if((hdma->ErrorCode & HAL_DMA_ERROR_TE) != 0U)
{
hdma->State = HAL_DMA_STATE_ABORT;
/* Disable the stream */
__HAL_DMA_DISABLE(hdma);
do
{
if (++count > timeout)
{
break;
}
}
while((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U);
/* Process Unlocked */
__HAL_UNLOCK(hdma);
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_EN) != 0U)
{
/* Change the DMA state to error if DMA disable fails */
hdma->State = HAL_DMA_STATE_ERROR;
}
else
{
/* Change the DMA state to Ready if DMA disable success */
hdma->State = HAL_DMA_STATE_READY;
}
}
if(hdma->XferErrorCallback != NULL)
{
/* Transfer error callback */
hdma->XferErrorCallback(hdma);
}
}
}
Any idea what I may be missing?
Solved! Go to Solution.
2021-06-17 02:18 PM
@Community member and @TDK Thank you both for your help.
I figured it out. I had to build void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) function in which I put the values I need to send, also in the Cube GUI, I had to make it Normal not circular in order to send the data only once.
It is working to send one array now. Thanks!
Karim
2021-06-17 09:17 AM
2021-06-17 09:19 AM
Make sure the au8ch buffer is somewhere accessible by DMA. What memory address is it at?
2021-06-17 09:22 AM
0x2001fff4
I initialized it at the beginning of the main()
2021-06-17 09:26 AM
2021-06-17 09:28 AM
I was reading this link, I tried placing it outside the main as a global var but it was 0x20000000 which is still the same domain.
How can it place it elsewhere?
2021-06-17 09:33 AM
I added this part to my code:
but still getting the same error, the array is now located at 0x20000010 which is still in the same range.
#if defined( __ICCARM__ )
#define DMA_BUFFER \
_Pragma("location=\".dma_buffer\"")
#else
#define DMA_BUFFER \
__attribute__((section(".dma_buffer")))
#endif
DMA_BUFFER unsigned char au8ch[4] = {70,54,35,4};
2021-06-17 09:42 AM
Have you read the article I gave link to? Read it. Reread it. For gcc (which is the default compiler for CubeIDE), you have to read the section about the linker script.
JW
2021-06-17 10:15 AM
Thanks, I read it, and reread it, and re-reread it.. Here is what I did:
in the file: STM32H753ZITX_RAM.ld I changed this code (I put what I changed in the comments below in the file) as recommended in solutions 1 and 2.
I only deployed solution 1 at first and it didn't fix it, so I added this section at the end.
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM_D1 AT> FLASH /* was >RAM AT> RAM_EXEC*/
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM_D1 AT> FLASH /* was >RAM*/
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM_D1 AT> FLASH /* was >RAM*/
/* I also added this part: */
.dma_buffer :
{
*(.dma_buffer)
} >RAM_D2
Then I added the code in the main.c in the previous comment.
#if defined( __ICCARM__ )
#define DMA_BUFFER \
_Pragma("location=\".dma_buffer\"")
#else
#define DMA_BUFFER \
__attribute__((section(".dma_buffer")))
#endif
DMA_BUFFER unsigned char au8ch[4] = {70,54,35,4};
But still, I got nothing. Any advice?
2021-06-17 11:33 AM
> But still, I got nothing.
That's an equivalent of "it does not work" and is not helpful.
So, how are your variables allocated now? What's in the mapfile? How is RAM_D2 set? Do you change the linker script you are actually using?
I don't use Cube/CubeIDE/Eclipse so can't really help in this detail.
JW