How to setup a SPI + DMA by the use of the LL lib for the STM32MP151C?
Hi All.
I develop M4 Core firmware using a custom board based on STM32MP151C.
There is no problem with SPI communication without using DMA. However, when DMA is used, waveforms do not occur the pins or only the NSS pins react, resulting in waveforms.
I want to know if I set the DMA wrong.
Below is the corresponding code.
__IO uint16_t __TEST_BUFFER[3];
void
MX_DMA_Init (void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA2_CLK_ENABLE();
__HAL_RCC_DMAMUX_CLK_ENABLE();
/* DMA2_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority (DMA2_Stream1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ (DMA2_Stream1_IRQn);
return;
}
void
MX_SPI2_Init ()
{
LL_SPI_InitTypeDef SPI_InitStruct =
{ 0 };
LL_GPIO_InitTypeDef GPIO_InitStruct =
{ 0 };
if (IS_ENGINEERING_BOOT_MODE())
{
LL_RCC_SetSPIClockSource (LL_RCC_SPI23_CLKSOURCE_PLL3Q);
}
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock (LL_APB1_GRP1_PERIPH_SPI2);
LL_AHB4_GRP1_EnableClock (LL_AHB4_GRP1_PERIPH_GPIOB);
LL_AHB4_GRP1_EnableClock (LL_AHB4_GRP1_PERIPH_GPIOI);
/**SPI2 GPIO Configuration
PB4 ------> SPI2_NSS
PI1 ------> SPI2_SCK
PI3 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_4;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_7;
LL_GPIO_Init (GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_1 | LL_GPIO_PIN_2 | LL_GPIO_PIN_3;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
LL_GPIO_Init (GPIOI, &GPIO_InitStruct);
/* SPI2 parameter configuration*/
SPI_InitStruct.TransferDirection = LL_SPI_HALF_DUPLEX_TX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_HARD_OUTPUT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 0xD;
LL_SPI_Init (SPI2, &SPI_InitStruct);
LL_SPI_SetStandard (SPI2, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_EnableNSSPulseMgt (SPI2);
LL_SPI_Enable(SPI2);
LL_DMA_SetPeriphRequest(DMA2, LL_DMA_STREAM_1, LL_DMAMUX1_REQ_SPI2_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_VERYHIGH);
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_HALFWORD);
LL_DMA_SetMemorySize (DMA2, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_HALFWORD);
LL_DMA_DisableFifoMode (DMA2, LL_DMA_STREAM_1);
LL_DMA_ConfigAddresses (DMA2,
LL_DMA_STREAM_1,
(uint32_t) &__TEST_BUFFER[0],
(uint32_t) &(SPI2->TXDR),
LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetDataLength (DMA2, LL_DMA_STREAM_1, 3);
LL_DMA_EnableStream (DMA2, LL_DMA_STREAM_1);
LL_DMA_EnableIT_TC (DMA2, LL_DMA_STREAM_1); // Enable transfer complete interrupt.
LL_DMA_EnableIT_TE (DMA2, LL_DMA_STREAM_1); // Enable transfer error interrupt.
return;
}
void DMA2_Stream1_IRQHandler(void)
{
if (LL_DMA_IsActiveFlag_TC1 (DMA2) == 1)
{
/* Clear flag DMA transfer complete */
LL_DMA_ClearFlag_TC1 (DMA2);
LL_SPI_DisableDMAReq_TX(SPI2);
}
if (LL_DMA_IsActiveFlag_TE1 (DMA2) == 1)
{
/* Clear flag DMA transfer error */
LL_DMA_ClearFlag_TE1 (DMA2);
LL_SPI_DisableDMAReq_TX(SPI2);
}
return;
}
int
main (void)
{
HAL_Init ();
/* If booted from Engineering mode */
if (IS_ENGINEERING_BOOT_MODE())
{
/* Configure the system clock */
SystemClock_Config ();
}
else
{
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/* IPCC initialisation */
MX_IPCC_Init ();
MX_VUART_Init ();
}
MX_DMA_Init ();
MX_SPI2_Init ();
__MTR_FEED_BFR = { 4152, 20536, 46700 };
while (1)
{
LL_DMA_ClearFlag_TC1(DMA2);
LL_SPI_EnableDMAReq_TX(SPI2);
while(!LL_SPI_IsEnabledDMAReq_TX(SPI2))
{
HAL_Delay(1);
}
}
}
need a lot of advice
Machilus
