All kind time of day! never such was and here again. With my last article enough time has passed, and it poses new challenges. And if I transmit data at 100 Mbps, now I had to threaten to 1600 Mbps…

On CPDV — the hero of our novel — he was able to read data at that speed!

So, my next project requires to read a data stream of 32-bit at up to 50 MHz (it is, incidentally, the same 1.6 Gbps) in an amount known in advance, let it be 10000. It would be just great to read from using the DMA from a single port but, unfortunately, suitable processors are not to be found (hope to review this case someone will correct), all suitable for speed ports somehow 16-bit.

But a trifle will not stop us — we read from two ports at once! However, this is generally not always be able to do with the right degree of control and synchronicity, but in our case it’s not so sad — there is a signal, which after 20 ns, the data will be on port to hold on to.

As well as the CPU we have — stm32h750 400 MHz, and bus and timers at 200 MHz, then it should work.

It would seem a simple case the signal to start forwarding DMA. But the only DMA is not possible for the port to issue an interrupt, but can’t manage DMA. But our processor is a good thing — DMAMUX, which is a generator of events for a DMA channel, but in this generator there are two suitable opportunities — or to use the EXTIT0 or interrupt signal from the timer TIM12 (such is the strange fantasy was the developers of the chip).

On termination we will not make it in time — even on an empty working out to about 47 cycles, and the tact we have 2.5 ns…

But the time on the timer. It remains only to setactivity timer external signal of 100 MHz, and the length of the timer is set to 1 and its TRGO output will be triggered generator DMAMUX, and so he asks the team to forward DMA and the read port and forward the data in memory.

But stop! Port-16-bit, and we have 32… well, you can try to read another port… Only here for this need a second DMA channel, and it will take the same bus — that is, to read-we’ll do it, but can not manage to write data into memory. Well, theoretically, this processor has a different memory types, and look at the big picture of the structure of the processor it is possible to see that DMA and memory RAM_D1 sit on one and the same bus speed of 200 MHz. It remains to verify in practice.

DMA1->LIFCR |= ~0;
DMA1_Stream0->CR = (0b11 << DMA_SxCR_PL_Pos) | (0b01 << DMA_SxCR_MSIZE_Pos) | (0b01 << DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC;
DMA1_Stream0->M0AR = (uint32_t) data;
DMA1_Stream0->PAR = (uint32_t) &(GPIOE->IDR);
DMA1_Stream0->NDTR = 10000;
DMA1_Stream1->CR = (0b11 << DMA_SxCR_PL_Pos) | (0b01 << DMA_SxCR_MSIZE_Pos) | (0b01 << DMA_SxCR_PSIZE_Pos) | DMA_SxCR_MINC;
DMA1_Stream1->M0AR = (uint32_t) data2;
DMA1_Stream1->PAR = (uint32_t) &(GPIOD->IDR);
DMA1_Stream1->NDTR = 10000;
DMAMUX1_Channel0->CCR = DMAMUX_CxCR_EGE | (1);
DMAMUX1_Channel1->CCR = DMAMUX_CxCR_EGE | (2);
DMAMUX1_RequestGenerator0->RGCR = DMAMUX_RGxCR_GE | (0b01 << DMAMUX_RGxCR_GPOL_Pos) | (7);
DMAMUX1_RequestGenerator1->RGCR = DMAMUX_RGxCR_GE | (0b01 << DMAMUX_RGxCR_GPOL_Pos) | (7);
DMA1_Stream0->CR |= DMA_SxCR_EN;
DMA1_Stream1->CR |= DMA_SxCR_EN;
TIM12->CNT = 0;
TIM12->CCMR1 |= TIM_CCMR1_CC2S_0;
TIM12->CR2 = (0b010 << TIM_CR2_MMS_Pos);
TIM12->CR1 |= TIM_CR1_CEN;
while (DMA1_Stream0->NDTR)
i++;
TIM12->CR1 &= ~TIM_CR1_CEN;

And of course, it is necessary to place arrays of data and data2 in the desired memory segment, is as follows:

__attribute__((section(".dma_buffer"))) uint16_t data[10240],data2[10240];

and in the file for the linker, specify:

.dma_buffer : {
*(.dma_buffer) } >RAM_D1

To check, well the first option was implemented just a dumb up with
CPU (still 400 MHz):

 uint16_t * ptr = cpudata; volatile uint16_t * src = (GPIOE->IDR); volatile uint16_t * src2 = &(GPIOD->IDR); for (register int i = 0; i < 10000; i++) { *ptr++ = *src; *ptr++ = *src2;
}

To check the data cpudata were placed in different memory faster just walked (well, she really just 64K) ultra-fast memory (also 400 MHz) DTCMRAM.

Results

During the tests it turned out that using the CPU to read at the speed of 12.5 MHz of the two ports. And 25 MHz from a single. So that option is not working…

Using DMA and such a mother TIM12 was able to successfully read at a speed of 50 MHz, and for a few hours test, no errors neither. Read both ports, but to measure how far behind the reading the second DMA is not possible…

So in my (somewhat degenerate) case, was able to reach the speed of information transmission processor stm32h750 speed 32×50 = 1600 Mbps.

Source