2025-08-05 6:25 AM - edited 2025-08-05 6:35 AM
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.
2025-08-05 6:33 AM
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
2025-08-05 6:39 AM - edited 2025-08-05 7:34 AM
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.
2025-08-05 7:34 AM - edited 2025-08-05 7:37 AM
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
2025-08-05 7:38 AM
2025-08-05 7:43 AM
> 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
2025-08-05 7:54 AM
Thanks, for your reply,
Now it's work,
I just haven't understand the channel0_DMAMUX1 was on DMA1...
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.