cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G431 SPI2 (16-bit) DMA (DMAMUX) data transmission is incorrect.

Oleksii
Associate III

Here is the code:

 

 

void DMA_Init_SPI2(void *rxBuffer, void *txBuffer, uint16_t rxSIZE, uint16_t txSIZE) {

    RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN | RCC_AHB1ENR_DMAMUX1EN;

    // DMA1 Channel 1 для SPI2_RX (Peripheral-to-Memory)
    
    DMA1_Channel1->CCR = DMA_CCR_MINC |        // RAM++
                         DMA_CCR_TCIE |        // IRQ_EN
                         DMA_CCR_PSIZE_0 |     // 16-bit
                         DMA_CCR_MSIZE_0 |     // 16-bit
                         DMA_CCR_CIRC
                         ;
    DMA1_Channel1->CNDTR = rxSIZE;              
    DMA1_Channel1->CPAR = (uint32_t)&(SPI2->DR);
    DMA1_Channel1->CMAR = (uint32_t)rxBuffer;   
    DMAMUX1_Channel0->CCR = 12 ;               // SPI2_RX (Table 91 rm440)
    
 // DMA1 Channel 2 для SPI2_RX (Memory to Peripheral)
 
    DMA1_Channel2->CCR = DMA_CCR_MINC 	 |     // RAM++
                         DMA_CCR_DIR     |     // RAM -> SPI
                         DMA_CCR_PSIZE_0 |     // 16-bit
                         DMA_CCR_MSIZE_0       // 16-bit
                         ;

    DMA1_Channel2->CNDTR = txSIZE;              
    DMA1_Channel2->CPAR = (uint32_t)&(SPI2->DR); 
    DMA1_Channel2->CMAR = (uint32_t)txBuffer; 
    DMAMUX1_Channel1->CCR = 13;                // SPI2_TX (Table 91)

    NVIC_EnableIRQ(DMA1_Channel1_IRQn);
}

uint8_t dmaComplete;

void DMA1_Channel1_IRQHandler(void) {

    if (DMA1->ISR & DMA_ISR_TCIF1) {

        DMA1->IFCR = DMA_IFCR_CTCIF1;

        //DMA1_Channel1->CCR &= ~DMA_CCR_EN;
        DMA1_Channel2->CCR &= ~DMA_CCR_EN;

        dmaComplete = 1;

    }

//  DMA1->IFCR |= DMA_IFCR_CGIF1;
}
#define SPI2_DMA_enable  SPI2->CR2  |=  3; // 16 BIT
#define SPI2_DMA_disabled SPI2->CR2 |= ~3;

#define SPI2_CS_on   GPIOA->BRR =  1<<10;
#define SPI2_CS_off  GPIOA->BSRR = 1<<10;

void IIM42652_ReadSPI2_DMA(uint8_t startReadCommand,uint16_t* ram,uint16_t size) {

	dmaComplete = 0;

    ram[0] = (uint16_t)startReadCommand << 8; //example 0xAD00

    SPI2_CS_on
    
    DMA1_Channel2->CNDTR = size;
    DMA1_Channel2->CPAR = (uint32_t)&(SPI2->DR);
    DMA1_Channel2->CMAR = (uint32_t*)ram;
    DMA1_Channel2->CCR |= DMA_CCR_EN;
    
 	while (!dmaComplete);
 
    SPI2_CS_off

}
void ConfigSPI2(void) {

	RCC->APB1ENR1 |= RCC_APB1ENR1_SPI2EN;
	SPI2->CR1 = (1 << 2) | (2 << 3) | (3 <<  | 0; // master | clk/8 |  SSM=1 SSI =1 
	SPI2->CR2 |= (0b1111 <<  | 0; // 16 BIT /
	

	//SPI2->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;


	SPI2->CR1 |= (1 << 6);// EN SP2
}
uint16_t spi2_rx_buf[30]={0},spi2rxsize = 12,
	 spi2_tx_buf[30]={0},spi2txsize = 12;

int main(void) {

	// Настройка системного тактирования

	SystemClock_Config();
	GPIO_INIT();
	CAN_Config();

	I2C2_Init();

	ConfigSPI2();
	DMA_Init_SPI2(spi2_rx_buf,spi2_tx_buf,spi2rxsize,spi2txsize);
	init_iim42652(&imu_iim42652);
	
	DMA1_Channel1->CCR |= DMA_CCR_EN; // Rx circle
	SPI2_DMA_enable	
	
    while (1) {
	
	if(readyINT1){readyINT1 = 0; 
		      IIM42652_ReadSPI2_DMA(0xAD,spi2_tx_buf,12);//Read FIFO
		      if((*spi2_rx_buf) &0x04) sendACC = 1;
		      
		      }
	//..........
	
	if (!systick_pause) {
	 	if(sendACC){sendACC =0;
		     CAN_SendMessage(id+1,(uint8_t*) spi2_rx_buf, 8);
		     CAN_SendMessage(id+2,(uint8_t*) spi2_rx_buf+8, 8);
		     };
		systick_pause = 20;
	};
	

    }
}

 

 

 I checked SPI2 the operation using standard methods (in a loop) for sending and receiving data, and everything works as expected; the data is received correctly.

[0C 00 ] 14 00 78 F4 FF EA FF 19 08 02 00 F3 FF FC

 

But as soon as I enable the DMA, everything starts to behave strangely. The first half-word (16 bits) is received correctly, but then there is a change in the data or some garbage.

 

[0C 00] 00 14 DC 78 60 FF 16 00 02 08 F5 00 FD FF

 

Can anyone suggest where I might be missing something or doing it wrong? Unfortunately, the RM440 contains little information on DMA (DMAMUX) and sometimes does not correspond to stm32g431xx.h. I have already asked questions on GROK, DeepSeek, and ChatGPT—none of them could offer anything useful regarding this issue.))

 

 

 

2 REPLIES 2
gbm
Principal

To change SPI DMA settings  in SPI CR2, SPI must be disabled in CR1. RX DMA must be enabled before starting TX.

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Oleksii
Associate III
#define SPI2_DMA_enable  SPI2->CR2  |=  3; // 16 BIT
DMA1_Channel1->CCR |= DMA_CCR_EN; // Rx circle
	SPI2_DMA_enable	

Thank you for the response. The datasheet does not specify that SPI needs to be disabled to enable DMA.

However, I have tried both options, and it works either way. Believe me, I have spent more than one day trying to find the problem.

Also, please note that the data is received, but it is incorrect; it is similar to what is expected.
Marker bayt 14 ...78

[0C 00 ]14 00 78 F4 FF EA FF 19 08 02 00 F3 FF FC   

[0C 00] 00 14 DC 78 60 FF 16 00 02 08 F5 00 FD FF