2025-09-10 2:48 AM
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 :
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 :
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 !
2025-09-10 5:38 AM
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 ?
2025-09-10 6:15 AM
Thank you for your reply,
I try to add as you say Rx[0 - 2] = 0xFF
but i have the same result :
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