2025-02-28 12:52 AM - last edited on 2025-02-28 1:01 AM by Andrew Neil
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.))
2025-02-28 1:17 AM
To change SPI DMA settings in SPI CR2, SPI must be disabled in CR1. RX DMA must be enabled before starting TX.
2025-02-28 1:46 AM
#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