0
\$\begingroup\$

MCU: STM32f030f4p6

There is garbage in reception buffer, when I use SPI and 2 DMAs (for reception and transmission).

void sendMsg2(uint32_t size, uint8_t* rx, uint8_t* tx){
DMA1_Channel2->CMAR=rx;
DMA1_Channel2->CNDTR=size;
DMA1_Channel2->CCR=DMA_CCR_MINC
        |DMA_CCR_TCIE
        |DMA_CCR_EN;

SCB->SCR=SCB_SCR_SLEEPONEXIT_Msk;
GPIOA->BSRR=GPIO_BSRR_BR_4;

DMA1_Channel3->CMAR=tx;
DMA1_Channel3->CNDTR=size;
DMA1_Channel3->CCR=DMA_CCR_MINC
        |DMA_CCR_DIR
        |DMA_CCR_EN;

__asm volatile("wfi");

DMA1_Channel3->CCR=0;
DMA1_Channel2->CCR=0;
}

But when I use 1 loop and 1 DMA it works.

EX1:

void sendMsg2(uint32_t size, uint8_t* rx, uint8_t* tx){
DMA1_Channel2->CMAR=rx;
DMA1_Channel2->CNDTR=size;
DMA1_Channel2->CCR=DMA_CCR_MINC
        |DMA_CCR_TCIE
        |DMA_CCR_EN;

for(register uint32_t i=0; i<size; i++){
    while(!(SPI1->SR&SPI_SR_RXNE));
    rx[i]=SPI1_DR_8;
}

DMA1_Channel2->CCR=0;
}

EX2:

void sendMsg2(uint32_t size, uint8_t* rx, uint8_t* tx){
DMA1_Channel3->CMAR=tx;
DMA1_Channel3->CNDTR=size;
DMA1_Channel3->CCR=DMA_CCR_MINC
        |DMA_CCR_DIR
        |DMA_CCR_EN;

for(register uint32_t i=0; i<size; i++){
    while(!(SPI1->SR&SPI_SR_TXE));
    SPI1_DR_8=tx[i];
}

DMA1_Channel3->CCR=0;
}
\$\endgroup\$
  • \$\begingroup\$ You need to edit this to make the code sufficient to reproduce the problem, and to show the data clearly, both what is expected and what is found, so probably you would have two hexdumps one after the other. \$\endgroup\$ – Chris Stratton Mar 8 at 20:52
  • 1
    \$\begingroup\$ Are you sending and receiving valid data simultaneously? Or are you trying to send THEN receive valid data? Because SPI is full duplex and receives a bit every time a bit is transmitted. If your RX DMA is enabled when your TX DMA starts transmitting, it will interpret anything and everything on MISO as valid receive data as long as you are transmitting. If you want to send then receive, you need to enable your RX DMA after the transmission is finished (i.e. TX DMA transfer complete ISR). But do not release slave select line during the hand-off since that would just interrupt the slave). \$\endgroup\$ – Toor Mar 8 at 21:00
  • 1
    \$\begingroup\$ There is an edit command you can use for your original post. Don't add additional info like that into the comments. \$\endgroup\$ – Toor Mar 8 at 21:47
  • \$\begingroup\$ Are you sure that wfi will wait long enough? \$\endgroup\$ – JimmyB May 13 at 11:10
0
\$\begingroup\$

your init function does not set the periph register address in the DMA configuration.

So it takes the data from the unknown address.

\$\endgroup\$
  • \$\begingroup\$ It set paddr in another function. void initSpiDma(){ DMA1_Channel2->CPAR=&SPI1->DR; DMA1_Channel3->CPAR=&SPI1->DR; // NVIC->ISER[0]=(0b1<<10); } \$\endgroup\$ – uis Mar 14 at 19:11
0
\$\begingroup\$

But when I use 1 loop and 1 DMA it works.

No, it doesn't. That is, your "working" code examples actually don't use DMA.

From the Reference Manual:

When starting communication using DMA [...] these steps must be followed [...]:

1.Enable DMA Rx buffer in the RXDMAEN bit in the SPI_CR2 register, if DMA Rx is used.

  1. Enable DMA streams for Tx and Rx in DMA registers, if the streams are used.

  2. Enable DMA Tx buffer in the TXDMAEN bit in the SPI_CR2 register, if DMA Tx is used.

  3. Enable the SPI by setting the SPE bit.

See also the code example in section "A.14.5 SPI master configuration with DMA code example".

Notice that, in order to use DMA, the DMA channel(s) must be set up and the peripheral must be told to use them.

Did you do all that in the code you did not include in your question?

Specifically, did you enable the SPI's DMA requests and set up the DMA channels before enabling the SPI?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.