cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA Memory to peripheral

Quentin_27
Associate III

Hello everyone,

I'm currently working on an SPI bus on an STM32U031C6 + S2LP.

I'd like to use my SPI with DMA mode.

The SPI bus I used previously worked on this board. As this is my first time using DMA, I'm simply trying to send data without necessarily performing a read, but rather by analyzing the bytes using a logic analyzer.

 

My SPI configuration is defined as follows:

//-----------------------------------------------------------------------------
void S2LP_InitIO (void)
//-----------------------------------------------------------------------------
{
	RCC->APBENR2 |= RCC_APBENR2_SPI1EN;

	GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE11)) | (GPIO_MODER_MODE11_0); //-- Select output mode (01)

	//--- PA15 en sortie (pour Spirit-SDn) ---
	GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE15)) | (GPIO_MODER_MODE15_0); //-- Select output mode (01)

	//--- PA0 en entree sans pull-up/down (pour Spirit-GPIO0) ---
	GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODE0 )); //-- Select input mode (00)
	GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPD0 )); //-- Input Floating (00)


	//======= Bus SPI : PA5,6,7 (SCLK, MISO, MOSI) ==========
	//--- Mode Alternate Function
	GPIOA->MODER = (GPIOA->MODER & 	~(GPIO_MODER_MODE5  | GPIO_MODER_MODE6  | GPIO_MODER_MODE7)) |
									 (GPIO_MODER_MODE5_1 | GPIO_MODER_MODE6_1 | GPIO_MODER_MODE7_1);


	GPIOA->AFR[0] &= ~(
	    (0xF << (5 * 4)) |  // Clear PA5
	    (0xF << (6 * 4)) |  // Clear PA6
	    (0xF << (7 * 4))    // Clear PA7
	);

	GPIOA->AFR[0] |= (
	    (0x5 << (5 * 4)) |  // PA5 -> AF5
	    (0x5 << (6 * 4)) |  // PA6 -> AF5
	    (0x5 << (7 * 4))    // PA7 -> AF5
	);

	SPI1->CR1 &= ~SPI_CR1_SPE; // <-- Désactiver SPI

	SPI1->CR2 = SPI_CR2_FRXTH | SPI_CR2_TXDMAEN ;//| SPI_CR2_RXDMAEN;

	SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_BR_0 | SPI_CR1_SSM | SPI_CR1_SSI ;		//--- Master, BR:Fpclk/4, CPOL et CPHA a zero

	SPI1->CR1 |= SPI_CR1_SPE;					//--- Enable SPI1

	if (!(SPI1->CR1 & SPI_CR1_SPE)) {
	    Error_Handler(); // ou breakpoint
	}

}

 

Here my function for try DMA Mode :

//-----------------------------------------------------------------------------
uint8_t SpiritDeviceVersion (void)
//-----------------------------------------------------------------------------
{
	S2LP_CS_DEBUT;

	uint8_t aTxBuffer[3] = {0x01, 0xF1, 0x00};
	RCC->AHBENR |= RCC_AHBENR_DMA1EN;	// Horloge DMA1 ON

	DMA1_Channel1->CPAR = (uint32_t) &(SPI1->DR);
	DMA1_Channel1->CMAR = (uint32_t) &(aTxBuffer[0]);

	DMA1_Channel1->CCR = 0;
	DMA1_Channel1->CCR |= (DMA_CCR_DIR);	// Direction vers peripherique (TX)
	DMA1_Channel1->CCR |= (DMA_CCR_MINC);	//MEM increment mode
	DMA1_Channel1->CCR |= (DMA_CCR_PL);		// Haute priorite
	DMA1_Channel1->CNDTR = 0x03;			//3 data

	DMA1_Channel1->CCR |= DMA_CCR_EN;
	DMAMUX1_Channel1->CCR = 37; // SPI_TX
	while(DMA1_Channel1->CNDTR != 0) asm("nop");

	S2LP_CS_FIN;
	return toto;

}

 

I'm currently stuck in the While CNDTR != 0 condition.

I think my counter should be decrementing, but it never does, and I don't see any information on the SPI bus...

If you have any ideas ?

Thank you for your time.

6 REPLIES 6
waclawek.jan
Super User

Where do you enable SPI (SPIx_CR1->SPE=1)?

If in doubts, always start by reading out and checking content of relevant peripherals (SPI, DMAMUX, DMA, GPIO).

JW

Quentin_27
Associate III

 

Sorry,

Before posting my message, I tried moving: SPI1->CR1 |= SPI_CR1_SPE;

I'm enabeling SPI after configuration of SPI-> CRx registers

I've corrected my message, and will add a capture of my DMACCR1 Register.

waclawek.jan
Super User

Read out and check/post content of registers of relevant peripherals (SPI, DMAMUX, DMA, GPIO).

JW

PS.I would set up DMAMUX before enabling DMA; and also the DMAMUX channel assignment may be wrong:

JW

Quentin_27
Associate III

So,

I have checked my peripherals, the SPI is runing and the DMA1 too.
But i'm still struck in while DMA1_Channel1->CNDTR != 0.

Is correct to configure and/or enable DMA after SPI clock ?

 

Regards.

waclawek.jan
Super User

> Is correct to configure and/or enable DMA after SPI clock ?

Probably yes.

As I've said and gave a link above, your problem may be incorrect DMAMUX channel - for DMA channel 1 you need to set up DMAMUX channel 0.

JW

Quentin_27
Associate III

Thanks, for your reply,
Now it's work,

Quentin_27_1-1754405483444.png

I just haven't understand the channel0_DMAMUX1 was on DMA1...

Quentin_27_0-1754405424506.png

I will now set the rx method, if I can help anyone my code below:

	volatile uint8_t	toto;



	uint8_t aTxBuffer[3] = {0x01, 0xF1, 0x00};

	RCC->AHBENR |= RCC_AHBENR_DMA1EN;	// Horloge DMA1 ON
	DMA1_Channel1->CPAR = (uint32_t) &(SPI1->DR);
	DMA1_Channel1->CMAR = (uint32_t) &(aTxBuffer[0]);

	DMA1_Channel1->CCR = 0;
	DMA1_Channel1->CCR |= (DMA_CCR_DIR);	// Direction vers peripherique (TX)
	DMA1_Channel1->CCR |= (DMA_CCR_MINC);	//MEM increment mode
	DMA1_Channel1->CCR |= (DMA_CCR_PL);		// Haute priorite

	DMA1_Channel1->CNDTR = 0x03;			//3 data


	DMAMUX1_Channel0->CCR = 37;
	DMA1_Channel1->CCR |= DMA_CCR_EN;

	S2LP_CS_DEBUT;
	while(DMA1_Channel1->CNDTR != 0) asm("nop");

	S2LP_CS_FIN;

Thanks for your time.