2022-02-12 03:10 PM
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;
2022-02-12 04:53 PM
> In :/stm32h745nucleoTest_CM7/Drivers/STM32H7xx_HAL_Driver/stm32h7xx_hal_dma.c
In the latest source - in following two lines:
> 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
2022-02-12 09:15 PM
Could it be the sequence in wrong order?
2022-02-13 10:46 AM
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.
2022-02-14 12:17 AM
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
2022-02-14 03:19 AM
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
2022-02-14 10:16 AM
I believe that M0AR/PAR/NDTR are all write-protected until CR1.EN = 0. The RM says so.
JW