cancel
Showing results for 
Search instead for 
Did you mean: 

Possible HAL spi bug?, also question on fast spi dma transfer initiation.

Ihawk.1
Associate II

In :

/stm32h745nucleoTest_CM7/Drivers/STM32H7xx_HAL_Driver/stm32h7xx_hal_dma.c

we find:

 if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */

 {

  /* Clear all interrupt flags at correct offset within the register */

  regs_dma->IFCR = 0x3FUL << (hdma->StreamIndex & 0x1FU);

surely 0x3FUL will over write the bottom bit of the next channel entry?

My next question:

I use:

HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*)StartAddress, n);

to write a burst of 24 bit spi words.

However the HAL code is exhaustive and quite slow.

What do I need to do to quickly trigger another burst using the same spi and dma channels, but with a different source memory pointer, what is the minimum amount of register writes that are needed?. The following code is missing something vital, but I cant figure it out:

SPI2->CR1 &= ~1;

SPI2->CFG1 &= ~1<<15;//txdmaen

DMA1_Stream4->CR &= ~1;

DMA1_Stream4->CR |= 1<<5;

DMA1_Stream4->NDTR = n;

DMA1_Stream4->M0AR = StartAddress;

DMA1->HIFCR = 0x1f;

DMA1_Stream4->CR |= 1<<4;

DMA1_Stream4->CR |=1;

  SPI2->CR2 |= n;

SPI2->CFG1 |= 1<<15;//txdmaen

SPI2->CFG2 |= 1<22;// master mode bit set

SPI2->CR1 |= 1 ;

SPI2->CR1 |= 1<<9;

6 REPLIES 6
Pavel A.
Evangelist III

> In :/stm32h745nucleoTest_CM7/Drivers/STM32H7xx_HAL_Driver/stm32h7xx_hal_dma.c

In the latest source - in following two lines:

https://github.com/STMicroelectronics/stm32h7xx_hal_driver/blob/2bfa1cae79926af47ff79a48757d29a38c9c8978/Src/stm32h7xx_hal_dma.c#L851

https://github.com/STMicroelectronics/stm32h7xx_hal_driver/blob/2bfa1cae79926af47ff79a48757d29a38c9c8978/Src/stm32h7xx_hal_dma.c#L1788

> surely 0x3FUL will over write the bottom bit of the next channel entry?

No it won't.. Each channel entry in DMA_LIFCR, DMA_HIFCR takes 6 bits (including one unused) so 3F is ok.

--pa

S.Ma
Principal

Could it be the sequence in wrong order?

Ihawk.1
Associate II

Hi Pavel, thanks, OK the bit fields are 6 wide, I hadnt noticed.

.(customer)

Yes, it could be that the register sequence is in the wrong order, or the wrong register values, or missing register values, or a combination or permutation of these. I have yet to find a working formula. I thought I had reproduced the sequence that occurs in the HAL calls, but I have spent hours on this and cant find the missing magic.

Read out and check/post content of SPI, DMAMUX, DMA registers at the perceived point of failure.

> DMA1_Stream4->CR &= ~1;

A delay may be needed after disabling the stream, until it accepts further write into its registers. You are supposed to wait until hardware clears the same enable bit (this is not a memory-like register, read returns state of a different register than write writes into).

JW

Ihawk.1
Associate II

Thanks JW, that might explain the apparent flakey operation of this code, I wonder if I would get enough delay by just reordering it to put a gap between the stream disable and the subsequent writes to DMA registers, a poling loop here would be ugly.

SPI1->CFG1 &= ~1<<15;// SPI_CFG1_TXDMAEN

SPI1->CR1 &= ~(1<<9);//c start

DMA1_Stream3->CR &= ~1;//disable dma stream

  DMA1_Stream3->M0AR = StartAddress;

  DMA1_Stream3->PAR =  (uint32_t)&SPI1->TXDR;//0x40013020;

  DMA1_Stream3->NDTR = n;

  SPI1->CR2 = n ;// no words

SPI1->CFG1 |= 23 | 1<<15 ;//txdmaen & no of bits in spi word

SPI1->CR1 |= 1;

DMA1_Stream3->CR |= 1<<4 | 1<<3 | 1;//enable dma stream//enable transfer complete interrupt and enable dma stream

SPI1->CR1 |= 1<<9;//c start

I believe that M0AR/PAR/NDTR are all write-protected until CR1.EN = 0. The RM says so.

JW