cancel
Showing results for 
Search instead for 
Did you mean: 

CubeMX initialization for UART DMA TX does not set peripheral address

JBake
Associate

I generated a project using the LL libraries for the STM32L011 as the HAL is far too bloated to use with this part. After porting some known working DMA TX code from an old F103 StdPeriph project, I couldn't get anything to transmit out. What I found was missing was that the initialization function never sets the peripheral address to be the UART's TDR. Calling the following line solves the problem and I believe it should be done in the intialization instead of during the TX function where I have it now from debugging:

LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)&LPUART1->TDR);

My DMA TX function for reference:

void LPUART_DMA_TX(uint8_t* data, uint8_t size)

{

LL_LPUART_DisableDMAReq_TX(LPUART1); // Disable DMA requests from LPUART

LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_2); // Disable DMA channel

LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)&LPUART1->TDR);

while (DMA1_Channel2->CCR & 0x01) // While EN bit is high

__NOP(); // Wait for disable to finish

LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, size);

LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_2, (uint32_t)data); // Set source address

LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_LOW);

LL_DMA_ClearFlag_GI2(DMA1); // Clear global interrupt flag for channel 2

LL_DMA_ClearFlag_TC2(DMA1);

LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2); // Enable transfer complete interrupt

LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2);

LL_LPUART_EnableDMAReq_TX(LPUART1); // Enable DMA requests

LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2); // Enable channel

LL_LPUART_ClearFlag_TC(LPUART1);

}

The generated code from CubeMX is as follows (uses DMA channels 2 and 3 for TX/RX respectively):

/* LPUART1 init function */

static void MX_LPUART1_UART_Init(void)

{

 LL_LPUART_InitTypeDef LPUART_InitStruct;

 LL_GPIO_InitTypeDef GPIO_InitStruct;

 /* Peripheral clock enable */

 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPUART1);

  

 /**LPUART1 GPIO Configuration  

 PA1  ------> LPUART1_TX

 PA3  ------> LPUART1_RX 

 */

 GPIO_InitStruct.Pin = LL_GPIO_PIN_1;

 GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

 GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;

 GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

 GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;

 GPIO_InitStruct.Alternate = LL_GPIO_AF_6;

 LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = LL_GPIO_PIN_3;

 GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;

 GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;

 GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;

 GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;

 GPIO_InitStruct.Alternate = LL_GPIO_AF_6;

 LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 /* LPUART1 DMA Init */

  

 /* LPUART1_TX Init */

 LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_2, LL_DMA_REQUEST_5);

 LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

 LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_LOW);

 LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_NORMAL);

 LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT);

 LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT);

 LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_BYTE);

 LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_BYTE);

 /* LPUART1_RX Init */

 LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_3, LL_DMA_REQUEST_5);

 LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_3, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);

 LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PRIORITY_LOW);

 LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MODE_NORMAL);

 LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PERIPH_NOINCREMENT);

 LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MEMORY_INCREMENT);

 LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_PDATAALIGN_BYTE);

 LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_3, LL_DMA_MDATAALIGN_BYTE);

 /* LPUART1 interrupt Init */

 NVIC_SetPriority(AES_RNG_LPUART1_IRQn, 0);

 NVIC_EnableIRQ(AES_RNG_LPUART1_IRQn);

 LPUART_InitStruct.BaudRate = 57600;

 LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;

 LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;

 LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;

 LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;

 LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;

 LL_LPUART_Init(LPUART1, &LPUART_InitStruct);

}

0 REPLIES 0