cancel
Showing results for 
Search instead for 
Did you mean: 

SPI DMA STM32U031 wrong data

Quentin_27
Associate III

Hi everyone,

Im currently trying to use SPI with DMA mode on STM32U031G6 with an S2LP,
In this specific case I want to obtain the number of bytes present in my FIFO (10 bytes here), but the problem is that my reading through DMA mode does not work.

Below is the data that I analyze in SPI using a logic analyzer : 

Quentin_27_0-1757497219651.png
we have the read command (0x01) + the FIFO status command (0x90) + the command (0x00) where I get my response 0x0A or my 10 bytes.

 

What I don't understand is that the read_1_registre_DMA function returns 1 on the 3rd data item that I want to read as below :

Quentin_27_1-1757497434702.png

Below is the function where I give my 3 Tx commands and where I expect 3 responses in return for Rx but the data is not correct for RX[2] (3rd element, or for me I should find my 0xA):

//-----------------------------------------------------------------------------
uint8_t S2LP_Read1Registre (uint8_t address)
//-----------------------------------------------------------------------------
{
	S2LP_Init_DMA_Mode();

	// Préparer les commandes SPI (HEADER + adresse FIFO)
	g_SPI_DMA_TxBuffer[0] = (HEADER_READ | HEADER_ADDRESS);
	g_SPI_DMA_TxBuffer[1] = address;
	g_SPI_DMA_TxBuffer[2] = (0x00);

	// Sélection du S2LP
	S2LP_CS_DEBUT;

	// Setup CNDTR
	DMA1_Channel2->CNDTR = 0x03; // RX
	DMA1_Channel1->CNDTR = 0x03; // TX

	// Lancer RX puis TX
	DMA1_Channel2->CCR |= DMA_CCR_EN;
	DMA1_Channel1->CCR |= DMA_CCR_EN;

	// Attente fin TX (canal 1), puis RX (canal 2)
	while(DMA1_Channel1->CNDTR != 0) asm("nop");
	while(DMA1_Channel2->CNDTR != 0) asm("nop");


	// Fin de communication
	S2LP_CS_FIN;

	// Désactiver les DMA
	DMA1_Channel1->CCR &= ~DMA_CCR_EN;
	DMA1_Channel2->CCR &= ~DMA_CCR_EN;

	uint8_t toto = g_SPI_DMA_RxBuffer[2]; //--- lecture data recue
	return toto;
}

 

And the init_DMA Function:

uint8_t g_SPI_DMA_TxBuffer[BUF_SIZE] = {0};
uint8_t g_SPI_DMA_RxBuffer[BUF_SIZE] = {0};

void S2LP_Init_DMA_Mode (void)
{

	RCC->AHBENR |= RCC_AHBENR_DMA1EN;	// Horloge DMA1 ON
	//Config Tx
	DMA1_Channel1->CPAR = (uint32_t) &(SPI1->DR);				// Definie l'adresse SPI.DR comme adresse peripherique
	DMA1_Channel1->CMAR = (uint32_t) &(g_SPI_DMA_TxBuffer[0]);	// Definie l'adresse tableau comme buffer Tx

	DMA1_Channel1->CCR = 0;					// Pour etre sur de commencer la config à vide
	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_1);		// Haute priorite pour le SPI gere uniquement les operations faites en DMA
	//DMA1_Channel1->CNDTR = 0x03;			//	3 data

	//Config Rx
	DMA1_Channel2->CPAR = (uint32_t) &(SPI1->DR);				// Definie l'adresse SPI.DR comme adresse peripherique
	DMA1_Channel2->CMAR = (uint32_t) &(g_SPI_DMA_RxBuffer[0]);	// Definie l'adresse tableau comme buffer Rx

	DMA1_Channel2->CCR = 0;					// Pour etre sur de commencer la config à vide
											// Attention ici on active pas DMA_CCR_DIR car on va dans le sens inverse justement !
	DMA1_Channel2->CCR |= (DMA_CCR_MINC);	//MEM increment mode
	DMA1_Channel2->CCR |= (DMA_CCR_PL_0 | DMA_CCR_PL_1);		// Haute priorite pour le SPI gere uniquement les opérations faites en DMA

	//DMA1_Channel2->CNDTR = 0x01;			//1 data

	// -- Usage DMA MUX --
	// Selection du MUX DMAMUX1 channel_x <=HARD=> DMA_Channel_x+1
											//----------------------------------------------------------
	DMAMUX1_Channel0->CCR = 37;				// Selection du MUX DMAMUX1 channel_0 <=HARD=> DMA_Channel_1
	DMAMUX1_Channel1->CCR = 36;				// Selection du MUX DMAMUX1 channel_1 <=HARD=> DMA_Channel_2
											//			...						...																
}

 

Thanks for your time !

2 REPLIES 2
Danish1
Lead III

RX[2] does not have the expected value.

Do you know that RX[0] and RX[1] are being received correctly?

You observe RX[0] and RX[1] have the expected values after the transfer. But might they have had those values before the transfer? Can you put e.g. 0xff into all of them prior to the transfer to test this?

Understanding if any bytes are received correctly will help diagnose where the problem might be. For example, do you set SPI_CR2_RXDMAEN as well as SPI_CR2_TXDMAEN ?

Quentin_27
Associate III

Thank you for your reply,
I try to add as you say Rx[0 - 2] = 0xFF
but i have the same result :

Quentin_27_0-1757510042911.png

Bellow the SPI_IO_init code where I enable DMA for SPI-Rx and SPI-Tx

//-----------------------------------------------------------------------------
void S2LP_InitIO (void)
//-----------------------------------------------------------------------------
{

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

	//--- PA15 -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 )); 
	GPIOA->PUPDR = (GPIOA->PUPDR & ~(GPIO_PUPDR_PUPD0 )); //-- Input Floating (00)


	//======= Bus SPI : PA5,6,7 (SCLK, MISO, MOSI) ==========
	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
	);




	//--- Pull-down sur PA6, PA2 pour SDO, GPIO0 en mode StandBy
	GPIOA->PUPDR &= ~(GPIO_PUPDR_PUPD6); //-- (00)
	GPIOA->PUPDR |= (GPIO_PUPDR_PUPD6_1); //-- Pull down (10)

	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_MSTR | SPI_CR1_BR_0 | SPI_CR1_SSM | SPI_CR1_SSI;



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

	if (!(SPI1->CR1 & SPI_CR1_SPE))
	{
	    Error_Handler();
	}
	S2LP_Init_DMA_Mode();
}

 

Thanks