cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with SPI2/DMA in Receives only for STM32L476RG (Nucleo) via LL Template.

Riscy
Senior

Under the HAL template the SPI2/DMA in received only which worked fine. I have MISO and MOSI loop back for test purpose and need to send 3 or 4 byte per session.

Because the client code is LL template so I can't use HAL solution. Below is the LL snips for which I use UART command to run the init. The DMA interrupt is not invoked after transmitting 3 or 4 byte data. After checking out the SRC in DMA1 and SPI2 register list including NVIC I found no difference from the working HAL template code. I don't see DMA interrupt flag set. I'm running out of ideas about what to do next and why DMA interrupt is not invoked by SPI2 received operation, have I missed something?

NB: The BOOT1 is grounded by eval board (via 10K). I also have UART/Systick up and running which means the interrupt system is working fine. I wish to note this is demo FW as testbed which is MIXED HAL and LL template.

//========================================================================

// Purpose:- None MX Way to setup GPIO

// Input:-

// Output:-

// Note:- None

//========================================================================

static void STM32_DMASPI_GPIO_Init(void)

{

 /* Peripheral clock enable */

 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);

 //LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);

 //LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); // Already Enabled by previous code

 //__HAL_RCC_DMA1_CLK_ENABLE();

 LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

 /**SPI2 GPIO Configuration

 PB13  ------> SPI2_SCK

 PB14  ------> SPI2_MISO

 PB15  ------> SPI2_MOSI

 */

 GPIO_InitStruct.Pin = LL_GPIO_PIN_13|LL_GPIO_PIN_14|LL_GPIO_PIN_15;

 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_5;

 LL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 //------------------------------------------------------/CS

 GPIO_InitStruct.Pin = SPI2_CS_PIN;

 GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;

 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_0; // Ignored due to MODE.

 LL_GPIO_Init(SPI2_CS_GPIO_Port, &GPIO_InitStruct);

// or in G12 Load MCU

//   LL_GPIO_SetAFPin_0_7(SPI1_SCK_LL,LL_GPIO_AF_5);

//   LL_GPIO_SetAFPin_0_7(SPI1_MOSI_LL,LL_GPIO_AF_5);

// LL_GPIO_SetAFPin_0_7(SPI1_MISO_LL,LL_GPIO_AF_5);

}

//========================================================================

// Purpose:- None MX Way to setup DMA and SPI

// Input:-

// Output:-

// Note:- None

//========================================================================

static void SMT32_DMASPI_Init(bool IncludeDMA)

{

//L99DM02_SPI_SEND TxData;

if (IncludeDMA==FALSE)

{

STM32_DMASPI_InitSPI2();

LL_SPI_Enable( SPI2 );//enable SPI2 port

return;

}

STM32_DMASPI_DMA1_A();

STM32_DMASPI_InitSPI2();

}

static void STM32_DMASPI_DMA1_A(void)

{

LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);

/* (2) Configure NVIC for DMA transfer complete/error interrupts */

//__HAL_RCC_DMA1_CLK_ENABLE();

HAL_NVIC_SetPriority(DMA1_Channel4_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);

//LL_SPI_SetDMAParity_RX(SPI2,LL_SPI_DMA_PARITY_ODD);

/* (4) Configure the DMA1_Channel4 functional parameters */

LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_4, LL_DMA_REQUEST_4);

LL_DMA_ConfigTransfer(DMA1, LL_DMA_CHANNEL_4,

LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_PRIORITY_HIGH | LL_DMA_MODE_CIRCULAR |

LL_DMA_PERIPH_NOINCREMENT | LL_DMA_MEMORY_INCREMENT |

LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE);

LL_DMA_ConfigAddresses(DMA1, LL_DMA_CHANNEL_4, LL_SPI_DMA_GetRegAddr(SPI2), (uint32_t)SPIRXData,

LL_DMA_GetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4));

LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, 3);

/* (5) Enable DMA interrupts complete/error */

LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_4);

LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_4);

LL_DMA_EnableIT_HT(DMA1, LL_DMA_CHANNEL_4); // HAL has this set, not sure why?

}

static void STM32_DMASPI_InitSPI2(void)

{

LL_SPI_InitTypeDef SpiInitStruct;

LL_SPI_StructInit( &SpiInitStruct );

// L99 : CPOL = 0 CPHA = 0 which is not same as TLE which operate with CPOL = 0 CPHA = 1

SpiInitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;

SpiInitStruct.Mode = LL_SPI_MODE_MASTER;

SpiInitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;

SpiInitStruct.ClockPolarity = LL_SPI_POLARITY_HIGH;

SpiInitStruct.ClockPhase = LL_SPI_PHASE_2EDGE;

//SpiInitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;   //CPOL=0

//SpiInitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;     //CPHA=0

SpiInitStruct.NSS = LL_SPI_NSS_SOFT;

SpiInitStruct.BitOrder = LL_SPI_MSB_FIRST;

SpiInitStruct.CRCPoly = 7;

SpiInitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;

SpiInitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV64;

HAL_NVIC_DisableIRQ( SPI2_IRQn );

LL_SPI_DeInit( SPI2 );

LL_SPI_Init( SPI2, &SpiInitStruct );

LL_SPI_SetStandard(SPI2, LL_SPI_PROTOCOL_MOTOROLA);

//LL_SPI_DisableNSSPulseMgt(SPI2);

//LL_SPI_EnableNSSPulseMgt(SPI2);

LL_SPI_SetRxFIFOThreshold( SPI2, LL_SPI_RX_FIFO_TH_QUARTER ); // set RXNE to trigger on 1 byte

//LL_SPI_EnableIT_RXNE(SPI2);

}

static void STM32_DMASPI_Run(void)

{

LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);

LL_SPI_Disable( SPI2 );

//NVIC_EnableIRQ(DMA1_Channel4_IRQn);

LL_DMA_ClearFlag_TC4(DMA1);

LL_DMA_ClearFlag_TE4(DMA1);

LL_DMA_SetMemoryAddress( DMA1, LL_DMA_CHANNEL_4, (uint32_t)&SPIRXData );

HAL_NVIC_EnableIRQ(SPI2_IRQn );

HAL_NVIC_EnableIRQ(DMA1_Channel4_IRQn);

LL_SPI_Enable( SPI2 );//enable SPI2 port

LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);

LL_SPI_EnableDMAReq_RX(SPI2);

zprintf("__NVIC_GetActive: 0x%4x\n",__NVIC_GetActive(DMA1_Channel4_IRQn));

zprintf("__NVIC_GetEnableIRQ: 0x%4x\n",__NVIC_GetEnableIRQ(DMA1_Channel4_IRQn));

zprintf("__NVIC_GetPriorityGrouping: 0x%4x\n",__NVIC_GetPriorityGrouping());

ActivateSpiCS( 0 );

// write transmit data to SPI, command first, then upper data byte, then lower data byte

LL_SPI_TransmitData8( SPI2, 0x1A );

LL_SPI_TransmitData8( SPI2, 0x2B );

LL_SPI_TransmitData8( SPI2, 0xAA );

LL_SPI_TransmitData8( SPI2, 0xBB );

}

static void STM32_DMASPI_Polling_Run(void)

{

SMT32_DMASPI_Init(FALSE); // SPI Only.

ActivateSpiCS( 0 );

// write transmit data to SPI, command first, then upper data byte, then lower data byte

LL_SPI_TransmitData8( SPI2, 0x1A );

LL_SPI_TransmitData8( SPI2, 0x2B );

LL_SPI_TransmitData8( SPI2, 0xAA );

while( LL_SPI_IsActiveFlag_BSY( SPI2 ) );      // wait for SPI transfer complete

DeactivateSpiCS();             // unset device CS active

SPIRXData[0] = *((BYTE*)&SPI2->DR);;

SPIRXData[1] = *((BYTE*)&SPI2->DR);;

SPIRXData[2] = *((BYTE*)&SPI2->DR);;

zprintf("Received Data 0x%1x, 0x%1x, 0x%1x\n",SPIRXData[0],SPIRXData[1],SPIRXData[2]);

}

2 REPLIES 2
Riscy
Senior

I just fixed the bug after discovering this statement:

LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_4, LL_DMA_REQUEST_4);

The datasheet indicated SPI2-RX goes to DMA_CHANNEL_4 and also DMA_REQUEST_4 but when MXCube creates code it points to LL_DMA_REQUEST_1 not LL_DMA_REQUEST_4 as per datasheet s

It is in reference manual RM0351 Page 338 (STM32L47xxx, STM32L48xxx, STM32L49xxx and STM32L4Axxx) which clearly link SPI2_RX to LL_DMA_REQUEST_4 so I still confused between LL_DMA_REQUEST_4 and LL_DMA_REQUEST_1 is reference manual in error?.

Can anyone explain this?

Hi @Community member​ ,

Generated code with current STM32CubeMX version (6.6.1) contains following line:

  LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_4, LL_DMA_REQUEST_1);

This is aligned with the content of table 44 in the RM0351:

0693W00000QNt6sQAD.pngAre you sing an older version of the tool where it is possible that there was an issue?

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.