2021-04-01 05:00 AM
Dear ST Community,
I would like to set up the USART1 and DMA2 in a way, so that the DMA automatically stores the data received by the USART to a buffer variable.
To achieve that I used STM32CubeMX to generate the configuration code utilizing the Low Level- library and added some necessary commands.
Without DMA request enabled the USART1_IRQHandler is entered and via the debugger I can read the expected data within the USART1->RDR register. With the DMA request enabled neither the USART nor the DMA IRQHandler are accessed. Therefore, I suspect that my problem is that with the DMA Request enabled no interrupt is issued when sending data.
If you can find problems with my code I would really appreciate your answers.
The compiler otimization flag is set to -O0. The code is as follows:
Declaration of the buffer variable:
__attribute__ ((section(".buffers"), used))
uint8_t usart1_rx_buffer[10];
with the key .buffers is mapped to the SRAM memory address 0x38000000 in the linker script according to https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices:
.buffers(NOLOAD) : {
. = ALIGN(4);
*(.buffers*)
} > RAM_D3
Commands within the main function:
LL_APB4_GRP1_EnableClock(LL_APB4_GRP1_PERIPH_SYSCFG);
NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART1_UART_Init();
while (1)
{
__asm("nop");
}
SystemClock_Config():
LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_4)
{
}
LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY);
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0);
LL_RCC_HSI_Enable();
/* Wait till HSI is ready */
while(LL_RCC_HSI_IsReady() != 1)
{
}
LL_RCC_HSI_SetCalibTrimming(32);
LL_RCC_HSI_SetDivider(LL_RCC_HSI_DIV1);
LL_RCC_PLL_SetSource(LL_RCC_PLLSOURCE_HSI);
LL_RCC_PLL1P_Enable();
LL_RCC_PLL1_SetVCOInputRange(LL_RCC_PLLINPUTRANGE_8_16);
LL_RCC_PLL1_SetVCOOutputRange(LL_RCC_PLLVCORANGE_WIDE);
LL_RCC_PLL1_SetM(4);
LL_RCC_PLL1_SetN(60);
LL_RCC_PLL1_SetP(2);
LL_RCC_PLL1_SetQ(2);
LL_RCC_PLL1_SetR(2);
LL_RCC_PLL1_Enable();
/* Wait till PLL is ready */
while(LL_RCC_PLL1_IsReady() != 1)
{
}
/* Intermediate AHB prescaler 2 when target frequency clock is higher than 80 MHz */
LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1);
LL_RCC_SetSysPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAHBPrescaler(LL_RCC_AHB_DIV_2);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_2);
LL_RCC_SetAPB3Prescaler(LL_RCC_APB3_DIV_2);
LL_RCC_SetAPB4Prescaler(LL_RCC_APB4_DIV_2);
LL_Init1msTick(480000000);
LL_SetSystemCoreClock(480000000);
LL_RCC_SetUSARTClockSource(LL_RCC_USART16_CLKSOURCE_PCLK2);
MX_GPIO_Init():
/* GPIO Ports Clock Enable */
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
MX_DMA_Init():
/* DMA controller clock enable */
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
NVIC_SetPriority(DMA2_Stream0_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(DMA2_Stream0_IRQn);
NVIC_SetPriority(DMA2_Stream1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(DMA2_Stream1_IRQn);
MX_USART1_UART_Init():
LL_USART_InitTypeDef USART_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOB);
/**USART1 GPIO Configuration
PB14 ------> USART1_TX
PB15 ------> USART1_RX */
GPIO_InitStruct.Pin = LL_GPIO_PIN_14|LL_GPIO_PIN_15;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_4;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USART1 interrupt Init */
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
NVIC_EnableIRQ(USART1_IRQn);
USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
USART_InitStruct.BaudRate = 115200;
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
LL_USART_Init(USART1, &USART_InitStruct);
LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
LL_USART_SetRXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_2);
LL_USART_DisableFIFO(USART1);
LL_USART_ConfigAsyncMode(USART1);
LL_USART_EnableDMAReq_RX(USART1);
LL_USART_DisableOneBitSamp(USART1);
LL_USART_DisableIT_TC(USART1);
LL_USART_ClearFlag_TC(USART1);
LL_USART_EnableIT_RXNE_RXFNE(USART1);
LL_USART_Enable(USART1);
/* Polling USART1 initialisation */
while((!(LL_USART_IsActiveFlag_REACK(USART1))))
{
}
/* USART1_RX Init */
LL_DMA_SetPeriphRequest(DMA2, LL_DMA_STREAM_0, LL_DMAMUX1_REQ_USART1_RX);
LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_0, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_0, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MODE_CIRCULAR);
LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_0, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_DisableFifoMode(DMA2, LL_DMA_STREAM_0);
/* USART1_TX Init */
LL_DMA_SetPeriphRequest(DMA2, LL_DMA_STREAM_1, LL_DMAMUX1_REQ_USART1_TX);
LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_1, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_1, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA2, LL_DMA_STREAM_1, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_1, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_DisableFifoMode(DMA2, LL_DMA_STREAM_1);
LL_DMA_SetPeriphAddress(DMA2, LL_DMA_STREAM_0, (uint32_t)(&(USART1->RDR)));
LL_DMA_SetMemoryAddress(DMA2, LL_DMA_STREAM_0, (uint32_t)(&usart1_rx_buffer));
LL_DMA_SetDataLength(DMA2, LL_DMA_STREAM_0, 4);
LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_0, LL_DMA_MBURST_SINGLE);
LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_0, LL_DMA_PRIORITY_HIGH);
LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_0);
LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_0);
LL_DMA_SetPeriphAddress(DMA2, LL_DMA_STREAM_1, (uint32_t)(&(USART1->TDR)));
LL_DMA_SetMemoryAddress(DMA2, LL_DMA_STREAM_1, (uint32_t)(&usart1_tx_buffer));
LL_DMA_SetDataLength(DMA2, LL_DMA_STREAM_1, 1);
LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_1, LL_DMA_MBURST_SINGLE);
LL_DMA_EnableIT_TC(DMA2, LL_DMA_STREAM_1);
LL_DMA_EnableStream(DMA2, LL_DMA_STREAM_1);
LL_USART_DisableDirectionTx(USART1);
LL_USART_EnableDirectionRx(USART1);
USART1_IRQHandler():
if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1))
LL_USART_ClearFlag_NE(USART1);
if(LL_USART_IsActiveFlag_FE(USART1))
LL_USART_ClearFlag_FE(USART1);
if(LL_USART_IsActiveFlag_ORE(USART1))
LL_USART_ClearFlag_ORE(USART1);
if(LL_USART_IsActiveFlag_TC(USART1))
LL_USART_ClearFlag_TC(USART1);
DMA2_Stream0_IRQHandler():
if(LL_DMA_IsActiveFlag_HT0(DMA2))
LL_DMA_ClearFlag_HT0(DMA2);
if(LL_DMA_IsActiveFlag_TC0(DMA2))
LL_DMA_ClearFlag_TC0(DMA2);
DMA2_Stream1_IRQHandler():
if(LL_DMA_IsActiveFlag_HT1(DMA2))
LL_DMA_ClearFlag_HT1(DMA2);
if(LL_DMA_IsActiveFlag_TC1(DMA2))
LL_DMA_ClearFlag_TC1(DMA2);